diff options
author | 2018-05-10 12:55:40 +0100 | |
---|---|---|
committer | 2018-05-10 22:49:34 +0100 | |
commit | 0d0f3164160e50ddb78022f662c5438fc167f50d (patch) | |
tree | 13bfdad1117db0adfb8b434ff1b8e1589c0c43ea | |
parent | 9d7905fffb9eca8f4fa6f3f3d7d3deb9718e3005 (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.cc | 2 | ||||
-rw-r--r-- | libdexfile/dex/dex_file_loader.h | 2 | ||||
-rw-r--r-- | runtime/base/file_utils.cc | 15 | ||||
-rw-r--r-- | runtime/dex/art_dex_file_loader.cc | 5 | ||||
-rw-r--r-- | runtime/dex/art_dex_file_loader_test.cc | 61 |
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 |