diff options
| author | 2021-04-19 14:00:14 +0000 | |
|---|---|---|
| committer | 2021-04-20 15:52:54 +0000 | |
| commit | 1c7d0ce3c63a14f569e64939c48bf6b7db2ac9a7 (patch) | |
| tree | 5d5c950f140998c975fbc2321c98e4999f2e8407 | |
| parent | 4501517c28357189f60f05494facc7e6ba2a8513 (diff) | |
Extra OatDexFile checks when defining classes.
Add a check that the class def index from TypeLookupTable is
valid and checks that OatClass data is within the oat file.
Add a TODO for a check that we cannot do with the data
currently recorded in the oat file.
Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing
Bug: 148412019
Change-Id: Ie23a24cf72bb5a3cc432680db2c870a33d58b030
| -rw-r--r-- | runtime/oat_file.cc | 71 |
1 files changed, 36 insertions, 35 deletions
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc index 3c29480405..b646eb1df4 100644 --- a/runtime/oat_file.cc +++ b/runtime/oat_file.cc @@ -2073,46 +2073,46 @@ OatFile::OatClass OatDexFile::GetOatClass(uint16_t class_def_index) const { } uint32_t oat_class_offset = GetOatClassOffset(class_def_index); - - const uint8_t* oat_class_pointer = oat_file_->Begin() + oat_class_offset; - CHECK_LT(reinterpret_cast<const void*>(oat_class_pointer), - reinterpret_cast<const void*>(oat_file_->End())) << oat_file_->GetLocation(); - - const uint8_t* status_pointer = oat_class_pointer; - CHECK_LT(status_pointer, oat_file_->End()) << oat_file_->GetLocation(); - ClassStatus status = enum_cast<ClassStatus>(*reinterpret_cast<const int16_t*>(status_pointer)); - CHECK_LE(status, ClassStatus::kLast) << static_cast<uint32_t>(status) - << " at " << oat_file_->GetLocation(); - - const uint8_t* type_pointer = status_pointer + sizeof(uint16_t); - CHECK_LT(type_pointer, oat_file_->End()) << oat_file_->GetLocation(); - OatClassType type = static_cast<OatClassType>(*reinterpret_cast<const uint16_t*>(type_pointer)); - CHECK_LT(type, OatClassType::kOatClassMax) << oat_file_->GetLocation(); - - const uint8_t* after_type_pointer = type_pointer + sizeof(int16_t); - CHECK_LE(after_type_pointer, oat_file_->End()) << oat_file_->GetLocation(); + CHECK_GE(oat_class_offset, sizeof(OatHeader)) << oat_file_->GetLocation(); + CHECK_LT(oat_class_offset, oat_file_->Size()) << oat_file_->GetLocation(); + CHECK_LE(/* status */ sizeof(uint16_t) + /* type */ sizeof(uint16_t), + oat_file_->Size() - oat_class_offset) << oat_file_->GetLocation(); + const uint8_t* current_pointer = oat_file_->Begin() + oat_class_offset; + + uint16_t status_value = *reinterpret_cast<const uint16_t*>(current_pointer); + current_pointer += sizeof(uint16_t); + uint16_t type_value = *reinterpret_cast<const uint16_t*>(current_pointer); + current_pointer += sizeof(uint16_t); + CHECK_LE(status_value, enum_cast<uint8_t>(ClassStatus::kLast)) + << static_cast<uint32_t>(status_value) << " at " << oat_file_->GetLocation(); + CHECK_LT(type_value, enum_cast<uint8_t>(OatClassType::kOatClassMax)) << oat_file_->GetLocation(); + ClassStatus status = enum_cast<ClassStatus>(status_value); + OatClassType type = enum_cast<OatClassType>(type_value); uint32_t bitmap_size = 0; - const uint8_t* bitmap_pointer = nullptr; - const uint8_t* methods_pointer = nullptr; + const uint32_t* bitmap_pointer = nullptr; + const OatMethodOffsets* methods_pointer = nullptr; if (type != OatClassType::kNoneCompiled) { if (type == OatClassType::kSomeCompiled) { - bitmap_size = static_cast<uint32_t>(*reinterpret_cast<const uint32_t*>(after_type_pointer)); - bitmap_pointer = after_type_pointer + sizeof(bitmap_size); - CHECK_LE(bitmap_pointer, oat_file_->End()) << oat_file_->GetLocation(); - methods_pointer = bitmap_pointer + bitmap_size; + CHECK_LE(sizeof(uint32_t), static_cast<size_t>(oat_file_->End() - current_pointer)) + << oat_file_->GetLocation(); + bitmap_size = *reinterpret_cast<const uint32_t*>(current_pointer); + current_pointer += sizeof(uint32_t); + CHECK_LE(bitmap_size, static_cast<size_t>(oat_file_->End() - current_pointer)) + << oat_file_->GetLocation(); + bitmap_pointer = reinterpret_cast<const uint32_t*>(current_pointer); + current_pointer += bitmap_size; + CHECK_LE(BitVector::NumSetBits(bitmap_pointer, bitmap_size * kBitsPerByte), + static_cast<size_t>(oat_file_->End() - current_pointer) / sizeof(OatMethodOffsets)) + << oat_file_->GetLocation(); } else { - methods_pointer = after_type_pointer; + // TODO: We do not have enough information here to check if the array extends beyond + // the end of the oat file. We should record the number of methods in the oat file. } - CHECK_LE(methods_pointer, oat_file_->End()) << oat_file_->GetLocation(); + methods_pointer = reinterpret_cast<const OatMethodOffsets*>(current_pointer); } - return OatFile::OatClass(oat_file_, - status, - type, - bitmap_size, - reinterpret_cast<const uint32_t*>(bitmap_pointer), - reinterpret_cast<const OatMethodOffsets*>(methods_pointer)); + return OatFile::OatClass(oat_file_, status, type, bitmap_size, bitmap_pointer, methods_pointer); } const dex::ClassDef* OatDexFile::FindClassDef(const DexFile& dex_file, @@ -2125,9 +2125,10 @@ const dex::ClassDef* OatDexFile::FindClassDef(const DexFile& dex_file, if (LIKELY((oat_dex_file != nullptr) && oat_dex_file->GetTypeLookupTable().Valid())) { used_lookup_table = true; const uint32_t class_def_idx = oat_dex_file->GetTypeLookupTable().Lookup(descriptor, hash); - lookup_table_classdef = (class_def_idx != dex::kDexNoIndex) - ? &dex_file.GetClassDef(class_def_idx) - : nullptr; + if (class_def_idx != dex::kDexNoIndex) { + CHECK_LT(class_def_idx, dex_file.NumClassDefs()) << oat_dex_file->GetOatFile()->GetLocation(); + lookup_table_classdef = &dex_file.GetClassDef(class_def_idx); + } if (!kIsDebugBuild) { return lookup_table_classdef; } |