Add sub-range (base,size) arguments to DexFileLoader::OpenCommon
We will need to be able to specify the sub-range with multidex,
since one container will be able to store several dex files.
Make the checksum argument optional, and default to checksum
from the dex header if it is not provided.
Be defensive about the container argument, since apps
like to use this internal method directly.
Bug: 266950186
Test: test.py -b --host --optimizing --64
Change-Id: I1cdbd1ec608238f8cc4d86b440712c9a268fe8ff
diff --git a/libdexfile/dex/dex_file_loader.cc b/libdexfile/dex/dex_file_loader.cc
index bd5863a..1fe1113 100644
--- a/libdexfile/dex/dex_file_loader.cc
+++ b/libdexfile/dex/dex_file_loader.cc
@@ -19,6 +19,7 @@
#include <sys/stat.h>
#include <memory>
+#include <optional>
#include "android-base/stringprintf.h"
#include "base/bit_utils.h"
@@ -192,7 +193,10 @@
DCHECK(!error_msg->empty());
return {};
}
+ DCHECK(root_container_ != nullptr);
std::unique_ptr<const DexFile> dex_file = OpenCommon(root_container_,
+ root_container_->Begin(),
+ root_container_->Size(),
location_,
location_checksum,
oat_dex_file,
@@ -315,23 +319,18 @@
if (!MapRootContainer(error_msg)) {
return false;
}
- const uint8_t* base = root_container_->Begin();
- size_t size = root_container_->Size();
- if (size < sizeof(DexFile::Header)) {
- *error_msg =
- StringPrintf("DexFile: failed to open dex file '%s' that is too short to have a header",
- location_.c_str());
- return false;
- }
- const DexFile::Header* dex_header = reinterpret_cast<const DexFile::Header*>(base);
- std::unique_ptr<const DexFile> dex_file = OpenCommon(root_container_,
- location_,
- dex_header->checksum_,
- /*oat_dex_file=*/nullptr,
- verify,
- verify_checksum,
- error_msg,
- nullptr);
+ DCHECK(root_container_ != nullptr);
+ std::unique_ptr<const DexFile> dex_file =
+ OpenCommon(root_container_,
+ root_container_->Begin(),
+ root_container_->Size(),
+ location_,
+ /*location_checksum*/ {}, // Use default checksum from dex header.
+ /*oat_dex_file=*/nullptr,
+ verify,
+ verify_checksum,
+ error_msg,
+ nullptr);
if (dex_file.get() != nullptr) {
dex_files->push_back(std::move(dex_file));
return true;
@@ -343,30 +342,33 @@
return false;
}
-std::unique_ptr<DexFile> DexFileLoader::OpenCommon(
- const std::shared_ptr<DexFileContainer>& container,
- const std::string& location,
- uint32_t location_checksum,
- const OatDexFile* oat_dex_file,
- bool verify,
- bool verify_checksum,
- std::string* error_msg,
- DexFileLoaderErrorCode* error_code) {
- CHECK(container != nullptr);
- const uint8_t* base = container->Begin();
- size_t size = container->Size();
+std::unique_ptr<DexFile> DexFileLoader::OpenCommon(std::shared_ptr<DexFileContainer> container,
+ const uint8_t* base,
+ size_t size,
+ const std::string& location,
+ std::optional<uint32_t> location_checksum,
+ const OatDexFile* oat_dex_file,
+ bool verify,
+ bool verify_checksum,
+ std::string* error_msg,
+ DexFileLoaderErrorCode* error_code) {
+ if (container == nullptr) {
+ // We should never pass null here, but use reasonable default for app compat anyway.
+ container = std::make_shared<MemoryDexFileContainer>(base, size);
+ }
if (error_code != nullptr) {
*error_code = DexFileLoaderErrorCode::kDexFileError;
}
std::unique_ptr<DexFile> dex_file;
+ auto header = reinterpret_cast<const DexFile::Header*>(base);
if (size >= sizeof(StandardDexFile::Header) && StandardDexFile::IsMagicValid(base)) {
- dex_file.reset(
- new StandardDexFile(base, size, location, location_checksum, oat_dex_file, container));
+ uint32_t checksum = location_checksum.value_or(header->checksum_);
+ dex_file.reset(new StandardDexFile(base, size, location, checksum, oat_dex_file, container));
} else if (size >= sizeof(CompactDexFile::Header) && CompactDexFile::IsMagicValid(base)) {
- dex_file.reset(
- new CompactDexFile(base, size, location, location_checksum, oat_dex_file, container));
+ uint32_t checksum = location_checksum.value_or(header->checksum_);
+ dex_file.reset(new CompactDexFile(base, size, location, checksum, oat_dex_file, container));
} else {
- *error_msg = "Invalid or truncated dex file";
+ *error_msg = StringPrintf("Invalid or truncated dex file '%s'", location.c_str());
}
if (dex_file == nullptr) {
*error_msg =
@@ -456,7 +458,9 @@
return false;
}
- std::unique_ptr<const DexFile> dex_file = OpenCommon(std::move(container),
+ std::unique_ptr<const DexFile> dex_file = OpenCommon(container,
+ container->Begin(),
+ container->Size(),
location,
zip_entry->GetCrc32(),
/*oat_dex_file=*/nullptr,