summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/class_loader_context.cc20
-rw-r--r--runtime/class_loader_context_test.cc61
2 files changed, 73 insertions, 8 deletions
diff --git a/runtime/class_loader_context.cc b/runtime/class_loader_context.cc
index e7051b35d8..e97c6a0850 100644
--- a/runtime/class_loader_context.cc
+++ b/runtime/class_loader_context.cc
@@ -16,6 +16,9 @@
#include "class_loader_context.h"
+#include <stdlib.h>
+
+#include "android-base/file.h"
#include "art_field-inl.h"
#include "base/dchecked_vector.h"
#include "base/stl_util.h"
@@ -202,10 +205,21 @@ bool ClassLoaderContext::OpenDexFiles(InstructionSet isa, const std::string& cla
for (ClassLoaderInfo& info : class_loader_chain_) {
for (const std::string& cp_elem : info.classpath) {
// If path is relative, append it to the provided base directory.
- std::string location = cp_elem;
- if (location[0] != '/') {
- location = classpath_dir + '/' + location;
+ std::string raw_location = cp_elem;
+ if (raw_location[0] != '/') {
+ raw_location = classpath_dir + '/' + raw_location;
+ }
+
+ std::string location; // the real location of the class path element.
+
+ if (!android::base::Realpath(raw_location, &location)) {
+ // If we can't get the realpath of the location there might be something wrong with the
+ // classpath (maybe the file was deleted).
+ // Do not continue in this case and return false.
+ PLOG(ERROR) << "Could not get the realpath of dex location " << raw_location;
+ return false;
}
+
std::string error_msg;
// When opening the dex files from the context we expect their checksum to match their
// contents. So pass true to verify_checksum.
diff --git a/runtime/class_loader_context_test.cc b/runtime/class_loader_context_test.cc
index d4688c1904..458f9f3345 100644
--- a/runtime/class_loader_context_test.cc
+++ b/runtime/class_loader_context_test.cc
@@ -15,14 +15,16 @@
*/
#include <gtest/gtest.h>
+#include <stdlib.h>
-#include "class_loader_context.h"
-#include "common_runtime_test.h"
#include "base/dchecked_vector.h"
#include "base/stl_util.h"
+#include "class_loader_context.h"
#include "class_linker.h"
+#include "common_runtime_test.h"
#include "dex_file.h"
+#include "dex2oat_environment_test.h"
#include "handle_scope-inl.h"
#include "mirror/class.h"
#include "mirror/class_loader.h"
@@ -89,9 +91,22 @@ class ClassLoaderContextTest : public CommonRuntimeTest {
info.opened_dex_files[cur_open_dex_index++];
std::unique_ptr<const DexFile>& expected_dex_file = dex_files_for_cp_elem[i];
- ASSERT_EQ(expected_dex_file->GetLocation(), opened_dex_file->GetLocation());
+ std::string expected_location = expected_dex_file->GetBaseLocation();
+ UniqueCPtr<const char[]> expected_real_location(
+ realpath(expected_location.c_str(), nullptr));
+ ASSERT_TRUE(expected_real_location != nullptr) << expected_location;
+ expected_location.assign(expected_real_location.get());
+ expected_location += DexFile::GetMultiDexSuffix(expected_dex_file->GetLocation());
+
+ ASSERT_EQ(expected_location, opened_dex_file->GetLocation());
ASSERT_EQ(expected_dex_file->GetLocationChecksum(), opened_dex_file->GetLocationChecksum());
- ASSERT_EQ(info.classpath[k], opened_dex_file->GetBaseLocation());
+
+ std::string class_path_location = info.classpath[k];
+ UniqueCPtr<const char[]> class_path_location_real(
+ realpath(class_path_location.c_str(), nullptr));
+ ASSERT_TRUE(class_path_location_real != nullptr);
+ class_path_location.assign(class_path_location_real.get());
+ ASSERT_EQ(class_path_location, opened_dex_file->GetBaseLocation());
}
}
}
@@ -234,7 +249,6 @@ TEST_F(ClassLoaderContextTest, OpenValidDexFiles) {
std::string dex_name = GetTestDexFileName("Main");
std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles("Main");
-
std::unique_ptr<ClassLoaderContext> context =
ClassLoaderContext::Create(
"PCL[" + multidex_name + ":" + myclass_dex_name + "];" +
@@ -253,6 +267,43 @@ TEST_F(ClassLoaderContextTest, OpenValidDexFiles) {
VerifyOpenDexFiles(context.get(), 1, all_dex_files1);
}
+class ScratchSymLink {
+ public:
+ explicit ScratchSymLink(const std::string& file) {
+ // Use a temporary scratch file to get a unique name for the link.
+ ScratchFile scratchFile;
+ scratch_link_name_ = scratchFile.GetFilename() + ".link.jar";
+ CHECK_EQ(0, symlink(file.c_str(), scratch_link_name_.c_str()));
+ }
+
+ ~ScratchSymLink() {
+ CHECK_EQ(0, unlink(scratch_link_name_.c_str()));
+ }
+
+ const std::string& GetFilename() { return scratch_link_name_; }
+
+ private:
+ std::string scratch_link_name_;
+};
+
+TEST_F(ClassLoaderContextTest, OpenValidDexFilesSymLink) {
+ std::string myclass_dex_name = GetTestDexFileName("MyClass");
+ // Now replace the dex location with a symlink.
+ ScratchSymLink link(myclass_dex_name);
+
+ std::unique_ptr<ClassLoaderContext> context =
+ ClassLoaderContext::Create("PCL[" + link.GetFilename() + "]");
+
+ ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, /*classpath_dir*/ ""));
+
+ VerifyContextSize(context.get(), 1);
+ std::vector<std::vector<std::unique_ptr<const DexFile>>*> all_dex_files0;
+ std::vector<std::unique_ptr<const DexFile>> myclass_dex_files = OpenTestDexFiles("MyClass");
+ all_dex_files0.push_back(&myclass_dex_files);
+
+ VerifyOpenDexFiles(context.get(), 0, all_dex_files0);
+}
+
TEST_F(ClassLoaderContextTest, OpenInvalidDexFilesMix) {
std::string dex_name = GetTestDexFileName("Main");
std::unique_ptr<ClassLoaderContext> context =