diff options
| -rw-r--r-- | runtime/class_loader_context.cc | 16 | ||||
| -rw-r--r-- | runtime/class_loader_context_test.cc | 37 |
2 files changed, 37 insertions, 16 deletions
diff --git a/runtime/class_loader_context.cc b/runtime/class_loader_context.cc index 165b42d9bb..8949f5a324 100644 --- a/runtime/class_loader_context.cc +++ b/runtime/class_loader_context.cc @@ -53,6 +53,7 @@ static constexpr char kClassLoaderSharedLibrarySeparator = '#'; static constexpr char kClassLoaderSeparator = ';'; static constexpr char kClasspathSeparator = ':'; static constexpr char kDexFileChecksumSeparator = '*'; +static constexpr char kInMemoryDexClassLoaderClasspathMagic[] = "<unknown>"; ClassLoaderContext::ClassLoaderContext() : special_shared_library_(false), @@ -169,6 +170,8 @@ std::unique_ptr<ClassLoaderContext::ClassLoaderInfo> ClassLoaderContext::ParseCl // Checksums are not provided and dex locations themselves have no meaning // (although we keep them in the spec to simplify parsing). Treat this as // an unknown class loader. + // We can hit this case if dex2oat is invoked with a spec containing IMC. + // Because the dex file data is only available at runtime, we cannot proceed. return nullptr; } } @@ -197,6 +200,7 @@ std::unique_ptr<ClassLoaderContext::ClassLoaderInfo> ClassLoaderContext::ParseCl std::unique_ptr<ClassLoaderInfo> info(new ClassLoaderInfo(class_loader_type)); if (!parse_checksums) { + DCHECK(class_loader_type != kInMemoryDexClassLoader); Split(classpath, kClasspathSeparator, &info->classpath); } else { std::vector<std::string> classpath_elements; @@ -211,6 +215,10 @@ std::unique_ptr<ClassLoaderContext::ClassLoaderInfo> ClassLoaderContext::ParseCl if (!android::base::ParseUint(dex_file_with_checksum[1].c_str(), &checksum)) { return nullptr; } + if ((class_loader_type == kInMemoryDexClassLoader) && + (dex_file_with_checksum[0] != kInMemoryDexClassLoaderClasspathMagic)) { + return nullptr; + } info->classpath.push_back(dex_file_with_checksum[0]); info->checksums.push_back(checksum); @@ -416,6 +424,8 @@ bool ClassLoaderContext::OpenDexFiles(InstructionSet isa, while (!work_list.empty()) { ClassLoaderInfo* info = work_list.back(); work_list.pop_back(); + DCHECK(info->type != kInMemoryDexClassLoader) << __FUNCTION__ << " not supported for IMC"; + size_t opened_dex_files_index = info->opened_dex_files.size(); for (const std::string& cp_elem : info->classpath) { // If path is relative, append it to the provided base directory. @@ -624,8 +634,10 @@ void ClassLoaderContext::EncodeContextInternal(const ClassLoaderInfo& info, if (k > 0) { out << kClasspathSeparator; } - // Find paths that were relative and convert them back from absolute. - if (!base_dir.empty() && location.substr(0, base_dir.length()) == base_dir) { + if (info.type == kInMemoryDexClassLoader) { + out << kInMemoryDexClassLoaderClasspathMagic; + } else if (!base_dir.empty() && location.substr(0, base_dir.length()) == base_dir) { + // Find paths that were relative and convert them back from absolute. out << location.substr(base_dir.length() + 1).c_str(); } else { out << location.c_str(); diff --git a/runtime/class_loader_context_test.cc b/runtime/class_loader_context_test.cc index 7fba830787..531a69031d 100644 --- a/runtime/class_loader_context_test.cc +++ b/runtime/class_loader_context_test.cc @@ -283,10 +283,22 @@ TEST_F(ClassLoaderContextTest, ParseValidContextDLC) { VerifyClassLoaderDLC(context.get(), 0, "a.dex"); } -TEST_F(ClassLoaderContextTest, ParseInvalidContextIMC) { +TEST_F(ClassLoaderContextTest, ParseValidContextIMC) { + std::unique_ptr<ClassLoaderContext> context = ParseContextWithChecksums("IMC[<unknown>*111]"); + ASSERT_FALSE(context == nullptr); +} + +TEST_F(ClassLoaderContextTest, ParseInvalidContextIMCNoChecksum) { // IMC is treated as an unknown class loader unless a checksum is provided. // This is because the dex location is always bogus. - std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create("IMC[a.dex]"); + std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create("IMC[<unknown>]"); + ASSERT_TRUE(context == nullptr); +} + +TEST_F(ClassLoaderContextTest, ParseInvalidContextIMCWrongClasspathMagic) { + // IMC does not support arbitrary dex location. A magic marker must be used + // otherwise the spec should be rejected. + std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create("IMC[a.dex*111]"); ASSERT_TRUE(context == nullptr); } @@ -500,11 +512,7 @@ TEST_F(ClassLoaderContextTest, OpenDexFilesForIMCFails) { std::unique_ptr<ClassLoaderContext> context; std::string dex_name = GetTestDexFileName("Main"); - context = ParseContextWithChecksums("PCL[" + dex_name + "*111]"); - VerifyContextSize(context.get(), 1); - ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ".")); - - context = ParseContextWithChecksums("IMC[" + dex_name + "*111]"); + context = ParseContextWithChecksums("IMC[<unknown>*111]"); VerifyContextSize(context.get(), 1); ASSERT_FALSE(context->OpenDexFiles(InstructionSet::kArm, ".")); } @@ -1202,7 +1210,7 @@ TEST_F(ClassLoaderContextTest, VerifyClassLoaderContextMatch) { } TEST_F(ClassLoaderContextTest, VerifyClassLoaderContextWithIMCMatch) { - std::string context_spec = "PCL[a.dex*123:b.dex*456];DLC[c.dex*890];IMC[d.dex*111]"; + std::string context_spec = "PCL[a.dex*123:b.dex*456];DLC[c.dex*890];IMC[<unknown>*111]"; std::unique_ptr<ClassLoaderContext> context = ParseContextWithChecksums(context_spec); // Pretend that we successfully open the dex files to pass the DCHECKS. // (as it's much easier to test all the corner cases without relying on actual dex files). @@ -1211,7 +1219,7 @@ TEST_F(ClassLoaderContextTest, VerifyClassLoaderContextWithIMCMatch) { VerifyContextSize(context.get(), 3); VerifyClassLoaderPCL(context.get(), 0, "a.dex:b.dex"); VerifyClassLoaderDLC(context.get(), 1, "c.dex"); - VerifyClassLoaderIMC(context.get(), 2, "d.dex"); + VerifyClassLoaderIMC(context.get(), 2, "<unknown>"); ASSERT_EQ(context->VerifyClassLoaderContextMatch(context_spec), ClassLoaderContext::VerificationResult::kVerifies); @@ -1286,18 +1294,19 @@ TEST_F(ClassLoaderContextTest, VerifyClassLoaderContextMatchWithSL) { TEST_F(ClassLoaderContextTest, VerifyClassLoaderContextMatchWithIMCSL) { std::string context_spec = - "IMC[a.dex*123:b.dex*456]{IMC[d.dex*321];IMC[e.dex*654]#IMC[f.dex*098:g.dex*999]}" - ";DLC[c.dex*890]"; + "IMC[<unknown>*123:<unknown>*456]" + "{IMC[<unknown>*321];IMC[<unknown>*654]#IMC[<unknown>*098:<unknown>*999]};" + "DLC[c.dex*890]"; std::unique_ptr<ClassLoaderContext> context = ParseContextWithChecksums(context_spec); // Pretend that we successfully open the dex files to pass the DCHECKS. // (as it's much easier to test all the corner cases without relying on actual dex files). PretendContextOpenedDexFiles(context.get()); VerifyContextSize(context.get(), 2); - VerifyClassLoaderIMC(context.get(), 0, "a.dex:b.dex"); + VerifyClassLoaderIMC(context.get(), 0, "<unknown>:<unknown>"); VerifyClassLoaderDLC(context.get(), 1, "c.dex"); - VerifyClassLoaderSharedLibraryIMC(context.get(), 0, 0, "d.dex"); - VerifyClassLoaderSharedLibraryIMC(context.get(), 0, 1, "f.dex:g.dex"); + VerifyClassLoaderSharedLibraryIMC(context.get(), 0, 0, "<unknown>"); + VerifyClassLoaderSharedLibraryIMC(context.get(), 0, 1, "<unknown>:<unknown>"); ASSERT_EQ(context->VerifyClassLoaderContextMatch(context_spec), ClassLoaderContext::VerificationResult::kVerifies); |