summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libdexfile/dex/dex_file_verifier.cc65
1 files changed, 35 insertions, 30 deletions
diff --git a/libdexfile/dex/dex_file_verifier.cc b/libdexfile/dex/dex_file_verifier.cc
index 7e0b109854..b94d7ce6b2 100644
--- a/libdexfile/dex/dex_file_verifier.cc
+++ b/libdexfile/dex/dex_file_verifier.cc
@@ -127,7 +127,7 @@ class DexFileVerifier {
public:
DexFileVerifier(const DexFile* dex_file, const char* location, bool verify_checksum)
: dex_file_(dex_file),
- begin_(dex_file->Begin()),
+ offset_base_address_(dex_file->Begin()),
size_(0), // Initialized after we verify the header.
location_(location),
verify_checksum_(verify_checksum),
@@ -151,23 +151,27 @@ class DexFileVerifier {
template <class T = uint8_t>
ALWAYS_INLINE const T* OffsetToPtr(size_t offset) {
DCHECK_LE(offset, size_);
- return reinterpret_cast<const T*>(begin_ + offset);
+ return reinterpret_cast<const T*>(offset_base_address_ + offset);
}
ALWAYS_INLINE size_t PtrToOffset(const void* ptr) {
- DCHECK_GE(ptr, begin_);
- DCHECK_LE(ptr, begin_ + size_);
- return reinterpret_cast<const uint8_t*>(ptr) - begin_;
+ DCHECK_GE(ptr, dex_file_->Begin());
+ DCHECK_LE(ptr, EndOfFile());
+ return reinterpret_cast<const uint8_t*>(ptr) - offset_base_address_;
}
// Converts the pointer `ptr` into `offset`.
// Returns `true` if the offset is within the bounds of the container.
// TODO: Try to remove this overload. Avoid creating invalid pointers.
ALWAYS_INLINE WARN_UNUSED bool PtrToOffset(const void* ptr, /*out*/ size_t* offset) {
- *offset = reinterpret_cast<const uint8_t*>(ptr) - begin_;
+ *offset = reinterpret_cast<const uint8_t*>(ptr) - offset_base_address_;
return *offset <= size_;
}
+ ALWAYS_INLINE const uint8_t* EndOfFile() {
+ return OffsetToPtr(size_);
+ }
+
// Helper functions to retrieve names from the dex file. We do not want to rely on DexFile
// functionality, as we're still verifying the dex file.
@@ -380,8 +384,9 @@ class DexFileVerifier {
bool VerifyTypeDescriptor(dex::TypeIndex idx, const char* error_msg, ExtraCheckFn extra_check);
const DexFile* const dex_file_;
- const uint8_t* const begin_;
+ const uint8_t* const offset_base_address_;
size_t size_;
+ ArrayRef<const uint8_t> data_; // The "data" section of the dex file.
const char* const location_;
const bool verify_checksum_;
const DexFile::Header* const header_;
@@ -638,7 +643,7 @@ bool DexFileVerifier::CheckHeader() {
}
// Check that all offsets are inside the file.
- bool result =
+ bool ok =
CheckValidOffsetAndSize(header_->link_off_,
header_->link_size_,
/* alignment= */ 0,
@@ -679,7 +684,11 @@ bool DexFileVerifier::CheckHeader() {
// is supposed to be a multiple of 4.
/* alignment= */ 0,
"data");
- return result;
+
+ if (ok) {
+ data_ = ArrayRef<const uint8_t>(OffsetToPtr(header_->data_off_), header_->data_size_);
+ }
+ return ok;
}
bool DexFileVerifier::CheckMap() {
@@ -695,7 +704,7 @@ bool DexFileVerifier::CheckMap() {
uint32_t last_offset = 0;
uint32_t last_type = 0;
uint32_t data_item_count = 0;
- uint32_t data_items_left = header_->data_size_;
+ uint32_t data_items_left = data_.size();
uint32_t used_bits = 0;
// Check the validity of the size of the map list.
@@ -794,14 +803,14 @@ bool DexFileVerifier::CheckMap() {
#define DECODE_UNSIGNED_CHECKED_FROM(ptr, var) \
uint32_t var; \
- if (!DecodeUnsignedLeb128Checked(&(ptr), begin_ + size_, &(var))) { \
+ if (!DecodeUnsignedLeb128Checked(&(ptr), EndOfFile(), &(var))) { \
ErrorStringPrintf("Read out of bounds"); \
return false; \
}
#define DECODE_SIGNED_CHECKED_FROM(ptr, var) \
int32_t var; \
- if (!DecodeSignedLeb128Checked(&(ptr), begin_ + size_, &(var))) { \
+ if (!DecodeSignedLeb128Checked(&(ptr), EndOfFile(), &(var))) { \
ErrorStringPrintf("Read out of bounds"); \
return false; \
}
@@ -1417,13 +1426,12 @@ bool DexFileVerifier::CheckIntraClassDataItemFields(size_t count) {
// We cannot use ClassAccessor::Field yet as it could read beyond the end of the data section.
const uint8_t* ptr = ptr_;
- const uint8_t* data_end = OffsetToPtr(header_->data_off_ + header_->data_size_);
uint32_t prev_index = 0;
for (size_t i = 0; i != count; ++i) {
uint32_t field_idx_diff, access_flags;
- if (UNLIKELY(!DecodeUnsignedLeb128Checked(&ptr, data_end, &field_idx_diff)) ||
- UNLIKELY(!DecodeUnsignedLeb128Checked(&ptr, data_end, &access_flags))) {
+ if (UNLIKELY(!DecodeUnsignedLeb128Checked(&ptr, data_.end(), &field_idx_diff)) ||
+ UNLIKELY(!DecodeUnsignedLeb128Checked(&ptr, data_.end(), &access_flags))) {
ErrorStringPrintf("encoded_field read out of bounds");
return false;
}
@@ -1457,7 +1465,6 @@ bool DexFileVerifier::CheckIntraClassDataItemMethods(size_t num_methods,
// We cannot use ClassAccessor::Method yet as it could read beyond the end of the data section.
const uint8_t* ptr = ptr_;
- const uint8_t* data_end = OffsetToPtr(header_->data_off_ + header_->data_size_);
// Load the first direct method for the check below.
size_t remaining_direct_methods = num_direct_methods;
@@ -1469,9 +1476,9 @@ bool DexFileVerifier::CheckIntraClassDataItemMethods(size_t num_methods,
uint32_t prev_index = 0;
for (size_t i = 0; i != num_methods; ++i) {
uint32_t method_idx_diff, access_flags, code_off;
- if (UNLIKELY(!DecodeUnsignedLeb128Checked(&ptr, data_end, &method_idx_diff)) ||
- UNLIKELY(!DecodeUnsignedLeb128Checked(&ptr, data_end, &access_flags)) ||
- UNLIKELY(!DecodeUnsignedLeb128Checked(&ptr, data_end, &code_off))) {
+ if (UNLIKELY(!DecodeUnsignedLeb128Checked(&ptr, data_.end(), &method_idx_diff)) ||
+ UNLIKELY(!DecodeUnsignedLeb128Checked(&ptr, data_.end(), &access_flags)) ||
+ UNLIKELY(!DecodeUnsignedLeb128Checked(&ptr, data_.end(), &code_off))) {
ErrorStringPrintf("encoded_method read out of bounds");
return false;
}
@@ -1517,13 +1524,11 @@ bool DexFileVerifier::CheckIntraClassDataItemMethods(size_t num_methods,
bool DexFileVerifier::CheckIntraClassDataItem() {
// We cannot use ClassAccessor yet as it could read beyond the end of the data section.
const uint8_t* ptr = ptr_;
- const uint8_t* data_end = OffsetToPtr(header_->data_off_ + header_->data_size_);
-
uint32_t static_fields_size, instance_fields_size, direct_methods_size, virtual_methods_size;
- if (UNLIKELY(!DecodeUnsignedLeb128Checked(&ptr, data_end, &static_fields_size)) ||
- UNLIKELY(!DecodeUnsignedLeb128Checked(&ptr, data_end, &instance_fields_size)) ||
- UNLIKELY(!DecodeUnsignedLeb128Checked(&ptr, data_end, &direct_methods_size)) ||
- UNLIKELY(!DecodeUnsignedLeb128Checked(&ptr, data_end, &virtual_methods_size))) {
+ if (UNLIKELY(!DecodeUnsignedLeb128Checked(&ptr, data_.end(), &static_fields_size)) ||
+ UNLIKELY(!DecodeUnsignedLeb128Checked(&ptr, data_.end(), &instance_fields_size)) ||
+ UNLIKELY(!DecodeUnsignedLeb128Checked(&ptr, data_.end(), &direct_methods_size)) ||
+ UNLIKELY(!DecodeUnsignedLeb128Checked(&ptr, data_.end(), &virtual_methods_size))) {
ErrorStringPrintf("class_data_item read out of bounds");
return false;
}
@@ -1668,7 +1673,7 @@ bool DexFileVerifier::CheckIntraCodeItem() {
bool DexFileVerifier::CheckIntraStringDataItem() {
DECODE_UNSIGNED_CHECKED_FROM(ptr_, size);
- const uint8_t* file_end = begin_ + size_;
+ const uint8_t* file_end = EndOfFile();
for (uint32_t i = 0; i < size; i++) {
CHECK_LT(i, size); // b/15014252 Prevents hitting the impossible case below
@@ -1771,7 +1776,7 @@ bool DexFileVerifier::CheckIntraDebugInfoItem() {
}
while (true) {
- if (UNLIKELY(ptr_ >= begin_ + size_)) {
+ if (UNLIKELY(ptr_ >= EndOfFile())) {
// Went past the end.
return false;
}
@@ -2226,8 +2231,8 @@ bool DexFileVerifier::CheckIntraIdSection(size_t offset, uint32_t count) {
template <DexFile::MapItemType kType>
bool DexFileVerifier::CheckIntraDataSection(size_t offset, uint32_t count) {
- size_t data_start = header_->data_off_;
- size_t data_end = data_start + header_->data_size_;
+ size_t data_start = PtrToOffset(data_.begin());
+ size_t data_end = PtrToOffset(data_.end());
// Check the validity of the offset of the section.
if (UNLIKELY((offset < data_start) || (offset > data_end))) {
@@ -2257,7 +2262,7 @@ bool DexFileVerifier::CheckIntraSection() {
const dex::MapList* map = OffsetToPtr<dex::MapList>(header_->map_off_);
const dex::MapItem* item = map->list_;
uint32_t count = map->size_;
- ptr_ = begin_;
+ ptr_ = dex_file_->Begin();
// Preallocate offset map to avoid some allocations. We can only guess from the list items,
// not derived things.