diff options
| -rw-r--r-- | runtime/class_loader_context.cc | 20 | ||||
| -rw-r--r-- | runtime/class_loader_context_test.cc | 61 |
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 = |