summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Nicolas Geoffray <ngeoffray@google.com> 2018-05-10 12:55:40 +0100
committer Nicolas Geoffray <ngeoffray@google.com> 2018-05-10 22:49:34 +0100
commit0d0f3164160e50ddb78022f662c5438fc167f50d (patch)
tree13bfdad1117db0adfb8b434ff1b8e1589c0c43ea
parent9d7905fffb9eca8f4fa6f3f3d7d3deb9718e3005 (diff)
Handle multidex in LocationIsOnSystemFramework.
bug: 79111915 Test: art_dex_file_loader_test.cc Change-Id: I507ad98c62b4c589196685d74abdeaf748502a61
-rw-r--r--libdexfile/dex/dex_file_loader.cc2
-rw-r--r--libdexfile/dex/dex_file_loader.h2
-rw-r--r--runtime/base/file_utils.cc15
-rw-r--r--runtime/dex/art_dex_file_loader.cc5
-rw-r--r--runtime/dex/art_dex_file_loader_test.cc61
5 files changed, 73 insertions, 12 deletions
diff --git a/libdexfile/dex/dex_file_loader.cc b/libdexfile/dex/dex_file_loader.cc
index 1e0f5ac6ae..457addf114 100644
--- a/libdexfile/dex/dex_file_loader.cc
+++ b/libdexfile/dex/dex_file_loader.cc
@@ -191,6 +191,8 @@ std::string DexFileLoader::GetDexCanonicalLocation(const char* dex_location) {
std::string base_location = GetBaseLocation(dex_location);
const char* suffix = dex_location + base_location.size();
DCHECK(suffix[0] == 0 || suffix[0] == kMultiDexSeparator);
+ // Warning: Bionic implementation of realpath() allocates > 12KB on the stack.
+ // Do not run this code on a small stack, e.g. in signal handler.
UniqueCPtr<const char[]> path(realpath(base_location.c_str(), nullptr));
if (path != nullptr && path.get() != base_location) {
return std::string(path.get()) + suffix;
diff --git a/libdexfile/dex/dex_file_loader.h b/libdexfile/dex/dex_file_loader.h
index 28cdfc13ce..01532203eb 100644
--- a/libdexfile/dex/dex_file_loader.h
+++ b/libdexfile/dex/dex_file_loader.h
@@ -71,7 +71,7 @@ class DexFileLoader {
// of the dex file. In the second case (oat) it will include the file name
// and possibly some multidex annotation to uniquely identify it.
// canonical_dex_location:
- // the dex_location where it's file name part has been made canonical.
+ // the dex_location where its file name part has been made canonical.
static std::string GetDexCanonicalLocation(const char* dex_location);
// For normal dex files, location and base location coincide. If a dex file is part of a multidex
diff --git a/runtime/base/file_utils.cc b/runtime/base/file_utils.cc
index 7921985b15..537216c198 100644
--- a/runtime/base/file_utils.cc
+++ b/runtime/base/file_utils.cc
@@ -261,12 +261,12 @@ std::string ReplaceFileExtension(const std::string& filename, const std::string&
}
}
-bool LocationIsOnSystem(const char* location) {
- UniqueCPtr<const char[]> path(realpath(location, nullptr));
- return path != nullptr && android::base::StartsWith(path.get(), GetAndroidRoot().c_str());
+bool LocationIsOnSystem(const char* path) {
+ UniqueCPtr<const char[]> full_path(realpath(path, nullptr));
+ return path != nullptr && android::base::StartsWith(full_path.get(), GetAndroidRoot().c_str());
}
-bool LocationIsOnSystemFramework(const char* location) {
+bool LocationIsOnSystemFramework(const char* full_path) {
std::string error_msg;
std::string root_path = GetAndroidRootSafe(&error_msg);
if (root_path.empty()) {
@@ -275,12 +275,7 @@ bool LocationIsOnSystemFramework(const char* location) {
return false;
}
std::string framework_path = root_path + "/framework/";
-
- // Warning: Bionic implementation of realpath() allocates > 12KB on the stack.
- // Do not run this code on a small stack, e.g. in signal handler.
- UniqueCPtr<const char[]> path(realpath(location, nullptr));
- return path != nullptr &&
- android::base::StartsWith(path.get(), framework_path.c_str());
+ return android::base::StartsWith(full_path, framework_path);
}
} // namespace art
diff --git a/runtime/dex/art_dex_file_loader.cc b/runtime/dex/art_dex_file_loader.cc
index 415e451098..392ce1e7f5 100644
--- a/runtime/dex/art_dex_file_loader.cc
+++ b/runtime/dex/art_dex_file_loader.cc
@@ -534,7 +534,10 @@ std::unique_ptr<DexFile> ArtDexFileLoader::OpenCommon(const uint8_t* base,
// Check if this dex file is located in the framework directory.
// If it is, set a flag on the dex file. This is used by hidden API
// policy decision logic.
- if (dex_file != nullptr && LocationIsOnSystemFramework(location.c_str())) {
+ // Location can contain multidex suffix, so fetch its canonical version. Note
+ // that this will call `realpath`.
+ std::string path = DexFileLoader::GetDexCanonicalLocation(location.c_str());
+ if (dex_file != nullptr && LocationIsOnSystemFramework(path.c_str())) {
dex_file->SetIsPlatformDexFile();
}
diff --git a/runtime/dex/art_dex_file_loader_test.cc b/runtime/dex/art_dex_file_loader_test.cc
index aee397b65b..274a6df702 100644
--- a/runtime/dex/art_dex_file_loader_test.cc
+++ b/runtime/dex/art_dex_file_loader_test.cc
@@ -49,20 +49,31 @@ class ArtDexFileLoaderTest : public CommonRuntimeTest {
CommonRuntimeTest::SetUp();
std::string dex_location = GetTestDexFileName("Main");
+ std::string multidex_location = GetTestDexFileName("MultiDex");
data_location_path_ = android_data_ + "/foo.jar";
system_location_path_ = GetAndroidRoot() + "/foo.jar";
system_framework_location_path_ = GetAndroidRoot() + "/framework/foo.jar";
+ data_multi_location_path_ = android_data_ + "/multifoo.jar";
+ system_multi_location_path_ = GetAndroidRoot() + "/multifoo.jar";
+ system_framework_multi_location_path_ = GetAndroidRoot() + "/framework/multifoo.jar";
Copy(dex_location, data_location_path_);
Copy(dex_location, system_location_path_);
Copy(dex_location, system_framework_location_path_);
+
+ Copy(multidex_location, data_multi_location_path_);
+ Copy(multidex_location, system_multi_location_path_);
+ Copy(multidex_location, system_framework_multi_location_path_);
}
virtual void TearDown() {
remove(data_location_path_.c_str());
remove(system_location_path_.c_str());
remove(system_framework_location_path_.c_str());
+ remove(data_multi_location_path_.c_str());
+ remove(system_multi_location_path_.c_str());
+ remove(system_framework_multi_location_path_.c_str());
CommonRuntimeTest::TearDown();
}
@@ -70,6 +81,9 @@ class ArtDexFileLoaderTest : public CommonRuntimeTest {
std::string data_location_path_;
std::string system_location_path_;
std::string system_framework_location_path_;
+ std::string data_multi_location_path_;
+ std::string system_multi_location_path_;
+ std::string system_framework_multi_location_path_;
};
// TODO: Port OpenTestDexFile(s) need to be ported to use non-ART utilities, and
@@ -390,6 +404,53 @@ TEST_F(ArtDexFileLoaderTest, IsPlatformDexFile) {
for (std::unique_ptr<const DexFile>& dex_file : dex_files) {
ASSERT_TRUE(dex_file->IsPlatformDexFile());
}
+
+ dex_files.clear();
+
+ // Load multidex file from a non-system directory and check that it is not flagged as framework.
+ success = loader.Open(data_multi_location_path_.c_str(),
+ data_multi_location_path_,
+ /* verify */ false,
+ /* verify_checksum */ false,
+ &error_msg,
+ &dex_files);
+ ASSERT_TRUE(success) << error_msg;
+ ASSERT_GT(dex_files.size(), 1u);
+ for (std::unique_ptr<const DexFile>& dex_file : dex_files) {
+ ASSERT_FALSE(dex_file->IsPlatformDexFile());
+ }
+
+ dex_files.clear();
+
+ // Load multidex file from a system, non-framework directory and check that it is not flagged
+ // as framework.
+ success = loader.Open(system_multi_location_path_.c_str(),
+ system_multi_location_path_,
+ /* verify */ false,
+ /* verify_checksum */ false,
+ &error_msg,
+ &dex_files);
+ ASSERT_TRUE(success);
+ ASSERT_GT(dex_files.size(), 1u);
+ for (std::unique_ptr<const DexFile>& dex_file : dex_files) {
+ ASSERT_FALSE(dex_file->IsPlatformDexFile());
+ }
+
+ dex_files.clear();
+
+ // Load multidex file from a system/framework directory and check that it is flagged as a
+ // framework dex.
+ success = loader.Open(system_framework_multi_location_path_.c_str(),
+ system_framework_multi_location_path_,
+ /* verify */ false,
+ /* verify_checksum */ false,
+ &error_msg,
+ &dex_files);
+ ASSERT_TRUE(success);
+ ASSERT_GT(dex_files.size(), 1u);
+ for (std::unique_ptr<const DexFile>& dex_file : dex_files) {
+ ASSERT_TRUE(dex_file->IsPlatformDexFile());
+ }
}
} // namespace art