Handle multidex in LocationIsOnSystemFramework.
bug: 79111915
Test: art_dex_file_loader_test.cc
(cherry picked from commit 0d0f3164160e50ddb78022f662c5438fc167f50d)
Change-Id: I1ee65e6a410f2a7610d0bf210eacd3cf3df13b18
diff --git a/libdexfile/dex/dex_file_loader.cc b/libdexfile/dex/dex_file_loader.cc
index 1e0f5ac..457addf 100644
--- a/libdexfile/dex/dex_file_loader.cc
+++ b/libdexfile/dex/dex_file_loader.cc
@@ -191,6 +191,8 @@
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 28cdfc1..0153220 100644
--- a/libdexfile/dex/dex_file_loader.h
+++ b/libdexfile/dex/dex_file_loader.h
@@ -71,7 +71,7 @@
// 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 09a9b97..462ee76 100644
--- a/runtime/base/file_utils.cc
+++ b/runtime/base/file_utils.cc
@@ -314,12 +314,12 @@
}
}
-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()) {
@@ -328,12 +328,7 @@
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 f3e6a69..16d26dc 100644
--- a/runtime/dex/art_dex_file_loader.cc
+++ b/runtime/dex/art_dex_file_loader.cc
@@ -534,7 +534,10 @@
// 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 3e0d666..555fe5c 100644
--- a/runtime/dex/art_dex_file_loader_test.cc
+++ b/runtime/dex/art_dex_file_loader_test.cc
@@ -49,20 +49,31 @@
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 @@
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 @@
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