• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "dex_file_verifier.h"
18 
19 #include <zlib.h>
20 #include <memory>
21 
22 #include "base/stringprintf.h"
23 #include "dex_file-inl.h"
24 #include "leb128.h"
25 #include "safe_map.h"
26 #include "utf-inl.h"
27 #include "utils.h"
28 
29 namespace art {
30 
MapTypeToBitMask(uint32_t map_type)31 static uint32_t MapTypeToBitMask(uint32_t map_type) {
32   switch (map_type) {
33     case DexFile::kDexTypeHeaderItem:               return 1 << 0;
34     case DexFile::kDexTypeStringIdItem:             return 1 << 1;
35     case DexFile::kDexTypeTypeIdItem:               return 1 << 2;
36     case DexFile::kDexTypeProtoIdItem:              return 1 << 3;
37     case DexFile::kDexTypeFieldIdItem:              return 1 << 4;
38     case DexFile::kDexTypeMethodIdItem:             return 1 << 5;
39     case DexFile::kDexTypeClassDefItem:             return 1 << 6;
40     case DexFile::kDexTypeMapList:                  return 1 << 7;
41     case DexFile::kDexTypeTypeList:                 return 1 << 8;
42     case DexFile::kDexTypeAnnotationSetRefList:     return 1 << 9;
43     case DexFile::kDexTypeAnnotationSetItem:        return 1 << 10;
44     case DexFile::kDexTypeClassDataItem:            return 1 << 11;
45     case DexFile::kDexTypeCodeItem:                 return 1 << 12;
46     case DexFile::kDexTypeStringDataItem:           return 1 << 13;
47     case DexFile::kDexTypeDebugInfoItem:            return 1 << 14;
48     case DexFile::kDexTypeAnnotationItem:           return 1 << 15;
49     case DexFile::kDexTypeEncodedArrayItem:         return 1 << 16;
50     case DexFile::kDexTypeAnnotationsDirectoryItem: return 1 << 17;
51   }
52   return 0;
53 }
54 
IsDataSectionType(uint32_t map_type)55 static bool IsDataSectionType(uint32_t map_type) {
56   switch (map_type) {
57     case DexFile::kDexTypeHeaderItem:
58     case DexFile::kDexTypeStringIdItem:
59     case DexFile::kDexTypeTypeIdItem:
60     case DexFile::kDexTypeProtoIdItem:
61     case DexFile::kDexTypeFieldIdItem:
62     case DexFile::kDexTypeMethodIdItem:
63     case DexFile::kDexTypeClassDefItem:
64       return false;
65   }
66   return true;
67 }
68 
CheckLoadStringByIdx(uint32_t idx,const char * error_string)69 const char* DexFileVerifier::CheckLoadStringByIdx(uint32_t idx, const char* error_string) {
70   if (UNLIKELY(!CheckIndex(idx, dex_file_->NumStringIds(), error_string))) {
71     return nullptr;
72   }
73   return dex_file_->StringDataByIdx(idx);
74 }
75 
CheckLoadStringByTypeIdx(uint32_t type_idx,const char * error_string)76 const char* DexFileVerifier::CheckLoadStringByTypeIdx(uint32_t type_idx, const char* error_string) {
77   if (UNLIKELY(!CheckIndex(type_idx, dex_file_->NumTypeIds(), error_string))) {
78     return nullptr;
79   }
80   const DexFile::TypeId& type_id = dex_file_->GetTypeId(type_idx);
81   uint32_t idx = type_id.descriptor_idx_;
82   return CheckLoadStringByIdx(idx, error_string);
83 }
84 
CheckLoadFieldId(uint32_t idx,const char * error_string)85 const DexFile::FieldId* DexFileVerifier::CheckLoadFieldId(uint32_t idx, const char* error_string) {
86   if (UNLIKELY(!CheckIndex(idx, dex_file_->NumFieldIds(), error_string))) {
87     return nullptr;
88   }
89   return &dex_file_->GetFieldId(idx);
90 }
91 
CheckLoadMethodId(uint32_t idx,const char * err_string)92 const DexFile::MethodId* DexFileVerifier::CheckLoadMethodId(uint32_t idx, const char* err_string) {
93   if (UNLIKELY(!CheckIndex(idx, dex_file_->NumMethodIds(), err_string))) {
94     return nullptr;
95   }
96   return &dex_file_->GetMethodId(idx);
97 }
98 
99 // Helper macro to load string and return false on error.
100 #define LOAD_STRING(var, idx, error)                  \
101   const char* var = CheckLoadStringByIdx(idx, error); \
102   if (UNLIKELY(var == nullptr)) {                     \
103     return false;                                     \
104   }
105 
106 // Helper macro to load string by type idx and return false on error.
107 #define LOAD_STRING_BY_TYPE(var, type_idx, error)              \
108   const char* var = CheckLoadStringByTypeIdx(type_idx, error); \
109   if (UNLIKELY(var == nullptr)) {                              \
110     return false;                                              \
111   }
112 
113 // Helper macro to load method id. Return last parameter on error.
114 #define LOAD_METHOD(var, idx, error_string, error_stmt)                 \
115   const DexFile::MethodId* var  = CheckLoadMethodId(idx, error_string); \
116   if (UNLIKELY(var == nullptr)) {                                       \
117     error_stmt;                                                         \
118   }
119 
120 // Helper macro to load method id. Return last parameter on error.
121 #define LOAD_FIELD(var, idx, fmt, error_stmt)               \
122   const DexFile::FieldId* var = CheckLoadFieldId(idx, fmt); \
123   if (UNLIKELY(var == nullptr)) {                           \
124     error_stmt;                                             \
125   }
126 
Verify(const DexFile * dex_file,const uint8_t * begin,size_t size,const char * location,std::string * error_msg)127 bool DexFileVerifier::Verify(const DexFile* dex_file, const uint8_t* begin, size_t size,
128                              const char* location, std::string* error_msg) {
129   std::unique_ptr<DexFileVerifier> verifier(new DexFileVerifier(dex_file, begin, size, location));
130   if (!verifier->Verify()) {
131     *error_msg = verifier->FailureReason();
132     return false;
133   }
134   return true;
135 }
136 
CheckShortyDescriptorMatch(char shorty_char,const char * descriptor,bool is_return_type)137 bool DexFileVerifier::CheckShortyDescriptorMatch(char shorty_char, const char* descriptor,
138                                                 bool is_return_type) {
139   switch (shorty_char) {
140     case 'V':
141       if (UNLIKELY(!is_return_type)) {
142         ErrorStringPrintf("Invalid use of void");
143         return false;
144       }
145       FALLTHROUGH_INTENDED;
146     case 'B':
147     case 'C':
148     case 'D':
149     case 'F':
150     case 'I':
151     case 'J':
152     case 'S':
153     case 'Z':
154       if (UNLIKELY((descriptor[0] != shorty_char) || (descriptor[1] != '\0'))) {
155         ErrorStringPrintf("Shorty vs. primitive type mismatch: '%c', '%s'",
156                           shorty_char, descriptor);
157         return false;
158       }
159       break;
160     case 'L':
161       if (UNLIKELY((descriptor[0] != 'L') && (descriptor[0] != '['))) {
162         ErrorStringPrintf("Shorty vs. type mismatch: '%c', '%s'", shorty_char, descriptor);
163         return false;
164       }
165       break;
166     default:
167       ErrorStringPrintf("Bad shorty character: '%c'", shorty_char);
168       return false;
169   }
170   return true;
171 }
172 
CheckListSize(const void * start,size_t count,size_t elem_size,const char * label)173 bool DexFileVerifier::CheckListSize(const void* start, size_t count, size_t elem_size,
174                                     const char* label) {
175   // Check that size is not 0.
176   CHECK_NE(elem_size, 0U);
177 
178   const uint8_t* range_start = reinterpret_cast<const uint8_t*>(start);
179   const uint8_t* file_start = reinterpret_cast<const uint8_t*>(begin_);
180 
181   // Check for overflow.
182   uintptr_t max = 0 - 1;
183   size_t available_bytes_till_end_of_mem = max - reinterpret_cast<uintptr_t>(start);
184   size_t max_count = available_bytes_till_end_of_mem / elem_size;
185   if (max_count < count) {
186     ErrorStringPrintf("Overflow in range for %s: %zx for %zu@%zu", label,
187                       static_cast<size_t>(range_start - file_start),
188                       count, elem_size);
189     return false;
190   }
191 
192   const uint8_t* range_end = range_start + count * elem_size;
193   const uint8_t* file_end = file_start + size_;
194   if (UNLIKELY((range_start < file_start) || (range_end > file_end))) {
195     // Note: these two tests are enough as we make sure above that there's no overflow.
196     ErrorStringPrintf("Bad range for %s: %zx to %zx", label,
197                       static_cast<size_t>(range_start - file_start),
198                       static_cast<size_t>(range_end - file_start));
199     return false;
200   }
201   return true;
202 }
203 
CheckList(size_t element_size,const char * label,const uint8_t ** ptr)204 bool DexFileVerifier::CheckList(size_t element_size, const char* label, const uint8_t* *ptr) {
205   // Check that the list is available. The first 4B are the count.
206   if (!CheckListSize(*ptr, 1, 4U, label)) {
207     return false;
208   }
209 
210   uint32_t count = *reinterpret_cast<const uint32_t*>(*ptr);
211   if (count > 0) {
212     if (!CheckListSize(*ptr + 4, count, element_size, label)) {
213       return false;
214     }
215   }
216 
217   *ptr += 4 + count * element_size;
218   return true;
219 }
220 
CheckIndex(uint32_t field,uint32_t limit,const char * label)221 bool DexFileVerifier::CheckIndex(uint32_t field, uint32_t limit, const char* label) {
222   if (UNLIKELY(field >= limit)) {
223     ErrorStringPrintf("Bad index for %s: %x >= %x", label, field, limit);
224     return false;
225   }
226   return true;
227 }
228 
CheckValidOffsetAndSize(uint32_t offset,uint32_t size,const char * label)229 bool DexFileVerifier::CheckValidOffsetAndSize(uint32_t offset, uint32_t size, const char* label) {
230   if (size == 0) {
231     if (offset != 0) {
232       ErrorStringPrintf("Offset(%d) should be zero when size is zero for %s.", offset, label);
233       return false;
234     }
235   }
236   if (size_ <= offset) {
237     ErrorStringPrintf("Offset(%d) should be within file size(%zu) for %s.", offset, size_, label);
238     return false;
239   }
240   return true;
241 }
242 
CheckHeader()243 bool DexFileVerifier::CheckHeader() {
244   // Check file size from the header.
245   uint32_t expected_size = header_->file_size_;
246   if (size_ != expected_size) {
247     ErrorStringPrintf("Bad file size (%zd, expected %ud)", size_, expected_size);
248     return false;
249   }
250 
251   // Compute and verify the checksum in the header.
252   uint32_t adler_checksum = adler32(0L, Z_NULL, 0);
253   const uint32_t non_sum = sizeof(header_->magic_) + sizeof(header_->checksum_);
254   const uint8_t* non_sum_ptr = reinterpret_cast<const uint8_t*>(header_) + non_sum;
255   adler_checksum = adler32(adler_checksum, non_sum_ptr, expected_size - non_sum);
256   if (adler_checksum != header_->checksum_) {
257     ErrorStringPrintf("Bad checksum (%08x, expected %08x)", adler_checksum, header_->checksum_);
258     return false;
259   }
260 
261   // Check the contents of the header.
262   if (header_->endian_tag_ != DexFile::kDexEndianConstant) {
263     ErrorStringPrintf("Unexpected endian_tag: %x", header_->endian_tag_);
264     return false;
265   }
266 
267   if (header_->header_size_ != sizeof(DexFile::Header)) {
268     ErrorStringPrintf("Bad header size: %ud", header_->header_size_);
269     return false;
270   }
271 
272   // Check that all offsets are inside the file.
273   bool result =
274       CheckValidOffsetAndSize(header_->link_off_, header_->link_size_, "link") &&
275       CheckValidOffsetAndSize(header_->map_off_, header_->map_off_, "map") &&
276       CheckValidOffsetAndSize(header_->string_ids_off_, header_->string_ids_size_, "string-ids") &&
277       CheckValidOffsetAndSize(header_->type_ids_off_, header_->type_ids_size_, "type-ids") &&
278       CheckValidOffsetAndSize(header_->proto_ids_off_, header_->proto_ids_size_, "proto-ids") &&
279       CheckValidOffsetAndSize(header_->field_ids_off_, header_->field_ids_size_, "field-ids") &&
280       CheckValidOffsetAndSize(header_->method_ids_off_, header_->method_ids_size_, "method-ids") &&
281       CheckValidOffsetAndSize(header_->class_defs_off_, header_->class_defs_size_, "class-defs") &&
282       CheckValidOffsetAndSize(header_->data_off_, header_->data_size_, "data");
283 
284   return result;
285 }
286 
CheckMap()287 bool DexFileVerifier::CheckMap() {
288   const DexFile::MapList* map = reinterpret_cast<const DexFile::MapList*>(begin_ +
289                                                                           header_->map_off_);
290   // Check that map list content is available.
291   if (!CheckListSize(map, 1, sizeof(DexFile::MapList), "maplist content")) {
292     return false;
293   }
294 
295   const DexFile::MapItem* item = map->list_;
296 
297   uint32_t count = map->size_;
298   uint32_t last_offset = 0;
299   uint32_t data_item_count = 0;
300   uint32_t data_items_left = header_->data_size_;
301   uint32_t used_bits = 0;
302 
303   // Sanity check the size of the map list.
304   if (!CheckListSize(item, count, sizeof(DexFile::MapItem), "map size")) {
305     return false;
306   }
307 
308   // Check the items listed in the map.
309   for (uint32_t i = 0; i < count; i++) {
310     if (UNLIKELY(last_offset >= item->offset_ && i != 0)) {
311       ErrorStringPrintf("Out of order map item: %x then %x", last_offset, item->offset_);
312       return false;
313     }
314     if (UNLIKELY(item->offset_ >= header_->file_size_)) {
315       ErrorStringPrintf("Map item after end of file: %x, size %x",
316                         item->offset_, header_->file_size_);
317       return false;
318     }
319 
320     if (IsDataSectionType(item->type_)) {
321       uint32_t icount = item->size_;
322       if (UNLIKELY(icount > data_items_left)) {
323         ErrorStringPrintf("Too many items in data section: %ud", data_item_count + icount);
324         return false;
325       }
326       data_items_left -= icount;
327       data_item_count += icount;
328     }
329 
330     uint32_t bit = MapTypeToBitMask(item->type_);
331 
332     if (UNLIKELY(bit == 0)) {
333       ErrorStringPrintf("Unknown map section type %x", item->type_);
334       return false;
335     }
336 
337     if (UNLIKELY((used_bits & bit) != 0)) {
338       ErrorStringPrintf("Duplicate map section of type %x", item->type_);
339       return false;
340     }
341 
342     used_bits |= bit;
343     last_offset = item->offset_;
344     item++;
345   }
346 
347   // Check for missing sections in the map.
348   if (UNLIKELY((used_bits & MapTypeToBitMask(DexFile::kDexTypeHeaderItem)) == 0)) {
349     ErrorStringPrintf("Map is missing header entry");
350     return false;
351   }
352   if (UNLIKELY((used_bits & MapTypeToBitMask(DexFile::kDexTypeMapList)) == 0)) {
353     ErrorStringPrintf("Map is missing map_list entry");
354     return false;
355   }
356   if (UNLIKELY((used_bits & MapTypeToBitMask(DexFile::kDexTypeStringIdItem)) == 0 &&
357                ((header_->string_ids_off_ != 0) || (header_->string_ids_size_ != 0)))) {
358     ErrorStringPrintf("Map is missing string_ids entry");
359     return false;
360   }
361   if (UNLIKELY((used_bits & MapTypeToBitMask(DexFile::kDexTypeTypeIdItem)) == 0 &&
362                ((header_->type_ids_off_ != 0) || (header_->type_ids_size_ != 0)))) {
363     ErrorStringPrintf("Map is missing type_ids entry");
364     return false;
365   }
366   if (UNLIKELY((used_bits & MapTypeToBitMask(DexFile::kDexTypeProtoIdItem)) == 0 &&
367                ((header_->proto_ids_off_ != 0) || (header_->proto_ids_size_ != 0)))) {
368     ErrorStringPrintf("Map is missing proto_ids entry");
369     return false;
370   }
371   if (UNLIKELY((used_bits & MapTypeToBitMask(DexFile::kDexTypeFieldIdItem)) == 0 &&
372                ((header_->field_ids_off_ != 0) || (header_->field_ids_size_ != 0)))) {
373     ErrorStringPrintf("Map is missing field_ids entry");
374     return false;
375   }
376   if (UNLIKELY((used_bits & MapTypeToBitMask(DexFile::kDexTypeMethodIdItem)) == 0 &&
377                ((header_->method_ids_off_ != 0) || (header_->method_ids_size_ != 0)))) {
378     ErrorStringPrintf("Map is missing method_ids entry");
379     return false;
380   }
381   if (UNLIKELY((used_bits & MapTypeToBitMask(DexFile::kDexTypeClassDefItem)) == 0 &&
382                ((header_->class_defs_off_ != 0) || (header_->class_defs_size_ != 0)))) {
383     ErrorStringPrintf("Map is missing class_defs entry");
384     return false;
385   }
386   return true;
387 }
388 
ReadUnsignedLittleEndian(uint32_t size)389 uint32_t DexFileVerifier::ReadUnsignedLittleEndian(uint32_t size) {
390   uint32_t result = 0;
391   if (LIKELY(CheckListSize(ptr_, size, sizeof(uint8_t), "encoded_value"))) {
392     for (uint32_t i = 0; i < size; i++) {
393       result |= ((uint32_t) *(ptr_++)) << (i * 8);
394     }
395   }
396   return result;
397 }
398 
CheckAndGetHandlerOffsets(const DexFile::CodeItem * code_item,uint32_t * handler_offsets,uint32_t handlers_size)399 bool DexFileVerifier::CheckAndGetHandlerOffsets(const DexFile::CodeItem* code_item,
400                                                 uint32_t* handler_offsets, uint32_t handlers_size) {
401   const uint8_t* handlers_base = DexFile::GetCatchHandlerData(*code_item, 0);
402 
403   for (uint32_t i = 0; i < handlers_size; i++) {
404     bool catch_all;
405     size_t offset = ptr_ - handlers_base;
406     int32_t size = DecodeSignedLeb128(&ptr_);
407 
408     if (UNLIKELY((size < -65536) || (size > 65536))) {
409       ErrorStringPrintf("Invalid exception handler size: %d", size);
410       return false;
411     }
412 
413     if (size <= 0) {
414       catch_all = true;
415       size = -size;
416     } else {
417       catch_all = false;
418     }
419 
420     handler_offsets[i] = static_cast<uint32_t>(offset);
421 
422     while (size-- > 0) {
423       uint32_t type_idx = DecodeUnsignedLeb128(&ptr_);
424       if (!CheckIndex(type_idx, header_->type_ids_size_, "handler type_idx")) {
425         return false;
426       }
427 
428       uint32_t addr = DecodeUnsignedLeb128(&ptr_);
429       if (UNLIKELY(addr >= code_item->insns_size_in_code_units_)) {
430         ErrorStringPrintf("Invalid handler addr: %x", addr);
431         return false;
432       }
433     }
434 
435     if (catch_all) {
436       uint32_t addr = DecodeUnsignedLeb128(&ptr_);
437       if (UNLIKELY(addr >= code_item->insns_size_in_code_units_)) {
438         ErrorStringPrintf("Invalid handler catch_all_addr: %x", addr);
439         return false;
440       }
441     }
442   }
443 
444   return true;
445 }
446 
CheckClassDataItemField(uint32_t idx,uint32_t access_flags,bool expect_static)447 bool DexFileVerifier::CheckClassDataItemField(uint32_t idx, uint32_t access_flags,
448                                               bool expect_static) {
449   if (!CheckIndex(idx, header_->field_ids_size_, "class_data_item field_idx")) {
450     return false;
451   }
452 
453   bool is_static = (access_flags & kAccStatic) != 0;
454   if (UNLIKELY(is_static != expect_static)) {
455     ErrorStringPrintf("Static/instance field not in expected list");
456     return false;
457   }
458 
459   if (UNLIKELY((access_flags & ~kAccJavaFlagsMask) != 0)) {
460     ErrorStringPrintf("Bad class_data_item field access_flags %x", access_flags);
461     return false;
462   }
463 
464   return true;
465 }
466 
CheckClassDataItemMethod(uint32_t idx,uint32_t access_flags,uint32_t code_offset,bool expect_direct)467 bool DexFileVerifier::CheckClassDataItemMethod(uint32_t idx, uint32_t access_flags,
468                                                uint32_t code_offset, bool expect_direct) {
469   if (!CheckIndex(idx, header_->method_ids_size_, "class_data_item method_idx")) {
470     return false;
471   }
472 
473   bool is_direct = (access_flags & (kAccStatic | kAccPrivate | kAccConstructor)) != 0;
474   bool expect_code = (access_flags & (kAccNative | kAccAbstract)) == 0;
475   bool is_synchronized = (access_flags & kAccSynchronized) != 0;
476   bool allow_synchronized = (access_flags & kAccNative) != 0;
477 
478   if (UNLIKELY(is_direct != expect_direct)) {
479     ErrorStringPrintf("Direct/virtual method not in expected list");
480     return false;
481   }
482 
483   constexpr uint32_t access_method_mask = kAccJavaFlagsMask | kAccConstructor |
484       kAccDeclaredSynchronized;
485   if (UNLIKELY(((access_flags & ~access_method_mask) != 0) ||
486                (is_synchronized && !allow_synchronized))) {
487     ErrorStringPrintf("Bad class_data_item method access_flags %x", access_flags);
488     return false;
489   }
490 
491   if (UNLIKELY(expect_code && (code_offset == 0))) {
492     ErrorStringPrintf("Unexpected zero value for class_data_item method code_off with access "
493                       "flags %x", access_flags);
494     return false;
495   } else if (UNLIKELY(!expect_code && (code_offset != 0))) {
496     ErrorStringPrintf("Unexpected non-zero value %x for class_data_item method code_off"
497                       " with access flags %x", code_offset, access_flags);
498     return false;
499   }
500 
501   return true;
502 }
503 
CheckPadding(size_t offset,uint32_t aligned_offset)504 bool DexFileVerifier::CheckPadding(size_t offset, uint32_t aligned_offset) {
505   if (offset < aligned_offset) {
506     if (!CheckListSize(begin_ + offset, aligned_offset - offset, sizeof(uint8_t), "section")) {
507       return false;
508     }
509     while (offset < aligned_offset) {
510       if (UNLIKELY(*ptr_ != '\0')) {
511         ErrorStringPrintf("Non-zero padding %x before section start at %zx", *ptr_, offset);
512         return false;
513       }
514       ptr_++;
515       offset++;
516     }
517   }
518   return true;
519 }
520 
CheckEncodedValue()521 bool DexFileVerifier::CheckEncodedValue() {
522   if (!CheckListSize(ptr_, 1, sizeof(uint8_t), "encoded_value header")) {
523     return false;
524   }
525 
526   uint8_t header_byte = *(ptr_++);
527   uint32_t value_type = header_byte & DexFile::kDexAnnotationValueTypeMask;
528   uint32_t value_arg = header_byte >> DexFile::kDexAnnotationValueArgShift;
529 
530   switch (value_type) {
531     case DexFile::kDexAnnotationByte:
532       if (UNLIKELY(value_arg != 0)) {
533         ErrorStringPrintf("Bad encoded_value byte size %x", value_arg);
534         return false;
535       }
536       ptr_++;
537       break;
538     case DexFile::kDexAnnotationShort:
539     case DexFile::kDexAnnotationChar:
540       if (UNLIKELY(value_arg > 1)) {
541         ErrorStringPrintf("Bad encoded_value char/short size %x", value_arg);
542         return false;
543       }
544       ptr_ += value_arg + 1;
545       break;
546     case DexFile::kDexAnnotationInt:
547     case DexFile::kDexAnnotationFloat:
548       if (UNLIKELY(value_arg > 3)) {
549         ErrorStringPrintf("Bad encoded_value int/float size %x", value_arg);
550         return false;
551       }
552       ptr_ += value_arg + 1;
553       break;
554     case DexFile::kDexAnnotationLong:
555     case DexFile::kDexAnnotationDouble:
556       ptr_ += value_arg + 1;
557       break;
558     case DexFile::kDexAnnotationString: {
559       if (UNLIKELY(value_arg > 3)) {
560         ErrorStringPrintf("Bad encoded_value string size %x", value_arg);
561         return false;
562       }
563       uint32_t idx = ReadUnsignedLittleEndian(value_arg + 1);
564       if (!CheckIndex(idx, header_->string_ids_size_, "encoded_value string")) {
565         return false;
566       }
567       break;
568     }
569     case DexFile::kDexAnnotationType: {
570       if (UNLIKELY(value_arg > 3)) {
571         ErrorStringPrintf("Bad encoded_value type size %x", value_arg);
572         return false;
573       }
574       uint32_t idx = ReadUnsignedLittleEndian(value_arg + 1);
575       if (!CheckIndex(idx, header_->type_ids_size_, "encoded_value type")) {
576         return false;
577       }
578       break;
579     }
580     case DexFile::kDexAnnotationField:
581     case DexFile::kDexAnnotationEnum: {
582       if (UNLIKELY(value_arg > 3)) {
583         ErrorStringPrintf("Bad encoded_value field/enum size %x", value_arg);
584         return false;
585       }
586       uint32_t idx = ReadUnsignedLittleEndian(value_arg + 1);
587       if (!CheckIndex(idx, header_->field_ids_size_, "encoded_value field")) {
588         return false;
589       }
590       break;
591     }
592     case DexFile::kDexAnnotationMethod: {
593       if (UNLIKELY(value_arg > 3)) {
594         ErrorStringPrintf("Bad encoded_value method size %x", value_arg);
595         return false;
596       }
597       uint32_t idx = ReadUnsignedLittleEndian(value_arg + 1);
598       if (!CheckIndex(idx, header_->method_ids_size_, "encoded_value method")) {
599         return false;
600       }
601       break;
602     }
603     case DexFile::kDexAnnotationArray:
604       if (UNLIKELY(value_arg != 0)) {
605         ErrorStringPrintf("Bad encoded_value array value_arg %x", value_arg);
606         return false;
607       }
608       if (!CheckEncodedArray()) {
609         return false;
610       }
611       break;
612     case DexFile::kDexAnnotationAnnotation:
613       if (UNLIKELY(value_arg != 0)) {
614         ErrorStringPrintf("Bad encoded_value annotation value_arg %x", value_arg);
615         return false;
616       }
617       if (!CheckEncodedAnnotation()) {
618         return false;
619       }
620       break;
621     case DexFile::kDexAnnotationNull:
622       if (UNLIKELY(value_arg != 0)) {
623         ErrorStringPrintf("Bad encoded_value null value_arg %x", value_arg);
624         return false;
625       }
626       break;
627     case DexFile::kDexAnnotationBoolean:
628       if (UNLIKELY(value_arg > 1)) {
629         ErrorStringPrintf("Bad encoded_value boolean size %x", value_arg);
630         return false;
631       }
632       break;
633     default:
634       ErrorStringPrintf("Bogus encoded_value value_type %x", value_type);
635       return false;
636   }
637 
638   return true;
639 }
640 
CheckEncodedArray()641 bool DexFileVerifier::CheckEncodedArray() {
642   uint32_t size = DecodeUnsignedLeb128(&ptr_);
643 
644   while (size--) {
645     if (!CheckEncodedValue()) {
646       failure_reason_ = StringPrintf("Bad encoded_array value: %s", failure_reason_.c_str());
647       return false;
648     }
649   }
650   return true;
651 }
652 
CheckEncodedAnnotation()653 bool DexFileVerifier::CheckEncodedAnnotation() {
654   uint32_t idx = DecodeUnsignedLeb128(&ptr_);
655   if (!CheckIndex(idx, header_->type_ids_size_, "encoded_annotation type_idx")) {
656     return false;
657   }
658 
659   uint32_t size = DecodeUnsignedLeb128(&ptr_);
660   uint32_t last_idx = 0;
661 
662   for (uint32_t i = 0; i < size; i++) {
663     idx = DecodeUnsignedLeb128(&ptr_);
664     if (!CheckIndex(idx, header_->string_ids_size_, "annotation_element name_idx")) {
665       return false;
666     }
667 
668     if (UNLIKELY(last_idx >= idx && i != 0)) {
669       ErrorStringPrintf("Out-of-order annotation_element name_idx: %x then %x",
670                         last_idx, idx);
671       return false;
672     }
673 
674     if (!CheckEncodedValue()) {
675       return false;
676     }
677 
678     last_idx = idx;
679   }
680   return true;
681 }
682 
CheckIntraClassDataItem()683 bool DexFileVerifier::CheckIntraClassDataItem() {
684   ClassDataItemIterator it(*dex_file_, ptr_);
685 
686   // These calls use the raw access flags to check whether the whole dex field is valid.
687   uint32_t prev_index = 0;
688   for (; it.HasNextStaticField(); it.Next()) {
689     uint32_t curr_index = it.GetMemberIndex();
690     if (curr_index < prev_index) {
691       ErrorStringPrintf("out-of-order static field indexes %d and %d", prev_index, curr_index);
692       return false;
693     }
694     prev_index = curr_index;
695     if (!CheckClassDataItemField(curr_index, it.GetRawMemberAccessFlags(), true)) {
696       return false;
697     }
698   }
699   prev_index = 0;
700   for (; it.HasNextInstanceField(); it.Next()) {
701     uint32_t curr_index = it.GetMemberIndex();
702     if (curr_index < prev_index) {
703       ErrorStringPrintf("out-of-order instance field indexes %d and %d", prev_index, curr_index);
704       return false;
705     }
706     prev_index = curr_index;
707     if (!CheckClassDataItemField(curr_index, it.GetRawMemberAccessFlags(), false)) {
708       return false;
709     }
710   }
711   prev_index = 0;
712   for (; it.HasNextDirectMethod(); it.Next()) {
713     uint32_t curr_index = it.GetMemberIndex();
714     if (curr_index < prev_index) {
715       ErrorStringPrintf("out-of-order direct method indexes %d and %d", prev_index, curr_index);
716       return false;
717     }
718     prev_index = curr_index;
719     if (!CheckClassDataItemMethod(curr_index, it.GetRawMemberAccessFlags(),
720         it.GetMethodCodeItemOffset(), true)) {
721       return false;
722     }
723   }
724   prev_index = 0;
725   for (; it.HasNextVirtualMethod(); it.Next()) {
726     uint32_t curr_index = it.GetMemberIndex();
727     if (curr_index < prev_index) {
728       ErrorStringPrintf("out-of-order virtual method indexes %d and %d", prev_index, curr_index);
729       return false;
730     }
731     prev_index = curr_index;
732     if (!CheckClassDataItemMethod(curr_index, it.GetRawMemberAccessFlags(),
733         it.GetMethodCodeItemOffset(), false)) {
734       return false;
735     }
736   }
737 
738   ptr_ = it.EndDataPointer();
739   return true;
740 }
741 
CheckIntraCodeItem()742 bool DexFileVerifier::CheckIntraCodeItem() {
743   const DexFile::CodeItem* code_item = reinterpret_cast<const DexFile::CodeItem*>(ptr_);
744   if (!CheckListSize(code_item, 1, sizeof(DexFile::CodeItem), "code")) {
745     return false;
746   }
747 
748   if (UNLIKELY(code_item->ins_size_ > code_item->registers_size_)) {
749     ErrorStringPrintf("ins_size (%ud) > registers_size (%ud)",
750                       code_item->ins_size_, code_item->registers_size_);
751     return false;
752   }
753 
754   if (UNLIKELY((code_item->outs_size_ > 5) &&
755                (code_item->outs_size_ > code_item->registers_size_))) {
756     /*
757      * outs_size can be up to 5, even if registers_size is smaller, since the
758      * short forms of method invocation allow repetitions of a register multiple
759      * times within a single parameter list. However, longer parameter lists
760      * need to be represented in-order in the register file.
761      */
762     ErrorStringPrintf("outs_size (%ud) > registers_size (%ud)",
763                       code_item->outs_size_, code_item->registers_size_);
764     return false;
765   }
766 
767   const uint16_t* insns = code_item->insns_;
768   uint32_t insns_size = code_item->insns_size_in_code_units_;
769   if (!CheckListSize(insns, insns_size, sizeof(uint16_t), "insns size")) {
770     return false;
771   }
772 
773   // Grab the end of the insns if there are no try_items.
774   uint32_t try_items_size = code_item->tries_size_;
775   if (try_items_size == 0) {
776     ptr_ = reinterpret_cast<const uint8_t*>(&insns[insns_size]);
777     return true;
778   }
779 
780   // try_items are 4-byte aligned. Verify the spacer is 0.
781   if (((reinterpret_cast<uintptr_t>(&insns[insns_size]) & 3) != 0) && (insns[insns_size] != 0)) {
782     ErrorStringPrintf("Non-zero padding: %x", insns[insns_size]);
783     return false;
784   }
785 
786   const DexFile::TryItem* try_items = DexFile::GetTryItems(*code_item, 0);
787   ptr_ = DexFile::GetCatchHandlerData(*code_item, 0);
788   uint32_t handlers_size = DecodeUnsignedLeb128(&ptr_);
789 
790   if (!CheckListSize(try_items, try_items_size, sizeof(DexFile::TryItem), "try_items size")) {
791     return false;
792   }
793 
794   if (UNLIKELY((handlers_size == 0) || (handlers_size >= 65536))) {
795     ErrorStringPrintf("Invalid handlers_size: %ud", handlers_size);
796     return false;
797   }
798 
799   std::unique_ptr<uint32_t[]> handler_offsets(new uint32_t[handlers_size]);
800   if (!CheckAndGetHandlerOffsets(code_item, &handler_offsets[0], handlers_size)) {
801     return false;
802   }
803 
804   uint32_t last_addr = 0;
805   while (try_items_size--) {
806     if (UNLIKELY(try_items->start_addr_ < last_addr)) {
807       ErrorStringPrintf("Out-of_order try_item with start_addr: %x", try_items->start_addr_);
808       return false;
809     }
810 
811     if (UNLIKELY(try_items->start_addr_ >= insns_size)) {
812       ErrorStringPrintf("Invalid try_item start_addr: %x", try_items->start_addr_);
813       return false;
814     }
815 
816     uint32_t i;
817     for (i = 0; i < handlers_size; i++) {
818       if (try_items->handler_off_ == handler_offsets[i]) {
819         break;
820       }
821     }
822 
823     if (UNLIKELY(i == handlers_size)) {
824       ErrorStringPrintf("Bogus handler offset: %x", try_items->handler_off_);
825       return false;
826     }
827 
828     last_addr = try_items->start_addr_ + try_items->insn_count_;
829     if (UNLIKELY(last_addr > insns_size)) {
830       ErrorStringPrintf("Invalid try_item insn_count: %x", try_items->insn_count_);
831       return false;
832     }
833 
834     try_items++;
835   }
836 
837   return true;
838 }
839 
CheckIntraStringDataItem()840 bool DexFileVerifier::CheckIntraStringDataItem() {
841   uint32_t size = DecodeUnsignedLeb128(&ptr_);
842   const uint8_t* file_end = begin_ + size_;
843 
844   for (uint32_t i = 0; i < size; i++) {
845     CHECK_LT(i, size);  // b/15014252 Prevents hitting the impossible case below
846     if (UNLIKELY(ptr_ >= file_end)) {
847       ErrorStringPrintf("String data would go beyond end-of-file");
848       return false;
849     }
850 
851     uint8_t byte = *(ptr_++);
852 
853     // Switch on the high 4 bits.
854     switch (byte >> 4) {
855       case 0x00:
856         // Special case of bit pattern 0xxx.
857         if (UNLIKELY(byte == 0)) {
858           CHECK_LT(i, size);  // b/15014252 Actually hit this impossible case with clang
859           ErrorStringPrintf("String data shorter than indicated utf16_size %x", size);
860           return false;
861         }
862         break;
863       case 0x01:
864       case 0x02:
865       case 0x03:
866       case 0x04:
867       case 0x05:
868       case 0x06:
869       case 0x07:
870         // No extra checks necessary for bit pattern 0xxx.
871         break;
872       case 0x08:
873       case 0x09:
874       case 0x0a:
875       case 0x0b:
876       case 0x0f:
877         // Illegal bit patterns 10xx or 1111.
878         // Note: 1111 is valid for normal UTF-8, but not here.
879         ErrorStringPrintf("Illegal start byte %x in string data", byte);
880         return false;
881       case 0x0c:
882       case 0x0d: {
883         // Bit pattern 110x has an additional byte.
884         uint8_t byte2 = *(ptr_++);
885         if (UNLIKELY((byte2 & 0xc0) != 0x80)) {
886           ErrorStringPrintf("Illegal continuation byte %x in string data", byte2);
887           return false;
888         }
889         uint16_t value = ((byte & 0x1f) << 6) | (byte2 & 0x3f);
890         if (UNLIKELY((value != 0) && (value < 0x80))) {
891           ErrorStringPrintf("Illegal representation for value %x in string data", value);
892           return false;
893         }
894         break;
895       }
896       case 0x0e: {
897         // Bit pattern 1110 has 2 additional bytes.
898         uint8_t byte2 = *(ptr_++);
899         if (UNLIKELY((byte2 & 0xc0) != 0x80)) {
900           ErrorStringPrintf("Illegal continuation byte %x in string data", byte2);
901           return false;
902         }
903         uint8_t byte3 = *(ptr_++);
904         if (UNLIKELY((byte3 & 0xc0) != 0x80)) {
905           ErrorStringPrintf("Illegal continuation byte %x in string data", byte3);
906           return false;
907         }
908         uint16_t value = ((byte & 0x0f) << 12) | ((byte2 & 0x3f) << 6) | (byte3 & 0x3f);
909         if (UNLIKELY(value < 0x800)) {
910           ErrorStringPrintf("Illegal representation for value %x in string data", value);
911           return false;
912         }
913         break;
914       }
915     }
916   }
917 
918   if (UNLIKELY(*(ptr_++) != '\0')) {
919     ErrorStringPrintf("String longer than indicated size %x", size);
920     return false;
921   }
922 
923   return true;
924 }
925 
CheckIntraDebugInfoItem()926 bool DexFileVerifier::CheckIntraDebugInfoItem() {
927   DecodeUnsignedLeb128(&ptr_);
928   uint32_t parameters_size = DecodeUnsignedLeb128(&ptr_);
929   if (UNLIKELY(parameters_size > 65536)) {
930     ErrorStringPrintf("Invalid parameters_size: %x", parameters_size);
931     return false;
932   }
933 
934   for (uint32_t j = 0; j < parameters_size; j++) {
935     uint32_t parameter_name = DecodeUnsignedLeb128(&ptr_);
936     if (parameter_name != 0) {
937       parameter_name--;
938       if (!CheckIndex(parameter_name, header_->string_ids_size_, "debug_info_item parameter_name")) {
939         return false;
940       }
941     }
942   }
943 
944   while (true) {
945     uint8_t opcode = *(ptr_++);
946     switch (opcode) {
947       case DexFile::DBG_END_SEQUENCE: {
948         return true;
949       }
950       case DexFile::DBG_ADVANCE_PC: {
951         DecodeUnsignedLeb128(&ptr_);
952         break;
953       }
954       case DexFile::DBG_ADVANCE_LINE: {
955         DecodeSignedLeb128(&ptr_);
956         break;
957       }
958       case DexFile::DBG_START_LOCAL: {
959         uint32_t reg_num = DecodeUnsignedLeb128(&ptr_);
960         if (UNLIKELY(reg_num >= 65536)) {
961           ErrorStringPrintf("Bad reg_num for opcode %x", opcode);
962           return false;
963         }
964         uint32_t name_idx = DecodeUnsignedLeb128(&ptr_);
965         if (name_idx != 0) {
966           name_idx--;
967           if (!CheckIndex(name_idx, header_->string_ids_size_, "DBG_START_LOCAL name_idx")) {
968             return false;
969           }
970         }
971         uint32_t type_idx = DecodeUnsignedLeb128(&ptr_);
972         if (type_idx != 0) {
973           type_idx--;
974           if (!CheckIndex(type_idx, header_->type_ids_size_, "DBG_START_LOCAL type_idx")) {
975             return false;
976           }
977         }
978         break;
979       }
980       case DexFile::DBG_END_LOCAL:
981       case DexFile::DBG_RESTART_LOCAL: {
982         uint32_t reg_num = DecodeUnsignedLeb128(&ptr_);
983         if (UNLIKELY(reg_num >= 65536)) {
984           ErrorStringPrintf("Bad reg_num for opcode %x", opcode);
985           return false;
986         }
987         break;
988       }
989       case DexFile::DBG_START_LOCAL_EXTENDED: {
990         uint32_t reg_num = DecodeUnsignedLeb128(&ptr_);
991         if (UNLIKELY(reg_num >= 65536)) {
992           ErrorStringPrintf("Bad reg_num for opcode %x", opcode);
993           return false;
994         }
995         uint32_t name_idx = DecodeUnsignedLeb128(&ptr_);
996         if (name_idx != 0) {
997           name_idx--;
998           if (!CheckIndex(name_idx, header_->string_ids_size_, "DBG_START_LOCAL_EXTENDED name_idx")) {
999             return false;
1000           }
1001         }
1002         uint32_t type_idx = DecodeUnsignedLeb128(&ptr_);
1003         if (type_idx != 0) {
1004           type_idx--;
1005           if (!CheckIndex(type_idx, header_->type_ids_size_, "DBG_START_LOCAL_EXTENDED type_idx")) {
1006             return false;
1007           }
1008         }
1009         uint32_t sig_idx = DecodeUnsignedLeb128(&ptr_);
1010         if (sig_idx != 0) {
1011           sig_idx--;
1012           if (!CheckIndex(sig_idx, header_->string_ids_size_, "DBG_START_LOCAL_EXTENDED sig_idx")) {
1013             return false;
1014           }
1015         }
1016         break;
1017       }
1018       case DexFile::DBG_SET_FILE: {
1019         uint32_t name_idx = DecodeUnsignedLeb128(&ptr_);
1020         if (name_idx != 0) {
1021           name_idx--;
1022           if (!CheckIndex(name_idx, header_->string_ids_size_, "DBG_SET_FILE name_idx")) {
1023             return false;
1024           }
1025         }
1026         break;
1027       }
1028     }
1029   }
1030 }
1031 
CheckIntraAnnotationItem()1032 bool DexFileVerifier::CheckIntraAnnotationItem() {
1033   if (!CheckListSize(ptr_, 1, sizeof(uint8_t), "annotation visibility")) {
1034     return false;
1035   }
1036 
1037   // Check visibility
1038   switch (*(ptr_++)) {
1039     case DexFile::kDexVisibilityBuild:
1040     case DexFile::kDexVisibilityRuntime:
1041     case DexFile::kDexVisibilitySystem:
1042       break;
1043     default:
1044       ErrorStringPrintf("Bad annotation visibility: %x", *ptr_);
1045       return false;
1046   }
1047 
1048   if (!CheckEncodedAnnotation()) {
1049     return false;
1050   }
1051 
1052   return true;
1053 }
1054 
CheckIntraAnnotationsDirectoryItem()1055 bool DexFileVerifier::CheckIntraAnnotationsDirectoryItem() {
1056   const DexFile::AnnotationsDirectoryItem* item =
1057       reinterpret_cast<const DexFile::AnnotationsDirectoryItem*>(ptr_);
1058   if (!CheckListSize(item, 1, sizeof(DexFile::AnnotationsDirectoryItem), "annotations_directory")) {
1059     return false;
1060   }
1061 
1062   // Field annotations follow immediately after the annotations directory.
1063   const DexFile::FieldAnnotationsItem* field_item =
1064       reinterpret_cast<const DexFile::FieldAnnotationsItem*>(item + 1);
1065   uint32_t field_count = item->fields_size_;
1066   if (!CheckListSize(field_item, field_count, sizeof(DexFile::FieldAnnotationsItem), "field_annotations list")) {
1067     return false;
1068   }
1069 
1070   uint32_t last_idx = 0;
1071   for (uint32_t i = 0; i < field_count; i++) {
1072     if (UNLIKELY(last_idx >= field_item->field_idx_ && i != 0)) {
1073       ErrorStringPrintf("Out-of-order field_idx for annotation: %x then %x", last_idx, field_item->field_idx_);
1074       return false;
1075     }
1076     last_idx = field_item->field_idx_;
1077     field_item++;
1078   }
1079 
1080   // Method annotations follow immediately after field annotations.
1081   const DexFile::MethodAnnotationsItem* method_item =
1082       reinterpret_cast<const DexFile::MethodAnnotationsItem*>(field_item);
1083   uint32_t method_count = item->methods_size_;
1084   if (!CheckListSize(method_item, method_count, sizeof(DexFile::MethodAnnotationsItem), "method_annotations list")) {
1085     return false;
1086   }
1087 
1088   last_idx = 0;
1089   for (uint32_t i = 0; i < method_count; i++) {
1090     if (UNLIKELY(last_idx >= method_item->method_idx_ && i != 0)) {
1091       ErrorStringPrintf("Out-of-order method_idx for annotation: %x then %x",
1092                        last_idx, method_item->method_idx_);
1093       return false;
1094     }
1095     last_idx = method_item->method_idx_;
1096     method_item++;
1097   }
1098 
1099   // Parameter annotations follow immediately after method annotations.
1100   const DexFile::ParameterAnnotationsItem* parameter_item =
1101       reinterpret_cast<const DexFile::ParameterAnnotationsItem*>(method_item);
1102   uint32_t parameter_count = item->parameters_size_;
1103   if (!CheckListSize(parameter_item, parameter_count, sizeof(DexFile::ParameterAnnotationsItem),
1104                      "parameter_annotations list")) {
1105     return false;
1106   }
1107 
1108   last_idx = 0;
1109   for (uint32_t i = 0; i < parameter_count; i++) {
1110     if (UNLIKELY(last_idx >= parameter_item->method_idx_ && i != 0)) {
1111       ErrorStringPrintf("Out-of-order method_idx for annotation: %x then %x",
1112                         last_idx, parameter_item->method_idx_);
1113       return false;
1114     }
1115     last_idx = parameter_item->method_idx_;
1116     parameter_item++;
1117   }
1118 
1119   // Return a pointer to the end of the annotations.
1120   ptr_ = reinterpret_cast<const uint8_t*>(parameter_item);
1121   return true;
1122 }
1123 
CheckIntraSectionIterate(size_t offset,uint32_t section_count,uint16_t type)1124 bool DexFileVerifier::CheckIntraSectionIterate(size_t offset, uint32_t section_count,
1125                                                uint16_t type) {
1126   // Get the right alignment mask for the type of section.
1127   size_t alignment_mask;
1128   switch (type) {
1129     case DexFile::kDexTypeClassDataItem:
1130     case DexFile::kDexTypeStringDataItem:
1131     case DexFile::kDexTypeDebugInfoItem:
1132     case DexFile::kDexTypeAnnotationItem:
1133     case DexFile::kDexTypeEncodedArrayItem:
1134       alignment_mask = sizeof(uint8_t) - 1;
1135       break;
1136     default:
1137       alignment_mask = sizeof(uint32_t) - 1;
1138       break;
1139   }
1140 
1141   // Iterate through the items in the section.
1142   for (uint32_t i = 0; i < section_count; i++) {
1143     size_t aligned_offset = (offset + alignment_mask) & ~alignment_mask;
1144 
1145     // Check the padding between items.
1146     if (!CheckPadding(offset, aligned_offset)) {
1147       return false;
1148     }
1149 
1150     // Check depending on the section type.
1151     switch (type) {
1152       case DexFile::kDexTypeStringIdItem: {
1153         if (!CheckListSize(ptr_, 1, sizeof(DexFile::StringId), "string_ids")) {
1154           return false;
1155         }
1156         ptr_ += sizeof(DexFile::StringId);
1157         break;
1158       }
1159       case DexFile::kDexTypeTypeIdItem: {
1160         if (!CheckListSize(ptr_, 1, sizeof(DexFile::TypeId), "type_ids")) {
1161           return false;
1162         }
1163         ptr_ += sizeof(DexFile::TypeId);
1164         break;
1165       }
1166       case DexFile::kDexTypeProtoIdItem: {
1167         if (!CheckListSize(ptr_, 1, sizeof(DexFile::ProtoId), "proto_ids")) {
1168           return false;
1169         }
1170         ptr_ += sizeof(DexFile::ProtoId);
1171         break;
1172       }
1173       case DexFile::kDexTypeFieldIdItem: {
1174         if (!CheckListSize(ptr_, 1, sizeof(DexFile::FieldId), "field_ids")) {
1175           return false;
1176         }
1177         ptr_ += sizeof(DexFile::FieldId);
1178         break;
1179       }
1180       case DexFile::kDexTypeMethodIdItem: {
1181         if (!CheckListSize(ptr_, 1, sizeof(DexFile::MethodId), "method_ids")) {
1182           return false;
1183         }
1184         ptr_ += sizeof(DexFile::MethodId);
1185         break;
1186       }
1187       case DexFile::kDexTypeClassDefItem: {
1188         if (!CheckListSize(ptr_, 1, sizeof(DexFile::ClassDef), "class_defs")) {
1189           return false;
1190         }
1191         ptr_ += sizeof(DexFile::ClassDef);
1192         break;
1193       }
1194       case DexFile::kDexTypeTypeList: {
1195         if (!CheckList(sizeof(DexFile::TypeItem), "type_list", &ptr_)) {
1196           return false;
1197         }
1198         break;
1199       }
1200       case DexFile::kDexTypeAnnotationSetRefList: {
1201         if (!CheckList(sizeof(DexFile::AnnotationSetRefItem), "annotation_set_ref_list", &ptr_)) {
1202           return false;
1203         }
1204         break;
1205       }
1206       case DexFile::kDexTypeAnnotationSetItem: {
1207         if (!CheckList(sizeof(uint32_t), "annotation_set_item", &ptr_)) {
1208           return false;
1209         }
1210         break;
1211       }
1212       case DexFile::kDexTypeClassDataItem: {
1213         if (!CheckIntraClassDataItem()) {
1214           return false;
1215         }
1216         break;
1217       }
1218       case DexFile::kDexTypeCodeItem: {
1219         if (!CheckIntraCodeItem()) {
1220           return false;
1221         }
1222         break;
1223       }
1224       case DexFile::kDexTypeStringDataItem: {
1225         if (!CheckIntraStringDataItem()) {
1226           return false;
1227         }
1228         break;
1229       }
1230       case DexFile::kDexTypeDebugInfoItem: {
1231         if (!CheckIntraDebugInfoItem()) {
1232           return false;
1233         }
1234         break;
1235       }
1236       case DexFile::kDexTypeAnnotationItem: {
1237         if (!CheckIntraAnnotationItem()) {
1238           return false;
1239         }
1240         break;
1241       }
1242       case DexFile::kDexTypeEncodedArrayItem: {
1243         if (!CheckEncodedArray()) {
1244           return false;
1245         }
1246         break;
1247       }
1248       case DexFile::kDexTypeAnnotationsDirectoryItem: {
1249         if (!CheckIntraAnnotationsDirectoryItem()) {
1250           return false;
1251         }
1252         break;
1253       }
1254       default:
1255         ErrorStringPrintf("Unknown map item type %x", type);
1256         return false;
1257     }
1258 
1259     if (IsDataSectionType(type)) {
1260       offset_to_type_map_.Put(aligned_offset, type);
1261     }
1262 
1263     aligned_offset = ptr_ - begin_;
1264     if (UNLIKELY(aligned_offset > size_)) {
1265       ErrorStringPrintf("Item %d at ends out of bounds", i);
1266       return false;
1267     }
1268 
1269     offset = aligned_offset;
1270   }
1271 
1272   return true;
1273 }
1274 
CheckIntraIdSection(size_t offset,uint32_t count,uint16_t type)1275 bool DexFileVerifier::CheckIntraIdSection(size_t offset, uint32_t count, uint16_t type) {
1276   uint32_t expected_offset;
1277   uint32_t expected_size;
1278 
1279   // Get the expected offset and size from the header.
1280   switch (type) {
1281     case DexFile::kDexTypeStringIdItem:
1282       expected_offset = header_->string_ids_off_;
1283       expected_size = header_->string_ids_size_;
1284       break;
1285     case DexFile::kDexTypeTypeIdItem:
1286       expected_offset = header_->type_ids_off_;
1287       expected_size = header_->type_ids_size_;
1288       break;
1289     case DexFile::kDexTypeProtoIdItem:
1290       expected_offset = header_->proto_ids_off_;
1291       expected_size = header_->proto_ids_size_;
1292       break;
1293     case DexFile::kDexTypeFieldIdItem:
1294       expected_offset = header_->field_ids_off_;
1295       expected_size = header_->field_ids_size_;
1296       break;
1297     case DexFile::kDexTypeMethodIdItem:
1298       expected_offset = header_->method_ids_off_;
1299       expected_size = header_->method_ids_size_;
1300       break;
1301     case DexFile::kDexTypeClassDefItem:
1302       expected_offset = header_->class_defs_off_;
1303       expected_size = header_->class_defs_size_;
1304       break;
1305     default:
1306       ErrorStringPrintf("Bad type for id section: %x", type);
1307       return false;
1308   }
1309 
1310   // Check that the offset and size are what were expected from the header.
1311   if (UNLIKELY(offset != expected_offset)) {
1312     ErrorStringPrintf("Bad offset for section: got %zx, expected %x", offset, expected_offset);
1313     return false;
1314   }
1315   if (UNLIKELY(count != expected_size)) {
1316     ErrorStringPrintf("Bad size for section: got %x, expected %x", count, expected_size);
1317     return false;
1318   }
1319 
1320   return CheckIntraSectionIterate(offset, count, type);
1321 }
1322 
CheckIntraDataSection(size_t offset,uint32_t count,uint16_t type)1323 bool DexFileVerifier::CheckIntraDataSection(size_t offset, uint32_t count, uint16_t type) {
1324   size_t data_start = header_->data_off_;
1325   size_t data_end = data_start + header_->data_size_;
1326 
1327   // Sanity check the offset of the section.
1328   if (UNLIKELY((offset < data_start) || (offset > data_end))) {
1329     ErrorStringPrintf("Bad offset for data subsection: %zx", offset);
1330     return false;
1331   }
1332 
1333   if (!CheckIntraSectionIterate(offset, count, type)) {
1334     return false;
1335   }
1336 
1337   size_t next_offset = ptr_ - begin_;
1338   if (next_offset > data_end) {
1339     ErrorStringPrintf("Out-of-bounds end of data subsection: %zx", next_offset);
1340     return false;
1341   }
1342 
1343   return true;
1344 }
1345 
CheckIntraSection()1346 bool DexFileVerifier::CheckIntraSection() {
1347   const DexFile::MapList* map = reinterpret_cast<const DexFile::MapList*>(begin_ + header_->map_off_);
1348   const DexFile::MapItem* item = map->list_;
1349 
1350   uint32_t count = map->size_;
1351   size_t offset = 0;
1352   ptr_ = begin_;
1353 
1354   // Check the items listed in the map.
1355   while (count--) {
1356     uint32_t section_offset = item->offset_;
1357     uint32_t section_count = item->size_;
1358     uint16_t type = item->type_;
1359 
1360     // Check for padding and overlap between items.
1361     if (!CheckPadding(offset, section_offset)) {
1362       return false;
1363     } else if (UNLIKELY(offset > section_offset)) {
1364       ErrorStringPrintf("Section overlap or out-of-order map: %zx, %x", offset, section_offset);
1365       return false;
1366     }
1367 
1368     // Check each item based on its type.
1369     switch (type) {
1370       case DexFile::kDexTypeHeaderItem:
1371         if (UNLIKELY(section_count != 1)) {
1372           ErrorStringPrintf("Multiple header items");
1373           return false;
1374         }
1375         if (UNLIKELY(section_offset != 0)) {
1376           ErrorStringPrintf("Header at %x, not at start of file", section_offset);
1377           return false;
1378         }
1379         ptr_ = begin_ + header_->header_size_;
1380         offset = header_->header_size_;
1381         break;
1382       case DexFile::kDexTypeStringIdItem:
1383       case DexFile::kDexTypeTypeIdItem:
1384       case DexFile::kDexTypeProtoIdItem:
1385       case DexFile::kDexTypeFieldIdItem:
1386       case DexFile::kDexTypeMethodIdItem:
1387       case DexFile::kDexTypeClassDefItem:
1388         if (!CheckIntraIdSection(section_offset, section_count, type)) {
1389           return false;
1390         }
1391         offset = ptr_ - begin_;
1392         break;
1393       case DexFile::kDexTypeMapList:
1394         if (UNLIKELY(section_count != 1)) {
1395           ErrorStringPrintf("Multiple map list items");
1396           return false;
1397         }
1398         if (UNLIKELY(section_offset != header_->map_off_)) {
1399           ErrorStringPrintf("Map not at header-defined offset: %x, expected %x",
1400                             section_offset, header_->map_off_);
1401           return false;
1402         }
1403         ptr_ += sizeof(uint32_t) + (map->size_ * sizeof(DexFile::MapItem));
1404         offset = section_offset + sizeof(uint32_t) + (map->size_ * sizeof(DexFile::MapItem));
1405         break;
1406       case DexFile::kDexTypeTypeList:
1407       case DexFile::kDexTypeAnnotationSetRefList:
1408       case DexFile::kDexTypeAnnotationSetItem:
1409       case DexFile::kDexTypeClassDataItem:
1410       case DexFile::kDexTypeCodeItem:
1411       case DexFile::kDexTypeStringDataItem:
1412       case DexFile::kDexTypeDebugInfoItem:
1413       case DexFile::kDexTypeAnnotationItem:
1414       case DexFile::kDexTypeEncodedArrayItem:
1415       case DexFile::kDexTypeAnnotationsDirectoryItem:
1416         if (!CheckIntraDataSection(section_offset, section_count, type)) {
1417           return false;
1418         }
1419         offset = ptr_ - begin_;
1420         break;
1421       default:
1422         ErrorStringPrintf("Unknown map item type %x", type);
1423         return false;
1424     }
1425 
1426     item++;
1427   }
1428 
1429   return true;
1430 }
1431 
CheckOffsetToTypeMap(size_t offset,uint16_t type)1432 bool DexFileVerifier::CheckOffsetToTypeMap(size_t offset, uint16_t type) {
1433   auto it = offset_to_type_map_.find(offset);
1434   if (UNLIKELY(it == offset_to_type_map_.end())) {
1435     ErrorStringPrintf("No data map entry found @ %zx; expected %x", offset, type);
1436     return false;
1437   }
1438   if (UNLIKELY(it->second != type)) {
1439     ErrorStringPrintf("Unexpected data map entry @ %zx; expected %x, found %x",
1440                       offset, type, it->second);
1441     return false;
1442   }
1443   return true;
1444 }
1445 
FindFirstClassDataDefiner(const uint8_t * ptr,bool * success)1446 uint16_t DexFileVerifier::FindFirstClassDataDefiner(const uint8_t* ptr, bool* success) {
1447   ClassDataItemIterator it(*dex_file_, ptr);
1448   *success = true;
1449 
1450   if (it.HasNextStaticField() || it.HasNextInstanceField()) {
1451     LOAD_FIELD(field, it.GetMemberIndex(), "first_class_data_definer field_id",
1452                *success = false; return DexFile::kDexNoIndex16)
1453     return field->class_idx_;
1454   }
1455 
1456   if (it.HasNextDirectMethod() || it.HasNextVirtualMethod()) {
1457     LOAD_METHOD(method, it.GetMemberIndex(), "first_class_data_definer method_id",
1458                 *success = false; return DexFile::kDexNoIndex16)
1459     return method->class_idx_;
1460   }
1461 
1462   return DexFile::kDexNoIndex16;
1463 }
1464 
FindFirstAnnotationsDirectoryDefiner(const uint8_t * ptr,bool * success)1465 uint16_t DexFileVerifier::FindFirstAnnotationsDirectoryDefiner(const uint8_t* ptr, bool* success) {
1466   const DexFile::AnnotationsDirectoryItem* item =
1467       reinterpret_cast<const DexFile::AnnotationsDirectoryItem*>(ptr);
1468   *success = true;
1469 
1470   if (item->fields_size_ != 0) {
1471     DexFile::FieldAnnotationsItem* field_items = (DexFile::FieldAnnotationsItem*) (item + 1);
1472     LOAD_FIELD(field, field_items[0].field_idx_, "first_annotations_dir_definer field_id",
1473                *success = false; return DexFile::kDexNoIndex16)
1474     return field->class_idx_;
1475   }
1476 
1477   if (item->methods_size_ != 0) {
1478     DexFile::MethodAnnotationsItem* method_items = (DexFile::MethodAnnotationsItem*) (item + 1);
1479     LOAD_METHOD(method, method_items[0].method_idx_, "first_annotations_dir_definer method id",
1480                 *success = false; return DexFile::kDexNoIndex16)
1481     return method->class_idx_;
1482   }
1483 
1484   if (item->parameters_size_ != 0) {
1485     DexFile::ParameterAnnotationsItem* parameter_items = (DexFile::ParameterAnnotationsItem*) (item + 1);
1486     LOAD_METHOD(method, parameter_items[0].method_idx_, "first_annotations_dir_definer method id",
1487                 *success = false; return DexFile::kDexNoIndex16)
1488     return method->class_idx_;
1489   }
1490 
1491   return DexFile::kDexNoIndex16;
1492 }
1493 
CheckInterStringIdItem()1494 bool DexFileVerifier::CheckInterStringIdItem() {
1495   const DexFile::StringId* item = reinterpret_cast<const DexFile::StringId*>(ptr_);
1496 
1497   // Check the map to make sure it has the right offset->type.
1498   if (!CheckOffsetToTypeMap(item->string_data_off_, DexFile::kDexTypeStringDataItem)) {
1499     return false;
1500   }
1501 
1502   // Check ordering between items.
1503   if (previous_item_ != nullptr) {
1504     const DexFile::StringId* prev_item = reinterpret_cast<const DexFile::StringId*>(previous_item_);
1505     const char* prev_str = dex_file_->GetStringData(*prev_item);
1506     const char* str = dex_file_->GetStringData(*item);
1507     if (UNLIKELY(CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues(prev_str, str) >= 0)) {
1508       ErrorStringPrintf("Out-of-order string_ids: '%s' then '%s'", prev_str, str);
1509       return false;
1510     }
1511   }
1512 
1513   ptr_ += sizeof(DexFile::StringId);
1514   return true;
1515 }
1516 
CheckInterTypeIdItem()1517 bool DexFileVerifier::CheckInterTypeIdItem() {
1518   const DexFile::TypeId* item = reinterpret_cast<const DexFile::TypeId*>(ptr_);
1519 
1520   LOAD_STRING(descriptor, item->descriptor_idx_, "inter_type_id_item descriptor_idx")
1521 
1522   // Check that the descriptor is a valid type.
1523   if (UNLIKELY(!IsValidDescriptor(descriptor))) {
1524     ErrorStringPrintf("Invalid type descriptor: '%s'", descriptor);
1525     return false;
1526   }
1527 
1528   // Check ordering between items.
1529   if (previous_item_ != nullptr) {
1530     const DexFile::TypeId* prev_item = reinterpret_cast<const DexFile::TypeId*>(previous_item_);
1531     if (UNLIKELY(prev_item->descriptor_idx_ >= item->descriptor_idx_)) {
1532       ErrorStringPrintf("Out-of-order type_ids: %x then %x",
1533                         prev_item->descriptor_idx_, item->descriptor_idx_);
1534       return false;
1535     }
1536   }
1537 
1538   ptr_ += sizeof(DexFile::TypeId);
1539   return true;
1540 }
1541 
CheckInterProtoIdItem()1542 bool DexFileVerifier::CheckInterProtoIdItem() {
1543   const DexFile::ProtoId* item = reinterpret_cast<const DexFile::ProtoId*>(ptr_);
1544 
1545   LOAD_STRING(shorty, item->shorty_idx_, "inter_proto_id_item shorty_idx")
1546 
1547   if (item->parameters_off_ != 0 &&
1548       !CheckOffsetToTypeMap(item->parameters_off_, DexFile::kDexTypeTypeList)) {
1549     return false;
1550   }
1551 
1552   // Check the return type and advance the shorty.
1553   LOAD_STRING_BY_TYPE(return_type, item->return_type_idx_, "inter_proto_id_item return_type_idx")
1554   if (!CheckShortyDescriptorMatch(*shorty, return_type, true)) {
1555     return false;
1556   }
1557   shorty++;
1558 
1559   DexFileParameterIterator it(*dex_file_, *item);
1560   while (it.HasNext() && *shorty != '\0') {
1561     if (!CheckIndex(it.GetTypeIdx(), dex_file_->NumTypeIds(),
1562                     "inter_proto_id_item shorty type_idx")) {
1563       return false;
1564     }
1565     const char* descriptor = it.GetDescriptor();
1566     if (!CheckShortyDescriptorMatch(*shorty, descriptor, false)) {
1567       return false;
1568     }
1569     it.Next();
1570     shorty++;
1571   }
1572   if (UNLIKELY(it.HasNext() || *shorty != '\0')) {
1573     ErrorStringPrintf("Mismatched length for parameters and shorty");
1574     return false;
1575   }
1576 
1577   // Check ordering between items. This relies on type_ids being in order.
1578   if (previous_item_ != nullptr) {
1579     const DexFile::ProtoId* prev = reinterpret_cast<const DexFile::ProtoId*>(previous_item_);
1580     if (UNLIKELY(prev->return_type_idx_ > item->return_type_idx_)) {
1581       ErrorStringPrintf("Out-of-order proto_id return types");
1582       return false;
1583     } else if (prev->return_type_idx_ == item->return_type_idx_) {
1584       DexFileParameterIterator curr_it(*dex_file_, *item);
1585       DexFileParameterIterator prev_it(*dex_file_, *prev);
1586 
1587       while (curr_it.HasNext() && prev_it.HasNext()) {
1588         uint16_t prev_idx = prev_it.GetTypeIdx();
1589         uint16_t curr_idx = curr_it.GetTypeIdx();
1590         if (prev_idx == DexFile::kDexNoIndex16) {
1591           break;
1592         }
1593         if (UNLIKELY(curr_idx == DexFile::kDexNoIndex16)) {
1594           ErrorStringPrintf("Out-of-order proto_id arguments");
1595           return false;
1596         }
1597 
1598         if (prev_idx < curr_idx) {
1599           break;
1600         } else if (UNLIKELY(prev_idx > curr_idx)) {
1601           ErrorStringPrintf("Out-of-order proto_id arguments");
1602           return false;
1603         }
1604 
1605         prev_it.Next();
1606         curr_it.Next();
1607       }
1608     }
1609   }
1610 
1611   ptr_ += sizeof(DexFile::ProtoId);
1612   return true;
1613 }
1614 
CheckInterFieldIdItem()1615 bool DexFileVerifier::CheckInterFieldIdItem() {
1616   const DexFile::FieldId* item = reinterpret_cast<const DexFile::FieldId*>(ptr_);
1617 
1618   // Check that the class descriptor is valid.
1619   LOAD_STRING_BY_TYPE(class_descriptor, item->class_idx_, "inter_field_id_item class_idx")
1620   if (UNLIKELY(!IsValidDescriptor(class_descriptor) || class_descriptor[0] != 'L')) {
1621     ErrorStringPrintf("Invalid descriptor for class_idx: '%s'", class_descriptor);
1622     return false;
1623   }
1624 
1625   // Check that the type descriptor is a valid field name.
1626   LOAD_STRING_BY_TYPE(type_descriptor, item->type_idx_, "inter_field_id_item type_idx")
1627   if (UNLIKELY(!IsValidDescriptor(type_descriptor) || type_descriptor[0] == 'V')) {
1628     ErrorStringPrintf("Invalid descriptor for type_idx: '%s'", type_descriptor);
1629     return false;
1630   }
1631 
1632   // Check that the name is valid.
1633   LOAD_STRING(descriptor, item->name_idx_, "inter_field_id_item name_idx")
1634   if (UNLIKELY(!IsValidMemberName(descriptor))) {
1635     ErrorStringPrintf("Invalid field name: '%s'", descriptor);
1636     return false;
1637   }
1638 
1639   // Check ordering between items. This relies on the other sections being in order.
1640   if (previous_item_ != nullptr) {
1641     const DexFile::FieldId* prev_item = reinterpret_cast<const DexFile::FieldId*>(previous_item_);
1642     if (UNLIKELY(prev_item->class_idx_ > item->class_idx_)) {
1643       ErrorStringPrintf("Out-of-order field_ids");
1644       return false;
1645     } else if (prev_item->class_idx_ == item->class_idx_) {
1646       if (UNLIKELY(prev_item->name_idx_ > item->name_idx_)) {
1647         ErrorStringPrintf("Out-of-order field_ids");
1648         return false;
1649       } else if (prev_item->name_idx_ == item->name_idx_) {
1650         if (UNLIKELY(prev_item->type_idx_ >= item->type_idx_)) {
1651           ErrorStringPrintf("Out-of-order field_ids");
1652           return false;
1653         }
1654       }
1655     }
1656   }
1657 
1658   ptr_ += sizeof(DexFile::FieldId);
1659   return true;
1660 }
1661 
CheckInterMethodIdItem()1662 bool DexFileVerifier::CheckInterMethodIdItem() {
1663   const DexFile::MethodId* item = reinterpret_cast<const DexFile::MethodId*>(ptr_);
1664 
1665   // Check that the class descriptor is a valid reference name.
1666   LOAD_STRING_BY_TYPE(class_descriptor, item->class_idx_, "inter_method_id_item class_idx")
1667   if (UNLIKELY(!IsValidDescriptor(class_descriptor) || (class_descriptor[0] != 'L' &&
1668                                                         class_descriptor[0] != '['))) {
1669     ErrorStringPrintf("Invalid descriptor for class_idx: '%s'", class_descriptor);
1670     return false;
1671   }
1672 
1673   // Check that the name is valid.
1674   LOAD_STRING(descriptor, item->name_idx_, "inter_method_id_item name_idx")
1675   if (UNLIKELY(!IsValidMemberName(descriptor))) {
1676     ErrorStringPrintf("Invalid method name: '%s'", descriptor);
1677     return false;
1678   }
1679 
1680   // Check that the proto id is valid.
1681   if (UNLIKELY(!CheckIndex(item->proto_idx_, dex_file_->NumProtoIds(),
1682                            "inter_method_id_item proto_idx"))) {
1683     return false;
1684   }
1685 
1686   // Check ordering between items. This relies on the other sections being in order.
1687   if (previous_item_ != nullptr) {
1688     const DexFile::MethodId* prev_item = reinterpret_cast<const DexFile::MethodId*>(previous_item_);
1689     if (UNLIKELY(prev_item->class_idx_ > item->class_idx_)) {
1690       ErrorStringPrintf("Out-of-order method_ids");
1691       return false;
1692     } else if (prev_item->class_idx_ == item->class_idx_) {
1693       if (UNLIKELY(prev_item->name_idx_ > item->name_idx_)) {
1694         ErrorStringPrintf("Out-of-order method_ids");
1695         return false;
1696       } else if (prev_item->name_idx_ == item->name_idx_) {
1697         if (UNLIKELY(prev_item->proto_idx_ >= item->proto_idx_)) {
1698           ErrorStringPrintf("Out-of-order method_ids");
1699           return false;
1700         }
1701       }
1702     }
1703   }
1704 
1705   ptr_ += sizeof(DexFile::MethodId);
1706   return true;
1707 }
1708 
CheckInterClassDefItem()1709 bool DexFileVerifier::CheckInterClassDefItem() {
1710   const DexFile::ClassDef* item = reinterpret_cast<const DexFile::ClassDef*>(ptr_);
1711 
1712   // Check for duplicate class def.
1713   if (defined_classes_.find(item->class_idx_) != defined_classes_.end()) {
1714     ErrorStringPrintf("Redefinition of class with type idx: '%d'", item->class_idx_);
1715     return false;
1716   }
1717   defined_classes_.insert(item->class_idx_);
1718 
1719   LOAD_STRING_BY_TYPE(class_descriptor, item->class_idx_, "inter_class_def_item class_idx")
1720   if (UNLIKELY(!IsValidDescriptor(class_descriptor) || class_descriptor[0] != 'L')) {
1721     ErrorStringPrintf("Invalid class descriptor: '%s'", class_descriptor);
1722     return false;
1723   }
1724 
1725   // Only allow non-runtime modifiers.
1726   if ((item->access_flags_ & ~kAccJavaFlagsMask) != 0) {
1727     ErrorStringPrintf("Invalid class flags: '%d'", item->access_flags_);
1728     return false;
1729   }
1730 
1731   if (item->interfaces_off_ != 0 &&
1732       !CheckOffsetToTypeMap(item->interfaces_off_, DexFile::kDexTypeTypeList)) {
1733     return false;
1734   }
1735   if (item->annotations_off_ != 0 &&
1736       !CheckOffsetToTypeMap(item->annotations_off_, DexFile::kDexTypeAnnotationsDirectoryItem)) {
1737     return false;
1738   }
1739   if (item->class_data_off_ != 0 &&
1740       !CheckOffsetToTypeMap(item->class_data_off_, DexFile::kDexTypeClassDataItem)) {
1741     return false;
1742   }
1743   if (item->static_values_off_ != 0 &&
1744       !CheckOffsetToTypeMap(item->static_values_off_, DexFile::kDexTypeEncodedArrayItem)) {
1745     return false;
1746   }
1747 
1748   if (item->superclass_idx_ != DexFile::kDexNoIndex16) {
1749     LOAD_STRING_BY_TYPE(superclass_descriptor, item->superclass_idx_,
1750                         "inter_class_def_item superclass_idx")
1751     if (UNLIKELY(!IsValidDescriptor(superclass_descriptor) || superclass_descriptor[0] != 'L')) {
1752       ErrorStringPrintf("Invalid superclass: '%s'", superclass_descriptor);
1753       return false;
1754     }
1755   }
1756 
1757   const DexFile::TypeList* interfaces = dex_file_->GetInterfacesList(*item);
1758   if (interfaces != nullptr) {
1759     uint32_t size = interfaces->Size();
1760 
1761     // Ensure that all interfaces refer to classes (not arrays or primitives).
1762     for (uint32_t i = 0; i < size; i++) {
1763       LOAD_STRING_BY_TYPE(inf_descriptor, interfaces->GetTypeItem(i).type_idx_,
1764                           "inter_class_def_item interface type_idx")
1765       if (UNLIKELY(!IsValidDescriptor(inf_descriptor) || inf_descriptor[0] != 'L')) {
1766         ErrorStringPrintf("Invalid interface: '%s'", inf_descriptor);
1767         return false;
1768       }
1769     }
1770 
1771     /*
1772      * Ensure that there are no duplicates. This is an O(N^2) test, but in
1773      * practice the number of interfaces implemented by any given class is low.
1774      */
1775     for (uint32_t i = 1; i < size; i++) {
1776       uint32_t idx1 = interfaces->GetTypeItem(i).type_idx_;
1777       for (uint32_t j =0; j < i; j++) {
1778         uint32_t idx2 = interfaces->GetTypeItem(j).type_idx_;
1779         if (UNLIKELY(idx1 == idx2)) {
1780           ErrorStringPrintf("Duplicate interface: '%s'", dex_file_->StringByTypeIdx(idx1));
1781           return false;
1782         }
1783       }
1784     }
1785   }
1786 
1787   // Check that references in class_data_item are to the right class.
1788   if (item->class_data_off_ != 0) {
1789     const uint8_t* data = begin_ + item->class_data_off_;
1790     bool success;
1791     uint16_t data_definer = FindFirstClassDataDefiner(data, &success);
1792     if (!success) {
1793       return false;
1794     }
1795     if (UNLIKELY((data_definer != item->class_idx_) && (data_definer != DexFile::kDexNoIndex16))) {
1796       ErrorStringPrintf("Invalid class_data_item");
1797       return false;
1798     }
1799   }
1800 
1801   // Check that references in annotations_directory_item are to right class.
1802   if (item->annotations_off_ != 0) {
1803     const uint8_t* data = begin_ + item->annotations_off_;
1804     bool success;
1805     uint16_t annotations_definer = FindFirstAnnotationsDirectoryDefiner(data, &success);
1806     if (!success) {
1807       return false;
1808     }
1809     if (UNLIKELY((annotations_definer != item->class_idx_) &&
1810                  (annotations_definer != DexFile::kDexNoIndex16))) {
1811       ErrorStringPrintf("Invalid annotations_directory_item");
1812       return false;
1813     }
1814   }
1815 
1816   ptr_ += sizeof(DexFile::ClassDef);
1817   return true;
1818 }
1819 
CheckInterAnnotationSetRefList()1820 bool DexFileVerifier::CheckInterAnnotationSetRefList() {
1821   const DexFile::AnnotationSetRefList* list =
1822       reinterpret_cast<const DexFile::AnnotationSetRefList*>(ptr_);
1823   const DexFile::AnnotationSetRefItem* item = list->list_;
1824   uint32_t count = list->size_;
1825 
1826   while (count--) {
1827     if (item->annotations_off_ != 0 &&
1828         !CheckOffsetToTypeMap(item->annotations_off_, DexFile::kDexTypeAnnotationSetItem)) {
1829       return false;
1830     }
1831     item++;
1832   }
1833 
1834   ptr_ = reinterpret_cast<const uint8_t*>(item);
1835   return true;
1836 }
1837 
CheckInterAnnotationSetItem()1838 bool DexFileVerifier::CheckInterAnnotationSetItem() {
1839   const DexFile::AnnotationSetItem* set = reinterpret_cast<const DexFile::AnnotationSetItem*>(ptr_);
1840   const uint32_t* offsets = set->entries_;
1841   uint32_t count = set->size_;
1842   uint32_t last_idx = 0;
1843 
1844   for (uint32_t i = 0; i < count; i++) {
1845     if (*offsets != 0 && !CheckOffsetToTypeMap(*offsets, DexFile::kDexTypeAnnotationItem)) {
1846       return false;
1847     }
1848 
1849     // Get the annotation from the offset and the type index for the annotation.
1850     const DexFile::AnnotationItem* annotation =
1851         reinterpret_cast<const DexFile::AnnotationItem*>(begin_ + *offsets);
1852     const uint8_t* data = annotation->annotation_;
1853     uint32_t idx = DecodeUnsignedLeb128(&data);
1854 
1855     if (UNLIKELY(last_idx >= idx && i != 0)) {
1856       ErrorStringPrintf("Out-of-order entry types: %x then %x", last_idx, idx);
1857       return false;
1858     }
1859 
1860     last_idx = idx;
1861     offsets++;
1862   }
1863 
1864   ptr_ = reinterpret_cast<const uint8_t*>(offsets);
1865   return true;
1866 }
1867 
CheckInterClassDataItem()1868 bool DexFileVerifier::CheckInterClassDataItem() {
1869   ClassDataItemIterator it(*dex_file_, ptr_);
1870   bool success;
1871   uint16_t defining_class = FindFirstClassDataDefiner(ptr_, &success);
1872   if (!success) {
1873     return false;
1874   }
1875 
1876   for (; it.HasNextStaticField() || it.HasNextInstanceField(); it.Next()) {
1877     LOAD_FIELD(field, it.GetMemberIndex(), "inter_class_data_item field_id", return false)
1878     if (UNLIKELY(field->class_idx_ != defining_class)) {
1879       ErrorStringPrintf("Mismatched defining class for class_data_item field");
1880       return false;
1881     }
1882   }
1883   for (; it.HasNextDirectMethod() || it.HasNextVirtualMethod(); it.Next()) {
1884     uint32_t code_off = it.GetMethodCodeItemOffset();
1885     if (code_off != 0 && !CheckOffsetToTypeMap(code_off, DexFile::kDexTypeCodeItem)) {
1886       return false;
1887     }
1888     LOAD_METHOD(method, it.GetMemberIndex(), "inter_class_data_item method_id", return false)
1889     if (UNLIKELY(method->class_idx_ != defining_class)) {
1890       ErrorStringPrintf("Mismatched defining class for class_data_item method");
1891       return false;
1892     }
1893   }
1894 
1895   ptr_ = it.EndDataPointer();
1896   return true;
1897 }
1898 
CheckInterAnnotationsDirectoryItem()1899 bool DexFileVerifier::CheckInterAnnotationsDirectoryItem() {
1900   const DexFile::AnnotationsDirectoryItem* item =
1901       reinterpret_cast<const DexFile::AnnotationsDirectoryItem*>(ptr_);
1902   bool success;
1903   uint16_t defining_class = FindFirstAnnotationsDirectoryDefiner(ptr_, &success);
1904   if (!success) {
1905     return false;
1906   }
1907 
1908   if (item->class_annotations_off_ != 0 &&
1909       !CheckOffsetToTypeMap(item->class_annotations_off_, DexFile::kDexTypeAnnotationSetItem)) {
1910     return false;
1911   }
1912 
1913   // Field annotations follow immediately after the annotations directory.
1914   const DexFile::FieldAnnotationsItem* field_item =
1915       reinterpret_cast<const DexFile::FieldAnnotationsItem*>(item + 1);
1916   uint32_t field_count = item->fields_size_;
1917   for (uint32_t i = 0; i < field_count; i++) {
1918     LOAD_FIELD(field, field_item->field_idx_, "inter_annotations_directory_item field_id",
1919                return false)
1920     if (UNLIKELY(field->class_idx_ != defining_class)) {
1921       ErrorStringPrintf("Mismatched defining class for field_annotation");
1922       return false;
1923     }
1924     if (!CheckOffsetToTypeMap(field_item->annotations_off_, DexFile::kDexTypeAnnotationSetItem)) {
1925       return false;
1926     }
1927     field_item++;
1928   }
1929 
1930   // Method annotations follow immediately after field annotations.
1931   const DexFile::MethodAnnotationsItem* method_item =
1932       reinterpret_cast<const DexFile::MethodAnnotationsItem*>(field_item);
1933   uint32_t method_count = item->methods_size_;
1934   for (uint32_t i = 0; i < method_count; i++) {
1935     LOAD_METHOD(method, method_item->method_idx_, "inter_annotations_directory_item method_id",
1936                 return false)
1937     if (UNLIKELY(method->class_idx_ != defining_class)) {
1938       ErrorStringPrintf("Mismatched defining class for method_annotation");
1939       return false;
1940     }
1941     if (!CheckOffsetToTypeMap(method_item->annotations_off_, DexFile::kDexTypeAnnotationSetItem)) {
1942       return false;
1943     }
1944     method_item++;
1945   }
1946 
1947   // Parameter annotations follow immediately after method annotations.
1948   const DexFile::ParameterAnnotationsItem* parameter_item =
1949       reinterpret_cast<const DexFile::ParameterAnnotationsItem*>(method_item);
1950   uint32_t parameter_count = item->parameters_size_;
1951   for (uint32_t i = 0; i < parameter_count; i++) {
1952     LOAD_METHOD(parameter_method, parameter_item->method_idx_,
1953                 "inter_annotations_directory_item parameter method_id", return false)
1954     if (UNLIKELY(parameter_method->class_idx_ != defining_class)) {
1955       ErrorStringPrintf("Mismatched defining class for parameter_annotation");
1956       return false;
1957     }
1958     if (!CheckOffsetToTypeMap(parameter_item->annotations_off_,
1959         DexFile::kDexTypeAnnotationSetRefList)) {
1960       return false;
1961     }
1962     parameter_item++;
1963   }
1964 
1965   ptr_ = reinterpret_cast<const uint8_t*>(parameter_item);
1966   return true;
1967 }
1968 
CheckInterSectionIterate(size_t offset,uint32_t count,uint16_t type)1969 bool DexFileVerifier::CheckInterSectionIterate(size_t offset, uint32_t count, uint16_t type) {
1970   // Get the right alignment mask for the type of section.
1971   size_t alignment_mask;
1972   switch (type) {
1973     case DexFile::kDexTypeClassDataItem:
1974       alignment_mask = sizeof(uint8_t) - 1;
1975       break;
1976     default:
1977       alignment_mask = sizeof(uint32_t) - 1;
1978       break;
1979   }
1980 
1981   // Iterate through the items in the section.
1982   previous_item_ = nullptr;
1983   for (uint32_t i = 0; i < count; i++) {
1984     uint32_t new_offset = (offset + alignment_mask) & ~alignment_mask;
1985     ptr_ = begin_ + new_offset;
1986     const uint8_t* prev_ptr = ptr_;
1987 
1988     // Check depending on the section type.
1989     switch (type) {
1990       case DexFile::kDexTypeStringIdItem: {
1991         if (!CheckInterStringIdItem()) {
1992           return false;
1993         }
1994         break;
1995       }
1996       case DexFile::kDexTypeTypeIdItem: {
1997         if (!CheckInterTypeIdItem()) {
1998           return false;
1999         }
2000         break;
2001       }
2002       case DexFile::kDexTypeProtoIdItem: {
2003         if (!CheckInterProtoIdItem()) {
2004           return false;
2005         }
2006         break;
2007       }
2008       case DexFile::kDexTypeFieldIdItem: {
2009         if (!CheckInterFieldIdItem()) {
2010           return false;
2011         }
2012         break;
2013       }
2014       case DexFile::kDexTypeMethodIdItem: {
2015         if (!CheckInterMethodIdItem()) {
2016           return false;
2017         }
2018         break;
2019       }
2020       case DexFile::kDexTypeClassDefItem: {
2021         if (!CheckInterClassDefItem()) {
2022           return false;
2023         }
2024         break;
2025       }
2026       case DexFile::kDexTypeAnnotationSetRefList: {
2027         if (!CheckInterAnnotationSetRefList()) {
2028           return false;
2029         }
2030         break;
2031       }
2032       case DexFile::kDexTypeAnnotationSetItem: {
2033         if (!CheckInterAnnotationSetItem()) {
2034           return false;
2035         }
2036         break;
2037       }
2038       case DexFile::kDexTypeClassDataItem: {
2039         if (!CheckInterClassDataItem()) {
2040           return false;
2041         }
2042         break;
2043       }
2044       case DexFile::kDexTypeAnnotationsDirectoryItem: {
2045         if (!CheckInterAnnotationsDirectoryItem()) {
2046           return false;
2047         }
2048         break;
2049       }
2050       default:
2051         ErrorStringPrintf("Unknown map item type %x", type);
2052         return false;
2053     }
2054 
2055     previous_item_ = prev_ptr;
2056     offset = ptr_ - begin_;
2057   }
2058 
2059   return true;
2060 }
2061 
CheckInterSection()2062 bool DexFileVerifier::CheckInterSection() {
2063   const DexFile::MapList* map = reinterpret_cast<const DexFile::MapList*>(begin_ + header_->map_off_);
2064   const DexFile::MapItem* item = map->list_;
2065   uint32_t count = map->size_;
2066 
2067   // Cross check the items listed in the map.
2068   while (count--) {
2069     uint32_t section_offset = item->offset_;
2070     uint32_t section_count = item->size_;
2071     uint16_t type = item->type_;
2072 
2073     switch (type) {
2074       case DexFile::kDexTypeHeaderItem:
2075       case DexFile::kDexTypeMapList:
2076       case DexFile::kDexTypeTypeList:
2077       case DexFile::kDexTypeCodeItem:
2078       case DexFile::kDexTypeStringDataItem:
2079       case DexFile::kDexTypeDebugInfoItem:
2080       case DexFile::kDexTypeAnnotationItem:
2081       case DexFile::kDexTypeEncodedArrayItem:
2082         break;
2083       case DexFile::kDexTypeStringIdItem:
2084       case DexFile::kDexTypeTypeIdItem:
2085       case DexFile::kDexTypeProtoIdItem:
2086       case DexFile::kDexTypeFieldIdItem:
2087       case DexFile::kDexTypeMethodIdItem:
2088       case DexFile::kDexTypeClassDefItem:
2089       case DexFile::kDexTypeAnnotationSetRefList:
2090       case DexFile::kDexTypeAnnotationSetItem:
2091       case DexFile::kDexTypeClassDataItem:
2092       case DexFile::kDexTypeAnnotationsDirectoryItem: {
2093         if (!CheckInterSectionIterate(section_offset, section_count, type)) {
2094           return false;
2095         }
2096         break;
2097       }
2098       default:
2099         ErrorStringPrintf("Unknown map item type %x", type);
2100         return false;
2101     }
2102 
2103     item++;
2104   }
2105 
2106   return true;
2107 }
2108 
Verify()2109 bool DexFileVerifier::Verify() {
2110   // Check the header.
2111   if (!CheckHeader()) {
2112     return false;
2113   }
2114 
2115   // Check the map section.
2116   if (!CheckMap()) {
2117     return false;
2118   }
2119 
2120   // Check structure within remaining sections.
2121   if (!CheckIntraSection()) {
2122     return false;
2123   }
2124 
2125   // Check references from one section to another.
2126   if (!CheckInterSection()) {
2127     return false;
2128   }
2129 
2130   return true;
2131 }
2132 
ErrorStringPrintf(const char * fmt,...)2133 void DexFileVerifier::ErrorStringPrintf(const char* fmt, ...) {
2134   va_list ap;
2135   va_start(ap, fmt);
2136   DCHECK(failure_reason_.empty()) << failure_reason_;
2137   failure_reason_ = StringPrintf("Failure to verify dex file '%s': ", location_);
2138   StringAppendV(&failure_reason_, fmt, ap);
2139   va_end(ap);
2140 }
2141 
2142 }  // namespace art
2143