diff options
| -rw-r--r-- | compiler/oat_writer.cc | 1 | ||||
| -rw-r--r-- | compiler/utils/test_dex_file_builder.h | 11 | ||||
| -rw-r--r-- | dex2oat/dex2oat.cc | 4 | ||||
| -rw-r--r-- | dexdump/dexdump.cc | 5 | ||||
| -rw-r--r-- | dexdump/dexdump_main.cc | 4 | ||||
| -rw-r--r-- | dexlist/dexlist.cc | 3 | ||||
| -rw-r--r-- | oatdump/oatdump.cc | 42 | ||||
| -rw-r--r-- | profman/profman.cc | 2 | ||||
| -rw-r--r-- | runtime/common_runtime_test.cc | 7 | ||||
| -rw-r--r-- | runtime/dex_file.cc | 55 | ||||
| -rw-r--r-- | runtime/dex_file.h | 29 | ||||
| -rw-r--r-- | runtime/dex_file_test.cc | 3 | ||||
| -rw-r--r-- | runtime/dex_file_verifier.cc | 20 | ||||
| -rw-r--r-- | runtime/dex_file_verifier.h | 25 | ||||
| -rw-r--r-- | runtime/dex_file_verifier_test.cc | 52 | ||||
| -rw-r--r-- | runtime/oat_file.cc | 5 | ||||
| -rw-r--r-- | runtime/oat_file_assistant_test.cc | 5 | ||||
| -rw-r--r-- | runtime/oat_file_manager.cc | 4 | ||||
| -rw-r--r-- | runtime/runtime.cc | 3 | ||||
| -rw-r--r-- | test/Android.run-test.mk | 3 |
20 files changed, 223 insertions, 60 deletions
diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc index c179342d6e..cdc7df11b6 100644 --- a/compiler/oat_writer.cc +++ b/compiler/oat_writer.cc @@ -2195,6 +2195,7 @@ bool OatWriter::OpenDexFiles( oat_dex_file.dex_file_location_checksum_, /* oat_dex_file */ nullptr, verify, + verify, &error_msg)); if (dex_files.back() == nullptr) { LOG(ERROR) << "Failed to open dex file from oat file. File: " << oat_dex_file.GetLocation() diff --git a/compiler/utils/test_dex_file_builder.h b/compiler/utils/test_dex_file_builder.h index fb37804649..6921780a85 100644 --- a/compiler/utils/test_dex_file_builder.h +++ b/compiler/utils/test_dex_file_builder.h @@ -227,9 +227,18 @@ class TestDexFileBuilder { // Write the complete header again, just simpler that way. std::memcpy(&dex_file_data_[0], header_data.data, sizeof(DexFile::Header)); + static constexpr bool kVerify = false; + static constexpr bool kVerifyChecksum = false; std::string error_msg; std::unique_ptr<const DexFile> dex_file(DexFile::Open( - &dex_file_data_[0], dex_file_data_.size(), dex_location, 0u, nullptr, false, &error_msg)); + &dex_file_data_[0], + dex_file_data_.size(), + dex_location, + 0u, + nullptr, + kVerify, + kVerifyChecksum, + &error_msg)); CHECK(dex_file != nullptr) << error_msg; return dex_file; } diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc index 2dce2f1d47..24a4d586a2 100644 --- a/dex2oat/dex2oat.cc +++ b/dex2oat/dex2oat.cc @@ -1985,8 +1985,10 @@ class Dex2Oat FINAL { if (location == OatFile::kSpecialSharedLibrary) { break; } + static constexpr bool kVerifyChecksum = true; std::string error_msg; - if (!DexFile::Open(location.c_str(), location.c_str(), &error_msg, opened_dex_files)) { + if (!DexFile::Open( + location.c_str(), location.c_str(), kVerifyChecksum, &error_msg, opened_dex_files)) { // If we fail to open the dex file because it's been stripped, try to open the dex file // from its corresponding oat file. OatFileAssistant oat_file_assistant(location.c_str(), isa, false, false); diff --git a/dexdump/dexdump.cc b/dexdump/dexdump.cc index 9e06a7c31b..48b773e90b 100644 --- a/dexdump/dexdump.cc +++ b/dexdump/dexdump.cc @@ -1635,11 +1635,10 @@ int processFile(const char* fileName) { // If the file is not a .dex file, the function tries .zip/.jar/.apk files, // all of which are Zip archives with "classes.dex" inside. - // - // TODO(ajcbik): implement gOptions.ignoreBadChecksum + const bool kVerifyChecksum = !gOptions.ignoreBadChecksum; std::string error_msg; std::vector<std::unique_ptr<const DexFile>> dex_files; - if (!DexFile::Open(fileName, fileName, &error_msg, &dex_files)) { + if (!DexFile::Open(fileName, fileName, kVerifyChecksum, &error_msg, &dex_files)) { // Display returned error message to user. Note that this error behavior // differs from the error messages shown by the original Dalvik dexdump. fputs(error_msg.c_str(), stderr); diff --git a/dexdump/dexdump_main.cc b/dexdump/dexdump_main.cc index 32e9d521c1..f716ba8be7 100644 --- a/dexdump/dexdump_main.cc +++ b/dexdump/dexdump_main.cc @@ -17,8 +17,8 @@ * * This is a re-implementation of the original dexdump utility that was * based on Dalvik functions in libdex into a new dexdump that is now - * based on Art functions in libart instead. The output is identical to - * the original for correct DEX files. Error messages may differ, however. + * based on Art functions in libart instead. The output is very similar to + * to the original for correct DEX files. Error messages may differ, however. * Also, ODEX files are no longer supported. */ diff --git a/dexlist/dexlist.cc b/dexlist/dexlist.cc index d20c16919a..6f19df55fd 100644 --- a/dexlist/dexlist.cc +++ b/dexlist/dexlist.cc @@ -180,9 +180,10 @@ void dumpClass(const DexFile* pDexFile, u4 idx) { static int processFile(const char* fileName) { // If the file is not a .dex file, the function tries .zip/.jar/.apk files, // all of which are Zip archives with "classes.dex" inside. + static constexpr bool kVerifyChecksum = true; std::string error_msg; std::vector<std::unique_ptr<const DexFile>> dex_files; - if (!DexFile::Open(fileName, fileName, &error_msg, &dex_files)) { + if (!DexFile::Open(fileName, fileName, kVerifyChecksum, &error_msg, &dex_files)) { fputs(error_msg.c_str(), stderr); fputc('\n', stderr); return -1; diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc index 7239a479db..bb35f8dc30 100644 --- a/oatdump/oatdump.cc +++ b/oatdump/oatdump.cc @@ -35,7 +35,7 @@ #include "debug/elf_debug_writer.h" #include "debug/method_debug_info.h" #include "dex_file-inl.h" -#include "dex_instruction.h" +#include "dex_instruction-inl.h" #include "disassembler.h" #include "elf_builder.h" #include "gc/space/image_space.h" @@ -578,6 +578,7 @@ class OatDumper { // Print embedded dex file data range. const uint8_t* const oat_file_begin = oat_dex_file.GetOatFile()->Begin(); const uint8_t* const dex_file_pointer = oat_dex_file.GetDexFilePointer(); + std::set<uint32_t> string_ids; uint32_t dex_offset = dchecked_integral_cast<uint32_t>(dex_file_pointer - oat_file_begin); os << StringPrintf("dex-file: 0x%08x..0x%08x\n", dex_offset, @@ -623,7 +624,7 @@ class OatDumper { << " (" << oat_class.GetType() << ")\n"; // TODO: include bitmap here if type is kOatClassSomeCompiled? if (options_.list_classes_) continue; - if (!DumpOatClass(&vios, oat_class, *dex_file, class_def, &stop_analysis)) { + if (!DumpOatClass(&vios, oat_class, *dex_file, class_def, &stop_analysis, string_ids)) { success = false; } if (stop_analysis) { @@ -631,7 +632,7 @@ class OatDumper { return success; } } - + os << "Number of unique strings loaded from dex code: " << string_ids.size() << "\n"; os << std::flush; return success; } @@ -725,7 +726,8 @@ class OatDumper { bool DumpOatClass(VariableIndentationOutputStream* vios, const OatFile::OatClass& oat_class, const DexFile& dex_file, - const DexFile::ClassDef& class_def, bool* stop_analysis) { + const DexFile::ClassDef& class_def, bool* stop_analysis, + std::set<uint32_t>& string_ids) { bool success = true; bool addr_found = false; const uint8_t* class_data = dex_file.GetClassData(class_def); @@ -739,7 +741,7 @@ class OatDumper { while (it.HasNextDirectMethod()) { if (!DumpOatMethod(vios, class_def, class_method_index, oat_class, dex_file, it.GetMemberIndex(), it.GetMethodCodeItem(), - it.GetRawMemberAccessFlags(), &addr_found)) { + it.GetRawMemberAccessFlags(), &addr_found, string_ids)) { success = false; } if (addr_found) { @@ -752,7 +754,7 @@ class OatDumper { while (it.HasNextVirtualMethod()) { if (!DumpOatMethod(vios, class_def, class_method_index, oat_class, dex_file, it.GetMemberIndex(), it.GetMethodCodeItem(), - it.GetRawMemberAccessFlags(), &addr_found)) { + it.GetRawMemberAccessFlags(), &addr_found, string_ids)) { success = false; } if (addr_found) { @@ -777,9 +779,35 @@ class OatDumper { uint32_t class_method_index, const OatFile::OatClass& oat_class, const DexFile& dex_file, uint32_t dex_method_idx, const DexFile::CodeItem* code_item, - uint32_t method_access_flags, bool* addr_found) { + uint32_t method_access_flags, bool* addr_found, + std::set<uint32_t>& string_ids) { bool success = true; + if (code_item != nullptr) { + const uint16_t* code_ptr = code_item->insns_; + const uint16_t* code_end = code_item->insns_ + code_item->insns_size_in_code_units_; + + while (code_ptr < code_end) { + const Instruction* inst = Instruction::At(code_ptr); + switch (inst->Opcode()) { + case Instruction::CONST_STRING: { + uint32_t string_index = inst->VRegB_21c(); + string_ids.insert(string_index); + break; + } + case Instruction::CONST_STRING_JUMBO: { + uint32_t string_index = inst->VRegB_31c(); + string_ids.insert(string_index); + break; + } + + default: + break; + } + + code_ptr += inst->SizeInCodeUnits(); + } + } // TODO: Support regex std::string method_name = dex_file.GetMethodName(dex_file.GetMethodId(dex_method_idx)); if (method_name.find(options_.method_filter_) == std::string::npos) { diff --git a/profman/profman.cc b/profman/profman.cc index 754e4315d0..d2c9cb2e3f 100644 --- a/profman/profman.cc +++ b/profman/profman.cc @@ -234,6 +234,7 @@ class ProfMan FINAL { MemMap::Init(); // for ZipArchive::OpenFromFd std::vector<const DexFile*> dex_files; assert(dex_locations_.size() == apks_fd_.size()); + static constexpr bool kVerifyChecksum = true; for (size_t i = 0; i < dex_locations_.size(); ++i) { std::string error_msg; std::vector<std::unique_ptr<const DexFile>> dex_files_for_location; @@ -246,6 +247,7 @@ class ProfMan FINAL { } if (DexFile::OpenFromZip(*zip_archive, dex_locations_[i], + kVerifyChecksum, &error_msg, &dex_files_for_location)) { } else { diff --git a/runtime/common_runtime_test.cc b/runtime/common_runtime_test.cc index 5bdb36cafc..3509d9aef9 100644 --- a/runtime/common_runtime_test.cc +++ b/runtime/common_runtime_test.cc @@ -284,7 +284,8 @@ std::unique_ptr<const DexFile> CommonRuntimeTestImpl::LoadExpectSingleDexFile( std::vector<std::unique_ptr<const DexFile>> dex_files; std::string error_msg; MemMap::Init(); - if (!DexFile::Open(location, location, &error_msg, &dex_files)) { + static constexpr bool kVerifyChecksum = true; + if (!DexFile::Open(location, location, kVerifyChecksum, &error_msg, &dex_files)) { LOG(FATAL) << "Could not open .dex file '" << location << "': " << error_msg << "\n"; UNREACHABLE(); } else { @@ -480,9 +481,11 @@ std::string CommonRuntimeTestImpl::GetTestDexFileName(const char* name) { std::vector<std::unique_ptr<const DexFile>> CommonRuntimeTestImpl::OpenTestDexFiles( const char* name) { std::string filename = GetTestDexFileName(name); + static constexpr bool kVerifyChecksum = true; std::string error_msg; std::vector<std::unique_ptr<const DexFile>> dex_files; - bool success = DexFile::Open(filename.c_str(), filename.c_str(), &error_msg, &dex_files); + bool success = DexFile::Open( + filename.c_str(), filename.c_str(), kVerifyChecksum, &error_msg, &dex_files); CHECK(success) << "Failed to open '" << filename << "': " << error_msg; for (auto& dex_file : dex_files) { CHECK_EQ(PROT_READ, dex_file->GetPermissions()); diff --git a/runtime/dex_file.cc b/runtime/dex_file.cc index 05c95e069e..5a203afd1a 100644 --- a/runtime/dex_file.cc +++ b/runtime/dex_file.cc @@ -109,7 +109,7 @@ bool DexFile::GetChecksum(const char* filename, uint32_t* checksum, std::string* } if (IsDexMagic(magic)) { std::unique_ptr<const DexFile> dex_file( - DexFile::OpenFile(fd.release(), filename, false, error_msg)); + DexFile::OpenFile(fd.release(), filename, false, false, error_msg)); if (dex_file.get() == nullptr) { return false; } @@ -120,7 +120,10 @@ bool DexFile::GetChecksum(const char* filename, uint32_t* checksum, std::string* return false; } -bool DexFile::Open(const char* filename, const char* location, std::string* error_msg, +bool DexFile::Open(const char* filename, + const char* location, + bool verify_checksum, + std::string* error_msg, std::vector<std::unique_ptr<const DexFile>>* dex_files) { ScopedTrace trace(std::string("Open dex file ") + location); DCHECK(dex_files != nullptr) << "DexFile::Open: out-param is nullptr"; @@ -131,10 +134,13 @@ bool DexFile::Open(const char* filename, const char* location, std::string* erro return false; } if (IsZipMagic(magic)) { - return DexFile::OpenZip(fd.release(), location, error_msg, dex_files); + return DexFile::OpenZip(fd.release(), location, verify_checksum, error_msg, dex_files); } if (IsDexMagic(magic)) { - std::unique_ptr<const DexFile> dex_file(DexFile::OpenFile(fd.release(), location, true, + std::unique_ptr<const DexFile> dex_file(DexFile::OpenFile(fd.release(), + location, + /* verify */ true, + verify_checksum, error_msg)); if (dex_file.get() != nullptr) { dex_files->push_back(std::move(dex_file)); @@ -207,6 +213,7 @@ std::unique_ptr<const DexFile> DexFile::Open(const uint8_t* base, size_t size, uint32_t location_checksum, const OatDexFile* oat_dex_file, bool verify, + bool verify_checksum, std::string* error_msg) { ScopedTrace trace(std::string("Open dex file from RAM ") + location); std::unique_ptr<const DexFile> dex_file = OpenMemory(base, @@ -220,6 +227,7 @@ std::unique_ptr<const DexFile> DexFile::Open(const uint8_t* base, size_t size, dex_file->Begin(), dex_file->Size(), location.c_str(), + verify_checksum, error_msg)) { return nullptr; } @@ -227,7 +235,10 @@ std::unique_ptr<const DexFile> DexFile::Open(const uint8_t* base, size_t size, return dex_file; } -std::unique_ptr<const DexFile> DexFile::OpenFile(int fd, const char* location, bool verify, +std::unique_ptr<const DexFile> DexFile::OpenFile(int fd, + const char* location, + bool verify, + bool verify_checksum, std::string* error_msg) { ScopedTrace trace(std::string("Open dex file ") + location); CHECK(location != nullptr); @@ -276,7 +287,9 @@ std::unique_ptr<const DexFile> DexFile::OpenFile(int fd, const char* location, b } if (verify && !DexFileVerifier::Verify(dex_file.get(), dex_file->Begin(), dex_file->Size(), - location, error_msg)) { + location, + verify_checksum, + error_msg)) { return nullptr; } @@ -285,7 +298,10 @@ std::unique_ptr<const DexFile> DexFile::OpenFile(int fd, const char* location, b const char* DexFile::kClassesDex = "classes.dex"; -bool DexFile::OpenZip(int fd, const std::string& location, std::string* error_msg, +bool DexFile::OpenZip(int fd, + const std::string& location, + bool verify_checksum, + std::string* error_msg, std::vector<std::unique_ptr<const DexFile>>* dex_files) { ScopedTrace trace("Dex file open Zip " + std::string(location)); DCHECK(dex_files != nullptr) << "DexFile::OpenZip: out-param is nullptr"; @@ -294,7 +310,7 @@ bool DexFile::OpenZip(int fd, const std::string& location, std::string* error_ms DCHECK(!error_msg->empty()); return false; } - return DexFile::OpenFromZip(*zip_archive, location, error_msg, dex_files); + return DexFile::OpenFromZip(*zip_archive, location, verify_checksum, error_msg, dex_files); } std::unique_ptr<const DexFile> DexFile::OpenMemory(const std::string& location, @@ -310,8 +326,11 @@ std::unique_ptr<const DexFile> DexFile::OpenMemory(const std::string& location, error_msg); } -std::unique_ptr<const DexFile> DexFile::Open(const ZipArchive& zip_archive, const char* entry_name, - const std::string& location, std::string* error_msg, +std::unique_ptr<const DexFile> DexFile::Open(const ZipArchive& zip_archive, + const char* entry_name, + const std::string& location, + bool verify_checksum, + std::string* error_msg, ZipOpenErrorCode* error_code) { ScopedTrace trace("Dex file open from Zip Archive " + std::string(location)); CHECK(!location.empty()); @@ -342,7 +361,9 @@ std::unique_ptr<const DexFile> DexFile::Open(const ZipArchive& zip_archive, cons } CHECK(dex_file->IsReadOnly()) << location; if (!DexFileVerifier::Verify(dex_file.get(), dex_file->Begin(), dex_file->Size(), - location.c_str(), error_msg)) { + location.c_str(), + verify_checksum, + error_msg)) { *error_code = ZipOpenErrorCode::kVerifyError; return nullptr; } @@ -356,14 +377,16 @@ std::unique_ptr<const DexFile> DexFile::Open(const ZipArchive& zip_archive, cons // seems an excessive number. static constexpr size_t kWarnOnManyDexFilesThreshold = 100; -bool DexFile::OpenFromZip(const ZipArchive& zip_archive, const std::string& location, +bool DexFile::OpenFromZip(const ZipArchive& zip_archive, + const std::string& location, + bool verify_checksum, std::string* error_msg, std::vector<std::unique_ptr<const DexFile>>* dex_files) { ScopedTrace trace("Dex file open from Zip " + std::string(location)); DCHECK(dex_files != nullptr) << "DexFile::OpenFromZip: out-param is nullptr"; ZipOpenErrorCode error_code; - std::unique_ptr<const DexFile> dex_file(Open(zip_archive, kClassesDex, location, error_msg, - &error_code)); + std::unique_ptr<const DexFile> dex_file( + Open(zip_archive, kClassesDex, location, verify_checksum, error_msg, &error_code)); if (dex_file.get() == nullptr) { return false; } else { @@ -378,8 +401,8 @@ bool DexFile::OpenFromZip(const ZipArchive& zip_archive, const std::string& loca for (size_t i = 1; ; ++i) { std::string name = GetMultiDexClassesDexName(i); std::string fake_location = GetMultiDexLocation(i, location.c_str()); - std::unique_ptr<const DexFile> next_dex_file(Open(zip_archive, name.c_str(), fake_location, - error_msg, &error_code)); + std::unique_ptr<const DexFile> next_dex_file( + Open(zip_archive, name.c_str(), fake_location, verify_checksum, error_msg, &error_code)); if (next_dex_file.get() == nullptr) { if (error_code != ZipOpenErrorCode::kEntryNotFound) { LOG(WARNING) << error_msg; diff --git a/runtime/dex_file.h b/runtime/dex_file.h index 638821bfb7..759986e183 100644 --- a/runtime/dex_file.h +++ b/runtime/dex_file.h @@ -416,7 +416,10 @@ class DexFile { static bool GetChecksum(const char* filename, uint32_t* checksum, std::string* error_msg); // Opens .dex files found in the container, guessing the container format based on file extension. - static bool Open(const char* filename, const char* location, std::string* error_msg, + static bool Open(const char* filename, + const char* location, + bool verify_checksum, + std::string* error_msg, std::vector<std::unique_ptr<const DexFile>>* dex_files); // Checks whether the given file has the dex magic, or is a zip file with a classes.dex entry. @@ -429,10 +432,13 @@ class DexFile { uint32_t location_checksum, const OatDexFile* oat_dex_file, bool verify, + bool verify_checksum, std::string* error_msg); // Open all classesXXX.dex files from a zip archive. - static bool OpenFromZip(const ZipArchive& zip_archive, const std::string& location, + static bool OpenFromZip(const ZipArchive& zip_archive, + const std::string& location, + bool verify_checksum, std::string* error_msg, std::vector<std::unique_ptr<const DexFile>>* dex_files); @@ -1177,11 +1183,17 @@ class DexFile { private: // Opens a .dex file - static std::unique_ptr<const DexFile> OpenFile(int fd, const char* location, - bool verify, std::string* error_msg); + static std::unique_ptr<const DexFile> OpenFile(int fd, + const char* location, + bool verify, + bool verify_checksum, + std::string* error_msg); // Opens dex files from within a .jar, .zip, or .apk file - static bool OpenZip(int fd, const std::string& location, std::string* error_msg, + static bool OpenZip(int fd, + const std::string& location, + bool verify_checksum, + std::string* error_msg, std::vector<std::unique_ptr<const DexFile>>* dex_files); enum class ZipOpenErrorCode { // private @@ -1195,8 +1207,11 @@ class DexFile { // Opens .dex file from the entry_name in a zip archive. error_code is undefined when non-null // return. - static std::unique_ptr<const DexFile> Open(const ZipArchive& zip_archive, const char* entry_name, - const std::string& location, std::string* error_msg, + static std::unique_ptr<const DexFile> Open(const ZipArchive& zip_archive, + const char* entry_name, + const std::string& location, + bool verify_checksum, + std::string* error_msg, ZipOpenErrorCode* error_code); // Opens a .dex file at the given address backed by a MemMap diff --git a/runtime/dex_file_test.cc b/runtime/dex_file_test.cc index 796701d86b..4f8e6f1fc0 100644 --- a/runtime/dex_file_test.cc +++ b/runtime/dex_file_test.cc @@ -154,9 +154,10 @@ static std::unique_ptr<const DexFile> OpenDexFileBase64(const char* base64, // read dex file ScopedObjectAccess soa(Thread::Current()); + static constexpr bool kVerifyChecksum = true; std::string error_msg; std::vector<std::unique_ptr<const DexFile>> tmp; - bool success = DexFile::Open(location, location, &error_msg, &tmp); + bool success = DexFile::Open(location, location, kVerifyChecksum, &error_msg, &tmp); CHECK(success) << error_msg; EXPECT_EQ(1U, tmp.size()); std::unique_ptr<const DexFile> dex_file = std::move(tmp[0]); diff --git a/runtime/dex_file_verifier.cc b/runtime/dex_file_verifier.cc index 1d243490ab..5132efc03c 100644 --- a/runtime/dex_file_verifier.cc +++ b/runtime/dex_file_verifier.cc @@ -128,9 +128,14 @@ const DexFile::MethodId* DexFileVerifier::CheckLoadMethodId(uint32_t idx, const error_stmt; \ } -bool DexFileVerifier::Verify(const DexFile* dex_file, const uint8_t* begin, size_t size, - const char* location, std::string* error_msg) { - std::unique_ptr<DexFileVerifier> verifier(new DexFileVerifier(dex_file, begin, size, location)); +bool DexFileVerifier::Verify(const DexFile* dex_file, + const uint8_t* begin, + size_t size, + const char* location, + bool verify_checksum, + std::string* error_msg) { + std::unique_ptr<DexFileVerifier> verifier( + new DexFileVerifier(dex_file, begin, size, location, verify_checksum)); if (!verifier->Verify()) { *error_msg = verifier->FailureReason(); return false; @@ -273,8 +278,13 @@ bool DexFileVerifier::CheckHeader() { const uint8_t* non_sum_ptr = reinterpret_cast<const uint8_t*>(header_) + non_sum; adler_checksum = adler32(adler_checksum, non_sum_ptr, expected_size - non_sum); if (adler_checksum != header_->checksum_) { - ErrorStringPrintf("Bad checksum (%08x, expected %08x)", adler_checksum, header_->checksum_); - return false; + if (verify_checksum_) { + ErrorStringPrintf("Bad checksum (%08x, expected %08x)", adler_checksum, header_->checksum_); + return false; + } else { + LOG(WARNING) << StringPrintf( + "Ignoring bad checksum (%08x, expected %08x)", adler_checksum, header_->checksum_); + } } // Check the contents of the header. diff --git a/runtime/dex_file_verifier.h b/runtime/dex_file_verifier.h index 90409db44b..133e4326bc 100644 --- a/runtime/dex_file_verifier.h +++ b/runtime/dex_file_verifier.h @@ -26,17 +26,31 @@ namespace art { class DexFileVerifier { public: - static bool Verify(const DexFile* dex_file, const uint8_t* begin, size_t size, - const char* location, std::string* error_msg); + static bool Verify(const DexFile* dex_file, + const uint8_t* begin, + size_t size, + const char* location, + bool verify_checksum, + std::string* error_msg); const std::string& FailureReason() const { return failure_reason_; } private: - DexFileVerifier(const DexFile* dex_file, const uint8_t* begin, size_t size, const char* location) - : dex_file_(dex_file), begin_(begin), size_(size), location_(location), - header_(&dex_file->GetHeader()), ptr_(nullptr), previous_item_(nullptr) { + DexFileVerifier(const DexFile* dex_file, + const uint8_t* begin, + size_t size, + const char* location, + bool verify_checksum) + : dex_file_(dex_file), + begin_(begin), + size_(size), + location_(location), + verify_checksum_(verify_checksum), + header_(&dex_file->GetHeader()), + ptr_(nullptr), + previous_item_(nullptr) { } bool Verify(); @@ -176,6 +190,7 @@ class DexFileVerifier { const uint8_t* const begin_; const size_t size_; const char* const location_; + const bool verify_checksum_; const DexFile::Header* const header_; struct OffsetTypeMapEmptyFn { diff --git a/runtime/dex_file_verifier_test.cc b/runtime/dex_file_verifier_test.cc index 4e53914374..71c0ad9295 100644 --- a/runtime/dex_file_verifier_test.cc +++ b/runtime/dex_file_verifier_test.cc @@ -122,6 +122,10 @@ static void FixUpChecksum(uint8_t* dex_file) { class DexFileVerifierTest : public CommonRuntimeTest { protected: + DexFile* GetDexFile(const uint8_t* dex_bytes, size_t length) { + return new DexFile(dex_bytes, length, "tmp", 0, nullptr, nullptr); + } + void VerifyModification(const char* dex_file_base64_content, const char* location, std::function<void(DexFile*)> f, @@ -130,16 +134,17 @@ class DexFileVerifierTest : public CommonRuntimeTest { std::unique_ptr<uint8_t[]> dex_bytes = DecodeBase64(dex_file_base64_content, &length); CHECK(dex_bytes != nullptr); // Note: `dex_file` will be destroyed before `dex_bytes`. - std::unique_ptr<DexFile> dex_file( - new DexFile(dex_bytes.get(), length, "tmp", 0, nullptr, nullptr)); + std::unique_ptr<DexFile> dex_file(GetDexFile(dex_bytes.get(), length)); f(dex_file.get()); FixUpChecksum(const_cast<uint8_t*>(dex_file->Begin())); + static constexpr bool kVerifyChecksum = true; std::string error_msg; bool success = DexFileVerifier::Verify(dex_file.get(), dex_file->Begin(), dex_file->Size(), location, + kVerifyChecksum, &error_msg); if (expected_error == nullptr) { EXPECT_TRUE(success) << error_msg; @@ -175,7 +180,7 @@ static std::unique_ptr<const DexFile> OpenDexFileBase64(const char* base64, // read dex file ScopedObjectAccess soa(Thread::Current()); std::vector<std::unique_ptr<const DexFile>> tmp; - bool success = DexFile::Open(location, location, error_msg, &tmp); + bool success = DexFile::Open(location, location, true, error_msg, &tmp); CHECK(success) << error_msg; EXPECT_EQ(1U, tmp.size()); std::unique_ptr<const DexFile> dex_file = std::move(tmp[0]); @@ -1697,4 +1702,45 @@ TEST_F(DexFileVerifierTest, CircularInterfaceImplementation) { " implemented interface with type idx: '0'"); } +TEST_F(DexFileVerifierTest, Checksum) { + size_t length; + std::unique_ptr<uint8_t[]> dex_bytes = DecodeBase64(kGoodTestDex, &length); + CHECK(dex_bytes != nullptr); + // Note: `dex_file` will be destroyed before `dex_bytes`. + std::unique_ptr<DexFile> dex_file(GetDexFile(dex_bytes.get(), length)); + std::string error_msg; + + // Good checksum: all pass. + EXPECT_TRUE(DexFileVerifier::Verify(dex_file.get(), + dex_file->Begin(), + dex_file->Size(), + "good checksum, no verify", + /*verify_checksum*/ false, + &error_msg)); + EXPECT_TRUE(DexFileVerifier::Verify(dex_file.get(), + dex_file->Begin(), + dex_file->Size(), + "good checksum, verify", + /*verify_checksum*/ true, + &error_msg)); + + // Bad checksum: !verify_checksum passes verify_checksum fails. + DexFile::Header* header = reinterpret_cast<DexFile::Header*>( + const_cast<uint8_t*>(dex_file->Begin())); + header->checksum_ = 0; + EXPECT_TRUE(DexFileVerifier::Verify(dex_file.get(), + dex_file->Begin(), + dex_file->Size(), + "bad checksum, no verify", + /*verify_checksum*/ false, + &error_msg)); + EXPECT_FALSE(DexFileVerifier::Verify(dex_file.get(), + dex_file->Begin(), + dex_file->Size(), + "bad checksum, verify", + /*verify_checksum*/ true, + &error_msg)); + EXPECT_NE(error_msg.find("Bad checksum"), std::string::npos) << error_msg; +} + } // namespace art diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc index 62c723e76f..61dc287927 100644 --- a/runtime/oat_file.cc +++ b/runtime/oat_file.cc @@ -1167,12 +1167,15 @@ size_t OatFile::OatDexFile::FileSize() const { std::unique_ptr<const DexFile> OatFile::OatDexFile::OpenDexFile(std::string* error_msg) const { ScopedTrace trace(__PRETTY_FUNCTION__); + static constexpr bool kVerify = false; + static constexpr bool kVerifyChecksum = false; return DexFile::Open(dex_file_pointer_, FileSize(), dex_file_location_, dex_file_location_checksum_, this, - false /* verify */, + kVerify, + kVerifyChecksum, error_msg); } diff --git a/runtime/oat_file_assistant_test.cc b/runtime/oat_file_assistant_test.cc index c79a9a67b3..962115ed29 100644 --- a/runtime/oat_file_assistant_test.cc +++ b/runtime/oat_file_assistant_test.cc @@ -73,14 +73,15 @@ class OatFileAssistantTest : public CommonRuntimeTest { // GetMultiDexSrc2 should have the same primary dex checksum as // GetMultiDexSrc1, but a different secondary dex checksum. + static constexpr bool kVerifyChecksum = true; std::vector<std::unique_ptr<const DexFile>> multi1; ASSERT_TRUE(DexFile::Open(GetMultiDexSrc1().c_str(), - GetMultiDexSrc1().c_str(), &error_msg, &multi1)) << error_msg; + GetMultiDexSrc1().c_str(), kVerifyChecksum, &error_msg, &multi1)) << error_msg; ASSERT_GT(multi1.size(), 1u); std::vector<std::unique_ptr<const DexFile>> multi2; ASSERT_TRUE(DexFile::Open(GetMultiDexSrc2().c_str(), - GetMultiDexSrc2().c_str(), &error_msg, &multi2)) << error_msg; + GetMultiDexSrc2().c_str(), kVerifyChecksum, &error_msg, &multi2)) << error_msg; ASSERT_GT(multi2.size(), 1u); ASSERT_EQ(multi1[0]->GetLocationChecksum(), multi2[0]->GetLocationChecksum()); diff --git a/runtime/oat_file_manager.cc b/runtime/oat_file_manager.cc index fbae1daf43..b7e604036e 100644 --- a/runtime/oat_file_manager.cc +++ b/runtime/oat_file_manager.cc @@ -696,7 +696,9 @@ std::vector<std::unique_ptr<const DexFile>> OatFileManager::OpenDexFilesFromOat( if (dex_files.empty()) { if (oat_file_assistant.HasOriginalDexFiles()) { if (Runtime::Current()->IsDexFileFallbackEnabled()) { - if (!DexFile::Open(dex_location, dex_location, /*out*/ &error_msg, &dex_files)) { + static constexpr bool kVerifyChecksum = true; + if (!DexFile::Open( + dex_location, dex_location, kVerifyChecksum, /*out*/ &error_msg, &dex_files)) { LOG(WARNING) << error_msg; error_msgs->push_back("Failed to open dex files from " + std::string(dex_location) + " because: " + error_msg); diff --git a/runtime/runtime.cc b/runtime/runtime.cc index caf554550e..40e1b1363a 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -883,12 +883,13 @@ static size_t OpenDexFiles(const std::vector<std::string>& dex_filenames, for (size_t i = 0; i < dex_filenames.size(); i++) { const char* dex_filename = dex_filenames[i].c_str(); const char* dex_location = dex_locations[i].c_str(); + static constexpr bool kVerifyChecksum = true; std::string error_msg; if (!OS::FileExists(dex_filename)) { LOG(WARNING) << "Skipping non-existent dex file '" << dex_filename << "'"; continue; } - if (!DexFile::Open(dex_filename, dex_location, &error_msg, dex_files)) { + if (!DexFile::Open(dex_filename, dex_location, kVerifyChecksum, &error_msg, dex_files)) { LOG(WARNING) << "Failed to open .dex from file '" << dex_filename << "': " << error_msg; ++failure_count; } diff --git a/test/Android.run-test.mk b/test/Android.run-test.mk index ee651b5494..f118a7625a 100644 --- a/test/Android.run-test.mk +++ b/test/Android.run-test.mk @@ -209,9 +209,10 @@ ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),$(RUN_TYPES), $(IMAGE_TYPES), $(PICTEST_TYPES), $(DEBUGGABLE_TYPES), $(ART_TEST_RUN_TEST_SKIP), $(ALL_ADDRESS_SIZES)) -# Disable 137-cfi (b/27391690). +# Disable 149-suspend-all-stress, its output is flaky (b/28988206). # Disable 577-profile-foreign-dex (b/27454772). TEST_ART_BROKEN_ALL_TARGET_TESTS := \ + 149-suspend-all-stress \ 577-profile-foreign-dex \ ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),$(RUN_TYPES),$(PREBUILD_TYPES), \ |