summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/oat_writer.cc1
-rw-r--r--compiler/utils/test_dex_file_builder.h11
-rw-r--r--dex2oat/dex2oat.cc4
-rw-r--r--dexdump/dexdump.cc5
-rw-r--r--dexdump/dexdump_main.cc4
-rw-r--r--dexlist/dexlist.cc3
-rw-r--r--oatdump/oatdump.cc42
-rw-r--r--profman/profman.cc2
-rw-r--r--runtime/common_runtime_test.cc7
-rw-r--r--runtime/dex_file.cc55
-rw-r--r--runtime/dex_file.h29
-rw-r--r--runtime/dex_file_test.cc3
-rw-r--r--runtime/dex_file_verifier.cc20
-rw-r--r--runtime/dex_file_verifier.h25
-rw-r--r--runtime/dex_file_verifier_test.cc52
-rw-r--r--runtime/oat_file.cc5
-rw-r--r--runtime/oat_file_assistant_test.cc5
-rw-r--r--runtime/oat_file_manager.cc4
-rw-r--r--runtime/runtime.cc3
-rw-r--r--test/Android.run-test.mk3
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), \