summaryrefslogtreecommitdiffstats
path: root/runtime/dex_file_verifier.cc
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/dex_file_verifier.cc')
-rw-r--r--runtime/dex_file_verifier.cc546
1 files changed, 280 insertions, 266 deletions
diff --git a/runtime/dex_file_verifier.cc b/runtime/dex_file_verifier.cc
index 7dc2b31..56bf21d 100644
--- a/runtime/dex_file_verifier.cc
+++ b/runtime/dex_file_verifier.cc
@@ -65,12 +65,22 @@ static bool IsDataSectionType(uint32_t map_type) {
return true;
}
-static bool CheckShortyDescriptorMatch(char shorty_char, const char* descriptor,
- bool is_return_type) {
+bool DexFileVerifier::Verify(const DexFile* dex_file, const byte* begin, size_t size,
+ const char* location, std::string* error_msg) {
+ UniquePtr<DexFileVerifier> verifier(new DexFileVerifier(dex_file, begin, size, location));
+ if (!verifier->Verify()) {
+ *error_msg = verifier->FailureReason();
+ return false;
+ }
+ return true;
+}
+
+bool DexFileVerifier::CheckShortyDescriptorMatch(char shorty_char, const char* descriptor,
+ bool is_return_type) {
switch (shorty_char) {
case 'V':
- if (!is_return_type) {
- LOG(ERROR) << "Invalid use of void";
+ if (UNLIKELY(!is_return_type)) {
+ ErrorStringPrintf("Invalid use of void");
return false;
}
// Intentional fallthrough.
@@ -82,62 +92,58 @@ static bool CheckShortyDescriptorMatch(char shorty_char, const char* descriptor,
case 'J':
case 'S':
case 'Z':
- if ((descriptor[0] != shorty_char) || (descriptor[1] != '\0')) {
- LOG(ERROR) << StringPrintf("Shorty vs. primitive type mismatch: '%c', '%s'", shorty_char, descriptor);
+ if (UNLIKELY((descriptor[0] != shorty_char) || (descriptor[1] != '\0'))) {
+ ErrorStringPrintf("Shorty vs. primitive type mismatch: '%c', '%s'",
+ shorty_char, descriptor);
return false;
}
break;
case 'L':
- if ((descriptor[0] != 'L') && (descriptor[0] != '[')) {
- LOG(ERROR) << StringPrintf("Shorty vs. type mismatch: '%c', '%s'", shorty_char, descriptor);
+ if (UNLIKELY((descriptor[0] != 'L') && (descriptor[0] != '['))) {
+ ErrorStringPrintf("Shorty vs. type mismatch: '%c', '%s'", shorty_char, descriptor);
return false;
}
break;
default:
- LOG(ERROR) << "Bad shorty character: '" << shorty_char << "'";
+ ErrorStringPrintf("Bad shorty character: '%c'", shorty_char);
return false;
}
return true;
}
-bool DexFileVerifier::Verify(const DexFile* dex_file, const byte* begin, size_t size) {
- UniquePtr<DexFileVerifier> verifier(new DexFileVerifier(dex_file, begin, size));
- return verifier->Verify();
-}
-
-bool DexFileVerifier::CheckPointerRange(const void* start, const void* end, const char* label) const {
+bool DexFileVerifier::CheckPointerRange(const void* start, const void* end, const char* label) {
uint32_t range_start = reinterpret_cast<uint32_t>(start);
uint32_t range_end = reinterpret_cast<uint32_t>(end);
uint32_t file_start = reinterpret_cast<uint32_t>(begin_);
uint32_t file_end = file_start + size_;
- if ((range_start < file_start) || (range_start > file_end) ||
- (range_end < file_start) || (range_end > file_end)) {
- LOG(ERROR) << StringPrintf("Bad range for %s: %x to %x", label,
- range_start - file_start, range_end - file_start);
+ if (UNLIKELY((range_start < file_start) || (range_start > file_end) ||
+ (range_end < file_start) || (range_end > file_end))) {
+ ErrorStringPrintf("Bad range for %s: %x to %x", label,
+ range_start - file_start, range_end - file_start);
return false;
}
return true;
}
bool DexFileVerifier::CheckListSize(const void* start, uint32_t count,
- uint32_t element_size, const char* label) const {
+ uint32_t element_size, const char* label) {
const byte* list_start = reinterpret_cast<const byte*>(start);
return CheckPointerRange(list_start, list_start + (count * element_size), label);
}
-bool DexFileVerifier::CheckIndex(uint32_t field, uint32_t limit, const char* label) const {
- if (field >= limit) {
- LOG(ERROR) << StringPrintf("Bad index for %s: %x >= %x", label, field, limit);
+bool DexFileVerifier::CheckIndex(uint32_t field, uint32_t limit, const char* label) {
+ if (UNLIKELY(field >= limit)) {
+ ErrorStringPrintf("Bad index for %s: %x >= %x", label, field, limit);
return false;
}
return true;
}
-bool DexFileVerifier::CheckHeader() const {
+bool DexFileVerifier::CheckHeader() {
// Check file size from the header.
uint32_t expected_size = header_->file_size_;
if (size_ != expected_size) {
- LOG(ERROR) << "Bad file size (" << size_ << ", expected " << expected_size << ")";
+ ErrorStringPrintf("Bad file size (%zd, expected %ud)", size_, expected_size);
return false;
}
@@ -147,25 +153,25 @@ bool DexFileVerifier::CheckHeader() const {
const byte* non_sum_ptr = reinterpret_cast<const byte*>(header_) + non_sum;
adler_checksum = adler32(adler_checksum, non_sum_ptr, expected_size - non_sum);
if (adler_checksum != header_->checksum_) {
- LOG(ERROR) << StringPrintf("Bad checksum (%08x, expected %08x)", adler_checksum, header_->checksum_);
+ ErrorStringPrintf("Bad checksum (%08x, expected %08x)", adler_checksum, header_->checksum_);
return false;
}
// Check the contents of the header.
if (header_->endian_tag_ != DexFile::kDexEndianConstant) {
- LOG(ERROR) << StringPrintf("Unexpected endian_tag: %x", header_->endian_tag_);
+ ErrorStringPrintf("Unexpected endian_tag: %x", header_->endian_tag_);
return false;
}
if (header_->header_size_ != sizeof(DexFile::Header)) {
- LOG(ERROR) << "Bad header size: " << header_->header_size_;
+ ErrorStringPrintf("Bad header size: %ud", header_->header_size_);
return false;
}
return true;
}
-bool DexFileVerifier::CheckMap() const {
+bool DexFileVerifier::CheckMap() {
const DexFile::MapList* map = reinterpret_cast<const DexFile::MapList*>(begin_ + header_->map_off_);
const DexFile::MapItem* item = map->list_;
@@ -182,19 +188,20 @@ bool DexFileVerifier::CheckMap() const {
// Check the items listed in the map.
for (uint32_t i = 0; i < count; i++) {
- if (last_offset >= item->offset_ && i != 0) {
- LOG(ERROR) << StringPrintf("Out of order map item: %x then %x", last_offset, item->offset_);
+ if (UNLIKELY(last_offset >= item->offset_ && i != 0)) {
+ ErrorStringPrintf("Out of order map item: %x then %x", last_offset, item->offset_);
return false;
}
- if (item->offset_ >= header_->file_size_) {
- LOG(ERROR) << StringPrintf("Map item after end of file: %x, size %x", item->offset_, header_->file_size_);
+ if (UNLIKELY(item->offset_ >= header_->file_size_)) {
+ ErrorStringPrintf("Map item after end of file: %x, size %x",
+ item->offset_, header_->file_size_);
return false;
}
if (IsDataSectionType(item->type_)) {
uint32_t icount = item->size_;
- if (icount > data_items_left) {
- LOG(ERROR) << "Too many items in data section: " << data_item_count + icount;
+ if (UNLIKELY(icount > data_items_left)) {
+ ErrorStringPrintf("Too many items in data section: %ud", data_item_count + icount);
return false;
}
data_items_left -= icount;
@@ -203,13 +210,13 @@ bool DexFileVerifier::CheckMap() const {
uint32_t bit = MapTypeToBitMask(item->type_);
- if (bit == 0) {
- LOG(ERROR) << StringPrintf("Unknown map section type %x", item->type_);
+ if (UNLIKELY(bit == 0)) {
+ ErrorStringPrintf("Unknown map section type %x", item->type_);
return false;
}
- if ((used_bits & bit) != 0) {
- LOG(ERROR) << StringPrintf("Duplicate map section of type %x", item->type_);
+ if (UNLIKELY((used_bits & bit) != 0)) {
+ ErrorStringPrintf("Duplicate map section of type %x", item->type_);
return false;
}
@@ -219,63 +226,59 @@ bool DexFileVerifier::CheckMap() const {
}
// Check for missing sections in the map.
- if ((used_bits & MapTypeToBitMask(DexFile::kDexTypeHeaderItem)) == 0) {
- LOG(ERROR) << "Map is missing header entry";
+ if (UNLIKELY((used_bits & MapTypeToBitMask(DexFile::kDexTypeHeaderItem)) == 0)) {
+ ErrorStringPrintf("Map is missing header entry");
return false;
}
- if ((used_bits & MapTypeToBitMask(DexFile::kDexTypeMapList)) == 0) {
- LOG(ERROR) << "Map is missing map_list entry";
+ if (UNLIKELY((used_bits & MapTypeToBitMask(DexFile::kDexTypeMapList)) == 0)) {
+ ErrorStringPrintf("Map is missing map_list entry");
return false;
}
- if ((used_bits & MapTypeToBitMask(DexFile::kDexTypeStringIdItem)) == 0 &&
- ((header_->string_ids_off_ != 0) || (header_->string_ids_size_ != 0))) {
- LOG(ERROR) << "Map is missing string_ids entry";
+ if (UNLIKELY((used_bits & MapTypeToBitMask(DexFile::kDexTypeStringIdItem)) == 0 &&
+ ((header_->string_ids_off_ != 0) || (header_->string_ids_size_ != 0)))) {
+ ErrorStringPrintf("Map is missing string_ids entry");
return false;
}
- if ((used_bits & MapTypeToBitMask(DexFile::kDexTypeTypeIdItem)) == 0 &&
- ((header_->type_ids_off_ != 0) || (header_->type_ids_size_ != 0))) {
- LOG(ERROR) << "Map is missing type_ids entry";
+ if (UNLIKELY((used_bits & MapTypeToBitMask(DexFile::kDexTypeTypeIdItem)) == 0 &&
+ ((header_->type_ids_off_ != 0) || (header_->type_ids_size_ != 0)))) {
+ ErrorStringPrintf("Map is missing type_ids entry");
return false;
}
- if ((used_bits & MapTypeToBitMask(DexFile::kDexTypeProtoIdItem)) == 0 &&
- ((header_->proto_ids_off_ != 0) || (header_->proto_ids_size_ != 0))) {
- LOG(ERROR) << "Map is missing proto_ids entry";
+ if (UNLIKELY((used_bits & MapTypeToBitMask(DexFile::kDexTypeProtoIdItem)) == 0 &&
+ ((header_->proto_ids_off_ != 0) || (header_->proto_ids_size_ != 0)))) {
+ ErrorStringPrintf("Map is missing proto_ids entry");
return false;
}
- if ((used_bits & MapTypeToBitMask(DexFile::kDexTypeFieldIdItem)) == 0 &&
- ((header_->field_ids_off_ != 0) || (header_->field_ids_size_ != 0))) {
- LOG(ERROR) << "Map is missing field_ids entry";
+ if (UNLIKELY((used_bits & MapTypeToBitMask(DexFile::kDexTypeFieldIdItem)) == 0 &&
+ ((header_->field_ids_off_ != 0) || (header_->field_ids_size_ != 0)))) {
+ ErrorStringPrintf("Map is missing field_ids entry");
return false;
}
- if ((used_bits & MapTypeToBitMask(DexFile::kDexTypeMethodIdItem)) == 0 &&
- ((header_->method_ids_off_ != 0) || (header_->method_ids_size_ != 0))) {
- LOG(ERROR) << "Map is missing method_ids entry";
+ if (UNLIKELY((used_bits & MapTypeToBitMask(DexFile::kDexTypeMethodIdItem)) == 0 &&
+ ((header_->method_ids_off_ != 0) || (header_->method_ids_size_ != 0)))) {
+ ErrorStringPrintf("Map is missing method_ids entry");
return false;
}
- if ((used_bits & MapTypeToBitMask(DexFile::kDexTypeClassDefItem)) == 0 &&
- ((header_->class_defs_off_ != 0) || (header_->class_defs_size_ != 0))) {
- LOG(ERROR) << "Map is missing class_defs entry";
+ if (UNLIKELY((used_bits & MapTypeToBitMask(DexFile::kDexTypeClassDefItem)) == 0 &&
+ ((header_->class_defs_off_ != 0) || (header_->class_defs_size_ != 0)))) {
+ ErrorStringPrintf("Map is missing class_defs entry");
return false;
}
-
return true;
}
uint32_t DexFileVerifier::ReadUnsignedLittleEndian(uint32_t size) {
uint32_t result = 0;
- if (!CheckPointerRange(ptr_, ptr_ + size, "encoded_value")) {
- return 0;
- }
-
- for (uint32_t i = 0; i < size; i++) {
- result |= ((uint32_t) *(ptr_++)) << (i * 8);
+ if (LIKELY(CheckPointerRange(ptr_, ptr_ + size, "encoded_value"))) {
+ for (uint32_t i = 0; i < size; i++) {
+ result |= ((uint32_t) *(ptr_++)) << (i * 8);
+ }
}
-
return result;
}
bool DexFileVerifier::CheckAndGetHandlerOffsets(const DexFile::CodeItem* code_item,
- uint32_t* handler_offsets, uint32_t handlers_size) {
+ uint32_t* handler_offsets, uint32_t handlers_size) {
const byte* handlers_base = DexFile::GetCatchHandlerData(*code_item, 0);
for (uint32_t i = 0; i < handlers_size; i++) {
@@ -283,8 +286,8 @@ bool DexFileVerifier::CheckAndGetHandlerOffsets(const DexFile::CodeItem* code_it
uint32_t offset = reinterpret_cast<uint32_t>(ptr_) - reinterpret_cast<uint32_t>(handlers_base);
int32_t size = DecodeSignedLeb128(&ptr_);
- if ((size < -65536) || (size > 65536)) {
- LOG(ERROR) << "Invalid exception handler size: " << size;
+ if (UNLIKELY((size < -65536) || (size > 65536))) {
+ ErrorStringPrintf("Invalid exception handler size: %d", size);
return false;
}
@@ -304,16 +307,16 @@ bool DexFileVerifier::CheckAndGetHandlerOffsets(const DexFile::CodeItem* code_it
}
uint32_t addr = DecodeUnsignedLeb128(&ptr_);
- if (addr >= code_item->insns_size_in_code_units_) {
- LOG(ERROR) << StringPrintf("Invalid handler addr: %x", addr);
+ if (UNLIKELY(addr >= code_item->insns_size_in_code_units_)) {
+ ErrorStringPrintf("Invalid handler addr: %x", addr);
return false;
}
}
if (catch_all) {
uint32_t addr = DecodeUnsignedLeb128(&ptr_);
- if (addr >= code_item->insns_size_in_code_units_) {
- LOG(ERROR) << StringPrintf("Invalid handler catch_all_addr: %x", addr);
+ if (UNLIKELY(addr >= code_item->insns_size_in_code_units_)) {
+ ErrorStringPrintf("Invalid handler catch_all_addr: %x", addr);
return false;
}
}
@@ -323,21 +326,21 @@ bool DexFileVerifier::CheckAndGetHandlerOffsets(const DexFile::CodeItem* code_it
}
bool DexFileVerifier::CheckClassDataItemField(uint32_t idx, uint32_t access_flags,
- bool expect_static) const {
+ bool expect_static) {
if (!CheckIndex(idx, header_->field_ids_size_, "class_data_item field_idx")) {
return false;
}
bool is_static = (access_flags & kAccStatic) != 0;
- if (is_static != expect_static) {
- LOG(ERROR) << "Static/instance field not in expected list";
+ if (UNLIKELY(is_static != expect_static)) {
+ ErrorStringPrintf("Static/instance field not in expected list");
return false;
}
uint32_t access_field_mask = kAccPublic | kAccPrivate | kAccProtected | kAccStatic |
kAccFinal | kAccVolatile | kAccTransient | kAccSynthetic | kAccEnum;
- if ((access_flags & ~access_field_mask) != 0) {
- LOG(ERROR) << StringPrintf("Bad class_data_item field access_flags %x", access_flags);
+ if (UNLIKELY((access_flags & ~access_field_mask) != 0)) {
+ ErrorStringPrintf("Bad class_data_item field access_flags %x", access_flags);
return false;
}
@@ -345,7 +348,7 @@ bool DexFileVerifier::CheckClassDataItemField(uint32_t idx, uint32_t access_flag
}
bool DexFileVerifier::CheckClassDataItemMethod(uint32_t idx, uint32_t access_flags,
- uint32_t code_offset, bool expect_direct) const {
+ uint32_t code_offset, bool expect_direct) {
if (!CheckIndex(idx, header_->method_ids_size_, "class_data_item method_idx")) {
return false;
}
@@ -355,26 +358,27 @@ bool DexFileVerifier::CheckClassDataItemMethod(uint32_t idx, uint32_t access_fla
bool is_synchronized = (access_flags & kAccSynchronized) != 0;
bool allow_synchronized = (access_flags & kAccNative) != 0;
- if (is_direct != expect_direct) {
- LOG(ERROR) << "Direct/virtual method not in expected list";
+ if (UNLIKELY(is_direct != expect_direct)) {
+ ErrorStringPrintf("Direct/virtual method not in expected list");
return false;
}
uint32_t access_method_mask = kAccPublic | kAccPrivate | kAccProtected | kAccStatic |
kAccFinal | kAccSynchronized | kAccBridge | kAccVarargs | kAccNative | kAccAbstract |
kAccStrict | kAccSynthetic | kAccConstructor | kAccDeclaredSynchronized;
- if (((access_flags & ~access_method_mask) != 0) || (is_synchronized && !allow_synchronized)) {
- LOG(ERROR) << StringPrintf("Bad class_data_item method access_flags %x", access_flags);
+ if (UNLIKELY(((access_flags & ~access_method_mask) != 0) ||
+ (is_synchronized && !allow_synchronized))) {
+ ErrorStringPrintf("Bad class_data_item method access_flags %x", access_flags);
return false;
}
- if (expect_code && code_offset == 0) {
- LOG(ERROR)<< StringPrintf("Unexpected zero value for class_data_item method code_off"
- " with access flags %x", access_flags);
+ if (UNLIKELY(expect_code && (code_offset == 0))) {
+ ErrorStringPrintf("Unexpected zero value for class_data_item method code_off with access "
+ "flags %x", access_flags);
return false;
- } else if (!expect_code && code_offset != 0) {
- LOG(ERROR) << StringPrintf("Unexpected non-zero value %x for class_data_item method code_off"
- " with access flags %x", code_offset, access_flags);
+ } else if (UNLIKELY(!expect_code && (code_offset != 0))) {
+ ErrorStringPrintf("Unexpected non-zero value %x for class_data_item method code_off"
+ " with access flags %x", code_offset, access_flags);
return false;
}
@@ -387,8 +391,8 @@ bool DexFileVerifier::CheckPadding(uint32_t offset, uint32_t aligned_offset) {
return false;
}
while (offset < aligned_offset) {
- if (*ptr_ != '\0') {
- LOG(ERROR) << StringPrintf("Non-zero padding %x before section start at %x", *ptr_, offset);
+ if (UNLIKELY(*ptr_ != '\0')) {
+ ErrorStringPrintf("Non-zero padding %x before section start at %x", *ptr_, offset);
return false;
}
ptr_++;
@@ -409,24 +413,24 @@ bool DexFileVerifier::CheckEncodedValue() {
switch (value_type) {
case DexFile::kDexAnnotationByte:
- if (value_arg != 0) {
- LOG(ERROR) << StringPrintf("Bad encoded_value byte size %x", value_arg);
+ if (UNLIKELY(value_arg != 0)) {
+ ErrorStringPrintf("Bad encoded_value byte size %x", value_arg);
return false;
}
ptr_++;
break;
case DexFile::kDexAnnotationShort:
case DexFile::kDexAnnotationChar:
- if (value_arg > 1) {
- LOG(ERROR) << StringPrintf("Bad encoded_value char/short size %x", value_arg);
+ if (UNLIKELY(value_arg > 1)) {
+ ErrorStringPrintf("Bad encoded_value char/short size %x", value_arg);
return false;
}
ptr_ += value_arg + 1;
break;
case DexFile::kDexAnnotationInt:
case DexFile::kDexAnnotationFloat:
- if (value_arg > 3) {
- LOG(ERROR) << StringPrintf("Bad encoded_value int/float size %x", value_arg);
+ if (UNLIKELY(value_arg > 3)) {
+ ErrorStringPrintf("Bad encoded_value int/float size %x", value_arg);
return false;
}
ptr_ += value_arg + 1;
@@ -436,8 +440,8 @@ bool DexFileVerifier::CheckEncodedValue() {
ptr_ += value_arg + 1;
break;
case DexFile::kDexAnnotationString: {
- if (value_arg > 3) {
- LOG(ERROR) << StringPrintf("Bad encoded_value string size %x", value_arg);
+ if (UNLIKELY(value_arg > 3)) {
+ ErrorStringPrintf("Bad encoded_value string size %x", value_arg);
return false;
}
uint32_t idx = ReadUnsignedLittleEndian(value_arg + 1);
@@ -447,8 +451,8 @@ bool DexFileVerifier::CheckEncodedValue() {
break;
}
case DexFile::kDexAnnotationType: {
- if (value_arg > 3) {
- LOG(ERROR) << StringPrintf("Bad encoded_value type size %x", value_arg);
+ if (UNLIKELY(value_arg > 3)) {
+ ErrorStringPrintf("Bad encoded_value type size %x", value_arg);
return false;
}
uint32_t idx = ReadUnsignedLittleEndian(value_arg + 1);
@@ -459,8 +463,8 @@ bool DexFileVerifier::CheckEncodedValue() {
}
case DexFile::kDexAnnotationField:
case DexFile::kDexAnnotationEnum: {
- if (value_arg > 3) {
- LOG(ERROR) << StringPrintf("Bad encoded_value field/enum size %x", value_arg);
+ if (UNLIKELY(value_arg > 3)) {
+ ErrorStringPrintf("Bad encoded_value field/enum size %x", value_arg);
return false;
}
uint32_t idx = ReadUnsignedLittleEndian(value_arg + 1);
@@ -470,8 +474,8 @@ bool DexFileVerifier::CheckEncodedValue() {
break;
}
case DexFile::kDexAnnotationMethod: {
- if (value_arg > 3) {
- LOG(ERROR) << StringPrintf("Bad encoded_value method size %x", value_arg);
+ if (UNLIKELY(value_arg > 3)) {
+ ErrorStringPrintf("Bad encoded_value method size %x", value_arg);
return false;
}
uint32_t idx = ReadUnsignedLittleEndian(value_arg + 1);
@@ -481,8 +485,8 @@ bool DexFileVerifier::CheckEncodedValue() {
break;
}
case DexFile::kDexAnnotationArray:
- if (value_arg != 0) {
- LOG(ERROR) << StringPrintf("Bad encoded_value array value_arg %x", value_arg);
+ if (UNLIKELY(value_arg != 0)) {
+ ErrorStringPrintf("Bad encoded_value array value_arg %x", value_arg);
return false;
}
if (!CheckEncodedArray()) {
@@ -490,8 +494,8 @@ bool DexFileVerifier::CheckEncodedValue() {
}
break;
case DexFile::kDexAnnotationAnnotation:
- if (value_arg != 0) {
- LOG(ERROR) << StringPrintf("Bad encoded_value annotation value_arg %x", value_arg);
+ if (UNLIKELY(value_arg != 0)) {
+ ErrorStringPrintf("Bad encoded_value annotation value_arg %x", value_arg);
return false;
}
if (!CheckEncodedAnnotation()) {
@@ -499,19 +503,19 @@ bool DexFileVerifier::CheckEncodedValue() {
}
break;
case DexFile::kDexAnnotationNull:
- if (value_arg != 0) {
- LOG(ERROR) << StringPrintf("Bad encoded_value null value_arg %x", value_arg);
+ if (UNLIKELY(value_arg != 0)) {
+ ErrorStringPrintf("Bad encoded_value null value_arg %x", value_arg);
return false;
}
break;
case DexFile::kDexAnnotationBoolean:
- if (value_arg > 1) {
- LOG(ERROR) << StringPrintf("Bad encoded_value boolean size %x", value_arg);
+ if (UNLIKELY(value_arg > 1)) {
+ ErrorStringPrintf("Bad encoded_value boolean size %x", value_arg);
return false;
}
break;
default:
- LOG(ERROR) << StringPrintf("Bogus encoded_value value_type %x", value_type);
+ ErrorStringPrintf("Bogus encoded_value value_type %x", value_type);
return false;
}
@@ -523,7 +527,7 @@ bool DexFileVerifier::CheckEncodedArray() {
while (size--) {
if (!CheckEncodedValue()) {
- LOG(ERROR) << "Bad encoded_array value";
+ failure_reason_ = StringPrintf("Bad encoded_array value: %s", failure_reason_.c_str());
return false;
}
}
@@ -545,9 +549,9 @@ bool DexFileVerifier::CheckEncodedAnnotation() {
return false;
}
- if (last_idx >= idx && i != 0) {
- LOG(ERROR) << StringPrintf("Out-of-order annotation_element name_idx: %x then %x",
- last_idx, idx);
+ if (UNLIKELY(last_idx >= idx && i != 0)) {
+ ErrorStringPrintf("Out-of-order annotation_element name_idx: %x then %x",
+ last_idx, idx);
return false;
}
@@ -596,21 +600,22 @@ bool DexFileVerifier::CheckIntraCodeItem() {
return false;
}
- if (code_item->ins_size_ > code_item->registers_size_) {
- LOG(ERROR) << "ins_size (" << code_item->ins_size_ << ") > registers_size ("
- << code_item->registers_size_ << ")";
+ if (UNLIKELY(code_item->ins_size_ > code_item->registers_size_)) {
+ ErrorStringPrintf("ins_size (%ud) > registers_size (%ud)",
+ code_item->ins_size_, code_item->registers_size_);
return false;
}
- if ((code_item->outs_size_ > 5) && (code_item->outs_size_ > code_item->registers_size_)) {
+ if (UNLIKELY((code_item->outs_size_ > 5) &&
+ (code_item->outs_size_ > code_item->registers_size_))) {
/*
* outs_size can be up to 5, even if registers_size is smaller, since the
* short forms of method invocation allow repetitions of a register multiple
* times within a single parameter list. However, longer parameter lists
* need to be represented in-order in the register file.
*/
- LOG(ERROR) << "outs_size (" << code_item->outs_size_ << ") > registers_size ("
- << code_item->registers_size_ << ")";
+ ErrorStringPrintf("outs_size (%ud) > registers_size (%ud)",
+ code_item->outs_size_, code_item->registers_size_);
return false;
}
@@ -629,7 +634,7 @@ bool DexFileVerifier::CheckIntraCodeItem() {
// try_items are 4-byte aligned. Verify the spacer is 0.
if ((((uint32_t) &insns[insns_size] & 3) != 0) && (insns[insns_size] != 0)) {
- LOG(ERROR) << StringPrintf("Non-zero padding: %x", insns[insns_size]);
+ ErrorStringPrintf("Non-zero padding: %x", insns[insns_size]);
return false;
}
@@ -641,8 +646,8 @@ bool DexFileVerifier::CheckIntraCodeItem() {
return false;
}
- if ((handlers_size == 0) || (handlers_size >= 65536)) {
- LOG(ERROR) << "Invalid handlers_size: " << handlers_size;
+ if (UNLIKELY((handlers_size == 0) || (handlers_size >= 65536))) {
+ ErrorStringPrintf("Invalid handlers_size: %ud", handlers_size);
return false;
}
@@ -653,14 +658,13 @@ bool DexFileVerifier::CheckIntraCodeItem() {
uint32_t last_addr = 0;
while (try_items_size--) {
- if (try_items->start_addr_ < last_addr) {
- LOG(ERROR) << StringPrintf("Out-of_order try_item with start_addr: %x",
- try_items->start_addr_);
+ if (UNLIKELY(try_items->start_addr_ < last_addr)) {
+ ErrorStringPrintf("Out-of_order try_item with start_addr: %x", try_items->start_addr_);
return false;
}
- if (try_items->start_addr_ >= insns_size) {
- LOG(ERROR) << StringPrintf("Invalid try_item start_addr: %x", try_items->start_addr_);
+ if (UNLIKELY(try_items->start_addr_ >= insns_size)) {
+ ErrorStringPrintf("Invalid try_item start_addr: %x", try_items->start_addr_);
return false;
}
@@ -671,14 +675,14 @@ bool DexFileVerifier::CheckIntraCodeItem() {
}
}
- if (i == handlers_size) {
- LOG(ERROR) << StringPrintf("Bogus handler offset: %x", try_items->handler_off_);
+ if (UNLIKELY(i == handlers_size)) {
+ ErrorStringPrintf("Bogus handler offset: %x", try_items->handler_off_);
return false;
}
last_addr = try_items->start_addr_ + try_items->insn_count_;
- if (last_addr > insns_size) {
- LOG(ERROR) << StringPrintf("Invalid try_item insn_count: %x", try_items->insn_count_);
+ if (UNLIKELY(last_addr > insns_size)) {
+ ErrorStringPrintf("Invalid try_item insn_count: %x", try_items->insn_count_);
return false;
}
@@ -693,8 +697,8 @@ bool DexFileVerifier::CheckIntraStringDataItem() {
const byte* file_end = begin_ + size_;
for (uint32_t i = 0; i < size; i++) {
- if (ptr_ >= file_end) {
- LOG(ERROR) << "String data would go beyond end-of-file";
+ if (UNLIKELY(ptr_ >= file_end)) {
+ ErrorStringPrintf("String data would go beyond end-of-file");
return false;
}
@@ -704,8 +708,8 @@ bool DexFileVerifier::CheckIntraStringDataItem() {
switch (byte >> 4) {
case 0x00:
// Special case of bit pattern 0xxx.
- if (byte == 0) {
- LOG(ERROR) << StringPrintf("String data shorter than indicated utf16_size %x", size);
+ if (UNLIKELY(byte == 0)) {
+ ErrorStringPrintf("String data shorter than indicated utf16_size %x", size);
return false;
}
break;
@@ -725,19 +729,19 @@ bool DexFileVerifier::CheckIntraStringDataItem() {
case 0x0f:
// Illegal bit patterns 10xx or 1111.
// Note: 1111 is valid for normal UTF-8, but not here.
- LOG(ERROR) << StringPrintf("Illegal start byte %x in string data", byte);
+ ErrorStringPrintf("Illegal start byte %x in string data", byte);
return false;
case 0x0c:
case 0x0d: {
// Bit pattern 110x has an additional byte.
uint8_t byte2 = *(ptr_++);
- if ((byte2 & 0xc0) != 0x80) {
- LOG(ERROR) << StringPrintf("Illegal continuation byte %x in string data", byte2);
+ if (UNLIKELY((byte2 & 0xc0) != 0x80)) {
+ ErrorStringPrintf("Illegal continuation byte %x in string data", byte2);
return false;
}
uint16_t value = ((byte & 0x1f) << 6) | (byte2 & 0x3f);
- if ((value != 0) && (value < 0x80)) {
- LOG(ERROR) << StringPrintf("Illegal representation for value %x in string data", value);
+ if (UNLIKELY((value != 0) && (value < 0x80))) {
+ ErrorStringPrintf("Illegal representation for value %x in string data", value);
return false;
}
break;
@@ -745,18 +749,18 @@ bool DexFileVerifier::CheckIntraStringDataItem() {
case 0x0e: {
// Bit pattern 1110 has 2 additional bytes.
uint8_t byte2 = *(ptr_++);
- if ((byte2 & 0xc0) != 0x80) {
- LOG(ERROR) << StringPrintf("Illegal continuation byte %x in string data", byte2);
+ if (UNLIKELY((byte2 & 0xc0) != 0x80)) {
+ ErrorStringPrintf("Illegal continuation byte %x in string data", byte2);
return false;
}
uint8_t byte3 = *(ptr_++);
- if ((byte3 & 0xc0) != 0x80) {
- LOG(ERROR) << StringPrintf("Illegal continuation byte %x in string data", byte3);
+ if (UNLIKELY((byte3 & 0xc0) != 0x80)) {
+ ErrorStringPrintf("Illegal continuation byte %x in string data", byte3);
return false;
}
uint16_t value = ((byte & 0x0f) << 12) | ((byte2 & 0x3f) << 6) | (byte3 & 0x3f);
- if (value < 0x800) {
- LOG(ERROR) << StringPrintf("Illegal representation for value %x in string data", value);
+ if (UNLIKELY(value < 0x800)) {
+ ErrorStringPrintf("Illegal representation for value %x in string data", value);
return false;
}
break;
@@ -764,8 +768,8 @@ bool DexFileVerifier::CheckIntraStringDataItem() {
}
}
- if (*(ptr_++) != '\0') {
- LOG(ERROR) << StringPrintf("String longer than indicated size %x", size);
+ if (UNLIKELY(*(ptr_++) != '\0')) {
+ ErrorStringPrintf("String longer than indicated size %x", size);
return false;
}
@@ -775,8 +779,8 @@ bool DexFileVerifier::CheckIntraStringDataItem() {
bool DexFileVerifier::CheckIntraDebugInfoItem() {
DecodeUnsignedLeb128(&ptr_);
uint32_t parameters_size = DecodeUnsignedLeb128(&ptr_);
- if (parameters_size > 65536) {
- LOG(ERROR) << StringPrintf("Invalid parameters_size: %x", parameters_size);
+ if (UNLIKELY(parameters_size > 65536)) {
+ ErrorStringPrintf("Invalid parameters_size: %x", parameters_size);
return false;
}
@@ -806,8 +810,8 @@ bool DexFileVerifier::CheckIntraDebugInfoItem() {
}
case DexFile::DBG_START_LOCAL: {
uint32_t reg_num = DecodeUnsignedLeb128(&ptr_);
- if (reg_num >= 65536) {
- LOG(ERROR) << StringPrintf("Bad reg_num for opcode %x", opcode);
+ if (UNLIKELY(reg_num >= 65536)) {
+ ErrorStringPrintf("Bad reg_num for opcode %x", opcode);
return false;
}
uint32_t name_idx = DecodeUnsignedLeb128(&ptr_);
@@ -829,16 +833,16 @@ bool DexFileVerifier::CheckIntraDebugInfoItem() {
case DexFile::DBG_END_LOCAL:
case DexFile::DBG_RESTART_LOCAL: {
uint32_t reg_num = DecodeUnsignedLeb128(&ptr_);
- if (reg_num >= 65536) {
- LOG(ERROR) << StringPrintf("Bad reg_num for opcode %x", opcode);
+ if (UNLIKELY(reg_num >= 65536)) {
+ ErrorStringPrintf("Bad reg_num for opcode %x", opcode);
return false;
}
break;
}
case DexFile::DBG_START_LOCAL_EXTENDED: {
uint32_t reg_num = DecodeUnsignedLeb128(&ptr_);
- if (reg_num >= 65536) {
- LOG(ERROR) << StringPrintf("Bad reg_num for opcode %x", opcode);
+ if (UNLIKELY(reg_num >= 65536)) {
+ ErrorStringPrintf("Bad reg_num for opcode %x", opcode);
return false;
}
uint32_t name_idx = DecodeUnsignedLeb128(&ptr_);
@@ -890,7 +894,7 @@ bool DexFileVerifier::CheckIntraAnnotationItem() {
case DexFile::kDexVisibilitySystem:
break;
default:
- LOG(ERROR) << StringPrintf("Bad annotation visibility: %x", *ptr_);
+ ErrorStringPrintf("Bad annotation visibility: %x", *ptr_);
return false;
}
@@ -918,8 +922,8 @@ bool DexFileVerifier::CheckIntraAnnotationsDirectoryItem() {
uint32_t last_idx = 0;
for (uint32_t i = 0; i < field_count; i++) {
- if (last_idx >= field_item->field_idx_ && i != 0) {
- LOG(ERROR) << StringPrintf("Out-of-order field_idx for annotation: %x then %x", last_idx, field_item->field_idx_);
+ if (UNLIKELY(last_idx >= field_item->field_idx_ && i != 0)) {
+ ErrorStringPrintf("Out-of-order field_idx for annotation: %x then %x", last_idx, field_item->field_idx_);
return false;
}
last_idx = field_item->field_idx_;
@@ -936,9 +940,9 @@ bool DexFileVerifier::CheckIntraAnnotationsDirectoryItem() {
last_idx = 0;
for (uint32_t i = 0; i < method_count; i++) {
- if (last_idx >= method_item->method_idx_ && i != 0) {
- LOG(ERROR) << StringPrintf("Out-of-order method_idx for annotation: %x then %x",
- last_idx, method_item->method_idx_);
+ if (UNLIKELY(last_idx >= method_item->method_idx_ && i != 0)) {
+ ErrorStringPrintf("Out-of-order method_idx for annotation: %x then %x",
+ last_idx, method_item->method_idx_);
return false;
}
last_idx = method_item->method_idx_;
@@ -950,15 +954,15 @@ bool DexFileVerifier::CheckIntraAnnotationsDirectoryItem() {
reinterpret_cast<const DexFile::ParameterAnnotationsItem*>(method_item);
uint32_t parameter_count = item->parameters_size_;
if (!CheckListSize(parameter_item, parameter_count, sizeof(DexFile::ParameterAnnotationsItem),
- "parameter_annotations list")) {
+ "parameter_annotations list")) {
return false;
}
last_idx = 0;
for (uint32_t i = 0; i < parameter_count; i++) {
- if (last_idx >= parameter_item->method_idx_ && i != 0) {
- LOG(ERROR) << StringPrintf("Out-of-order method_idx for annotation: %x then %x",
- last_idx, parameter_item->method_idx_);
+ if (UNLIKELY(last_idx >= parameter_item->method_idx_ && i != 0)) {
+ ErrorStringPrintf("Out-of-order method_idx for annotation: %x then %x",
+ last_idx, parameter_item->method_idx_);
return false;
}
last_idx = parameter_item->method_idx_;
@@ -1059,7 +1063,7 @@ bool DexFileVerifier::CheckIntraSectionIterate(uint32_t offset, uint32_t count,
if (!CheckPointerRange(list, list + 1, "annotation_set_ref_list") ||
!CheckListSize(item, count, sizeof(DexFile::AnnotationSetRefItem),
- "annotation_set_ref_list size")) {
+ "annotation_set_ref_list size")) {
return false;
}
ptr_ = reinterpret_cast<const byte*>(item + count);
@@ -1121,7 +1125,7 @@ bool DexFileVerifier::CheckIntraSectionIterate(uint32_t offset, uint32_t count,
break;
}
default:
- LOG(ERROR) << StringPrintf("Unknown map item type %x", type);
+ ErrorStringPrintf("Unknown map item type %x", type);
return false;
}
@@ -1130,8 +1134,8 @@ bool DexFileVerifier::CheckIntraSectionIterate(uint32_t offset, uint32_t count,
}
aligned_offset = reinterpret_cast<uint32_t>(ptr_) - reinterpret_cast<uint32_t>(begin_);
- if (aligned_offset > size_) {
- LOG(ERROR) << StringPrintf("Item %d at ends out of bounds", i);
+ if (UNLIKELY(aligned_offset > size_)) {
+ ErrorStringPrintf("Item %d at ends out of bounds", i);
return false;
}
@@ -1172,17 +1176,17 @@ bool DexFileVerifier::CheckIntraIdSection(uint32_t offset, uint32_t count, uint1
expected_size = header_->class_defs_size_;
break;
default:
- LOG(ERROR) << StringPrintf("Bad type for id section: %x", type);
+ ErrorStringPrintf("Bad type for id section: %x", type);
return false;
}
// Check that the offset and size are what were expected from the header.
- if (offset != expected_offset) {
- LOG(ERROR) << StringPrintf("Bad offset for section: got %x, expected %x", offset, expected_offset);
+ if (UNLIKELY(offset != expected_offset)) {
+ ErrorStringPrintf("Bad offset for section: got %x, expected %x", offset, expected_offset);
return false;
}
- if (count != expected_size) {
- LOG(ERROR) << StringPrintf("Bad size for section: got %x, expected %x", count, expected_size);
+ if (UNLIKELY(count != expected_size)) {
+ ErrorStringPrintf("Bad size for section: got %x, expected %x", count, expected_size);
return false;
}
@@ -1194,8 +1198,8 @@ bool DexFileVerifier::CheckIntraDataSection(uint32_t offset, uint32_t count, uin
uint32_t data_end = data_start + header_->data_size_;
// Sanity check the offset of the section.
- if ((offset < data_start) || (offset > data_end)) {
- LOG(ERROR) << StringPrintf("Bad offset for data subsection: %x", offset);
+ if (UNLIKELY((offset < data_start) || (offset > data_end))) {
+ ErrorStringPrintf("Bad offset for data subsection: %x", offset);
return false;
}
@@ -1205,7 +1209,7 @@ bool DexFileVerifier::CheckIntraDataSection(uint32_t offset, uint32_t count, uin
uint32_t next_offset = reinterpret_cast<uint32_t>(ptr_) - reinterpret_cast<uint32_t>(begin_);
if (next_offset > data_end) {
- LOG(ERROR) << StringPrintf("Out-of-bounds end of data subsection: %x", next_offset);
+ ErrorStringPrintf("Out-of-bounds end of data subsection: %x", next_offset);
return false;
}
@@ -1229,20 +1233,20 @@ bool DexFileVerifier::CheckIntraSection() {
// Check for padding and overlap between items.
if (!CheckPadding(offset, section_offset)) {
return false;
- } else if (offset > section_offset) {
- LOG(ERROR) << StringPrintf("Section overlap or out-of-order map: %x, %x", offset, section_offset);
+ } else if (UNLIKELY(offset > section_offset)) {
+ ErrorStringPrintf("Section overlap or out-of-order map: %x, %x", offset, section_offset);
return false;
}
// Check each item based on its type.
switch (type) {
case DexFile::kDexTypeHeaderItem:
- if (section_count != 1) {
- LOG(ERROR) << "Multiple header items";
+ if (UNLIKELY(section_count != 1)) {
+ ErrorStringPrintf("Multiple header items");
return false;
}
- if (section_offset != 0) {
- LOG(ERROR) << StringPrintf("Header at %x, not at start of file", section_offset);
+ if (UNLIKELY(section_offset != 0)) {
+ ErrorStringPrintf("Header at %x, not at start of file", section_offset);
return false;
}
ptr_ = begin_ + header_->header_size_;
@@ -1260,13 +1264,13 @@ bool DexFileVerifier::CheckIntraSection() {
offset = reinterpret_cast<uint32_t>(ptr_) - reinterpret_cast<uint32_t>(begin_);
break;
case DexFile::kDexTypeMapList:
- if (section_count != 1) {
- LOG(ERROR) << "Multiple map list items";
+ if (UNLIKELY(section_count != 1)) {
+ ErrorStringPrintf("Multiple map list items");
return false;
}
- if (section_offset != header_->map_off_) {
- LOG(ERROR) << StringPrintf("Map not at header-defined offset: %x, expected %x",
- section_offset, header_->map_off_);
+ if (UNLIKELY(section_offset != header_->map_off_)) {
+ ErrorStringPrintf("Map not at header-defined offset: %x, expected %x",
+ section_offset, header_->map_off_);
return false;
}
ptr_ += sizeof(uint32_t) + (map->size_ * sizeof(DexFile::MapItem));
@@ -1288,7 +1292,7 @@ bool DexFileVerifier::CheckIntraSection() {
offset = reinterpret_cast<uint32_t>(ptr_) - reinterpret_cast<uint32_t>(begin_);
break;
default:
- LOG(ERROR) << StringPrintf("Unknown map item type %x", type);
+ ErrorStringPrintf("Unknown map item type %x", type);
return false;
}
@@ -1300,13 +1304,13 @@ bool DexFileVerifier::CheckIntraSection() {
bool DexFileVerifier::CheckOffsetToTypeMap(uint32_t offset, uint16_t type) {
auto it = offset_to_type_map_.find(offset);
- if (it == offset_to_type_map_.end()) {
- LOG(ERROR) << StringPrintf("No data map entry found @ %x; expected %x", offset, type);
+ if (UNLIKELY(it == offset_to_type_map_.end())) {
+ ErrorStringPrintf("No data map entry found @ %x; expected %x", offset, type);
return false;
}
- if (it->second != type) {
- LOG(ERROR) << StringPrintf("Unexpected data map entry @ %x; expected %x, found %x",
- offset, type, it->second);
+ if (UNLIKELY(it->second != type)) {
+ ErrorStringPrintf("Unexpected data map entry @ %x; expected %x, found %x",
+ offset, type, it->second);
return false;
}
return true;
@@ -1365,8 +1369,8 @@ bool DexFileVerifier::CheckInterStringIdItem() {
const DexFile::StringId* prev_item = reinterpret_cast<const DexFile::StringId*>(previous_item_);
const char* prev_str = dex_file_->GetStringData(*prev_item);
const char* str = dex_file_->GetStringData(*item);
- if (CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues(prev_str, str) >= 0) {
- LOG(ERROR) << StringPrintf("Out-of-order string_ids: '%s' then '%s'", prev_str, str);
+ if (UNLIKELY(CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues(prev_str, str) >= 0)) {
+ ErrorStringPrintf("Out-of-order string_ids: '%s' then '%s'", prev_str, str);
return false;
}
}
@@ -1380,17 +1384,17 @@ bool DexFileVerifier::CheckInterTypeIdItem() {
const char* descriptor = dex_file_->StringDataByIdx(item->descriptor_idx_);
// Check that the descriptor is a valid type.
- if (!IsValidDescriptor(descriptor)) {
- LOG(ERROR) << StringPrintf("Invalid type descriptor: '%s'", descriptor);
+ if (UNLIKELY(!IsValidDescriptor(descriptor))) {
+ ErrorStringPrintf("Invalid type descriptor: '%s'", descriptor);
return false;
}
// Check ordering between items.
if (previous_item_ != NULL) {
const DexFile::TypeId* prev_item = reinterpret_cast<const DexFile::TypeId*>(previous_item_);
- if (prev_item->descriptor_idx_ >= item->descriptor_idx_) {
- LOG(ERROR) << StringPrintf("Out-of-order type_ids: %x then %x",
- prev_item->descriptor_idx_, item->descriptor_idx_);
+ if (UNLIKELY(prev_item->descriptor_idx_ >= item->descriptor_idx_)) {
+ ErrorStringPrintf("Out-of-order type_ids: %x then %x",
+ prev_item->descriptor_idx_, item->descriptor_idx_);
return false;
}
}
@@ -1422,16 +1426,16 @@ bool DexFileVerifier::CheckInterProtoIdItem() {
it.Next();
shorty++;
}
- if (it.HasNext() || *shorty != '\0') {
- LOG(ERROR) << "Mismatched length for parameters and shorty";
+ if (UNLIKELY(it.HasNext() || *shorty != '\0')) {
+ ErrorStringPrintf("Mismatched length for parameters and shorty");
return false;
}
// Check ordering between items. This relies on type_ids being in order.
if (previous_item_ != NULL) {
const DexFile::ProtoId* prev = reinterpret_cast<const DexFile::ProtoId*>(previous_item_);
- if (prev->return_type_idx_ > item->return_type_idx_) {
- LOG(ERROR) << "Out-of-order proto_id return types";
+ if (UNLIKELY(prev->return_type_idx_ > item->return_type_idx_)) {
+ ErrorStringPrintf("Out-of-order proto_id return types");
return false;
} else if (prev->return_type_idx_ == item->return_type_idx_) {
DexFileParameterIterator curr_it(*dex_file_, *item);
@@ -1443,15 +1447,15 @@ bool DexFileVerifier::CheckInterProtoIdItem() {
if (prev_idx == DexFile::kDexNoIndex16) {
break;
}
- if (curr_idx == DexFile::kDexNoIndex16) {
- LOG(ERROR) << "Out-of-order proto_id arguments";
+ if (UNLIKELY(curr_idx == DexFile::kDexNoIndex16)) {
+ ErrorStringPrintf("Out-of-order proto_id arguments");
return false;
}
if (prev_idx < curr_idx) {
break;
- } else if (prev_idx > curr_idx) {
- LOG(ERROR) << "Out-of-order proto_id arguments";
+ } else if (UNLIKELY(prev_idx > curr_idx)) {
+ ErrorStringPrintf("Out-of-order proto_id arguments");
return false;
}
@@ -1470,38 +1474,38 @@ bool DexFileVerifier::CheckInterFieldIdItem() {
// Check that the class descriptor is valid.
const char* descriptor = dex_file_->StringByTypeIdx(item->class_idx_);
- if (!IsValidDescriptor(descriptor) || descriptor[0] != 'L') {
- LOG(ERROR) << "Invalid descriptor for class_idx: '" << descriptor << '"';
+ if (UNLIKELY(!IsValidDescriptor(descriptor) || descriptor[0] != 'L')) {
+ ErrorStringPrintf("Invalid descriptor for class_idx: '%s'", descriptor);
return false;
}
// Check that the type descriptor is a valid field name.
descriptor = dex_file_->StringByTypeIdx(item->type_idx_);
- if (!IsValidDescriptor(descriptor) || descriptor[0] == 'V') {
- LOG(ERROR) << "Invalid descriptor for type_idx: '" << descriptor << '"';
+ if (UNLIKELY(!IsValidDescriptor(descriptor) || descriptor[0] == 'V')) {
+ ErrorStringPrintf("Invalid descriptor for type_idx: '%s'", descriptor);
return false;
}
// Check that the name is valid.
descriptor = dex_file_->StringDataByIdx(item->name_idx_);
- if (!IsValidMemberName(descriptor)) {
- LOG(ERROR) << "Invalid field name: '" << descriptor << '"';
+ if (UNLIKELY(!IsValidMemberName(descriptor))) {
+ ErrorStringPrintf("Invalid field name: '%s'", descriptor);
return false;
}
// Check ordering between items. This relies on the other sections being in order.
if (previous_item_ != NULL) {
const DexFile::FieldId* prev_item = reinterpret_cast<const DexFile::FieldId*>(previous_item_);
- if (prev_item->class_idx_ > item->class_idx_) {
- LOG(ERROR) << "Out-of-order field_ids";
+ if (UNLIKELY(prev_item->class_idx_ > item->class_idx_)) {
+ ErrorStringPrintf("Out-of-order field_ids");
return false;
} else if (prev_item->class_idx_ == item->class_idx_) {
- if (prev_item->name_idx_ > item->name_idx_) {
- LOG(ERROR) << "Out-of-order field_ids";
+ if (UNLIKELY(prev_item->name_idx_ > item->name_idx_)) {
+ ErrorStringPrintf("Out-of-order field_ids");
return false;
} else if (prev_item->name_idx_ == item->name_idx_) {
- if (prev_item->type_idx_ >= item->type_idx_) {
- LOG(ERROR) << "Out-of-order field_ids";
+ if (UNLIKELY(prev_item->type_idx_ >= item->type_idx_)) {
+ ErrorStringPrintf("Out-of-order field_ids");
return false;
}
}
@@ -1517,31 +1521,31 @@ bool DexFileVerifier::CheckInterMethodIdItem() {
// Check that the class descriptor is a valid reference name.
const char* descriptor = dex_file_->StringByTypeIdx(item->class_idx_);
- if (!IsValidDescriptor(descriptor) || (descriptor[0] != 'L' && descriptor[0] != '[')) {
- LOG(ERROR) << "Invalid descriptor for class_idx: '" << descriptor << '"';
+ if (UNLIKELY(!IsValidDescriptor(descriptor) || (descriptor[0] != 'L' && descriptor[0] != '['))) {
+ ErrorStringPrintf("Invalid descriptor for class_idx: '%s'", descriptor);
return false;
}
// Check that the name is valid.
descriptor = dex_file_->StringDataByIdx(item->name_idx_);
- if (!IsValidMemberName(descriptor)) {
- LOG(ERROR) << "Invalid method name: '" << descriptor << '"';
+ if (UNLIKELY(!IsValidMemberName(descriptor))) {
+ ErrorStringPrintf("Invalid method name: '%s'", descriptor);
return false;
}
// Check ordering between items. This relies on the other sections being in order.
if (previous_item_ != NULL) {
const DexFile::MethodId* prev_item = reinterpret_cast<const DexFile::MethodId*>(previous_item_);
- if (prev_item->class_idx_ > item->class_idx_) {
- LOG(ERROR) << "Out-of-order method_ids";
+ if (UNLIKELY(prev_item->class_idx_ > item->class_idx_)) {
+ ErrorStringPrintf("Out-of-order method_ids");
return false;
} else if (prev_item->class_idx_ == item->class_idx_) {
- if (prev_item->name_idx_ > item->name_idx_) {
- LOG(ERROR) << "Out-of-order method_ids";
+ if (UNLIKELY(prev_item->name_idx_ > item->name_idx_)) {
+ ErrorStringPrintf("Out-of-order method_ids");
return false;
} else if (prev_item->name_idx_ == item->name_idx_) {
- if (prev_item->proto_idx_ >= item->proto_idx_) {
- LOG(ERROR) << "Out-of-order method_ids";
+ if (UNLIKELY(prev_item->proto_idx_ >= item->proto_idx_)) {
+ ErrorStringPrintf("Out-of-order method_ids");
return false;
}
}
@@ -1557,8 +1561,8 @@ bool DexFileVerifier::CheckInterClassDefItem() {
uint32_t class_idx = item->class_idx_;
const char* descriptor = dex_file_->StringByTypeIdx(class_idx);
- if (!IsValidDescriptor(descriptor) || descriptor[0] != 'L') {
- LOG(ERROR) << "Invalid class descriptor: '" << descriptor << "'";
+ if (UNLIKELY(!IsValidDescriptor(descriptor) || descriptor[0] != 'L')) {
+ ErrorStringPrintf("Invalid class descriptor: '%s'", descriptor);
return false;
}
@@ -1581,8 +1585,8 @@ bool DexFileVerifier::CheckInterClassDefItem() {
if (item->superclass_idx_ != DexFile::kDexNoIndex16) {
descriptor = dex_file_->StringByTypeIdx(item->superclass_idx_);
- if (!IsValidDescriptor(descriptor) || descriptor[0] != 'L') {
- LOG(ERROR) << "Invalid superclass: '" << descriptor << "'";
+ if (UNLIKELY(!IsValidDescriptor(descriptor) || descriptor[0] != 'L')) {
+ ErrorStringPrintf("Invalid superclass: '%s'", descriptor);
return false;
}
}
@@ -1594,8 +1598,8 @@ bool DexFileVerifier::CheckInterClassDefItem() {
// Ensure that all interfaces refer to classes (not arrays or primitives).
for (uint32_t i = 0; i < size; i++) {
descriptor = dex_file_->StringByTypeIdx(interfaces->GetTypeItem(i).type_idx_);
- if (!IsValidDescriptor(descriptor) || descriptor[0] != 'L') {
- LOG(ERROR) << "Invalid interface: '" << descriptor << "'";
+ if (UNLIKELY(!IsValidDescriptor(descriptor) || descriptor[0] != 'L')) {
+ ErrorStringPrintf("Invalid interface: '%s'", descriptor);
return false;
}
}
@@ -1608,8 +1612,8 @@ bool DexFileVerifier::CheckInterClassDefItem() {
uint32_t idx1 = interfaces->GetTypeItem(i).type_idx_;
for (uint32_t j =0; j < i; j++) {
uint32_t idx2 = interfaces->GetTypeItem(j).type_idx_;
- if (idx1 == idx2) {
- LOG(ERROR) << "Duplicate interface: '" << dex_file_->StringByTypeIdx(idx1) << "'";
+ if (UNLIKELY(idx1 == idx2)) {
+ ErrorStringPrintf("Duplicate interface: '%s'", dex_file_->StringByTypeIdx(idx1));
return false;
}
}
@@ -1620,8 +1624,8 @@ bool DexFileVerifier::CheckInterClassDefItem() {
if (item->class_data_off_ != 0) {
const byte* data = begin_ + item->class_data_off_;
uint16_t data_definer = FindFirstClassDataDefiner(data);
- if ((data_definer != item->class_idx_) && (data_definer != DexFile::kDexNoIndex16)) {
- LOG(ERROR) << "Invalid class_data_item";
+ if (UNLIKELY((data_definer != item->class_idx_) && (data_definer != DexFile::kDexNoIndex16))) {
+ ErrorStringPrintf("Invalid class_data_item");
return false;
}
}
@@ -1630,8 +1634,9 @@ bool DexFileVerifier::CheckInterClassDefItem() {
if (item->annotations_off_ != 0) {
const byte* data = begin_ + item->annotations_off_;
uint16_t annotations_definer = FindFirstAnnotationsDirectoryDefiner(data);
- if ((annotations_definer != item->class_idx_) && (annotations_definer != DexFile::kDexNoIndex16)) {
- LOG(ERROR) << "Invalid annotations_directory_item";
+ if (UNLIKELY((annotations_definer != item->class_idx_) &&
+ (annotations_definer != DexFile::kDexNoIndex16))) {
+ ErrorStringPrintf("Invalid annotations_directory_item");
return false;
}
}
@@ -1675,8 +1680,8 @@ bool DexFileVerifier::CheckInterAnnotationSetItem() {
const uint8_t* data = annotation->annotation_;
uint32_t idx = DecodeUnsignedLeb128(&data);
- if (last_idx >= idx && i != 0) {
- LOG(ERROR) << StringPrintf("Out-of-order entry types: %x then %x", last_idx, idx);
+ if (UNLIKELY(last_idx >= idx && i != 0)) {
+ ErrorStringPrintf("Out-of-order entry types: %x then %x", last_idx, idx);
return false;
}
@@ -1694,8 +1699,8 @@ bool DexFileVerifier::CheckInterClassDataItem() {
for (; it.HasNextStaticField() || it.HasNextInstanceField(); it.Next()) {
const DexFile::FieldId& field = dex_file_->GetFieldId(it.GetMemberIndex());
- if (field.class_idx_ != defining_class) {
- LOG(ERROR) << "Mismatched defining class for class_data_item field";
+ if (UNLIKELY(field.class_idx_ != defining_class)) {
+ ErrorStringPrintf("Mismatched defining class for class_data_item field");
return false;
}
}
@@ -1705,8 +1710,8 @@ bool DexFileVerifier::CheckInterClassDataItem() {
return false;
}
const DexFile::MethodId& method = dex_file_->GetMethodId(it.GetMemberIndex());
- if (method.class_idx_ != defining_class) {
- LOG(ERROR) << "Mismatched defining class for class_data_item method";
+ if (UNLIKELY(method.class_idx_ != defining_class)) {
+ ErrorStringPrintf("Mismatched defining class for class_data_item method");
return false;
}
}
@@ -1731,8 +1736,8 @@ bool DexFileVerifier::CheckInterAnnotationsDirectoryItem() {
uint32_t field_count = item->fields_size_;
for (uint32_t i = 0; i < field_count; i++) {
const DexFile::FieldId& field = dex_file_->GetFieldId(field_item->field_idx_);
- if (field.class_idx_ != defining_class) {
- LOG(ERROR) << "Mismatched defining class for field_annotation";
+ if (UNLIKELY(field.class_idx_ != defining_class)) {
+ ErrorStringPrintf("Mismatched defining class for field_annotation");
return false;
}
if (!CheckOffsetToTypeMap(field_item->annotations_off_, DexFile::kDexTypeAnnotationSetItem)) {
@@ -1747,8 +1752,8 @@ bool DexFileVerifier::CheckInterAnnotationsDirectoryItem() {
uint32_t method_count = item->methods_size_;
for (uint32_t i = 0; i < method_count; i++) {
const DexFile::MethodId& method = dex_file_->GetMethodId(method_item->method_idx_);
- if (method.class_idx_ != defining_class) {
- LOG(ERROR) << "Mismatched defining class for method_annotation";
+ if (UNLIKELY(method.class_idx_ != defining_class)) {
+ ErrorStringPrintf("Mismatched defining class for method_annotation");
return false;
}
if (!CheckOffsetToTypeMap(method_item->annotations_off_, DexFile::kDexTypeAnnotationSetItem)) {
@@ -1763,8 +1768,8 @@ bool DexFileVerifier::CheckInterAnnotationsDirectoryItem() {
uint32_t parameter_count = item->parameters_size_;
for (uint32_t i = 0; i < parameter_count; i++) {
const DexFile::MethodId& parameter_method = dex_file_->GetMethodId(parameter_item->method_idx_);
- if (parameter_method.class_idx_ != defining_class) {
- LOG(ERROR) << "Mismatched defining class for parameter_annotation";
+ if (UNLIKELY(parameter_method.class_idx_ != defining_class)) {
+ ErrorStringPrintf("Mismatched defining class for parameter_annotation");
return false;
}
if (!CheckOffsetToTypeMap(parameter_item->annotations_off_,
@@ -1860,7 +1865,7 @@ bool DexFileVerifier::CheckInterSectionIterate(uint32_t offset, uint32_t count,
break;
}
default:
- LOG(ERROR) << StringPrintf("Unknown map item type %x", type);
+ ErrorStringPrintf("Unknown map item type %x", type);
return false;
}
@@ -1908,7 +1913,7 @@ bool DexFileVerifier::CheckInterSection() {
break;
}
default:
- LOG(ERROR) << StringPrintf("Unknown map item type %x", type);
+ ErrorStringPrintf("Unknown map item type %x", type);
return false;
}
@@ -1942,4 +1947,13 @@ bool DexFileVerifier::Verify() {
return true;
}
+void DexFileVerifier::ErrorStringPrintf(const char* fmt, ...) {
+ va_list ap;
+ va_start(ap, fmt);
+ DCHECK(failure_reason_.empty()) << failure_reason_;
+ failure_reason_ = StringPrintf("Failure to verify dex file '%s': ", location_);
+ StringAppendV(&failure_reason_, fmt, ap);
+ va_end(ap);
+}
+
} // namespace art