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 <algorithm>
20 #include <bitset>
21 #include <limits>
22 #include <memory>
23 #include <stack>
24
25 #include "android-base/logging.h"
26 #include "android-base/macros.h"
27 #include "android-base/stringprintf.h"
28 #include "base/hash_map.h"
29 #include "base/leb128.h"
30 #include "base/safe_map.h"
31 #include "class_accessor-inl.h"
32 #include "code_item_accessors-inl.h"
33 #include "descriptors_names.h"
34 #include "dex_file-inl.h"
35 #include "dex_file_types.h"
36 #include "modifiers.h"
37 #include "utf-inl.h"
38
39 namespace art {
40 namespace dex {
41
42 using android::base::StringAppendV;
43 using android::base::StringPrintf;
44
45 namespace {
46
47 constexpr uint32_t kTypeIdLimit = std::numeric_limits<uint16_t>::max();
48
IsValidOrNoTypeId(uint16_t low,uint16_t high)49 constexpr bool IsValidOrNoTypeId(uint16_t low, uint16_t high) {
50 return (high == 0) || ((high == 0xffffU) && (low == 0xffffU));
51 }
52
IsValidTypeId(uint16_t low,uint16_t high)53 constexpr bool IsValidTypeId([[maybe_unused]] uint16_t low, uint16_t high) { return (high == 0); }
54
MapTypeToBitMask(DexFile::MapItemType map_item_type)55 constexpr uint32_t MapTypeToBitMask(DexFile::MapItemType map_item_type) {
56 switch (map_item_type) {
57 case DexFile::kDexTypeHeaderItem: return 1 << 0;
58 case DexFile::kDexTypeStringIdItem: return 1 << 1;
59 case DexFile::kDexTypeTypeIdItem: return 1 << 2;
60 case DexFile::kDexTypeProtoIdItem: return 1 << 3;
61 case DexFile::kDexTypeFieldIdItem: return 1 << 4;
62 case DexFile::kDexTypeMethodIdItem: return 1 << 5;
63 case DexFile::kDexTypeClassDefItem: return 1 << 6;
64 case DexFile::kDexTypeCallSiteIdItem: return 1 << 7;
65 case DexFile::kDexTypeMethodHandleItem: return 1 << 8;
66 case DexFile::kDexTypeMapList: return 1 << 9;
67 case DexFile::kDexTypeTypeList: return 1 << 10;
68 case DexFile::kDexTypeAnnotationSetRefList: return 1 << 11;
69 case DexFile::kDexTypeAnnotationSetItem: return 1 << 12;
70 case DexFile::kDexTypeClassDataItem: return 1 << 13;
71 case DexFile::kDexTypeCodeItem: return 1 << 14;
72 case DexFile::kDexTypeStringDataItem: return 1 << 15;
73 case DexFile::kDexTypeDebugInfoItem: return 1 << 16;
74 case DexFile::kDexTypeAnnotationItem: return 1 << 17;
75 case DexFile::kDexTypeEncodedArrayItem: return 1 << 18;
76 case DexFile::kDexTypeAnnotationsDirectoryItem: return 1 << 19;
77 case DexFile::kDexTypeHiddenapiClassData: return 1 << 20;
78 }
79 return 0;
80 }
81
IsDataSectionType(DexFile::MapItemType map_item_type)82 constexpr bool IsDataSectionType(DexFile::MapItemType map_item_type) {
83 switch (map_item_type) {
84 case DexFile::kDexTypeHeaderItem:
85 case DexFile::kDexTypeStringIdItem:
86 case DexFile::kDexTypeTypeIdItem:
87 case DexFile::kDexTypeProtoIdItem:
88 case DexFile::kDexTypeFieldIdItem:
89 case DexFile::kDexTypeMethodIdItem:
90 case DexFile::kDexTypeClassDefItem:
91 return false;
92 case DexFile::kDexTypeCallSiteIdItem:
93 case DexFile::kDexTypeMethodHandleItem:
94 case DexFile::kDexTypeMapList:
95 case DexFile::kDexTypeTypeList:
96 case DexFile::kDexTypeAnnotationSetRefList:
97 case DexFile::kDexTypeAnnotationSetItem:
98 case DexFile::kDexTypeClassDataItem:
99 case DexFile::kDexTypeCodeItem:
100 case DexFile::kDexTypeStringDataItem:
101 case DexFile::kDexTypeDebugInfoItem:
102 case DexFile::kDexTypeAnnotationItem:
103 case DexFile::kDexTypeEncodedArrayItem:
104 case DexFile::kDexTypeAnnotationsDirectoryItem:
105 case DexFile::kDexTypeHiddenapiClassData:
106 return true;
107 }
108 return true;
109 }
110
111 // Fields and methods may have only one of public/protected/private.
112 ALWAYS_INLINE
CheckAtMostOneOfPublicProtectedPrivate(uint32_t flags)113 constexpr bool CheckAtMostOneOfPublicProtectedPrivate(uint32_t flags) {
114 // Semantically we want 'return POPCOUNT(flags & kAcc) <= 1;'.
115 static_assert(IsPowerOfTwo(0), "0 not marked as power of two");
116 static_assert(IsPowerOfTwo(kAccPublic), "kAccPublic not marked as power of two");
117 static_assert(IsPowerOfTwo(kAccProtected), "kAccProtected not marked as power of two");
118 static_assert(IsPowerOfTwo(kAccPrivate), "kAccPrivate not marked as power of two");
119 return IsPowerOfTwo(flags & (kAccPublic | kAccProtected | kAccPrivate));
120 }
121
122 } // namespace
123
124 // Note: the anonymous namespace would be nice, but we need friend access into accessors.
125
126 class DexFileVerifier {
127 public:
DexFileVerifier(const DexFile * dex_file,const char * location,bool verify_checksum)128 DexFileVerifier(const DexFile* dex_file, const char* location, bool verify_checksum)
129 : dex_file_(dex_file),
130 offset_base_address_(dex_file->DataBegin()),
131 size_(dex_file->DataSize()),
132 location_(location),
133 verify_checksum_(verify_checksum),
134 header_(&dex_file->GetHeader()),
135 ptr_(nullptr),
136 previous_item_(nullptr),
137 init_indices_{std::numeric_limits<size_t>::max(),
138 std::numeric_limits<size_t>::max(),
139 std::numeric_limits<size_t>::max(),
140 std::numeric_limits<size_t>::max()} {
141 CHECK(!dex_file->IsCompactDexFile()) << "Not supported";
142 }
143
144 bool Verify();
145
FailureReason() const146 const std::string& FailureReason() const {
147 return failure_reason_;
148 }
149
150 private:
151 template <class T = uint8_t>
OffsetToPtr(size_t offset)152 ALWAYS_INLINE const T* OffsetToPtr(size_t offset) {
153 DCHECK_GE(offset, static_cast<size_t>(dex_file_->Begin() - offset_base_address_));
154 DCHECK_LE(offset, size_);
155 return reinterpret_cast<const T*>(offset_base_address_ + offset);
156 }
157
PtrToOffset(const void * ptr)158 ALWAYS_INLINE size_t PtrToOffset(const void* ptr) {
159 DCHECK_GE(ptr, dex_file_->Begin());
160 DCHECK_LE(ptr, EndOfFile());
161 return reinterpret_cast<const uint8_t*>(ptr) - offset_base_address_;
162 }
163
164 // Converts the pointer `ptr` into `offset`.
165 // Returns `true` if the offset is within the bounds of the container.
166 // TODO: Try to remove this overload. Avoid creating invalid pointers.
PtrToOffset(const void * ptr,size_t * offset)167 ALWAYS_INLINE WARN_UNUSED bool PtrToOffset(const void* ptr, /*out*/ size_t* offset) {
168 *offset = reinterpret_cast<const uint8_t*>(ptr) - offset_base_address_;
169 return *offset <= size_;
170 }
171
EndOfFile()172 ALWAYS_INLINE const uint8_t* EndOfFile() {
173 return OffsetToPtr(size_);
174 }
175
176 // Helper functions to retrieve names from the dex file. We do not want to rely on DexFile
177 // functionality, as we're still verifying the dex file.
178
GetString(dex::StringIndex string_idx)179 std::string GetString(dex::StringIndex string_idx) {
180 // All sources of the `string_idx` have already been checked in CheckIntraSection().
181 DCHECK_LT(string_idx.index_, header_->string_ids_size_);
182 const dex::StringId& string_id =
183 OffsetToPtr<dex::StringId>(header_->string_ids_off_)[string_idx.index_];
184
185 // The string offset has been checked at the start of `CheckInterSection()`
186 // to point to a string data item checked by `CheckIntraSection()`.
187 const uint8_t* ptr = OffsetToPtr(string_id.string_data_off_);
188 DecodeUnsignedLeb128(&ptr); // Ignore the result.
189 return reinterpret_cast<const char*>(ptr);
190 }
191
GetClass(dex::TypeIndex class_idx)192 std::string GetClass(dex::TypeIndex class_idx) {
193 // All sources of `class_idx` have already been checked in CheckIntraSection().
194 CHECK_LT(class_idx.index_, header_->type_ids_size_);
195
196 const dex::TypeId& type_id = OffsetToPtr<dex::TypeId>(header_->type_ids_off_)[class_idx.index_];
197
198 // The `type_id->descriptor_idx_` has already been checked in CheckIntraTypeIdItem().
199 // However, it may not have been checked to be a valid descriptor, so return the raw
200 // string without converting with `PrettyDescriptor()`.
201 return GetString(type_id.descriptor_idx_);
202 }
203
GetFieldDescription(uint32_t idx)204 std::string GetFieldDescription(uint32_t idx) {
205 // The `idx` has already been checked in `DexFileVerifier::CheckIntraClassDataItemFields()`.
206 CHECK_LT(idx, header_->field_ids_size_);
207
208 const dex::FieldId& field_id = OffsetToPtr<dex::FieldId>(header_->field_ids_off_)[idx];
209
210 // Indexes in `*field_id` have already been checked in CheckIntraFieldIdItem().
211 std::string class_name = GetClass(field_id.class_idx_);
212 std::string field_name = GetString(field_id.name_idx_);
213 return class_name + "." + field_name;
214 }
215
GetMethodDescription(uint32_t idx)216 std::string GetMethodDescription(uint32_t idx) {
217 // The `idx` has already been checked in `DexFileVerifier::CheckIntraClassDataItemMethods()`.
218 CHECK_LT(idx, header_->method_ids_size_);
219
220 const dex::MethodId& method_id = OffsetToPtr<dex::MethodId>(header_->method_ids_off_)[idx];
221
222 // Indexes in `method_id` have already been checked in CheckIntraMethodIdItem().
223 std::string class_name = GetClass(method_id.class_idx_);
224 std::string method_name = GetString(method_id.name_idx_);
225 return class_name + "." + method_name;
226 }
227
228 bool CheckShortyDescriptorMatch(char shorty_char, const char* descriptor, bool is_return_type);
229 bool CheckListSize(const void* start, size_t count, size_t element_size, const char* label);
230 // Check a list. The head is assumed to be at *ptr, and elements to be of size element_size. If
231 // successful, the ptr will be moved forward the amount covered by the list.
232 bool CheckList(size_t element_size, const char* label, const uint8_t* *ptr);
233 // Checks:
234 // * the offset is zero (when size is zero),
235 // * the offset falls within the area claimed by the file,
236 // * the offset + size also falls within the area claimed by the file, and
237 // * the alignment of the section
238 bool CheckValidOffsetAndSize(uint32_t offset, uint32_t size, size_t alignment, const char* label);
239 // Checks whether the size is less than the limit.
CheckSizeLimit(uint32_t size,uint32_t limit,const char * label)240 ALWAYS_INLINE bool CheckSizeLimit(uint32_t size, uint32_t limit, const char* label) {
241 if (size > limit) {
242 ErrorStringPrintf("Size(%u) should not exceed limit(%u) for %s.", size, limit, label);
243 return false;
244 }
245 return true;
246 }
CheckIndex(uint32_t field,uint32_t limit,const char * label)247 ALWAYS_INLINE bool CheckIndex(uint32_t field, uint32_t limit, const char* label) {
248 if (UNLIKELY(field >= limit)) {
249 ErrorStringPrintf("Bad index for %s: %x >= %x", label, field, limit);
250 return false;
251 }
252 return true;
253 }
254
255 bool CheckHeader();
256 bool CheckMap();
257
ReadUnsignedLittleEndian(uint32_t size,uint32_t * result)258 ALWAYS_INLINE bool ReadUnsignedLittleEndian(uint32_t size, /*out*/ uint32_t* result) {
259 if (!CheckListSize(ptr_, size, sizeof(uint8_t), "encoded_value")) {
260 return false;
261 }
262 *result = 0;
263 for (uint32_t i = 0; i < size; i++) {
264 *result |= ((uint32_t) * (ptr_++)) << (i * 8);
265 }
266 return true;
267 }
268 bool CheckAndGetHandlerOffsets(const dex::CodeItem* code_item,
269 uint32_t* handler_offsets, uint32_t handlers_size);
270 bool CheckClassDataItemField(uint32_t idx,
271 uint32_t access_flags,
272 uint32_t class_access_flags,
273 dex::TypeIndex class_type_index);
274 bool CheckClassDataItemMethod(uint32_t idx,
275 uint32_t access_flags,
276 uint32_t class_access_flags,
277 dex::TypeIndex class_type_index,
278 uint32_t code_offset,
279 bool expect_direct);
280 ALWAYS_INLINE
CheckOrder(const char * type_descr,uint32_t curr_index,uint32_t prev_index)281 bool CheckOrder(const char* type_descr, uint32_t curr_index, uint32_t prev_index) {
282 if (UNLIKELY(curr_index < prev_index)) {
283 ErrorStringPrintf("out-of-order %s indexes %" PRIu32 " and %" PRIu32,
284 type_descr,
285 prev_index,
286 curr_index);
287 return false;
288 }
289 return true;
290 }
291 bool CheckStaticFieldTypes(const dex::ClassDef& class_def);
292
293 bool CheckPadding(uint32_t aligned_offset, DexFile::MapItemType type);
294
295 // The encoded values, arrays and annotations are allowed to be very deeply nested,
296 // so use heap todo-list instead of stack recursion (the work is done in LIFO order).
297 struct ToDoItem {
298 uint32_t array_size = 0; // CheckArrayElement.
299 uint32_t annotation_size = 0; // CheckAnnotationElement.
300 uint32_t last_idx = kDexNoIndex; // CheckAnnotationElement.
301 };
302 using ToDoList = std::stack<ToDoItem>;
303 bool CheckEncodedValue();
304 bool CheckEncodedArray();
305 bool CheckArrayElement();
306 bool CheckEncodedAnnotation();
307 bool CheckAnnotationElement(/*inout*/ uint32_t* last_idx);
308 bool FlushToDoList();
309
310 bool CheckIntraTypeIdItem();
311 bool CheckIntraProtoIdItem();
312 bool CheckIntraFieldIdItem();
313 bool CheckIntraMethodIdItem();
314 bool CheckIntraClassDefItem(uint32_t class_def_index);
315 bool CheckIntraMethodHandleItem();
316 bool CheckIntraTypeList();
317 // Check all fields of the given type, reading `encoded_field` entries from `ptr_`.
318 template <bool kStatic>
319 bool CheckIntraClassDataItemFields(size_t count);
320 // Check direct or virtual methods, reading `encoded_method` entries from `ptr_`.
321 // Check virtual methods against duplicates with direct methods.
322 bool CheckIntraClassDataItemMethods(size_t num_methods,
323 ClassAccessor::Method* direct_methods,
324 size_t num_direct_methods);
325 bool CheckIntraClassDataItem();
326
327 bool CheckIntraCodeItem();
328 bool CheckIntraStringDataItem();
329 bool CheckIntraDebugInfoItem();
330 bool CheckIntraAnnotationItem();
331 bool CheckIntraAnnotationsDirectoryItem();
332 bool CheckIntraHiddenapiClassData();
333
334 template <DexFile::MapItemType kType>
335 bool CheckIntraSectionIterate(uint32_t count);
336 template <DexFile::MapItemType kType>
337 bool CheckIntraIdSection(size_t offset, uint32_t count);
338 template <DexFile::MapItemType kType>
339 bool CheckIntraDataSection(size_t offset, uint32_t count);
340 bool CheckIntraSection();
341
342 bool CheckOffsetToTypeMap(size_t offset, uint16_t type);
343
344 // Returns kDexNoIndex if there are no fields/methods, otherwise a 16-bit type index.
345 uint32_t FindFirstClassDataDefiner(const ClassAccessor& accessor);
346 uint32_t FindFirstAnnotationsDirectoryDefiner(const uint8_t* ptr);
347
348 bool CheckInterHiddenapiClassData();
349 bool CheckInterStringIdItem();
350 bool CheckInterTypeIdItem();
351 bool CheckInterProtoIdItem();
352 bool CheckInterFieldIdItem();
353 bool CheckInterMethodIdItem();
354 bool CheckInterClassDefItem();
355 bool CheckInterCallSiteIdItem();
356 bool CheckInterAnnotationSetRefList();
357 bool CheckInterAnnotationSetItem();
358 bool CheckInterClassDataItem();
359 bool CheckInterAnnotationsDirectoryItem();
360
361 bool CheckInterSectionIterate(size_t offset, uint32_t count, DexFile::MapItemType type);
362 bool CheckInterSection();
363
ErrorStringPrintf(const char * fmt,...)364 void ErrorStringPrintf(const char* fmt, ...)
365 __attribute__((__format__(__printf__, 2, 3))) COLD_ATTR {
366 va_list ap;
367 va_start(ap, fmt);
368 DCHECK(failure_reason_.empty()) << failure_reason_;
369 failure_reason_ = StringPrintf("Failure to verify dex file '%s': ", location_);
370 StringAppendV(&failure_reason_, fmt, ap);
371 va_end(ap);
372 }
FailureReasonIsSet() const373 bool FailureReasonIsSet() const { return failure_reason_.size() != 0; }
374
375 // Check validity of the given access flags, interpreted for a field in the context of a class
376 // with the given second access flags.
377 bool CheckFieldAccessFlags(uint32_t idx,
378 uint32_t field_access_flags,
379 uint32_t class_access_flags,
380 std::string* error_message);
381
382 // Check validity of the given method and access flags, in the context of a class with the given
383 // second access flags.
384 bool CheckMethodAccessFlags(uint32_t method_index,
385 uint32_t method_access_flags,
386 uint32_t class_access_flags,
387 uint32_t constructor_flags_by_name,
388 bool has_code,
389 bool expect_direct,
390 std::string* error_message);
391
392 // Check validity of given method if it's a constructor or class initializer.
393 bool CheckConstructorProperties(uint32_t method_index, uint32_t constructor_flags);
394
395 void FindStringRangesForMethodNames();
396
397 template <typename ExtraCheckFn>
398 bool VerifyTypeDescriptor(dex::TypeIndex idx, const char* error_msg, ExtraCheckFn extra_check);
399
400 const DexFile* const dex_file_;
401 const uint8_t* const offset_base_address_;
402 const size_t size_;
403 ArrayRef<const uint8_t> data_; // The "data" section of the dex file.
404 const char* const location_;
405 const bool verify_checksum_;
406 const DexFile::Header* const header_;
407 uint32_t dex_version_ = 0;
408
409 struct OffsetTypeMapEmptyFn {
410 // Make a hash map slot empty by making the offset 0. Offset 0 is a valid dex file offset that
411 // is in the offset of the dex file header. However, we only store data section items in the
412 // map, and these are after the header.
MakeEmptyart::dex::DexFileVerifier::OffsetTypeMapEmptyFn413 void MakeEmpty(std::pair<uint32_t, uint16_t>& pair) const {
414 pair.first = 0u;
415 }
416 // Check if a hash map slot is empty.
IsEmptyart::dex::DexFileVerifier::OffsetTypeMapEmptyFn417 bool IsEmpty(const std::pair<uint32_t, uint16_t>& pair) const {
418 return pair.first == 0;
419 }
420 };
421 struct OffsetTypeMapHashCompareFn {
422 // Hash function for offset.
operator ()art::dex::DexFileVerifier::OffsetTypeMapHashCompareFn423 size_t operator()(const uint32_t key) const {
424 return key;
425 }
426 // std::equal function for offset.
operator ()art::dex::DexFileVerifier::OffsetTypeMapHashCompareFn427 bool operator()(const uint32_t a, const uint32_t b) const {
428 return a == b;
429 }
430 };
431 // Map from offset to dex file type, HashMap for performance reasons.
432 HashMap<uint32_t,
433 uint16_t,
434 OffsetTypeMapEmptyFn,
435 OffsetTypeMapHashCompareFn,
436 OffsetTypeMapHashCompareFn> offset_to_type_map_;
437 const uint8_t* ptr_;
438 const void* previous_item_;
439
440 std::string failure_reason_;
441
442 // Cached string indices for "interesting" entries wrt/ method names. Will be populated by
443 // FindStringRangesForMethodNames (which is automatically called before verifying the
444 // classdataitem section).
445 //
446 // Strings starting with '<' are in the range
447 // [angle_bracket_start_index_,angle_bracket_end_index_).
448 // angle_init_angle_index_ and angle_clinit_angle_index_ denote the indices of "<init>" and
449 // "<clinit>", respectively. If any value is not found, the corresponding index will be larger
450 // than any valid string index for this dex file.
451 struct {
452 size_t angle_bracket_start_index;
453 size_t angle_bracket_end_index;
454 size_t angle_init_angle_index;
455 size_t angle_clinit_angle_index;
456 } init_indices_;
457
458 // A bitvector for verified type descriptors. Each bit corresponds to a type index. A set
459 // bit denotes that the descriptor has been verified wrt/ IsValidDescriptor.
460 std::vector<char> verified_type_descriptors_;
461
462 // Set of type ids for which there are ClassDef elements in the dex file. Using a bitset
463 // avoids all allocations. The bitset should be implemented as 8K of storage, which is
464 // tight enough for all callers.
465 std::bitset<kTypeIdLimit + 1> defined_classes_;
466
467 // Class definition indexes, valid only if corresponding `defined_classes_[.]` is true.
468 std::vector<uint16_t> defined_class_indexes_;
469
470 // Used by CheckEncodedValue to avoid recursion. Field so we can reuse allocated memory.
471 ToDoList todo_;
472 };
473
474 template <typename ExtraCheckFn>
VerifyTypeDescriptor(dex::TypeIndex idx,const char * error_msg,ExtraCheckFn extra_check)475 bool DexFileVerifier::VerifyTypeDescriptor(dex::TypeIndex idx,
476 const char* error_msg,
477 ExtraCheckFn extra_check) {
478 // All sources of the `idx` have already been checked in CheckIntraSection().
479 DCHECK_LT(idx.index_, header_->type_ids_size_);
480
481 char cached_char = verified_type_descriptors_[idx.index_];
482 if (cached_char != 0) {
483 if (!extra_check(cached_char)) {
484 const char* descriptor = dex_file_->GetTypeDescriptor(idx);
485 ErrorStringPrintf("%s: '%s'", error_msg, descriptor);
486 return false;
487 }
488 return true;
489 }
490
491 const char* descriptor = dex_file_->GetTypeDescriptor(idx);
492 if (UNLIKELY(!IsValidDescriptor(descriptor))) {
493 ErrorStringPrintf("%s: '%s'", error_msg, descriptor);
494 return false;
495 }
496 verified_type_descriptors_[idx.index_] = descriptor[0];
497
498 if (!extra_check(descriptor[0])) {
499 ErrorStringPrintf("%s: '%s'", error_msg, descriptor);
500 return false;
501 }
502 return true;
503 }
504
CheckShortyDescriptorMatch(char shorty_char,const char * descriptor,bool is_return_type)505 bool DexFileVerifier::CheckShortyDescriptorMatch(char shorty_char, const char* descriptor,
506 bool is_return_type) {
507 switch (shorty_char) {
508 case 'V':
509 if (UNLIKELY(!is_return_type)) {
510 ErrorStringPrintf("Invalid use of void");
511 return false;
512 }
513 FALLTHROUGH_INTENDED;
514 case 'B':
515 case 'C':
516 case 'D':
517 case 'F':
518 case 'I':
519 case 'J':
520 case 'S':
521 case 'Z':
522 if (UNLIKELY((descriptor[0] != shorty_char) || (descriptor[1] != '\0'))) {
523 ErrorStringPrintf("Shorty vs. primitive type mismatch: '%c', '%s'",
524 shorty_char, descriptor);
525 return false;
526 }
527 break;
528 case 'L':
529 if (UNLIKELY((descriptor[0] != 'L') && (descriptor[0] != '['))) {
530 ErrorStringPrintf("Shorty vs. type mismatch: '%c', '%s'", shorty_char, descriptor);
531 return false;
532 }
533 break;
534 default:
535 ErrorStringPrintf("Bad shorty character: '%c'", shorty_char);
536 return false;
537 }
538 return true;
539 }
540
CheckListSize(const void * start,size_t count,size_t elem_size,const char * label)541 bool DexFileVerifier::CheckListSize(const void* start, size_t count, size_t elem_size,
542 const char* label) {
543 // Check that element size is not 0.
544 DCHECK_NE(elem_size, 0U);
545
546 size_t offset;
547 if (!PtrToOffset(start, &offset)) {
548 ErrorStringPrintf("Offset beyond end of file for %s: %zx to %zx", label, offset, size_);
549 return false;
550 }
551
552 // Calculate the number of elements that fit until the end of file,
553 // rather than calculating the end of the range as that could overflow.
554 size_t max_elements = (size_ - offset) / elem_size;
555 if (UNLIKELY(max_elements < count)) {
556 ErrorStringPrintf(
557 "List too large for %s: %zx+%zu*%zu > %zx", label, offset, count, elem_size, size_);
558 return false;
559 }
560
561 return true;
562 }
563
CheckList(size_t element_size,const char * label,const uint8_t ** ptr)564 bool DexFileVerifier::CheckList(size_t element_size, const char* label, const uint8_t* *ptr) {
565 // Check that the list is available. The first 4B are the count.
566 if (!CheckListSize(*ptr, 1, 4U, label)) {
567 return false;
568 }
569
570 uint32_t count = *reinterpret_cast<const uint32_t*>(*ptr);
571 if (count > 0) {
572 if (!CheckListSize(*ptr + 4, count, element_size, label)) {
573 return false;
574 }
575 }
576
577 *ptr += 4 + count * element_size;
578 return true;
579 }
580
CheckValidOffsetAndSize(uint32_t offset,uint32_t size,size_t alignment,const char * label)581 bool DexFileVerifier::CheckValidOffsetAndSize(uint32_t offset,
582 uint32_t size,
583 size_t alignment,
584 const char* label) {
585 if (size == 0) {
586 if (offset != 0) {
587 ErrorStringPrintf("Offset(%d) should be zero when size is zero for %s.", offset, label);
588 return false;
589 }
590 return true;
591 }
592 size_t hdr_offset = PtrToOffset(header_);
593 if (offset < hdr_offset) {
594 ErrorStringPrintf("Offset(%d) should be after header(%zu) for %s.", offset, hdr_offset, label);
595 return false;
596 }
597 if (size_ <= offset) {
598 ErrorStringPrintf("Offset(%d) should be within file size(%zu) for %s.", offset, size_, label);
599 return false;
600 }
601 // Check that offset + size is within the file size. Note that we use `<` to allow the section to
602 // end at the same point as the file. Check written as a subtraction to be safe from overfow.
603 if (size_ - offset < size) {
604 ErrorStringPrintf(
605 "Section end(%d) should be within file size(%zu) for %s.", offset + size, size_, label);
606 return false;
607 }
608 if (alignment != 0 && !IsAlignedParam(offset, alignment)) {
609 ErrorStringPrintf("Offset(%d) should be aligned by %zu for %s.", offset, alignment, label);
610 return false;
611 }
612 return true;
613 }
614
CheckHeader()615 bool DexFileVerifier::CheckHeader() {
616 // Check magic.
617 size_t size = dex_file_->GetContainer()->End() - dex_file_->Begin();
618 if (size < sizeof(DexFile::Header)) {
619 ErrorStringPrintf("Empty or truncated file.");
620 return false;
621 }
622 if (!StandardDexFile::IsMagicValid(header_->magic_.data())) {
623 ErrorStringPrintf("Bad file magic");
624 return false;
625 }
626 if (!StandardDexFile::IsVersionValid(header_->magic_.data())) {
627 ErrorStringPrintf("Unknown dex version");
628 return false;
629 }
630 dex_version_ = header_->GetVersion();
631
632 // Check file size from the header.
633 size_t file_size = header_->file_size_;
634 size_t header_size = (dex_version_ >= 41) ? sizeof(DexFile::HeaderV41) : sizeof(DexFile::Header);
635 if (file_size < header_size) {
636 ErrorStringPrintf("Bad file size (%zu, expected at least %zu)", file_size, header_size);
637 return false;
638 }
639 if (file_size > size) {
640 ErrorStringPrintf("Bad file size (%zu, expected at most %zu)", file_size, size);
641 return false;
642 }
643 CHECK_GE(size, header_size); // Implied by the two checks above.
644
645 // Check header size.
646 if (header_->header_size_ != header_size) {
647 ErrorStringPrintf("Bad header size: %ud expected %zud", header_->header_size_, header_size);
648 return false;
649 }
650
651 // Check the endian.
652 if (header_->endian_tag_ != DexFile::kDexEndianConstant) {
653 ErrorStringPrintf("Unexpected endian_tag: %x", header_->endian_tag_);
654 return false;
655 }
656
657 // Compute and verify the checksum in the header.
658 uint32_t adler_checksum = dex_file_->CalculateChecksum();
659 if (adler_checksum != header_->checksum_) {
660 if (verify_checksum_) {
661 ErrorStringPrintf("Bad checksum (%08x, expected %08x)", adler_checksum, header_->checksum_);
662 return false;
663 } else {
664 LOG(WARNING) << StringPrintf(
665 "Ignoring bad checksum (%08x, expected %08x)", adler_checksum, header_->checksum_);
666 }
667 }
668
669 if (dex_version_ >= 41) {
670 auto headerV41 = reinterpret_cast<const DexFile::HeaderV41*>(header_);
671 if (headerV41->container_size_ <= headerV41->header_offset_) {
672 ErrorStringPrintf("Dex container is too small: size=%ud header_offset=%ud",
673 headerV41->container_size_,
674 headerV41->header_offset_);
675 return false;
676 }
677 uint32_t remainder = headerV41->container_size_ - headerV41->header_offset_;
678 if (headerV41->file_size_ > remainder) {
679 ErrorStringPrintf(
680 "Header file_size(%ud) is past multi-dex size(%ud)", headerV41->file_size_, remainder);
681 return false;
682 }
683 }
684
685 // Check that all offsets are inside the file.
686 bool ok =
687 CheckValidOffsetAndSize(header_->link_off_,
688 header_->link_size_,
689 /* alignment= */ 0,
690 "link") &&
691 CheckValidOffsetAndSize(header_->map_off_,
692 sizeof(dex::MapList),
693 /* alignment= */ 4,
694 "map") &&
695 CheckValidOffsetAndSize(header_->string_ids_off_,
696 header_->string_ids_size_,
697 /* alignment= */ 4,
698 "string-ids") &&
699 CheckValidOffsetAndSize(header_->type_ids_off_,
700 header_->type_ids_size_,
701 /* alignment= */ 4,
702 "type-ids") &&
703 CheckSizeLimit(header_->type_ids_size_, DexFile::kDexNoIndex16, "type-ids") &&
704 CheckValidOffsetAndSize(header_->proto_ids_off_,
705 header_->proto_ids_size_,
706 /* alignment= */ 4,
707 "proto-ids") &&
708 CheckSizeLimit(header_->proto_ids_size_, DexFile::kDexNoIndex16, "proto-ids") &&
709 CheckValidOffsetAndSize(header_->field_ids_off_,
710 header_->field_ids_size_,
711 /* alignment= */ 4,
712 "field-ids") &&
713 CheckValidOffsetAndSize(header_->method_ids_off_,
714 header_->method_ids_size_,
715 /* alignment= */ 4,
716 "method-ids") &&
717 CheckValidOffsetAndSize(header_->class_defs_off_,
718 header_->class_defs_size_,
719 /* alignment= */ 4,
720 "class-defs") &&
721 CheckValidOffsetAndSize(header_->data_off_,
722 header_->data_size_,
723 // Unaligned, spec doesn't talk about it, even though size
724 // is supposed to be a multiple of 4.
725 /* alignment= */ 0,
726 "data");
727
728 if (ok) {
729 data_ = (dex_version_ >= 41)
730 ? ArrayRef<const uint8_t>(dex_file_->Begin(), EndOfFile() - dex_file_->Begin())
731 : ArrayRef<const uint8_t>(OffsetToPtr(header_->data_off_), header_->data_size_);
732 }
733 return ok;
734 }
735
CheckMap()736 bool DexFileVerifier::CheckMap() {
737 const dex::MapList* map = OffsetToPtr<dex::MapList>(header_->map_off_);
738 // Check that map list content is available.
739 if (!CheckListSize(map, 1, sizeof(dex::MapList), "maplist content")) {
740 return false;
741 }
742
743 const dex::MapItem* item = map->list_;
744
745 uint32_t count = map->size_;
746 uint32_t last_offset = 0;
747 uint32_t last_type = 0;
748 uint32_t data_item_count = 0;
749 uint32_t data_items_left = data_.size();
750 uint32_t used_bits = 0;
751
752 // Check the validity of the size of the map list.
753 if (!CheckListSize(item, count, sizeof(dex::MapItem), "map size")) {
754 return false;
755 }
756
757 // Check the items listed in the map.
758 for (uint32_t i = 0; i < count; i++) {
759 if (UNLIKELY(last_offset >= item->offset_ && i != 0)) {
760 ErrorStringPrintf("Out of order map item: %x then %x for type %x last type was %x",
761 last_offset,
762 item->offset_,
763 static_cast<uint32_t>(item->type_),
764 last_type);
765 return false;
766 }
767 if (UNLIKELY(item->offset_ >= size_)) {
768 ErrorStringPrintf("Map item after end of file: %x, size %zx", item->offset_, size_);
769 return false;
770 }
771
772 DexFile::MapItemType item_type = static_cast<DexFile::MapItemType>(item->type_);
773 if (IsDataSectionType(item_type)) {
774 uint32_t icount = item->size_;
775 if (UNLIKELY(icount > data_items_left)) {
776 ErrorStringPrintf("Too many items in data section: %ud item_type %zx",
777 data_item_count + icount,
778 static_cast<size_t>(item_type));
779 return false;
780 }
781 data_items_left -= icount;
782 data_item_count += icount;
783 }
784
785 uint32_t bit = MapTypeToBitMask(item_type);
786
787 if (UNLIKELY(bit == 0)) {
788 ErrorStringPrintf("Unknown map section type %x", item->type_);
789 return false;
790 }
791
792 if (UNLIKELY((used_bits & bit) != 0)) {
793 ErrorStringPrintf("Duplicate map section of type %x", item->type_);
794 return false;
795 }
796
797 used_bits |= bit;
798 last_offset = item->offset_;
799 last_type = item->type_;
800 item++;
801 }
802
803 // Check for missing sections in the map.
804 if (UNLIKELY((used_bits & MapTypeToBitMask(DexFile::kDexTypeHeaderItem)) == 0)) {
805 ErrorStringPrintf("Map is missing header entry");
806 return false;
807 }
808 if (UNLIKELY((used_bits & MapTypeToBitMask(DexFile::kDexTypeMapList)) == 0)) {
809 ErrorStringPrintf("Map is missing map_list entry");
810 return false;
811 }
812 if (UNLIKELY((used_bits & MapTypeToBitMask(DexFile::kDexTypeStringIdItem)) == 0 &&
813 ((header_->string_ids_off_ != 0) || (header_->string_ids_size_ != 0)))) {
814 ErrorStringPrintf("Map is missing string_ids entry");
815 return false;
816 }
817 if (UNLIKELY((used_bits & MapTypeToBitMask(DexFile::kDexTypeTypeIdItem)) == 0 &&
818 ((header_->type_ids_off_ != 0) || (header_->type_ids_size_ != 0)))) {
819 ErrorStringPrintf("Map is missing type_ids entry");
820 return false;
821 }
822 if (UNLIKELY((used_bits & MapTypeToBitMask(DexFile::kDexTypeProtoIdItem)) == 0 &&
823 ((header_->proto_ids_off_ != 0) || (header_->proto_ids_size_ != 0)))) {
824 ErrorStringPrintf("Map is missing proto_ids entry");
825 return false;
826 }
827 if (UNLIKELY((used_bits & MapTypeToBitMask(DexFile::kDexTypeFieldIdItem)) == 0 &&
828 ((header_->field_ids_off_ != 0) || (header_->field_ids_size_ != 0)))) {
829 ErrorStringPrintf("Map is missing field_ids entry");
830 return false;
831 }
832 if (UNLIKELY((used_bits & MapTypeToBitMask(DexFile::kDexTypeMethodIdItem)) == 0 &&
833 ((header_->method_ids_off_ != 0) || (header_->method_ids_size_ != 0)))) {
834 ErrorStringPrintf("Map is missing method_ids entry");
835 return false;
836 }
837 if (UNLIKELY((used_bits & MapTypeToBitMask(DexFile::kDexTypeClassDefItem)) == 0 &&
838 ((header_->class_defs_off_ != 0) || (header_->class_defs_size_ != 0)))) {
839 ErrorStringPrintf("Map is missing class_defs entry");
840 return false;
841 }
842 return true;
843 }
844
845 #define DECODE_UNSIGNED_CHECKED_FROM(ptr, var) \
846 uint32_t var; \
847 if (!DecodeUnsignedLeb128Checked(&(ptr), EndOfFile(), &(var))) { \
848 ErrorStringPrintf("Read out of bounds"); \
849 return false; \
850 }
851
852 #define DECODE_SIGNED_CHECKED_FROM(ptr, var) \
853 int32_t var; \
854 if (!DecodeSignedLeb128Checked(&(ptr), EndOfFile(), &(var))) { \
855 ErrorStringPrintf("Read out of bounds"); \
856 return false; \
857 }
858
CheckAndGetHandlerOffsets(const dex::CodeItem * code_item,uint32_t * handler_offsets,uint32_t handlers_size)859 bool DexFileVerifier::CheckAndGetHandlerOffsets(const dex::CodeItem* code_item,
860 uint32_t* handler_offsets,
861 uint32_t handlers_size) {
862 CodeItemDataAccessor accessor(*dex_file_, code_item);
863 const uint8_t* handlers_base = accessor.GetCatchHandlerData();
864
865 for (uint32_t i = 0; i < handlers_size; i++) {
866 bool catch_all;
867 size_t offset = ptr_ - handlers_base;
868 DECODE_SIGNED_CHECKED_FROM(ptr_, size);
869
870 if (UNLIKELY((size < -65536) || (size > 65536))) {
871 ErrorStringPrintf("Invalid exception handler size: %d", size);
872 return false;
873 }
874
875 if (size <= 0) {
876 catch_all = true;
877 size = -size;
878 } else {
879 catch_all = false;
880 }
881
882 handler_offsets[i] = static_cast<uint32_t>(offset);
883
884 while (size-- > 0) {
885 DECODE_UNSIGNED_CHECKED_FROM(ptr_, type_idx);
886 if (!CheckIndex(type_idx, header_->type_ids_size_, "handler type_idx")) {
887 return false;
888 }
889
890 DECODE_UNSIGNED_CHECKED_FROM(ptr_, addr);
891 if (UNLIKELY(addr >= accessor.InsnsSizeInCodeUnits())) {
892 ErrorStringPrintf("Invalid handler addr: %x", addr);
893 return false;
894 }
895 }
896
897 if (catch_all) {
898 DECODE_UNSIGNED_CHECKED_FROM(ptr_, addr);
899 if (UNLIKELY(addr >= accessor.InsnsSizeInCodeUnits())) {
900 ErrorStringPrintf("Invalid handler catch_all_addr: %x", addr);
901 return false;
902 }
903 }
904 }
905
906 return true;
907 }
908
CheckClassDataItemField(uint32_t idx,uint32_t access_flags,uint32_t class_access_flags,dex::TypeIndex class_type_index)909 bool DexFileVerifier::CheckClassDataItemField(uint32_t idx,
910 uint32_t access_flags,
911 uint32_t class_access_flags,
912 dex::TypeIndex class_type_index) {
913 // The `idx` has already been checked in `CheckIntraClassDataItemFields()`.
914 DCHECK_LE(idx, header_->field_ids_size_);
915
916 // Check that it's the right class.
917 dex::TypeIndex my_class_index =
918 OffsetToPtr<dex::FieldId>(header_->field_ids_off_)[idx].class_idx_;
919 if (class_type_index != my_class_index) {
920 ErrorStringPrintf("Field's class index unexpected, %" PRIu16 "vs %" PRIu16,
921 my_class_index.index_,
922 class_type_index.index_);
923 return false;
924 }
925
926 // Check field access flags.
927 std::string error_msg;
928 if (!CheckFieldAccessFlags(idx, access_flags, class_access_flags, &error_msg)) {
929 ErrorStringPrintf("%s", error_msg.c_str());
930 return false;
931 }
932
933 return true;
934 }
935
CheckClassDataItemMethod(uint32_t idx,uint32_t access_flags,uint32_t class_access_flags,dex::TypeIndex class_type_index,uint32_t code_offset,bool expect_direct)936 bool DexFileVerifier::CheckClassDataItemMethod(uint32_t idx,
937 uint32_t access_flags,
938 uint32_t class_access_flags,
939 dex::TypeIndex class_type_index,
940 uint32_t code_offset,
941 bool expect_direct) {
942 // The `idx` has already been checked in `CheckIntraClassDataItemMethods()`.
943 DCHECK_LT(idx, header_->method_ids_size_);
944
945 const dex::MethodId& method_id = OffsetToPtr<dex::MethodId>(header_->method_ids_off_)[idx];
946
947 // Check that it's the right class.
948 dex::TypeIndex my_class_index = method_id.class_idx_;
949 if (class_type_index != my_class_index) {
950 ErrorStringPrintf("Method's class index unexpected, %" PRIu16 " vs %" PRIu16,
951 my_class_index.index_,
952 class_type_index.index_);
953 return false;
954 }
955
956 std::string error_msg;
957 uint32_t constructor_flags_by_name = 0;
958 {
959 uint32_t string_idx = method_id.name_idx_.index_;
960 if (!CheckIndex(string_idx, header_->string_ids_size_, "method flags verification")) {
961 return false;
962 }
963 if (UNLIKELY(string_idx < init_indices_.angle_bracket_end_index) &&
964 string_idx >= init_indices_.angle_bracket_start_index) {
965 if (string_idx == init_indices_.angle_clinit_angle_index) {
966 constructor_flags_by_name = kAccStatic | kAccConstructor;
967 } else if (string_idx == init_indices_.angle_init_angle_index) {
968 constructor_flags_by_name = kAccConstructor;
969 } else {
970 ErrorStringPrintf("Bad method name for method index %u", idx);
971 return false;
972 }
973 }
974 }
975
976 bool has_code = (code_offset != 0);
977 if (!CheckMethodAccessFlags(idx,
978 access_flags,
979 class_access_flags,
980 constructor_flags_by_name,
981 has_code,
982 expect_direct,
983 &error_msg)) {
984 ErrorStringPrintf("%s", error_msg.c_str());
985 return false;
986 }
987
988 if (constructor_flags_by_name != 0) {
989 if (!CheckConstructorProperties(idx, constructor_flags_by_name)) {
990 DCHECK(FailureReasonIsSet());
991 return false;
992 }
993 }
994
995 return true;
996 }
997
CheckPadding(uint32_t aligned_offset,DexFile::MapItemType type)998 bool DexFileVerifier::CheckPadding(uint32_t aligned_offset,
999 DexFile::MapItemType type) {
1000 size_t offset = PtrToOffset(ptr_);
1001 if (offset < aligned_offset) {
1002 if (!CheckListSize(OffsetToPtr(offset), aligned_offset - offset, sizeof(uint8_t), "section")) {
1003 return false;
1004 }
1005 if (dex_version_ >= 41) {
1006 ptr_ += aligned_offset - offset;
1007 return true;
1008 }
1009 while (offset < aligned_offset) {
1010 if (UNLIKELY(*ptr_ != '\0')) {
1011 ErrorStringPrintf("Non-zero padding %x before section of type %zu at offset 0x%zx",
1012 *ptr_,
1013 static_cast<size_t>(type),
1014 offset);
1015 return false;
1016 }
1017 ptr_++;
1018 offset++;
1019 }
1020 }
1021 return true;
1022 }
1023
CheckEncodedValue()1024 bool DexFileVerifier::CheckEncodedValue() {
1025 if (!CheckListSize(ptr_, 1, sizeof(uint8_t), "encoded_value header")) {
1026 return false;
1027 }
1028
1029 uint8_t header_byte = *(ptr_++);
1030 uint32_t value_type = header_byte & DexFile::kDexAnnotationValueTypeMask;
1031 uint32_t value_arg = header_byte >> DexFile::kDexAnnotationValueArgShift;
1032
1033 switch (value_type) {
1034 case DexFile::kDexAnnotationByte: {
1035 if (UNLIKELY(value_arg != 0)) {
1036 ErrorStringPrintf("Bad encoded_value byte size %x", value_arg);
1037 return false;
1038 }
1039 uint32_t value;
1040 if (!ReadUnsignedLittleEndian(value_arg + 1, &value)) {
1041 return false;
1042 }
1043 break;
1044 }
1045 case DexFile::kDexAnnotationShort:
1046 case DexFile::kDexAnnotationChar: {
1047 if (UNLIKELY(value_arg > 1)) {
1048 ErrorStringPrintf("Bad encoded_value char/short size %x", value_arg);
1049 return false;
1050 }
1051 uint32_t value;
1052 if (!ReadUnsignedLittleEndian(value_arg + 1, &value)) {
1053 return false;
1054 }
1055 break;
1056 }
1057 case DexFile::kDexAnnotationInt:
1058 case DexFile::kDexAnnotationFloat: {
1059 if (UNLIKELY(value_arg > 3)) {
1060 ErrorStringPrintf("Bad encoded_value int/float size %x", value_arg);
1061 return false;
1062 }
1063 uint32_t value;
1064 if (!ReadUnsignedLittleEndian(value_arg + 1, &value)) {
1065 return false;
1066 }
1067 break;
1068 }
1069 case DexFile::kDexAnnotationLong:
1070 case DexFile::kDexAnnotationDouble: {
1071 uint32_t value;
1072 if (!ReadUnsignedLittleEndian(value_arg + 1, &value)) {
1073 return false;
1074 }
1075 break;
1076 }
1077 case DexFile::kDexAnnotationString: {
1078 if (UNLIKELY(value_arg > 3)) {
1079 ErrorStringPrintf("Bad encoded_value string size %x", value_arg);
1080 return false;
1081 }
1082 uint32_t idx;
1083 if (!ReadUnsignedLittleEndian(value_arg + 1, &idx)) {
1084 return false;
1085 }
1086 if (!CheckIndex(idx, header_->string_ids_size_, "encoded_value string")) {
1087 return false;
1088 }
1089 break;
1090 }
1091 case DexFile::kDexAnnotationType: {
1092 if (UNLIKELY(value_arg > 3)) {
1093 ErrorStringPrintf("Bad encoded_value type size %x", value_arg);
1094 return false;
1095 }
1096 uint32_t idx;
1097 if (!ReadUnsignedLittleEndian(value_arg + 1, &idx)) {
1098 return false;
1099 }
1100 if (!CheckIndex(idx, header_->type_ids_size_, "encoded_value type")) {
1101 return false;
1102 }
1103 break;
1104 }
1105 case DexFile::kDexAnnotationField:
1106 case DexFile::kDexAnnotationEnum: {
1107 if (UNLIKELY(value_arg > 3)) {
1108 ErrorStringPrintf("Bad encoded_value field/enum size %x", value_arg);
1109 return false;
1110 }
1111 uint32_t idx;
1112 if (!ReadUnsignedLittleEndian(value_arg + 1, &idx)) {
1113 return false;
1114 }
1115 if (!CheckIndex(idx, header_->field_ids_size_, "encoded_value field")) {
1116 return false;
1117 }
1118 break;
1119 }
1120 case DexFile::kDexAnnotationMethod: {
1121 if (UNLIKELY(value_arg > 3)) {
1122 ErrorStringPrintf("Bad encoded_value method size %x", value_arg);
1123 return false;
1124 }
1125 uint32_t idx;
1126 if (!ReadUnsignedLittleEndian(value_arg + 1, &idx)) {
1127 return false;
1128 }
1129 if (!CheckIndex(idx, header_->method_ids_size_, "encoded_value method")) {
1130 return false;
1131 }
1132 break;
1133 }
1134 case DexFile::kDexAnnotationArray:
1135 if (UNLIKELY(value_arg != 0)) {
1136 ErrorStringPrintf("Bad encoded_value array value_arg %x", value_arg);
1137 return false;
1138 }
1139 if (!CheckEncodedArray()) {
1140 return false;
1141 }
1142 break;
1143 case DexFile::kDexAnnotationAnnotation:
1144 if (UNLIKELY(value_arg != 0)) {
1145 ErrorStringPrintf("Bad encoded_value annotation value_arg %x", value_arg);
1146 return false;
1147 }
1148 if (!CheckEncodedAnnotation()) {
1149 return false;
1150 }
1151 break;
1152 case DexFile::kDexAnnotationNull:
1153 if (UNLIKELY(value_arg != 0)) {
1154 ErrorStringPrintf("Bad encoded_value null value_arg %x", value_arg);
1155 return false;
1156 }
1157 break;
1158 case DexFile::kDexAnnotationBoolean:
1159 if (UNLIKELY(value_arg > 1)) {
1160 ErrorStringPrintf("Bad encoded_value boolean size %x", value_arg);
1161 return false;
1162 }
1163 break;
1164 case DexFile::kDexAnnotationMethodType: {
1165 if (UNLIKELY(value_arg > 3)) {
1166 ErrorStringPrintf("Bad encoded_value method type size %x", value_arg);
1167 return false;
1168 }
1169 uint32_t idx;
1170 if (!ReadUnsignedLittleEndian(value_arg + 1, &idx)) {
1171 return false;
1172 }
1173 if (!CheckIndex(idx, header_->proto_ids_size_, "method_type value")) {
1174 return false;
1175 }
1176 break;
1177 }
1178 case DexFile::kDexAnnotationMethodHandle: {
1179 if (UNLIKELY(value_arg > 3)) {
1180 ErrorStringPrintf("Bad encoded_value method handle size %x", value_arg);
1181 return false;
1182 }
1183 uint32_t idx;
1184 if (!ReadUnsignedLittleEndian(value_arg + 1, &idx)) {
1185 return false;
1186 }
1187 if (!CheckIndex(idx, dex_file_->NumMethodHandles(), "method_handle value")) {
1188 return false;
1189 }
1190 break;
1191 }
1192 default:
1193 ErrorStringPrintf("Bogus encoded_value value_type %x", value_type);
1194 return false;
1195 }
1196
1197 return true;
1198 }
1199
CheckEncodedArray()1200 bool DexFileVerifier::CheckEncodedArray() {
1201 DECODE_UNSIGNED_CHECKED_FROM(ptr_, size);
1202 todo_.emplace(ToDoItem{.array_size = size});
1203 return true;
1204 }
1205
1206 // Always called directly from FlushToDoList, which avoids recursion.
CheckArrayElement()1207 bool DexFileVerifier::CheckArrayElement() {
1208 if (!CheckEncodedValue()) {
1209 failure_reason_ = StringPrintf("Bad encoded_array value: %s", failure_reason_.c_str());
1210 return false;
1211 }
1212 return true;
1213 }
1214
CheckEncodedAnnotation()1215 bool DexFileVerifier::CheckEncodedAnnotation() {
1216 DECODE_UNSIGNED_CHECKED_FROM(ptr_, anno_idx);
1217 if (!CheckIndex(anno_idx, header_->type_ids_size_, "encoded_annotation type_idx")) {
1218 return false;
1219 }
1220
1221 DECODE_UNSIGNED_CHECKED_FROM(ptr_, size);
1222 todo_.emplace(ToDoItem{.annotation_size = size, .last_idx = kDexNoIndex});
1223 return true;
1224 }
1225
1226 // Always called directly from FlushToDoList, which avoids recursion.
CheckAnnotationElement(uint32_t * last_idx)1227 bool DexFileVerifier::CheckAnnotationElement(/*inout*/ uint32_t* last_idx) {
1228 DECODE_UNSIGNED_CHECKED_FROM(ptr_, idx);
1229 if (!CheckIndex(idx, header_->string_ids_size_, "annotation_element name_idx")) {
1230 return false;
1231 }
1232
1233 if (UNLIKELY(*last_idx >= idx && *last_idx != kDexNoIndex)) {
1234 ErrorStringPrintf("Out-of-order annotation_element name_idx: %x then %x", *last_idx, idx);
1235 return false;
1236 }
1237 *last_idx = idx;
1238
1239 return CheckEncodedValue();
1240 }
1241
1242 // Keep processing the rest of the to-do list until we are finished or encounter an error.
FlushToDoList()1243 bool DexFileVerifier::FlushToDoList() {
1244 while (!todo_.empty()) {
1245 ToDoItem& item = todo_.top();
1246 DCHECK(item.array_size == 0u || item.annotation_size == 0u);
1247 if (item.array_size > 0) {
1248 item.array_size--;
1249 if (!CheckArrayElement()) {
1250 return false;
1251 }
1252 } else if (item.annotation_size > 0) {
1253 item.annotation_size--;
1254 if (!CheckAnnotationElement(&item.last_idx)) {
1255 return false;
1256 }
1257 } else {
1258 todo_.pop();
1259 }
1260 }
1261 return true;
1262 }
1263
CheckStaticFieldTypes(const dex::ClassDef & class_def)1264 bool DexFileVerifier::CheckStaticFieldTypes(const dex::ClassDef& class_def) {
1265 ClassAccessor accessor(*dex_file_, ptr_);
1266 EncodedStaticFieldValueIterator array_it(*dex_file_, class_def);
1267
1268 for (const ClassAccessor::Field& field : accessor.GetStaticFields()) {
1269 if (!array_it.HasNext()) {
1270 break;
1271 }
1272 uint32_t index = field.GetIndex();
1273 // The `index` has already been checked in `CheckIntraClassDataItemFields()`.
1274 DCHECK_LT(index, header_->field_ids_size_);
1275 const dex::TypeId& type_id = dex_file_->GetTypeId(dex_file_->GetFieldId(index).type_idx_);
1276 const char* field_type_name =
1277 dex_file_->GetStringData(dex_file_->GetStringId(type_id.descriptor_idx_));
1278 Primitive::Type field_type = Primitive::GetType(field_type_name[0]);
1279 EncodedArrayValueIterator::ValueType array_type = array_it.GetValueType();
1280 // Ensure this matches RuntimeEncodedStaticFieldValueIterator.
1281 switch (array_type) {
1282 case EncodedArrayValueIterator::ValueType::kBoolean:
1283 if (field_type != Primitive::kPrimBoolean) {
1284 ErrorStringPrintf("unexpected static field initial value type: 'Z' vs '%c'",
1285 field_type_name[0]);
1286 return false;
1287 }
1288 break;
1289 case EncodedArrayValueIterator::ValueType::kByte:
1290 if (field_type != Primitive::kPrimByte) {
1291 ErrorStringPrintf("unexpected static field initial value type: 'B' vs '%c'",
1292 field_type_name[0]);
1293 return false;
1294 }
1295 break;
1296 case EncodedArrayValueIterator::ValueType::kShort:
1297 if (field_type != Primitive::kPrimShort) {
1298 ErrorStringPrintf("unexpected static field initial value type: 'S' vs '%c'",
1299 field_type_name[0]);
1300 return false;
1301 }
1302 break;
1303 case EncodedArrayValueIterator::ValueType::kChar:
1304 if (field_type != Primitive::kPrimChar) {
1305 ErrorStringPrintf("unexpected static field initial value type: 'C' vs '%c'",
1306 field_type_name[0]);
1307 return false;
1308 }
1309 break;
1310 case EncodedArrayValueIterator::ValueType::kInt:
1311 if (field_type != Primitive::kPrimInt) {
1312 ErrorStringPrintf("unexpected static field initial value type: 'I' vs '%c'",
1313 field_type_name[0]);
1314 return false;
1315 }
1316 break;
1317 case EncodedArrayValueIterator::ValueType::kLong:
1318 if (field_type != Primitive::kPrimLong) {
1319 ErrorStringPrintf("unexpected static field initial value type: 'J' vs '%c'",
1320 field_type_name[0]);
1321 return false;
1322 }
1323 break;
1324 case EncodedArrayValueIterator::ValueType::kFloat:
1325 if (field_type != Primitive::kPrimFloat) {
1326 ErrorStringPrintf("unexpected static field initial value type: 'F' vs '%c'",
1327 field_type_name[0]);
1328 return false;
1329 }
1330 break;
1331 case EncodedArrayValueIterator::ValueType::kDouble:
1332 if (field_type != Primitive::kPrimDouble) {
1333 ErrorStringPrintf("unexpected static field initial value type: 'D' vs '%c'",
1334 field_type_name[0]);
1335 return false;
1336 }
1337 break;
1338 case EncodedArrayValueIterator::ValueType::kNull:
1339 case EncodedArrayValueIterator::ValueType::kString:
1340 case EncodedArrayValueIterator::ValueType::kType:
1341 if (field_type != Primitive::kPrimNot) {
1342 ErrorStringPrintf("unexpected static field initial value type: 'L' vs '%c'",
1343 field_type_name[0]);
1344 return false;
1345 }
1346 break;
1347 default:
1348 ErrorStringPrintf("unexpected static field initial value type: %x", array_type);
1349 return false;
1350 }
1351 if (!array_it.MaybeNext()) {
1352 ErrorStringPrintf("unexpected encoded value type: '%c'", array_it.GetValueType());
1353 return false;
1354 }
1355 }
1356
1357 if (array_it.HasNext()) {
1358 ErrorStringPrintf("too many static field initial values");
1359 return false;
1360 }
1361 return true;
1362 }
1363
CheckIntraTypeIdItem()1364 bool DexFileVerifier::CheckIntraTypeIdItem() {
1365 if (!CheckListSize(ptr_, 1, sizeof(dex::TypeId), "type_ids")) {
1366 return false;
1367 }
1368
1369 const dex::TypeId* type_id = reinterpret_cast<const dex::TypeId*>(ptr_);
1370 if (!CheckIndex(type_id->descriptor_idx_.index_,
1371 header_->string_ids_size_,
1372 "type_id.descriptor")) {
1373 return false;
1374 }
1375
1376 ptr_ += sizeof(dex::TypeId);
1377 return true;
1378 }
1379
CheckIntraProtoIdItem()1380 bool DexFileVerifier::CheckIntraProtoIdItem() {
1381 if (!CheckListSize(ptr_, 1, sizeof(dex::ProtoId), "proto_ids")) {
1382 return false;
1383 }
1384
1385 const dex::ProtoId* proto_id = reinterpret_cast<const dex::ProtoId*>(ptr_);
1386 if (!CheckIndex(proto_id->shorty_idx_.index_, header_->string_ids_size_, "proto_id.shorty") ||
1387 !CheckIndex(proto_id->return_type_idx_.index_,
1388 header_->type_ids_size_,
1389 "proto_id.return_type")) {
1390 return false;
1391 }
1392
1393 ptr_ += sizeof(dex::ProtoId);
1394 return true;
1395 }
1396
CheckIntraFieldIdItem()1397 bool DexFileVerifier::CheckIntraFieldIdItem() {
1398 if (!CheckListSize(ptr_, 1, sizeof(dex::FieldId), "field_ids")) {
1399 return false;
1400 }
1401
1402 const dex::FieldId* field_id = reinterpret_cast<const dex::FieldId*>(ptr_);
1403 if (!CheckIndex(field_id->class_idx_.index_, header_->type_ids_size_, "field_id.class") ||
1404 !CheckIndex(field_id->type_idx_.index_, header_->type_ids_size_, "field_id.type") ||
1405 !CheckIndex(field_id->name_idx_.index_, header_->string_ids_size_, "field_id.name")) {
1406 return false;
1407 }
1408
1409 ptr_ += sizeof(dex::FieldId);
1410 return true;
1411 }
1412
CheckIntraMethodIdItem()1413 bool DexFileVerifier::CheckIntraMethodIdItem() {
1414 if (!CheckListSize(ptr_, 1, sizeof(dex::MethodId), "method_ids")) {
1415 return false;
1416 }
1417
1418 const dex::MethodId* method_id = reinterpret_cast<const dex::MethodId*>(ptr_);
1419 if (!CheckIndex(method_id->class_idx_.index_, header_->type_ids_size_, "method_id.class") ||
1420 !CheckIndex(method_id->proto_idx_.index_, header_->proto_ids_size_, "method_id.proto") ||
1421 !CheckIndex(method_id->name_idx_.index_, header_->string_ids_size_, "method_id.name")) {
1422 return false;
1423 }
1424
1425 ptr_ += sizeof(dex::MethodId);
1426 return true;
1427 }
1428
CheckIntraClassDefItem(uint32_t class_def_index)1429 bool DexFileVerifier::CheckIntraClassDefItem(uint32_t class_def_index) {
1430 if (!CheckListSize(ptr_, 1, sizeof(dex::ClassDef), "class_defs")) {
1431 return false;
1432 }
1433
1434 const dex::ClassDef* class_def = reinterpret_cast<const dex::ClassDef*>(ptr_);
1435 if (!CheckIndex(class_def->class_idx_.index_, header_->type_ids_size_, "class_def.class")) {
1436 return false;
1437 }
1438
1439 // Check superclass, if any.
1440 if (UNLIKELY(class_def->pad2_ != 0u)) {
1441 uint32_t combined =
1442 (static_cast<uint32_t>(class_def->pad2_) << 16) + class_def->superclass_idx_.index_;
1443 if (combined != 0xffffffffu) {
1444 ErrorStringPrintf("Invalid superclass type padding/index: %x", combined);
1445 return false;
1446 }
1447 } else if (!CheckIndex(class_def->superclass_idx_.index_,
1448 header_->type_ids_size_,
1449 "class_def.superclass")) {
1450 return false;
1451 }
1452
1453 DCHECK_LE(class_def->class_idx_.index_, kTypeIdLimit);
1454 DCHECK_LT(kTypeIdLimit, defined_classes_.size());
1455 if (defined_classes_[class_def->class_idx_.index_]) {
1456 ErrorStringPrintf("Redefinition of class with type idx: '%u'", class_def->class_idx_.index_);
1457 return false;
1458 }
1459 defined_classes_[class_def->class_idx_.index_] = true;
1460 DCHECK_LE(class_def->class_idx_.index_, defined_class_indexes_.size());
1461 defined_class_indexes_[class_def->class_idx_.index_] = class_def_index;
1462
1463 ptr_ += sizeof(dex::ClassDef);
1464 return true;
1465 }
1466
CheckIntraMethodHandleItem()1467 bool DexFileVerifier::CheckIntraMethodHandleItem() {
1468 if (!CheckListSize(ptr_, 1, sizeof(dex::MethodHandleItem), "method_handles")) {
1469 return false;
1470 }
1471
1472 const dex::MethodHandleItem* item = reinterpret_cast<const dex::MethodHandleItem*>(ptr_);
1473
1474 DexFile::MethodHandleType method_handle_type =
1475 static_cast<DexFile::MethodHandleType>(item->method_handle_type_);
1476 if (method_handle_type > DexFile::MethodHandleType::kLast) {
1477 ErrorStringPrintf("Bad method handle type %x", item->method_handle_type_);
1478 return false;
1479 }
1480
1481 uint32_t index = item->field_or_method_idx_;
1482 switch (method_handle_type) {
1483 case DexFile::MethodHandleType::kStaticPut:
1484 case DexFile::MethodHandleType::kStaticGet:
1485 case DexFile::MethodHandleType::kInstancePut:
1486 case DexFile::MethodHandleType::kInstanceGet:
1487 if (!CheckIndex(index, header_->field_ids_size_, "method_handle_item field_idx")) {
1488 return false;
1489 }
1490 break;
1491 case DexFile::MethodHandleType::kInvokeStatic:
1492 case DexFile::MethodHandleType::kInvokeInstance:
1493 case DexFile::MethodHandleType::kInvokeConstructor:
1494 case DexFile::MethodHandleType::kInvokeDirect:
1495 case DexFile::MethodHandleType::kInvokeInterface: {
1496 if (!CheckIndex(index, header_->method_ids_size_, "method_handle_item method_idx")) {
1497 return false;
1498 }
1499 break;
1500 }
1501 }
1502
1503 ptr_ += sizeof(dex::MethodHandleItem);
1504 return true;
1505 }
1506
CheckIntraTypeList()1507 bool DexFileVerifier::CheckIntraTypeList() {
1508 const dex::TypeList* type_list = reinterpret_cast<const dex::TypeList*>(ptr_);
1509 if (!CheckList(sizeof(dex::TypeItem), "type_list", &ptr_)) {
1510 return false;
1511 }
1512
1513 for (uint32_t i = 0, size = type_list->Size(); i != size; ++i) {
1514 if (!CheckIndex(type_list->GetTypeItem(i).type_idx_.index_,
1515 header_->type_ids_size_,
1516 "type_list.type")) {
1517 return false;
1518 }
1519 }
1520
1521 return true;
1522 }
1523
1524 template <bool kStatic>
CheckIntraClassDataItemFields(size_t count)1525 bool DexFileVerifier::CheckIntraClassDataItemFields(size_t count) {
1526 constexpr const char* kTypeDescr = kStatic ? "static field" : "instance field";
1527
1528 // We cannot use ClassAccessor::Field yet as it could read beyond the end of the data section.
1529 const uint8_t* ptr = ptr_;
1530
1531 uint32_t prev_index = 0;
1532 for (size_t i = 0; i != count; ++i) {
1533 uint32_t field_idx_diff, access_flags;
1534 if (UNLIKELY(!DecodeUnsignedLeb128Checked(&ptr, data_.end(), &field_idx_diff)) ||
1535 UNLIKELY(!DecodeUnsignedLeb128Checked(&ptr, data_.end(), &access_flags))) {
1536 ErrorStringPrintf("encoded_field read out of bounds");
1537 return false;
1538 }
1539 uint32_t curr_index = prev_index + field_idx_diff;
1540 // Check for overflow.
1541 if (!CheckIndex(curr_index, header_->field_ids_size_, "class_data_item field_idx")) {
1542 return false;
1543 }
1544 if (!CheckOrder(kTypeDescr, curr_index, prev_index)) {
1545 return false;
1546 }
1547 // Check that it falls into the right class-data list.
1548 bool is_static = (access_flags & kAccStatic) != 0;
1549 if (UNLIKELY(is_static != kStatic)) {
1550 ErrorStringPrintf("Static/instance field not in expected list");
1551 return false;
1552 }
1553
1554 prev_index = curr_index;
1555 }
1556
1557 ptr_ = ptr;
1558 return true;
1559 }
1560
CheckIntraClassDataItemMethods(size_t num_methods,ClassAccessor::Method * direct_methods,size_t num_direct_methods)1561 bool DexFileVerifier::CheckIntraClassDataItemMethods(size_t num_methods,
1562 ClassAccessor::Method* direct_methods,
1563 size_t num_direct_methods) {
1564 DCHECK(num_direct_methods == 0u || direct_methods != nullptr);
1565 const char* kTypeDescr = (direct_methods == nullptr) ? "direct method" : "virtual method";
1566
1567 // We cannot use ClassAccessor::Method yet as it could read beyond the end of the data section.
1568 const uint8_t* ptr = ptr_;
1569
1570 // Load the first direct method for the check below.
1571 size_t remaining_direct_methods = num_direct_methods;
1572 if (remaining_direct_methods != 0u) {
1573 DCHECK(direct_methods != nullptr);
1574 direct_methods->Read();
1575 }
1576
1577 uint32_t prev_index = 0;
1578 for (size_t i = 0; i != num_methods; ++i) {
1579 uint32_t method_idx_diff, access_flags, code_off;
1580 if (UNLIKELY(!DecodeUnsignedLeb128Checked(&ptr, data_.end(), &method_idx_diff)) ||
1581 UNLIKELY(!DecodeUnsignedLeb128Checked(&ptr, data_.end(), &access_flags)) ||
1582 UNLIKELY(!DecodeUnsignedLeb128Checked(&ptr, data_.end(), &code_off))) {
1583 ErrorStringPrintf("encoded_method read out of bounds");
1584 return false;
1585 }
1586 uint32_t curr_index = prev_index + method_idx_diff;
1587 // Check for overflow.
1588 if (!CheckIndex(curr_index, header_->method_ids_size_, "class_data_item method_idx")) {
1589 return false;
1590 }
1591 if (!CheckOrder(kTypeDescr, curr_index, prev_index)) {
1592 return false;
1593 }
1594
1595 // For virtual methods, we cross reference the method index to make sure
1596 // it doesn't match any direct methods.
1597 if (remaining_direct_methods != 0) {
1598 // The direct methods are already known to be in ascending index order.
1599 // So just keep up with the current index.
1600 while (true) {
1601 const uint32_t direct_idx = direct_methods->GetIndex();
1602 if (direct_idx > curr_index) {
1603 break;
1604 }
1605 if (direct_idx == curr_index) {
1606 ErrorStringPrintf("Found virtual method with same index as direct method: %u",
1607 curr_index);
1608 return false;
1609 }
1610 --remaining_direct_methods;
1611 if (remaining_direct_methods == 0u) {
1612 break;
1613 }
1614 direct_methods->Read();
1615 }
1616 }
1617
1618 prev_index = curr_index;
1619 }
1620
1621 ptr_ = ptr;
1622 return true;
1623 }
1624
CheckIntraClassDataItem()1625 bool DexFileVerifier::CheckIntraClassDataItem() {
1626 // We cannot use ClassAccessor yet as it could read beyond the end of the data section.
1627 const uint8_t* ptr = ptr_;
1628 uint32_t static_fields_size, instance_fields_size, direct_methods_size, virtual_methods_size;
1629 if (UNLIKELY(!DecodeUnsignedLeb128Checked(&ptr, data_.end(), &static_fields_size)) ||
1630 UNLIKELY(!DecodeUnsignedLeb128Checked(&ptr, data_.end(), &instance_fields_size)) ||
1631 UNLIKELY(!DecodeUnsignedLeb128Checked(&ptr, data_.end(), &direct_methods_size)) ||
1632 UNLIKELY(!DecodeUnsignedLeb128Checked(&ptr, data_.end(), &virtual_methods_size))) {
1633 ErrorStringPrintf("class_data_item read out of bounds");
1634 return false;
1635 }
1636 ptr_ = ptr;
1637
1638 // Check fields.
1639 if (!CheckIntraClassDataItemFields</*kStatic=*/ true>(static_fields_size)) {
1640 return false;
1641 }
1642 if (!CheckIntraClassDataItemFields</*kStatic=*/ false>(instance_fields_size)) {
1643 return false;
1644 }
1645
1646 // Check methods.
1647 const uint8_t* direct_methods_ptr = ptr_;
1648 if (!CheckIntraClassDataItemMethods(direct_methods_size,
1649 /*direct_methods=*/ nullptr,
1650 /*num_direct_methods=*/ 0u)) {
1651 return false;
1652 }
1653 // Direct methods have been checked, so we can now use ClassAccessor::Method to read them again.
1654 ClassAccessor::Method direct_methods(*dex_file_, direct_methods_ptr);
1655 if (!CheckIntraClassDataItemMethods(virtual_methods_size, &direct_methods, direct_methods_size)) {
1656 return false;
1657 }
1658
1659 return true;
1660 }
1661
CheckIntraCodeItem()1662 bool DexFileVerifier::CheckIntraCodeItem() {
1663 const dex::CodeItem* code_item = reinterpret_cast<const dex::CodeItem*>(ptr_);
1664
1665 DCHECK(dex_file_->IsStandardDexFile());
1666 if (!CheckListSize(code_item, 1, sizeof(StandardDexFile::CodeItem), "code")) {
1667 return false;
1668 }
1669
1670 CodeItemDataAccessor accessor(*dex_file_, code_item);
1671 if (UNLIKELY(accessor.InsSize() > accessor.RegistersSize())) {
1672 ErrorStringPrintf("ins_size (%ud) > registers_size (%ud)",
1673 accessor.InsSize(), accessor.RegistersSize());
1674 return false;
1675 }
1676
1677 if (UNLIKELY(accessor.OutsSize() > 5 && accessor.OutsSize() > accessor.RegistersSize())) {
1678 /*
1679 * outs_size can be up to 5, even if registers_size is smaller, since the
1680 * short forms of method invocation allow repetitions of a register multiple
1681 * times within a single parameter list. However, longer parameter lists
1682 * need to be represented in-order in the register file.
1683 */
1684 ErrorStringPrintf("outs_size (%ud) > registers_size (%ud)",
1685 accessor.OutsSize(), accessor.RegistersSize());
1686 return false;
1687 }
1688
1689 const uint16_t* insns = accessor.Insns();
1690 uint32_t insns_size = accessor.InsnsSizeInCodeUnits();
1691 if (!CheckListSize(insns, insns_size, sizeof(uint16_t), "insns size")) {
1692 return false;
1693 }
1694
1695 // Grab the end of the insns if there are no try_items.
1696 uint32_t try_items_size = accessor.TriesSize();
1697 if (try_items_size == 0) {
1698 ptr_ = reinterpret_cast<const uint8_t*>(&insns[insns_size]);
1699 return true;
1700 }
1701
1702 const dex::TryItem* try_items = accessor.TryItems().begin();
1703 if (!CheckListSize(try_items, try_items_size, sizeof(dex::TryItem), "try_items size")) {
1704 return false;
1705 }
1706
1707 // try_items are 4-byte aligned. Verify the spacer is 0.
1708 if (((reinterpret_cast<uintptr_t>(&insns[insns_size]) & 3) != 0) && (insns[insns_size] != 0)) {
1709 ErrorStringPrintf("Non-zero padding: %x", insns[insns_size]);
1710 return false;
1711 }
1712
1713 ptr_ = accessor.GetCatchHandlerData();
1714 DECODE_UNSIGNED_CHECKED_FROM(ptr_, handlers_size);
1715
1716 if (UNLIKELY((handlers_size == 0) || (handlers_size >= 65536))) {
1717 ErrorStringPrintf("Invalid handlers_size: %ud", handlers_size);
1718 return false;
1719 }
1720
1721 // Avoid an expensive allocation, if possible.
1722 std::unique_ptr<uint32_t[]> handler_offsets_uptr;
1723 uint32_t* handler_offsets;
1724 constexpr size_t kAllocaMaxSize = 1024;
1725 if (handlers_size < kAllocaMaxSize/sizeof(uint32_t)) {
1726 // Note: Clang does not specify alignment guarantees for alloca. So align by hand.
1727 handler_offsets =
1728 AlignUp(reinterpret_cast<uint32_t*>(alloca((handlers_size + 1) * sizeof(uint32_t))),
1729 alignof(uint32_t[]));
1730 } else {
1731 handler_offsets_uptr.reset(new uint32_t[handlers_size]);
1732 handler_offsets = handler_offsets_uptr.get();
1733 }
1734
1735 if (!CheckAndGetHandlerOffsets(code_item, &handler_offsets[0], handlers_size)) {
1736 return false;
1737 }
1738
1739 uint32_t last_addr = 0;
1740 for (; try_items_size != 0u; --try_items_size) {
1741 if (UNLIKELY(try_items->start_addr_ < last_addr)) {
1742 ErrorStringPrintf("Out-of_order try_item with start_addr: %x", try_items->start_addr_);
1743 return false;
1744 }
1745
1746 if (UNLIKELY(try_items->start_addr_ >= insns_size)) {
1747 ErrorStringPrintf("Invalid try_item start_addr: %x", try_items->start_addr_);
1748 return false;
1749 }
1750
1751 uint32_t i;
1752 for (i = 0; i < handlers_size; i++) {
1753 if (try_items->handler_off_ == handler_offsets[i]) {
1754 break;
1755 }
1756 }
1757
1758 if (UNLIKELY(i == handlers_size)) {
1759 ErrorStringPrintf("Bogus handler offset: %x", try_items->handler_off_);
1760 return false;
1761 }
1762
1763 last_addr = try_items->start_addr_ + try_items->insn_count_;
1764 if (UNLIKELY(last_addr > insns_size)) {
1765 ErrorStringPrintf("Invalid try_item insn_count: %x", try_items->insn_count_);
1766 return false;
1767 }
1768
1769 try_items++;
1770 }
1771
1772 return true;
1773 }
1774
CheckIntraStringDataItem()1775 bool DexFileVerifier::CheckIntraStringDataItem() {
1776 DECODE_UNSIGNED_CHECKED_FROM(ptr_, size);
1777 const uint8_t* file_end = EndOfFile();
1778
1779 size_t available_bytes = static_cast<size_t>(file_end - ptr_);
1780 if (available_bytes < size) {
1781 ErrorStringPrintf("String data would go beyond end-of-file");
1782 return false;
1783 }
1784 // Eagerly subtract one byte per character.
1785 available_bytes -= size;
1786
1787 for (uint32_t i = 0; i < size; i++) {
1788 CHECK_LT(i, size); // b/15014252 Prevents hitting the impossible case below
1789 uint8_t byte = *(ptr_++);
1790
1791 // Switch on the high 4 bits.
1792 switch (byte >> 4) {
1793 case 0x00:
1794 // Special case of bit pattern 0xxx.
1795 if (UNLIKELY(byte == 0)) {
1796 CHECK_LT(i, size); // b/15014252 Actually hit this impossible case with clang
1797 ErrorStringPrintf("String data shorter than indicated utf16_size %x", size);
1798 return false;
1799 }
1800 break;
1801 case 0x01:
1802 case 0x02:
1803 case 0x03:
1804 case 0x04:
1805 case 0x05:
1806 case 0x06:
1807 case 0x07:
1808 // No extra checks necessary for bit pattern 0xxx.
1809 break;
1810 case 0x08:
1811 case 0x09:
1812 case 0x0a:
1813 case 0x0b:
1814 case 0x0f:
1815 // Illegal bit patterns 10xx or 1111.
1816 // Note: 1111 is valid for normal UTF-8, but not here.
1817 ErrorStringPrintf("Illegal start byte %x in string data", byte);
1818 return false;
1819 case 0x0c:
1820 case 0x0d: {
1821 // Bit pattern 110x has an additional byte.
1822 if (available_bytes < 1u) {
1823 ErrorStringPrintf("String data would go beyond end-of-file");
1824 return false;
1825 }
1826 available_bytes -= 1u;
1827
1828 uint8_t byte2 = *(ptr_++);
1829 if (UNLIKELY((byte2 & 0xc0) != 0x80)) {
1830 ErrorStringPrintf("Illegal continuation byte %x in string data", byte2);
1831 return false;
1832 }
1833 uint16_t value = ((byte & 0x1f) << 6) | (byte2 & 0x3f);
1834 if (UNLIKELY((value != 0) && (value < 0x80))) {
1835 ErrorStringPrintf("Illegal representation for value %x in string data", value);
1836 return false;
1837 }
1838 break;
1839 }
1840 case 0x0e: {
1841 // Bit pattern 1110 has 2 additional bytes.
1842 if (available_bytes < 2u) {
1843 ErrorStringPrintf("String data would go beyond end-of-file");
1844 return false;
1845 }
1846 available_bytes -= 2u;
1847
1848 uint8_t byte2 = *(ptr_++);
1849 if (UNLIKELY((byte2 & 0xc0) != 0x80)) {
1850 ErrorStringPrintf("Illegal continuation byte %x in string data", byte2);
1851 return false;
1852 }
1853 uint8_t byte3 = *(ptr_++);
1854 if (UNLIKELY((byte3 & 0xc0) != 0x80)) {
1855 ErrorStringPrintf("Illegal continuation byte %x in string data", byte3);
1856 return false;
1857 }
1858 uint16_t value = ((byte & 0x0f) << 12) | ((byte2 & 0x3f) << 6) | (byte3 & 0x3f);
1859 if (UNLIKELY(value < 0x800)) {
1860 ErrorStringPrintf("Illegal representation for value %x in string data", value);
1861 return false;
1862 }
1863 break;
1864 }
1865 }
1866 }
1867
1868 if (available_bytes < 1u) {
1869 ErrorStringPrintf("String data would go beyond end-of-file");
1870 return false;
1871 }
1872 available_bytes -= 1u;
1873
1874 if (UNLIKELY(*(ptr_++) != '\0')) {
1875 ErrorStringPrintf("String longer than indicated size %x", size);
1876 return false;
1877 }
1878
1879 DCHECK_EQ(available_bytes, static_cast<size_t>(file_end - ptr_));
1880 return true;
1881 }
1882
CheckIntraDebugInfoItem()1883 bool DexFileVerifier::CheckIntraDebugInfoItem() {
1884 DECODE_UNSIGNED_CHECKED_FROM(ptr_, unused_line_start);
1885 DECODE_UNSIGNED_CHECKED_FROM(ptr_, parameters_size);
1886 if (UNLIKELY(parameters_size > 65536)) {
1887 ErrorStringPrintf("Invalid parameters_size: %x", parameters_size);
1888 return false;
1889 }
1890
1891 for (uint32_t j = 0; j < parameters_size; j++) {
1892 DECODE_UNSIGNED_CHECKED_FROM(ptr_, parameter_name);
1893 if (parameter_name != 0) {
1894 parameter_name--;
1895 if (!CheckIndex(parameter_name, header_->string_ids_size_, "debug_info_item parameter_name")) {
1896 return false;
1897 }
1898 }
1899 }
1900
1901 while (true) {
1902 if (UNLIKELY(ptr_ >= EndOfFile())) {
1903 // Went past the end.
1904 return false;
1905 }
1906 uint8_t opcode = *(ptr_++);
1907 switch (opcode) {
1908 case DexFile::DBG_END_SEQUENCE: {
1909 return true;
1910 }
1911 case DexFile::DBG_ADVANCE_PC: {
1912 DECODE_UNSIGNED_CHECKED_FROM(ptr_, unused_advance_pc);
1913 break;
1914 }
1915 case DexFile::DBG_ADVANCE_LINE: {
1916 DECODE_SIGNED_CHECKED_FROM(ptr_, unused_advance_line);
1917 break;
1918 }
1919 case DexFile::DBG_START_LOCAL: {
1920 DECODE_UNSIGNED_CHECKED_FROM(ptr_, reg_num);
1921 if (UNLIKELY(reg_num >= 65536)) {
1922 ErrorStringPrintf("Bad reg_num for opcode %x", opcode);
1923 return false;
1924 }
1925 DECODE_UNSIGNED_CHECKED_FROM(ptr_, name_idx);
1926 if (name_idx != 0) {
1927 name_idx--;
1928 if (!CheckIndex(name_idx, header_->string_ids_size_, "DBG_START_LOCAL name_idx")) {
1929 return false;
1930 }
1931 }
1932 DECODE_UNSIGNED_CHECKED_FROM(ptr_, type_idx);
1933 if (type_idx != 0) {
1934 type_idx--;
1935 if (!CheckIndex(type_idx, header_->type_ids_size_, "DBG_START_LOCAL type_idx")) {
1936 return false;
1937 }
1938 }
1939 break;
1940 }
1941 case DexFile::DBG_END_LOCAL:
1942 case DexFile::DBG_RESTART_LOCAL: {
1943 DECODE_UNSIGNED_CHECKED_FROM(ptr_, reg_num);
1944 if (UNLIKELY(reg_num >= 65536)) {
1945 ErrorStringPrintf("Bad reg_num for opcode %x", opcode);
1946 return false;
1947 }
1948 break;
1949 }
1950 case DexFile::DBG_START_LOCAL_EXTENDED: {
1951 DECODE_UNSIGNED_CHECKED_FROM(ptr_, reg_num);
1952 if (UNLIKELY(reg_num >= 65536)) {
1953 ErrorStringPrintf("Bad reg_num for opcode %x", opcode);
1954 return false;
1955 }
1956 DECODE_UNSIGNED_CHECKED_FROM(ptr_, name_idx);
1957 if (name_idx != 0) {
1958 name_idx--;
1959 if (!CheckIndex(name_idx, header_->string_ids_size_, "DBG_START_LOCAL_EXTENDED name_idx")) {
1960 return false;
1961 }
1962 }
1963 DECODE_UNSIGNED_CHECKED_FROM(ptr_, type_idx);
1964 if (type_idx != 0) {
1965 type_idx--;
1966 if (!CheckIndex(type_idx, header_->type_ids_size_, "DBG_START_LOCAL_EXTENDED type_idx")) {
1967 return false;
1968 }
1969 }
1970 DECODE_UNSIGNED_CHECKED_FROM(ptr_, sig_idx);
1971 if (sig_idx != 0) {
1972 sig_idx--;
1973 if (!CheckIndex(sig_idx, header_->string_ids_size_, "DBG_START_LOCAL_EXTENDED sig_idx")) {
1974 return false;
1975 }
1976 }
1977 break;
1978 }
1979 case DexFile::DBG_SET_FILE: {
1980 DECODE_UNSIGNED_CHECKED_FROM(ptr_, name_idx);
1981 if (name_idx != 0) {
1982 name_idx--;
1983 if (!CheckIndex(name_idx, header_->string_ids_size_, "DBG_SET_FILE name_idx")) {
1984 return false;
1985 }
1986 }
1987 break;
1988 }
1989 }
1990 }
1991 }
1992
CheckIntraAnnotationItem()1993 bool DexFileVerifier::CheckIntraAnnotationItem() {
1994 if (!CheckListSize(ptr_, 1, sizeof(uint8_t), "annotation visibility")) {
1995 return false;
1996 }
1997
1998 // Check visibility
1999 uint8_t visibility = *(ptr_++);
2000 switch (visibility) {
2001 case DexFile::kDexVisibilityBuild:
2002 case DexFile::kDexVisibilityRuntime:
2003 case DexFile::kDexVisibilitySystem:
2004 break;
2005 default:
2006 ErrorStringPrintf("Bad annotation visibility: %x", visibility);
2007 return false;
2008 }
2009
2010 CHECK(todo_.empty());
2011 if (!CheckEncodedAnnotation() || !FlushToDoList()) {
2012 return false;
2013 }
2014
2015 return true;
2016 }
2017
CheckIntraHiddenapiClassData()2018 bool DexFileVerifier::CheckIntraHiddenapiClassData() {
2019 const dex::HiddenapiClassData* item = reinterpret_cast<const dex::HiddenapiClassData*>(ptr_);
2020
2021 // Check expected header size.
2022 uint32_t num_header_elems = dex_file_->NumClassDefs() + 1;
2023 uint32_t elem_size = sizeof(uint32_t);
2024 uint32_t header_size = num_header_elems * elem_size;
2025 if (!CheckListSize(item, num_header_elems, elem_size, "hiddenapi class data section header")) {
2026 return false;
2027 }
2028
2029 // Check total size.
2030 if (!CheckListSize(item, item->size_, 1u, "hiddenapi class data section")) {
2031 return false;
2032 }
2033
2034 // Check that total size can fit header.
2035 if (item->size_ < header_size) {
2036 ErrorStringPrintf(
2037 "Hiddenapi class data too short to store header (%u < %u)", item->size_, header_size);
2038 return false;
2039 }
2040
2041 // The rest of the section depends on the class_data_item being verified first. We will finalize
2042 // verifying the hiddenapi_class_data_item in CheckInterHiddenapiClassData.
2043 const uint8_t* data_end = ptr_ + item->size_;
2044 ptr_ = data_end;
2045 return true;
2046 }
2047
CheckIntraAnnotationsDirectoryItem()2048 bool DexFileVerifier::CheckIntraAnnotationsDirectoryItem() {
2049 const dex::AnnotationsDirectoryItem* item =
2050 reinterpret_cast<const dex::AnnotationsDirectoryItem*>(ptr_);
2051 if (!CheckListSize(item, 1, sizeof(dex::AnnotationsDirectoryItem), "annotations_directory")) {
2052 return false;
2053 }
2054
2055 // Field annotations follow immediately after the annotations directory.
2056 const dex::FieldAnnotationsItem* field_item =
2057 reinterpret_cast<const dex::FieldAnnotationsItem*>(item + 1);
2058 uint32_t field_count = item->fields_size_;
2059 if (!CheckListSize(field_item,
2060 field_count,
2061 sizeof(dex::FieldAnnotationsItem),
2062 "field_annotations list")) {
2063 return false;
2064 }
2065
2066 uint32_t last_idx = 0;
2067 for (uint32_t i = 0; i < field_count; i++) {
2068 if (!CheckIndex(field_item->field_idx_, header_->field_ids_size_, "field annotation")) {
2069 return false;
2070 }
2071 if (UNLIKELY(last_idx >= field_item->field_idx_ && i != 0)) {
2072 ErrorStringPrintf("Out-of-order field_idx for annotation: %x then %x",
2073 last_idx, field_item->field_idx_);
2074 return false;
2075 }
2076 last_idx = field_item->field_idx_;
2077 field_item++;
2078 }
2079
2080 // Method annotations follow immediately after field annotations.
2081 const dex::MethodAnnotationsItem* method_item =
2082 reinterpret_cast<const dex::MethodAnnotationsItem*>(field_item);
2083 uint32_t method_count = item->methods_size_;
2084 if (!CheckListSize(method_item,
2085 method_count,
2086 sizeof(dex::MethodAnnotationsItem),
2087 "method_annotations list")) {
2088 return false;
2089 }
2090
2091 last_idx = 0;
2092 for (uint32_t i = 0; i < method_count; i++) {
2093 if (!CheckIndex(method_item->method_idx_, header_->method_ids_size_, "method annotation")) {
2094 return false;
2095 }
2096 if (UNLIKELY(last_idx >= method_item->method_idx_ && i != 0)) {
2097 ErrorStringPrintf("Out-of-order method_idx for annotation: %x then %x",
2098 last_idx, method_item->method_idx_);
2099 return false;
2100 }
2101 last_idx = method_item->method_idx_;
2102 method_item++;
2103 }
2104
2105 // Parameter annotations follow immediately after method annotations.
2106 const dex::ParameterAnnotationsItem* parameter_item =
2107 reinterpret_cast<const dex::ParameterAnnotationsItem*>(method_item);
2108 uint32_t parameter_count = item->parameters_size_;
2109 if (!CheckListSize(parameter_item, parameter_count, sizeof(dex::ParameterAnnotationsItem),
2110 "parameter_annotations list")) {
2111 return false;
2112 }
2113
2114 last_idx = 0;
2115 for (uint32_t i = 0; i < parameter_count; i++) {
2116 if (!CheckIndex(parameter_item->method_idx_,
2117 header_->method_ids_size_,
2118 "parameter annotation method")) {
2119 return false;
2120 }
2121 if (UNLIKELY(last_idx >= parameter_item->method_idx_ && i != 0)) {
2122 ErrorStringPrintf("Out-of-order method_idx for annotation: %x then %x",
2123 last_idx, parameter_item->method_idx_);
2124 return false;
2125 }
2126 last_idx = parameter_item->method_idx_;
2127 parameter_item++;
2128 }
2129
2130 // Return a pointer to the end of the annotations.
2131 ptr_ = reinterpret_cast<const uint8_t*>(parameter_item);
2132 return true;
2133 }
2134
2135 template <DexFile::MapItemType kType>
CheckIntraSectionIterate(uint32_t section_count)2136 bool DexFileVerifier::CheckIntraSectionIterate(uint32_t section_count) {
2137 // Get the right alignment mask for the type of section.
2138 size_t alignment_mask;
2139 switch (kType) {
2140 case DexFile::kDexTypeClassDataItem:
2141 case DexFile::kDexTypeStringDataItem:
2142 case DexFile::kDexTypeDebugInfoItem:
2143 case DexFile::kDexTypeAnnotationItem:
2144 case DexFile::kDexTypeEncodedArrayItem:
2145 alignment_mask = sizeof(uint8_t) - 1;
2146 break;
2147 default:
2148 alignment_mask = sizeof(uint32_t) - 1;
2149 break;
2150 }
2151
2152 // Iterate through the items in the section.
2153 for (uint32_t i = 0; i < section_count; i++) {
2154 size_t aligned_offset = (PtrToOffset(ptr_) + alignment_mask) & ~alignment_mask;
2155
2156 // Check the padding between items.
2157 if (!CheckPadding(aligned_offset, kType)) {
2158 return false;
2159 }
2160
2161 // Check depending on the section type.
2162 const uint8_t* start_ptr = ptr_;
2163 switch (kType) {
2164 case DexFile::kDexTypeStringIdItem: {
2165 if (!CheckListSize(ptr_, 1, sizeof(dex::StringId), "string_ids")) {
2166 return false;
2167 }
2168 ptr_ += sizeof(dex::StringId);
2169 break;
2170 }
2171 case DexFile::kDexTypeTypeIdItem: {
2172 if (!CheckIntraTypeIdItem()) {
2173 return false;
2174 }
2175 break;
2176 }
2177 case DexFile::kDexTypeProtoIdItem: {
2178 if (!CheckIntraProtoIdItem()) {
2179 return false;
2180 }
2181 break;
2182 }
2183 case DexFile::kDexTypeFieldIdItem: {
2184 if (!CheckIntraFieldIdItem()) {
2185 return false;
2186 }
2187 break;
2188 }
2189 case DexFile::kDexTypeMethodIdItem: {
2190 if (!CheckIntraMethodIdItem()) {
2191 return false;
2192 }
2193 break;
2194 }
2195 case DexFile::kDexTypeClassDefItem: {
2196 if (!CheckIntraClassDefItem(/*class_def_index=*/ i)) {
2197 return false;
2198 }
2199 break;
2200 }
2201 case DexFile::kDexTypeCallSiteIdItem: {
2202 if (!CheckListSize(ptr_, 1, sizeof(dex::CallSiteIdItem), "call_site_ids")) {
2203 return false;
2204 }
2205 ptr_ += sizeof(dex::CallSiteIdItem);
2206 break;
2207 }
2208 case DexFile::kDexTypeMethodHandleItem: {
2209 if (!CheckIntraMethodHandleItem()) {
2210 return false;
2211 }
2212 break;
2213 }
2214 case DexFile::kDexTypeTypeList: {
2215 if (!CheckIntraTypeList()) {
2216 return false;
2217 }
2218 break;
2219 }
2220 case DexFile::kDexTypeAnnotationSetRefList: {
2221 if (!CheckList(sizeof(dex::AnnotationSetRefItem), "annotation_set_ref_list", &ptr_)) {
2222 return false;
2223 }
2224 break;
2225 }
2226 case DexFile::kDexTypeAnnotationSetItem: {
2227 if (!CheckList(sizeof(uint32_t), "annotation_set_item", &ptr_)) {
2228 return false;
2229 }
2230 break;
2231 }
2232 case DexFile::kDexTypeClassDataItem: {
2233 if (!CheckIntraClassDataItem()) {
2234 return false;
2235 }
2236 break;
2237 }
2238 case DexFile::kDexTypeCodeItem: {
2239 if (!CheckIntraCodeItem()) {
2240 return false;
2241 }
2242 break;
2243 }
2244 case DexFile::kDexTypeStringDataItem: {
2245 if (!CheckIntraStringDataItem()) {
2246 return false;
2247 }
2248 break;
2249 }
2250 case DexFile::kDexTypeDebugInfoItem: {
2251 if (!CheckIntraDebugInfoItem()) {
2252 return false;
2253 }
2254 break;
2255 }
2256 case DexFile::kDexTypeAnnotationItem: {
2257 if (!CheckIntraAnnotationItem()) {
2258 return false;
2259 }
2260 break;
2261 }
2262 case DexFile::kDexTypeEncodedArrayItem: {
2263 CHECK(todo_.empty());
2264 if (!CheckEncodedArray() || !FlushToDoList()) {
2265 return false;
2266 }
2267 break;
2268 }
2269 case DexFile::kDexTypeAnnotationsDirectoryItem: {
2270 if (!CheckIntraAnnotationsDirectoryItem()) {
2271 return false;
2272 }
2273 break;
2274 }
2275 case DexFile::kDexTypeHiddenapiClassData: {
2276 if (!CheckIntraHiddenapiClassData()) {
2277 return false;
2278 }
2279 break;
2280 }
2281 case DexFile::kDexTypeHeaderItem:
2282 case DexFile::kDexTypeMapList:
2283 break;
2284 }
2285
2286 if (start_ptr == ptr_) {
2287 ErrorStringPrintf("Unknown map item type %x", kType);
2288 return false;
2289 }
2290
2291 if (IsDataSectionType(kType)) {
2292 if (aligned_offset == 0u) {
2293 ErrorStringPrintf("Item %d offset is 0", i);
2294 return false;
2295 }
2296 DCHECK(offset_to_type_map_.find(aligned_offset) == offset_to_type_map_.end());
2297 offset_to_type_map_.insert(std::pair<uint32_t, uint16_t>(aligned_offset, kType));
2298 }
2299
2300 if (!PtrToOffset(ptr_, &aligned_offset)) {
2301 ErrorStringPrintf("Item %d at ends out of bounds", i);
2302 return false;
2303 }
2304 }
2305
2306 return true;
2307 }
2308
2309 template <DexFile::MapItemType kType>
CheckIntraIdSection(size_t offset,uint32_t count)2310 bool DexFileVerifier::CheckIntraIdSection(size_t offset, uint32_t count) {
2311 uint32_t expected_offset;
2312 uint32_t expected_size;
2313
2314 // Get the expected offset and size from the header.
2315 switch (kType) {
2316 case DexFile::kDexTypeStringIdItem:
2317 expected_offset = header_->string_ids_off_;
2318 expected_size = header_->string_ids_size_;
2319 break;
2320 case DexFile::kDexTypeTypeIdItem:
2321 expected_offset = header_->type_ids_off_;
2322 expected_size = header_->type_ids_size_;
2323 break;
2324 case DexFile::kDexTypeProtoIdItem:
2325 expected_offset = header_->proto_ids_off_;
2326 expected_size = header_->proto_ids_size_;
2327 break;
2328 case DexFile::kDexTypeFieldIdItem:
2329 expected_offset = header_->field_ids_off_;
2330 expected_size = header_->field_ids_size_;
2331 break;
2332 case DexFile::kDexTypeMethodIdItem:
2333 expected_offset = header_->method_ids_off_;
2334 expected_size = header_->method_ids_size_;
2335 break;
2336 case DexFile::kDexTypeClassDefItem:
2337 expected_offset = header_->class_defs_off_;
2338 expected_size = header_->class_defs_size_;
2339 break;
2340 default:
2341 ErrorStringPrintf("Bad type for id section: %x", kType);
2342 return false;
2343 }
2344
2345 // Check that the offset and size are what were expected from the header.
2346 if (UNLIKELY(offset != expected_offset)) {
2347 ErrorStringPrintf("Bad offset for section: got %zx, expected %x", offset, expected_offset);
2348 return false;
2349 }
2350 if (UNLIKELY(count != expected_size)) {
2351 ErrorStringPrintf("Bad size for section: got %x, expected %x", count, expected_size);
2352 return false;
2353 }
2354
2355 return CheckIntraSectionIterate<kType>(count);
2356 }
2357
2358 template <DexFile::MapItemType kType>
CheckIntraDataSection(size_t offset,uint32_t count)2359 bool DexFileVerifier::CheckIntraDataSection(size_t offset, uint32_t count) {
2360 size_t data_start = PtrToOffset(data_.begin());
2361 size_t data_end = PtrToOffset(data_.end());
2362
2363 // Check the validity of the offset of the section.
2364 if (UNLIKELY((offset < data_start) || (offset > data_end))) {
2365 ErrorStringPrintf("Bad offset for data subsection: %zx", offset);
2366 return false;
2367 }
2368
2369 if (!CheckIntraSectionIterate<kType>(count)) {
2370 return false;
2371 }
2372
2373 // FIXME: Doing this check late means we may have already read memory outside the
2374 // data section and potentially outside the file, thus risking a segmentation fault.
2375 size_t next_offset;
2376 if (!PtrToOffset(ptr_, &next_offset) || next_offset > data_end) {
2377 ErrorStringPrintf("Out-of-bounds end of data subsection: %zu data_off=%u data_size=%u",
2378 next_offset,
2379 header_->data_off_,
2380 header_->data_size_);
2381 return false;
2382 }
2383
2384 return true;
2385 }
2386
CheckIntraSection()2387 bool DexFileVerifier::CheckIntraSection() {
2388 const dex::MapList* map = OffsetToPtr<dex::MapList>(header_->map_off_);
2389 const dex::MapItem* item = map->list_;
2390 uint32_t count = map->size_;
2391 ptr_ = dex_file_->Begin();
2392
2393 // Preallocate offset map to avoid some allocations. We can only guess from the list items,
2394 // not derived things.
2395 offset_to_type_map_.reserve(
2396 std::min(header_->class_defs_size_, 65535u) +
2397 std::min(header_->string_ids_size_, 65535u) +
2398 2 * std::min(header_->method_ids_size_, 65535u));
2399
2400 // Check the items listed in the map.
2401 for (; count != 0u; --count) {
2402 const uint8_t* initial_ptr = ptr_;
2403 uint32_t section_offset = item->offset_;
2404 uint32_t section_count = item->size_;
2405 DexFile::MapItemType type = static_cast<DexFile::MapItemType>(item->type_);
2406
2407 // Check for padding and overlap between items.
2408 size_t offset = PtrToOffset(ptr_);
2409 if (UNLIKELY(offset > section_offset)) {
2410 ErrorStringPrintf("Section overlap or out-of-order map: %zx, %x", offset, section_offset);
2411 return false;
2412 }
2413 if (!CheckPadding(section_offset, type)) {
2414 return false;
2415 }
2416
2417 // Check each item based on its type.
2418 switch (type) {
2419 case DexFile::kDexTypeHeaderItem: {
2420 if (UNLIKELY(section_count != 1)) {
2421 ErrorStringPrintf("Multiple header items");
2422 return false;
2423 }
2424 uint32_t expected = dex_version_ >= 41 ? PtrToOffset(dex_file_->Begin()) : 0;
2425 if (UNLIKELY(section_offset != expected)) {
2426 ErrorStringPrintf("Header at %x, expected %x", section_offset, expected);
2427 return false;
2428 }
2429 ptr_ += header_->header_size_;
2430 break;
2431 }
2432
2433 #define CHECK_INTRA_ID_SECTION_CASE(type) \
2434 case type: \
2435 if (!CheckIntraIdSection<type>(section_offset, section_count)) { \
2436 return false; \
2437 } \
2438 break;
2439 CHECK_INTRA_ID_SECTION_CASE(DexFile::kDexTypeStringIdItem)
2440 CHECK_INTRA_ID_SECTION_CASE(DexFile::kDexTypeTypeIdItem)
2441 CHECK_INTRA_ID_SECTION_CASE(DexFile::kDexTypeProtoIdItem)
2442 CHECK_INTRA_ID_SECTION_CASE(DexFile::kDexTypeFieldIdItem)
2443 CHECK_INTRA_ID_SECTION_CASE(DexFile::kDexTypeMethodIdItem)
2444 CHECK_INTRA_ID_SECTION_CASE(DexFile::kDexTypeClassDefItem)
2445 #undef CHECK_INTRA_ID_SECTION_CASE
2446
2447 case DexFile::kDexTypeMapList:
2448 if (UNLIKELY(section_count != 1)) {
2449 ErrorStringPrintf("Multiple map list items");
2450 return false;
2451 }
2452 if (UNLIKELY(section_offset != header_->map_off_)) {
2453 ErrorStringPrintf("Map not at header-defined offset: %x, expected %x",
2454 section_offset, header_->map_off_);
2455 return false;
2456 }
2457 ptr_ += sizeof(uint32_t) + (map->size_ * sizeof(dex::MapItem));
2458 break;
2459
2460 #define CHECK_INTRA_SECTION_ITERATE_CASE(type) \
2461 case type: \
2462 if (!CheckIntraSectionIterate<type>(section_count)) { \
2463 return false; \
2464 } \
2465 break;
2466 CHECK_INTRA_SECTION_ITERATE_CASE(DexFile::kDexTypeMethodHandleItem)
2467 CHECK_INTRA_SECTION_ITERATE_CASE(DexFile::kDexTypeCallSiteIdItem)
2468 #undef CHECK_INTRA_SECTION_ITERATE_CASE
2469
2470 #define CHECK_INTRA_DATA_SECTION_CASE(type) \
2471 case type: \
2472 if (!CheckIntraDataSection<type>(section_offset, section_count)) { \
2473 return false; \
2474 } \
2475 break;
2476 CHECK_INTRA_DATA_SECTION_CASE(DexFile::kDexTypeTypeList)
2477 CHECK_INTRA_DATA_SECTION_CASE(DexFile::kDexTypeAnnotationSetRefList)
2478 CHECK_INTRA_DATA_SECTION_CASE(DexFile::kDexTypeAnnotationSetItem)
2479 CHECK_INTRA_DATA_SECTION_CASE(DexFile::kDexTypeClassDataItem)
2480 CHECK_INTRA_DATA_SECTION_CASE(DexFile::kDexTypeCodeItem)
2481 CHECK_INTRA_DATA_SECTION_CASE(DexFile::kDexTypeStringDataItem)
2482 CHECK_INTRA_DATA_SECTION_CASE(DexFile::kDexTypeDebugInfoItem)
2483 CHECK_INTRA_DATA_SECTION_CASE(DexFile::kDexTypeAnnotationItem)
2484 CHECK_INTRA_DATA_SECTION_CASE(DexFile::kDexTypeEncodedArrayItem)
2485 CHECK_INTRA_DATA_SECTION_CASE(DexFile::kDexTypeAnnotationsDirectoryItem)
2486 CHECK_INTRA_DATA_SECTION_CASE(DexFile::kDexTypeHiddenapiClassData)
2487 #undef CHECK_INTRA_DATA_SECTION_CASE
2488 }
2489
2490 if (ptr_ == initial_ptr) {
2491 ErrorStringPrintf("Unknown map item type %x", type);
2492 return false;
2493 }
2494
2495 item++;
2496 }
2497
2498 return true;
2499 }
2500
CheckOffsetToTypeMap(size_t offset,uint16_t type)2501 bool DexFileVerifier::CheckOffsetToTypeMap(size_t offset, uint16_t type) {
2502 DCHECK(offset_to_type_map_.find(0) == offset_to_type_map_.end());
2503 auto it = offset_to_type_map_.find(offset);
2504 if (UNLIKELY(it == offset_to_type_map_.end())) {
2505 ErrorStringPrintf("No data map entry found @ %zx; expected %x", offset, type);
2506 return false;
2507 }
2508 if (UNLIKELY(it->second != type)) {
2509 ErrorStringPrintf("Unexpected data map entry @ %zx; expected %x, found %x",
2510 offset, type, it->second);
2511 return false;
2512 }
2513 return true;
2514 }
2515
FindFirstClassDataDefiner(const ClassAccessor & accessor)2516 uint32_t DexFileVerifier::FindFirstClassDataDefiner(const ClassAccessor& accessor) {
2517 // The data item and field/method indexes have already been checked in
2518 // `CheckIntraClassDataItem()` or its helper functions.
2519 if (accessor.NumFields() != 0) {
2520 ClassAccessor::Field read_field(*dex_file_, accessor.ptr_pos_);
2521 read_field.Read();
2522 DCHECK_LE(read_field.GetIndex(), dex_file_->NumFieldIds());
2523 return dex_file_->GetFieldId(read_field.GetIndex()).class_idx_.index_;
2524 }
2525
2526 if (accessor.NumMethods() != 0) {
2527 ClassAccessor::Method read_method(*dex_file_, accessor.ptr_pos_);
2528 read_method.Read();
2529 DCHECK_LE(read_method.GetIndex(), dex_file_->NumMethodIds());
2530 return dex_file_->GetMethodId(read_method.GetIndex()).class_idx_.index_;
2531 }
2532
2533 return kDexNoIndex;
2534 }
2535
FindFirstAnnotationsDirectoryDefiner(const uint8_t * ptr)2536 uint32_t DexFileVerifier::FindFirstAnnotationsDirectoryDefiner(const uint8_t* ptr) {
2537 // The annotations directory and field/method indexes have already been checked in
2538 // `CheckIntraAnnotationsDirectoryItem()`.
2539 const dex::AnnotationsDirectoryItem* item =
2540 reinterpret_cast<const dex::AnnotationsDirectoryItem*>(ptr);
2541
2542 if (item->fields_size_ != 0) {
2543 dex::FieldAnnotationsItem* field_items = (dex::FieldAnnotationsItem*) (item + 1);
2544 DCHECK_LE(field_items[0].field_idx_, dex_file_->NumFieldIds());
2545 return dex_file_->GetFieldId(field_items[0].field_idx_).class_idx_.index_;
2546 }
2547
2548 if (item->methods_size_ != 0) {
2549 dex::MethodAnnotationsItem* method_items = (dex::MethodAnnotationsItem*) (item + 1);
2550 DCHECK_LE(method_items[0].method_idx_, dex_file_->NumMethodIds());
2551 return dex_file_->GetMethodId(method_items[0].method_idx_).class_idx_.index_;
2552 }
2553
2554 if (item->parameters_size_ != 0) {
2555 dex::ParameterAnnotationsItem* parameter_items = (dex::ParameterAnnotationsItem*) (item + 1);
2556 DCHECK_LE(parameter_items[0].method_idx_, dex_file_->NumMethodIds());
2557 return dex_file_->GetMethodId(parameter_items[0].method_idx_).class_idx_.index_;
2558 }
2559
2560 return kDexNoIndex;
2561 }
2562
CheckInterHiddenapiClassData()2563 bool DexFileVerifier::CheckInterHiddenapiClassData() {
2564 const dex::HiddenapiClassData* item = reinterpret_cast<const dex::HiddenapiClassData*>(ptr_);
2565
2566 // Move pointer after the header. This data has been verified in CheckIntraHiddenapiClassData.
2567 uint32_t num_header_elems = dex_file_->NumClassDefs() + 1;
2568 uint32_t elem_size = sizeof(uint32_t);
2569 uint32_t header_size = num_header_elems * elem_size;
2570 const uint8_t* data_end = ptr_ + item->size_;
2571 ptr_ += header_size;
2572
2573 // Check offsets for each class def.
2574 for (uint32_t i = 0; i < dex_file_->NumClassDefs(); ++i) {
2575 const dex::ClassDef& class_def = dex_file_->GetClassDef(i);
2576 const uint8_t* class_data = dex_file_->GetClassData(class_def);
2577 uint32_t offset = item->flags_offset_[i];
2578
2579 if (offset == 0) {
2580 continue;
2581 }
2582
2583 // Check that class defs with no class data do not have any hiddenapi class data.
2584 if (class_data == nullptr) {
2585 ErrorStringPrintf(
2586 "Hiddenapi class data offset not zero for class def %u with no class data", i);
2587 return false;
2588 }
2589
2590 // Check that the offset is within the section.
2591 if (offset > item->size_) {
2592 ErrorStringPrintf(
2593 "Hiddenapi class data offset out of section bounds (%u > %u) for class def %u",
2594 offset, item->size_, i);
2595 return false;
2596 }
2597
2598 // Check that the offset matches current pointer position. We do not allow
2599 // offsets into already parsed data, or gaps between class def data.
2600 uint32_t ptr_offset = ptr_ - reinterpret_cast<const uint8_t*>(item);
2601 if (offset != ptr_offset) {
2602 ErrorStringPrintf(
2603 "Hiddenapi class data unexpected offset (%u != %u) for class def %u",
2604 offset, ptr_offset, i);
2605 return false;
2606 }
2607
2608 // Parse a uleb128 value for each field and method of this class.
2609 bool failure = false;
2610 auto fn_member = [&](const ClassAccessor::BaseItem& member, const char* member_type) {
2611 if (failure) {
2612 return;
2613 }
2614 uint32_t decoded_flags;
2615 if (!DecodeUnsignedLeb128Checked(&ptr_, data_end, &decoded_flags)) {
2616 ErrorStringPrintf("Hiddenapi class data value out of bounds (%p > %p) for %s %i",
2617 ptr_, data_end, member_type, member.GetIndex());
2618 failure = true;
2619 return;
2620 }
2621 if (!hiddenapi::ApiList(decoded_flags).IsValid()) {
2622 ErrorStringPrintf("Hiddenapi class data flags invalid (%u) for %s %i",
2623 decoded_flags, member_type, member.GetIndex());
2624 failure = true;
2625 return;
2626 }
2627 };
2628 auto fn_field = [&](const ClassAccessor::Field& field) { fn_member(field, "field"); };
2629 auto fn_method = [&](const ClassAccessor::Method& method) { fn_member(method, "method"); };
2630 ClassAccessor accessor(*dex_file_, class_data);
2631 accessor.VisitFieldsAndMethods(fn_field, fn_field, fn_method, fn_method);
2632 if (failure) {
2633 return false;
2634 }
2635 }
2636
2637 if (ptr_ != data_end) {
2638 ErrorStringPrintf("Hiddenapi class data wrong reported size (%u != %u)",
2639 static_cast<uint32_t>(ptr_ - reinterpret_cast<const uint8_t*>(item)),
2640 item->size_);
2641 return false;
2642 }
2643
2644 return true;
2645 }
2646
CheckInterStringIdItem()2647 bool DexFileVerifier::CheckInterStringIdItem() {
2648 const dex::StringId* item = reinterpret_cast<const dex::StringId*>(ptr_);
2649
2650 // Note: The mapping to string data items is eagerly verified at the start of CheckInterSection().
2651
2652 // Check ordering between items.
2653 if (previous_item_ != nullptr) {
2654 const dex::StringId* prev_item = reinterpret_cast<const dex::StringId*>(previous_item_);
2655 const char* prev_str = dex_file_->GetStringData(*prev_item);
2656 const char* str = dex_file_->GetStringData(*item);
2657 if (UNLIKELY(CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues(prev_str, str) >= 0)) {
2658 ErrorStringPrintf("Out-of-order string_ids: '%s' then '%s'", prev_str, str);
2659 return false;
2660 }
2661 }
2662
2663 ptr_ += sizeof(dex::StringId);
2664 return true;
2665 }
2666
CheckInterTypeIdItem()2667 bool DexFileVerifier::CheckInterTypeIdItem() {
2668 const dex::TypeId* item = reinterpret_cast<const dex::TypeId*>(ptr_);
2669
2670 {
2671 // Translate to index to potentially use cache.
2672 // The check in `CheckIntraIdSection()` guarantees that this index is valid.
2673 size_t index = item - OffsetToPtr<dex::TypeId>(header_->type_ids_off_);
2674 DCHECK_LE(index, header_->type_ids_size_);
2675 if (UNLIKELY(!VerifyTypeDescriptor(
2676 dex::TypeIndex(static_cast<decltype(dex::TypeIndex::index_)>(index)),
2677 "Invalid type descriptor",
2678 [](char) { return true; }))) {
2679 return false;
2680 }
2681 }
2682
2683 // Check ordering between items.
2684 if (previous_item_ != nullptr) {
2685 const dex::TypeId* prev_item = reinterpret_cast<const dex::TypeId*>(previous_item_);
2686 if (UNLIKELY(prev_item->descriptor_idx_ >= item->descriptor_idx_)) {
2687 ErrorStringPrintf("Out-of-order type_ids: %x then %x",
2688 prev_item->descriptor_idx_.index_,
2689 item->descriptor_idx_.index_);
2690 return false;
2691 }
2692 }
2693
2694 ptr_ += sizeof(dex::TypeId);
2695 return true;
2696 }
2697
CheckInterProtoIdItem()2698 bool DexFileVerifier::CheckInterProtoIdItem() {
2699 const dex::ProtoId* item = reinterpret_cast<const dex::ProtoId*>(ptr_);
2700
2701 const char* shorty = dex_file_->GetStringData(item->shorty_idx_);
2702
2703 if (item->parameters_off_ != 0 &&
2704 !CheckOffsetToTypeMap(item->parameters_off_, DexFile::kDexTypeTypeList)) {
2705 return false;
2706 }
2707
2708 // Check that return type is representable as a uint16_t;
2709 if (UNLIKELY(!IsValidOrNoTypeId(item->return_type_idx_.index_, item->pad_))) {
2710 ErrorStringPrintf("proto with return type idx outside uint16_t range '%x:%x'",
2711 item->pad_, item->return_type_idx_.index_);
2712 return false;
2713 }
2714 // Check the return type and advance the shorty.
2715 const char* return_type = dex_file_->GetTypeDescriptor(item->return_type_idx_);
2716 if (!CheckShortyDescriptorMatch(*shorty, return_type, true)) {
2717 return false;
2718 }
2719 shorty++;
2720
2721 DexFileParameterIterator it(*dex_file_, *item);
2722 while (it.HasNext() && *shorty != '\0') {
2723 if (!CheckIndex(it.GetTypeIdx().index_,
2724 dex_file_->NumTypeIds(),
2725 "inter_proto_id_item shorty type_idx")) {
2726 return false;
2727 }
2728 const char* descriptor = it.GetDescriptor();
2729 if (!CheckShortyDescriptorMatch(*shorty, descriptor, false)) {
2730 return false;
2731 }
2732 it.Next();
2733 shorty++;
2734 }
2735 if (UNLIKELY(it.HasNext() || *shorty != '\0')) {
2736 ErrorStringPrintf("Mismatched length for parameters and shorty");
2737 return false;
2738 }
2739
2740 // Check ordering between items. This relies on type_ids being in order.
2741 if (previous_item_ != nullptr) {
2742 const dex::ProtoId* prev = reinterpret_cast<const dex::ProtoId*>(previous_item_);
2743 if (UNLIKELY(prev->return_type_idx_ > item->return_type_idx_)) {
2744 ErrorStringPrintf("Out-of-order proto_id return types");
2745 return false;
2746 } else if (prev->return_type_idx_ == item->return_type_idx_) {
2747 DexFileParameterIterator curr_it(*dex_file_, *item);
2748 DexFileParameterIterator prev_it(*dex_file_, *prev);
2749
2750 while (curr_it.HasNext() && prev_it.HasNext()) {
2751 dex::TypeIndex prev_idx = prev_it.GetTypeIdx();
2752 dex::TypeIndex curr_idx = curr_it.GetTypeIdx();
2753 DCHECK_NE(prev_idx, dex::TypeIndex(DexFile::kDexNoIndex16));
2754 DCHECK_NE(curr_idx, dex::TypeIndex(DexFile::kDexNoIndex16));
2755
2756 if (prev_idx < curr_idx) {
2757 break;
2758 } else if (UNLIKELY(prev_idx > curr_idx)) {
2759 ErrorStringPrintf("Out-of-order proto_id arguments");
2760 return false;
2761 }
2762
2763 prev_it.Next();
2764 curr_it.Next();
2765 }
2766 if (!curr_it.HasNext()) {
2767 // Either a duplicate ProtoId or a ProtoId with a shorter argument list follows
2768 // a ProtoId with a longer one. Both cases are forbidden by the specification.
2769 ErrorStringPrintf("Out-of-order proto_id arguments");
2770 return false;
2771 }
2772 }
2773 }
2774
2775 ptr_ += sizeof(dex::ProtoId);
2776 return true;
2777 }
2778
CheckInterFieldIdItem()2779 bool DexFileVerifier::CheckInterFieldIdItem() {
2780 const dex::FieldId* item = reinterpret_cast<const dex::FieldId*>(ptr_);
2781
2782 // Check that the class descriptor is valid.
2783 if (UNLIKELY(!VerifyTypeDescriptor(item->class_idx_,
2784 "Invalid descriptor for class_idx",
2785 [](char d) { return d == 'L'; }))) {
2786 return false;
2787 }
2788
2789 // Check that the type descriptor is a valid field name.
2790 if (UNLIKELY(!VerifyTypeDescriptor(item->type_idx_,
2791 "Invalid descriptor for type_idx",
2792 [](char d) { return d != 'V'; }))) {
2793 return false;
2794 }
2795
2796 // Check that the name is valid.
2797 const char* field_name = dex_file_->GetStringData(item->name_idx_);
2798 if (UNLIKELY(!IsValidMemberName(field_name))) {
2799 ErrorStringPrintf("Invalid field name: '%s'", field_name);
2800 return false;
2801 }
2802
2803 // Check ordering between items. This relies on the other sections being in order.
2804 if (previous_item_ != nullptr) {
2805 const dex::FieldId* prev_item = reinterpret_cast<const dex::FieldId*>(previous_item_);
2806 if (UNLIKELY(prev_item->class_idx_ > item->class_idx_)) {
2807 ErrorStringPrintf("Out-of-order field_ids");
2808 return false;
2809 } else if (prev_item->class_idx_ == item->class_idx_) {
2810 if (UNLIKELY(prev_item->name_idx_ > item->name_idx_)) {
2811 ErrorStringPrintf("Out-of-order field_ids");
2812 return false;
2813 } else if (prev_item->name_idx_ == item->name_idx_) {
2814 if (UNLIKELY(prev_item->type_idx_ >= item->type_idx_)) {
2815 ErrorStringPrintf("Out-of-order field_ids");
2816 return false;
2817 }
2818 }
2819 }
2820 }
2821
2822 ptr_ += sizeof(dex::FieldId);
2823 return true;
2824 }
2825
CheckInterMethodIdItem()2826 bool DexFileVerifier::CheckInterMethodIdItem() {
2827 const dex::MethodId* item = reinterpret_cast<const dex::MethodId*>(ptr_);
2828
2829 // Check that the class descriptor is a valid reference name.
2830 if (UNLIKELY(!VerifyTypeDescriptor(item->class_idx_,
2831 "Invalid descriptor for class_idx",
2832 [](char d) { return d == 'L' || d == '['; }))) {
2833 return false;
2834 }
2835
2836 // Check that the name is valid.
2837 const char* method_name = dex_file_->GetStringData(item->name_idx_);
2838 if (UNLIKELY(!IsValidMemberName(method_name))) {
2839 ErrorStringPrintf("Invalid method name: '%s'", method_name);
2840 return false;
2841 }
2842
2843 // Check that the proto id is valid.
2844 if (UNLIKELY(!CheckIndex(item->proto_idx_.index_, dex_file_->NumProtoIds(),
2845 "inter_method_id_item proto_idx"))) {
2846 return false;
2847 }
2848
2849 // Check ordering between items. This relies on the other sections being in order.
2850 if (previous_item_ != nullptr) {
2851 const dex::MethodId* prev_item = reinterpret_cast<const dex::MethodId*>(previous_item_);
2852 if (UNLIKELY(prev_item->class_idx_ > item->class_idx_)) {
2853 ErrorStringPrintf("Out-of-order method_ids");
2854 return false;
2855 } else if (prev_item->class_idx_ == item->class_idx_) {
2856 if (UNLIKELY(prev_item->name_idx_ > item->name_idx_)) {
2857 ErrorStringPrintf("Out-of-order method_ids");
2858 return false;
2859 } else if (prev_item->name_idx_ == item->name_idx_) {
2860 if (UNLIKELY(prev_item->proto_idx_ >= item->proto_idx_)) {
2861 ErrorStringPrintf("Out-of-order method_ids");
2862 return false;
2863 }
2864 }
2865 }
2866 }
2867
2868 ptr_ += sizeof(dex::MethodId);
2869 return true;
2870 }
2871
CheckInterClassDefItem()2872 bool DexFileVerifier::CheckInterClassDefItem() {
2873 const dex::ClassDef* item = reinterpret_cast<const dex::ClassDef*>(ptr_);
2874
2875 // Check that class_idx_ is representable as a uint16_t;
2876 if (UNLIKELY(!IsValidTypeId(item->class_idx_.index_, item->pad1_))) {
2877 ErrorStringPrintf("class with type idx outside uint16_t range '%x:%x'", item->pad1_,
2878 item->class_idx_.index_);
2879 return false;
2880 }
2881 // Check that superclass_idx_ is representable as a uint16_t;
2882 if (UNLIKELY(!IsValidOrNoTypeId(item->superclass_idx_.index_, item->pad2_))) {
2883 ErrorStringPrintf("class with superclass type idx outside uint16_t range '%x:%x'", item->pad2_,
2884 item->superclass_idx_.index_);
2885 return false;
2886 }
2887 // Check for duplicate class def.
2888
2889 if (UNLIKELY(!VerifyTypeDescriptor(item->class_idx_,
2890 "Invalid class descriptor",
2891 [](char d) { return d == 'L'; }))) {
2892 return false;
2893 }
2894
2895 // Only allow non-runtime modifiers.
2896 if ((item->access_flags_ & ~kAccJavaFlagsMask) != 0) {
2897 ErrorStringPrintf("Invalid class flags: '%d'", item->access_flags_);
2898 return false;
2899 }
2900
2901 if (item->interfaces_off_ != 0 &&
2902 !CheckOffsetToTypeMap(item->interfaces_off_, DexFile::kDexTypeTypeList)) {
2903 return false;
2904 }
2905 if (item->annotations_off_ != 0 &&
2906 !CheckOffsetToTypeMap(item->annotations_off_, DexFile::kDexTypeAnnotationsDirectoryItem)) {
2907 return false;
2908 }
2909 if (item->class_data_off_ != 0 &&
2910 !CheckOffsetToTypeMap(item->class_data_off_, DexFile::kDexTypeClassDataItem)) {
2911 return false;
2912 }
2913 if (item->static_values_off_ != 0 &&
2914 !CheckOffsetToTypeMap(item->static_values_off_, DexFile::kDexTypeEncodedArrayItem)) {
2915 return false;
2916 }
2917
2918 if (item->superclass_idx_.IsValid()) {
2919 if (header_->GetVersion() >= DexFile::kClassDefinitionOrderEnforcedVersion) {
2920 // Check that a class does not inherit from itself directly (by having
2921 // the same type idx as its super class).
2922 if (UNLIKELY(item->superclass_idx_ == item->class_idx_)) {
2923 ErrorStringPrintf("Class with same type idx as its superclass: '%d'",
2924 item->class_idx_.index_);
2925 return false;
2926 }
2927
2928 // Check that a class is defined after its super class (if the
2929 // latter is defined in the same Dex file).
2930 uint16_t superclass_idx = item->superclass_idx_.index_;
2931 if (defined_classes_[superclass_idx]) {
2932 // The superclass is defined in this Dex file.
2933 if (&dex_file_->GetClassDef(defined_class_indexes_[superclass_idx]) > item) {
2934 // ClassDef item for super class appearing after the class' ClassDef item.
2935 ErrorStringPrintf("Invalid class definition ordering:"
2936 " class with type idx: '%d' defined before"
2937 " superclass with type idx: '%d'",
2938 item->class_idx_.index_,
2939 superclass_idx);
2940 return false;
2941 }
2942 }
2943 }
2944
2945 if (UNLIKELY(!VerifyTypeDescriptor(item->superclass_idx_,
2946 "Invalid superclass",
2947 [](char d) { return d == 'L'; }))) {
2948 return false;
2949 }
2950 }
2951
2952 // Check interfaces.
2953 const dex::TypeList* interfaces = dex_file_->GetInterfacesList(*item);
2954 if (interfaces != nullptr) {
2955 uint32_t size = interfaces->Size();
2956 for (uint32_t i = 0; i < size; i++) {
2957 if (header_->GetVersion() >= DexFile::kClassDefinitionOrderEnforcedVersion) {
2958 // Check that a class does not implement itself directly (by having the
2959 // same type idx as one of its immediate implemented interfaces).
2960 if (UNLIKELY(interfaces->GetTypeItem(i).type_idx_ == item->class_idx_)) {
2961 ErrorStringPrintf("Class with same type idx as implemented interface: '%d'",
2962 item->class_idx_.index_);
2963 return false;
2964 }
2965
2966 // Check that a class is defined after the interfaces it implements
2967 // (if they are defined in the same Dex file).
2968 uint16_t interface_idx = interfaces->GetTypeItem(i).type_idx_.index_;
2969 if (defined_classes_[interface_idx]) {
2970 // The interface is defined in this Dex file.
2971 if (&dex_file_->GetClassDef(defined_class_indexes_[interface_idx]) > item) {
2972 // ClassDef item for interface appearing after the class' ClassDef item.
2973 ErrorStringPrintf("Invalid class definition ordering:"
2974 " class with type idx: '%d' defined before"
2975 " implemented interface with type idx: '%d'",
2976 item->class_idx_.index_,
2977 interface_idx);
2978 return false;
2979 }
2980 }
2981 }
2982
2983 // Ensure that the interface refers to a class (not an array nor a primitive type).
2984 if (UNLIKELY(!VerifyTypeDescriptor(interfaces->GetTypeItem(i).type_idx_,
2985 "Invalid interface",
2986 [](char d) { return d == 'L'; }))) {
2987 return false;
2988 }
2989 }
2990
2991 /*
2992 * Ensure that there are no duplicates. This is an O(N^2) test, but in
2993 * practice the number of interfaces implemented by any given class is low.
2994 */
2995 for (uint32_t i = 1; i < size; i++) {
2996 dex::TypeIndex idx1 = interfaces->GetTypeItem(i).type_idx_;
2997 for (uint32_t j =0; j < i; j++) {
2998 dex::TypeIndex idx2 = interfaces->GetTypeItem(j).type_idx_;
2999 if (UNLIKELY(idx1 == idx2)) {
3000 ErrorStringPrintf("Duplicate interface: '%s'", dex_file_->GetTypeDescriptor(idx1));
3001 return false;
3002 }
3003 }
3004 }
3005 }
3006
3007 // Check that references in class_data_item are to the right class.
3008 if (item->class_data_off_ != 0) {
3009 ClassAccessor accessor(*dex_file_, OffsetToPtr(item->class_data_off_));
3010 uint32_t data_definer = FindFirstClassDataDefiner(accessor);
3011 DCHECK(IsUint<16>(data_definer) || data_definer == kDexNoIndex) << data_definer;
3012 if (UNLIKELY((data_definer != item->class_idx_.index_) && (data_definer != kDexNoIndex))) {
3013 ErrorStringPrintf("Invalid class_data_item");
3014 return false;
3015 }
3016 }
3017
3018 // Check that references in annotations_directory_item are to right class.
3019 if (item->annotations_off_ != 0) {
3020 // annotations_off_ is supposed to be aligned by 4.
3021 if (!IsAlignedParam(item->annotations_off_, 4)) {
3022 ErrorStringPrintf("Invalid annotations_off_, not aligned by 4");
3023 return false;
3024 }
3025 const uint8_t* data = OffsetToPtr(item->annotations_off_);
3026 uint32_t defining_class = FindFirstAnnotationsDirectoryDefiner(data);
3027 DCHECK(IsUint<16>(defining_class) || defining_class == kDexNoIndex) << defining_class;
3028 if (UNLIKELY((defining_class != item->class_idx_.index_) && (defining_class != kDexNoIndex))) {
3029 ErrorStringPrintf("Invalid annotations_directory_item");
3030 return false;
3031 }
3032 }
3033
3034 ptr_ += sizeof(dex::ClassDef);
3035 return true;
3036 }
3037
CheckInterCallSiteIdItem()3038 bool DexFileVerifier::CheckInterCallSiteIdItem() {
3039 const dex::CallSiteIdItem* item = reinterpret_cast<const dex::CallSiteIdItem*>(ptr_);
3040
3041 // Check call site referenced by item is in encoded array section.
3042 if (!CheckOffsetToTypeMap(item->data_off_, DexFile::kDexTypeEncodedArrayItem)) {
3043 DCHECK(!failure_reason_.empty()); // Error already set.
3044 return false;
3045 }
3046
3047 CallSiteArrayValueIterator it(*dex_file_, *item);
3048
3049 // Check Method Handle
3050 if (!it.HasNext() || it.GetValueType() != EncodedArrayValueIterator::ValueType::kMethodHandle) {
3051 ErrorStringPrintf("CallSiteArray missing method handle");
3052 return false;
3053 }
3054
3055 uint32_t handle_index = static_cast<uint32_t>(it.GetJavaValue().i);
3056 if (handle_index >= dex_file_->NumMethodHandles()) {
3057 ErrorStringPrintf("CallSite has bad method handle id: %x", handle_index);
3058 return false;
3059 }
3060
3061 // Check target method name.
3062 if (!it.MaybeNext()) {
3063 ErrorStringPrintf("unexpected encoded value type: '%c'", it.GetValueType());
3064 return false;
3065 }
3066 if (!it.HasNext() ||
3067 it.GetValueType() != EncodedArrayValueIterator::ValueType::kString) {
3068 ErrorStringPrintf("CallSiteArray missing target method name");
3069 return false;
3070 }
3071
3072 uint32_t name_index = static_cast<uint32_t>(it.GetJavaValue().i);
3073 if (name_index >= dex_file_->NumStringIds()) {
3074 ErrorStringPrintf("CallSite has bad method name id: %x", name_index);
3075 return false;
3076 }
3077
3078 // Check method type.
3079 if (!it.MaybeNext()) {
3080 ErrorStringPrintf("unexpected encoded value type: '%c'", it.GetValueType());
3081 return false;
3082 }
3083 if (!it.HasNext() ||
3084 it.GetValueType() != EncodedArrayValueIterator::ValueType::kMethodType) {
3085 ErrorStringPrintf("CallSiteArray missing method type");
3086 return false;
3087 }
3088
3089 uint32_t proto_index = static_cast<uint32_t>(it.GetJavaValue().i);
3090 if (proto_index >= dex_file_->NumProtoIds()) {
3091 ErrorStringPrintf("CallSite has bad method type: %x", proto_index);
3092 return false;
3093 }
3094
3095 ptr_ += sizeof(dex::CallSiteIdItem);
3096 return true;
3097 }
3098
CheckInterAnnotationSetRefList()3099 bool DexFileVerifier::CheckInterAnnotationSetRefList() {
3100 const dex::AnnotationSetRefList* list = reinterpret_cast<const dex::AnnotationSetRefList*>(ptr_);
3101 const dex::AnnotationSetRefItem* item = list->list_;
3102 uint32_t count = list->size_;
3103
3104 for (; count != 0u; --count) {
3105 if (item->annotations_off_ != 0 &&
3106 !CheckOffsetToTypeMap(item->annotations_off_, DexFile::kDexTypeAnnotationSetItem)) {
3107 return false;
3108 }
3109 item++;
3110 }
3111
3112 ptr_ = reinterpret_cast<const uint8_t*>(item);
3113 return true;
3114 }
3115
CheckInterAnnotationSetItem()3116 bool DexFileVerifier::CheckInterAnnotationSetItem() {
3117 const dex::AnnotationSetItem* set = reinterpret_cast<const dex::AnnotationSetItem*>(ptr_);
3118 const uint32_t* offsets = set->entries_;
3119 uint32_t count = set->size_;
3120 uint32_t last_idx = 0;
3121
3122 for (uint32_t i = 0; i < count; i++) {
3123 if (*offsets != 0 && !CheckOffsetToTypeMap(*offsets, DexFile::kDexTypeAnnotationItem)) {
3124 return false;
3125 }
3126
3127 // Get the annotation from the offset and the type index for the annotation.
3128 const dex::AnnotationItem* annotation = OffsetToPtr<dex::AnnotationItem>(*offsets);
3129 const uint8_t* data = annotation->annotation_;
3130 DECODE_UNSIGNED_CHECKED_FROM(data, idx);
3131
3132 if (UNLIKELY(last_idx >= idx && i != 0)) {
3133 ErrorStringPrintf("Out-of-order entry types: %x then %x", last_idx, idx);
3134 return false;
3135 }
3136
3137 last_idx = idx;
3138 offsets++;
3139 }
3140
3141 ptr_ = reinterpret_cast<const uint8_t*>(offsets);
3142 return true;
3143 }
3144
CheckInterClassDataItem()3145 bool DexFileVerifier::CheckInterClassDataItem() {
3146 ClassAccessor accessor(*dex_file_, ptr_);
3147 uint32_t defining_class = FindFirstClassDataDefiner(accessor);
3148 DCHECK(IsUint<16>(defining_class) || defining_class == kDexNoIndex) << defining_class;
3149 if (defining_class == kDexNoIndex) {
3150 return true; // Empty definitions are OK (but useless) and could be shared by multiple classes.
3151 }
3152 if (!defined_classes_[defining_class]) {
3153 // Should really have a class definition for this class data item.
3154 ErrorStringPrintf("Could not find declaring class for non-empty class data item.");
3155 return false;
3156 }
3157 const dex::TypeIndex class_type_index(defining_class);
3158 const dex::ClassDef& class_def = dex_file_->GetClassDef(defined_class_indexes_[defining_class]);
3159
3160 for (const ClassAccessor::Field& read_field : accessor.GetFields()) {
3161 // The index has already been checked in `CheckIntraClassDataItemFields()`.
3162 DCHECK_LE(read_field.GetIndex(), header_->field_ids_size_);
3163 const dex::FieldId& field = dex_file_->GetFieldId(read_field.GetIndex());
3164 if (UNLIKELY(field.class_idx_ != class_type_index)) {
3165 ErrorStringPrintf("Mismatched defining class for class_data_item field");
3166 return false;
3167 }
3168 if (!CheckClassDataItemField(read_field.GetIndex(),
3169 read_field.GetAccessFlags(),
3170 class_def.access_flags_,
3171 class_type_index)) {
3172 return false;
3173 }
3174 }
3175 size_t num_direct_methods = accessor.NumDirectMethods();
3176 size_t num_processed_methods = 0u;
3177 auto methods = accessor.GetMethods();
3178 auto it = methods.begin();
3179 for (; it != methods.end(); ++it, ++num_processed_methods) {
3180 uint32_t code_off = it->GetCodeItemOffset();
3181 if (code_off != 0 && !CheckOffsetToTypeMap(code_off, DexFile::kDexTypeCodeItem)) {
3182 return false;
3183 }
3184 // The index has already been checked in `CheckIntraClassDataItemMethods()`.
3185 DCHECK_LE(it->GetIndex(), header_->method_ids_size_);
3186 const dex::MethodId& method = dex_file_->GetMethodId(it->GetIndex());
3187 if (UNLIKELY(method.class_idx_ != class_type_index)) {
3188 ErrorStringPrintf("Mismatched defining class for class_data_item method");
3189 return false;
3190 }
3191 bool expect_direct = num_processed_methods < num_direct_methods;
3192 if (!CheckClassDataItemMethod(it->GetIndex(),
3193 it->GetAccessFlags(),
3194 class_def.access_flags_,
3195 class_type_index,
3196 it->GetCodeItemOffset(),
3197 expect_direct)) {
3198 return false;
3199 }
3200 }
3201
3202 // Check static field types against initial static values in encoded array.
3203 if (!CheckStaticFieldTypes(class_def)) {
3204 return false;
3205 }
3206
3207 ptr_ = it.GetDataPointer();
3208 return true;
3209 }
3210
CheckInterAnnotationsDirectoryItem()3211 bool DexFileVerifier::CheckInterAnnotationsDirectoryItem() {
3212 const dex::AnnotationsDirectoryItem* item =
3213 reinterpret_cast<const dex::AnnotationsDirectoryItem*>(ptr_);
3214 uint32_t defining_class = FindFirstAnnotationsDirectoryDefiner(ptr_);
3215 DCHECK(IsUint<16>(defining_class) || defining_class == kDexNoIndex) << defining_class;
3216
3217 if (item->class_annotations_off_ != 0 &&
3218 !CheckOffsetToTypeMap(item->class_annotations_off_, DexFile::kDexTypeAnnotationSetItem)) {
3219 return false;
3220 }
3221
3222 // Field annotations follow immediately after the annotations directory.
3223 const dex::FieldAnnotationsItem* field_item =
3224 reinterpret_cast<const dex::FieldAnnotationsItem*>(item + 1);
3225 uint32_t field_count = item->fields_size_;
3226 for (uint32_t i = 0; i < field_count; i++) {
3227 // The index has already been checked in `CheckIntraAnnotationsDirectoryItem()`.
3228 DCHECK_LE(field_item->field_idx_, header_->field_ids_size_);
3229 const dex::FieldId& field = dex_file_->GetFieldId(field_item->field_idx_);
3230 if (UNLIKELY(field.class_idx_.index_ != defining_class)) {
3231 ErrorStringPrintf("Mismatched defining class for field_annotation");
3232 return false;
3233 }
3234 if (!CheckOffsetToTypeMap(field_item->annotations_off_, DexFile::kDexTypeAnnotationSetItem)) {
3235 return false;
3236 }
3237 field_item++;
3238 }
3239
3240 // Method annotations follow immediately after field annotations.
3241 const dex::MethodAnnotationsItem* method_item =
3242 reinterpret_cast<const dex::MethodAnnotationsItem*>(field_item);
3243 uint32_t method_count = item->methods_size_;
3244 for (uint32_t i = 0; i < method_count; i++) {
3245 // The index has already been checked in `CheckIntraAnnotationsDirectoryItem()`.
3246 DCHECK_LE(method_item->method_idx_, header_->method_ids_size_);
3247 const dex::MethodId& method = dex_file_->GetMethodId(method_item->method_idx_);
3248 if (UNLIKELY(method.class_idx_.index_ != defining_class)) {
3249 ErrorStringPrintf("Mismatched defining class for method_annotation");
3250 return false;
3251 }
3252 if (!CheckOffsetToTypeMap(method_item->annotations_off_, DexFile::kDexTypeAnnotationSetItem)) {
3253 return false;
3254 }
3255 method_item++;
3256 }
3257
3258 // Parameter annotations follow immediately after method annotations.
3259 const dex::ParameterAnnotationsItem* parameter_item =
3260 reinterpret_cast<const dex::ParameterAnnotationsItem*>(method_item);
3261 uint32_t parameter_count = item->parameters_size_;
3262 for (uint32_t i = 0; i < parameter_count; i++) {
3263 // The index has already been checked in `CheckIntraAnnotationsDirectoryItem()`.
3264 DCHECK_LE(parameter_item->method_idx_, header_->method_ids_size_);
3265 const dex::MethodId& parameter_method = dex_file_->GetMethodId(parameter_item->method_idx_);
3266 if (UNLIKELY(parameter_method.class_idx_.index_ != defining_class)) {
3267 ErrorStringPrintf("Mismatched defining class for parameter_annotation");
3268 return false;
3269 }
3270 if (!CheckOffsetToTypeMap(parameter_item->annotations_off_,
3271 DexFile::kDexTypeAnnotationSetRefList)) {
3272 return false;
3273 }
3274 parameter_item++;
3275 }
3276
3277 ptr_ = reinterpret_cast<const uint8_t*>(parameter_item);
3278 return true;
3279 }
3280
CheckInterSectionIterate(size_t offset,uint32_t count,DexFile::MapItemType type)3281 bool DexFileVerifier::CheckInterSectionIterate(size_t offset,
3282 uint32_t count,
3283 DexFile::MapItemType type) {
3284 // Get the right alignment mask for the type of section.
3285 size_t alignment_mask;
3286 switch (type) {
3287 case DexFile::kDexTypeClassDataItem:
3288 alignment_mask = sizeof(uint8_t) - 1;
3289 break;
3290 default:
3291 alignment_mask = sizeof(uint32_t) - 1;
3292 break;
3293 }
3294
3295 // Iterate through the items in the section.
3296 previous_item_ = nullptr;
3297 for (uint32_t i = 0; i < count; i++) {
3298 uint32_t new_offset = (offset + alignment_mask) & ~alignment_mask;
3299 ptr_ = OffsetToPtr(new_offset);
3300 const uint8_t* prev_ptr = ptr_;
3301
3302 if (MapTypeToBitMask(type) == 0) {
3303 ErrorStringPrintf("Unknown map item type %x", type);
3304 return false;
3305 }
3306
3307 // Check depending on the section type.
3308 switch (type) {
3309 case DexFile::kDexTypeHeaderItem:
3310 case DexFile::kDexTypeMethodHandleItem:
3311 case DexFile::kDexTypeMapList:
3312 case DexFile::kDexTypeTypeList:
3313 case DexFile::kDexTypeCodeItem:
3314 case DexFile::kDexTypeStringDataItem:
3315 case DexFile::kDexTypeDebugInfoItem:
3316 case DexFile::kDexTypeAnnotationItem:
3317 case DexFile::kDexTypeEncodedArrayItem:
3318 break;
3319 case DexFile::kDexTypeHiddenapiClassData: {
3320 if (!CheckIntraHiddenapiClassData()) {
3321 return false;
3322 }
3323 break;
3324 }
3325 case DexFile::kDexTypeStringIdItem: {
3326 if (!CheckInterStringIdItem()) {
3327 return false;
3328 }
3329 break;
3330 }
3331 case DexFile::kDexTypeTypeIdItem: {
3332 if (!CheckInterTypeIdItem()) {
3333 return false;
3334 }
3335 break;
3336 }
3337 case DexFile::kDexTypeProtoIdItem: {
3338 if (!CheckInterProtoIdItem()) {
3339 return false;
3340 }
3341 break;
3342 }
3343 case DexFile::kDexTypeFieldIdItem: {
3344 if (!CheckInterFieldIdItem()) {
3345 return false;
3346 }
3347 break;
3348 }
3349 case DexFile::kDexTypeMethodIdItem: {
3350 if (!CheckInterMethodIdItem()) {
3351 return false;
3352 }
3353 break;
3354 }
3355 case DexFile::kDexTypeClassDefItem: {
3356 // There shouldn't be more class definitions than type ids allow.
3357 // This is checked in `CheckIntraClassDefItem()` by checking the type
3358 // index against `kTypeIdLimit` and rejecting dulicate definitions.
3359 DCHECK_LE(i, kTypeIdLimit);
3360 if (!CheckInterClassDefItem()) {
3361 return false;
3362 }
3363 break;
3364 }
3365 case DexFile::kDexTypeCallSiteIdItem: {
3366 if (!CheckInterCallSiteIdItem()) {
3367 return false;
3368 }
3369 break;
3370 }
3371 case DexFile::kDexTypeAnnotationSetRefList: {
3372 if (!CheckInterAnnotationSetRefList()) {
3373 return false;
3374 }
3375 break;
3376 }
3377 case DexFile::kDexTypeAnnotationSetItem: {
3378 if (!CheckInterAnnotationSetItem()) {
3379 return false;
3380 }
3381 break;
3382 }
3383 case DexFile::kDexTypeClassDataItem: {
3384 // There shouldn't be more class data than type ids allow.
3385 // This check should be redundant, since there are checks that the
3386 // class_idx_ is within range and that there is only one definition
3387 // for a given type id.
3388 if (i > kTypeIdLimit) {
3389 ErrorStringPrintf("Too many class data items");
3390 return false;
3391 }
3392 if (!CheckInterClassDataItem()) {
3393 return false;
3394 }
3395 break;
3396 }
3397 case DexFile::kDexTypeAnnotationsDirectoryItem: {
3398 if (!CheckInterAnnotationsDirectoryItem()) {
3399 return false;
3400 }
3401 break;
3402 }
3403 }
3404
3405 previous_item_ = prev_ptr;
3406 offset = PtrToOffset(ptr_);
3407 }
3408
3409 return true;
3410 }
3411
CheckInterSection()3412 bool DexFileVerifier::CheckInterSection() {
3413 // Eagerly verify that `StringId` offsets map to string data items to make sure
3414 // we can retrieve the string data for verifying other items (types, shorties, etc.).
3415 // After this we can safely use `DexFile` helpers such as `GetFieldId()` or `GetMethodId()`
3416 // but not `PrettyMethod()` or `PrettyField()` as descriptors have not been verified yet.
3417 const dex::StringId* string_ids = OffsetToPtr<dex::StringId>(header_->string_ids_off_);
3418 for (size_t i = 0, num_strings = header_->string_ids_size_; i != num_strings; ++i) {
3419 if (!CheckOffsetToTypeMap(string_ids[i].string_data_off_, DexFile::kDexTypeStringDataItem)) {
3420 return false;
3421 }
3422 }
3423
3424 const dex::MapList* map = OffsetToPtr<dex::MapList>(header_->map_off_);
3425 const dex::MapItem* item = map->list_;
3426 uint32_t count = map->size_;
3427
3428 // Cross check the items listed in the map.
3429 for (; count != 0u; --count) {
3430 uint32_t section_offset = item->offset_;
3431 uint32_t section_count = item->size_;
3432 DexFile::MapItemType type = static_cast<DexFile::MapItemType>(item->type_);
3433 bool found = false;
3434
3435 if (type == DexFile::kDexTypeClassDataItem) {
3436 FindStringRangesForMethodNames();
3437 }
3438
3439 switch (type) {
3440 case DexFile::kDexTypeHeaderItem:
3441 case DexFile::kDexTypeMapList:
3442 case DexFile::kDexTypeTypeList:
3443 case DexFile::kDexTypeCodeItem:
3444 case DexFile::kDexTypeStringDataItem:
3445 case DexFile::kDexTypeDebugInfoItem:
3446 case DexFile::kDexTypeAnnotationItem:
3447 case DexFile::kDexTypeEncodedArrayItem:
3448 found = true;
3449 break;
3450 case DexFile::kDexTypeStringIdItem:
3451 case DexFile::kDexTypeTypeIdItem:
3452 case DexFile::kDexTypeProtoIdItem:
3453 case DexFile::kDexTypeFieldIdItem:
3454 case DexFile::kDexTypeMethodIdItem:
3455 case DexFile::kDexTypeClassDefItem:
3456 case DexFile::kDexTypeCallSiteIdItem:
3457 case DexFile::kDexTypeMethodHandleItem:
3458 case DexFile::kDexTypeAnnotationSetRefList:
3459 case DexFile::kDexTypeAnnotationSetItem:
3460 case DexFile::kDexTypeClassDataItem:
3461 case DexFile::kDexTypeAnnotationsDirectoryItem:
3462 case DexFile::kDexTypeHiddenapiClassData: {
3463 if (!CheckInterSectionIterate(section_offset, section_count, type)) {
3464 return false;
3465 }
3466 found = true;
3467 break;
3468 }
3469 }
3470
3471 if (!found) {
3472 ErrorStringPrintf("Unknown map item type %x", item->type_);
3473 return false;
3474 }
3475
3476 item++;
3477 }
3478
3479 return true;
3480 }
3481
Verify()3482 bool DexFileVerifier::Verify() {
3483 // Check the header.
3484 if (!CheckHeader()) {
3485 return false;
3486 }
3487
3488 // Check the map section.
3489 if (!CheckMap()) {
3490 return false;
3491 }
3492
3493 DCHECK_LE(header_->type_ids_size_, kTypeIdLimit + 1u); // Checked in CheckHeader().
3494 verified_type_descriptors_.resize(header_->type_ids_size_, 0);
3495 defined_class_indexes_.resize(header_->type_ids_size_);
3496
3497 // Check structure within remaining sections.
3498 if (!CheckIntraSection()) {
3499 return false;
3500 }
3501
3502 // Check references from one section to another.
3503 if (!CheckInterSection()) {
3504 return false;
3505 }
3506
3507 CHECK(todo_.empty()); // No unprocessed work left over.
3508 return true;
3509 }
3510
CheckFieldAccessFlags(uint32_t idx,uint32_t field_access_flags,uint32_t class_access_flags,std::string * error_msg)3511 bool DexFileVerifier::CheckFieldAccessFlags(uint32_t idx,
3512 uint32_t field_access_flags,
3513 uint32_t class_access_flags,
3514 std::string* error_msg) {
3515 // Generally sort out >16-bit flags.
3516 if ((field_access_flags & ~kAccJavaFlagsMask) != 0) {
3517 *error_msg = StringPrintf("Bad field access_flags for %s: %x(%s)",
3518 GetFieldDescription(idx).c_str(),
3519 field_access_flags,
3520 PrettyJavaAccessFlags(field_access_flags).c_str());
3521 return false;
3522 }
3523
3524 // Flags allowed on fields, in general. Other lower-16-bit flags are to be ignored.
3525 constexpr uint32_t kFieldAccessFlags = kAccPublic |
3526 kAccPrivate |
3527 kAccProtected |
3528 kAccStatic |
3529 kAccFinal |
3530 kAccVolatile |
3531 kAccTransient |
3532 kAccSynthetic |
3533 kAccEnum;
3534
3535 // Fields may have only one of public/protected/final.
3536 if (!CheckAtMostOneOfPublicProtectedPrivate(field_access_flags)) {
3537 *error_msg = StringPrintf("Field may have only one of public/protected/private, %s: %x(%s)",
3538 GetFieldDescription(idx).c_str(),
3539 field_access_flags,
3540 PrettyJavaAccessFlags(field_access_flags).c_str());
3541 return false;
3542 }
3543
3544 // Interfaces have a pretty restricted list.
3545 if ((class_access_flags & kAccInterface) != 0) {
3546 // Interface fields must be public final static.
3547 constexpr uint32_t kPublicFinalStatic = kAccPublic | kAccFinal | kAccStatic;
3548 if ((field_access_flags & kPublicFinalStatic) != kPublicFinalStatic) {
3549 *error_msg = StringPrintf("Interface field is not public final static, %s: %x(%s)",
3550 GetFieldDescription(idx).c_str(),
3551 field_access_flags,
3552 PrettyJavaAccessFlags(field_access_flags).c_str());
3553 if (dex_file_->SupportsDefaultMethods()) {
3554 return false;
3555 } else {
3556 // Allow in older versions, but warn.
3557 LOG(WARNING) << "This dex file is invalid and will be rejected in the future. Error is: "
3558 << *error_msg;
3559 }
3560 }
3561 // Interface fields may be synthetic, but may not have other flags.
3562 constexpr uint32_t kDisallowed = ~(kPublicFinalStatic | kAccSynthetic);
3563 if ((field_access_flags & kFieldAccessFlags & kDisallowed) != 0) {
3564 *error_msg = StringPrintf("Interface field has disallowed flag, %s: %x(%s)",
3565 GetFieldDescription(idx).c_str(),
3566 field_access_flags,
3567 PrettyJavaAccessFlags(field_access_flags).c_str());
3568 if (dex_file_->SupportsDefaultMethods()) {
3569 return false;
3570 } else {
3571 // Allow in older versions, but warn.
3572 LOG(WARNING) << "This dex file is invalid and will be rejected in the future. Error is: "
3573 << *error_msg;
3574 }
3575 }
3576 return true;
3577 }
3578
3579 // Volatile fields may not be final.
3580 constexpr uint32_t kVolatileFinal = kAccVolatile | kAccFinal;
3581 if ((field_access_flags & kVolatileFinal) == kVolatileFinal) {
3582 *error_msg = StringPrintf("Fields may not be volatile and final: %s",
3583 GetFieldDescription(idx).c_str());
3584 return false;
3585 }
3586
3587 return true;
3588 }
3589
FindStringRangesForMethodNames()3590 void DexFileVerifier::FindStringRangesForMethodNames() {
3591 // Use DexFile::StringId* as RandomAccessIterator.
3592 const dex::StringId* first = OffsetToPtr<dex::StringId>(header_->string_ids_off_);
3593 const dex::StringId* last = first + header_->string_ids_size_;
3594
3595 auto get_string = [this](const dex::StringId& id) {
3596 const uint8_t* str_data_ptr = OffsetToPtr(id.string_data_off_);
3597 DecodeUnsignedLeb128(&str_data_ptr);
3598 return reinterpret_cast<const char*>(str_data_ptr);
3599 };
3600 auto compare = [&get_string](const dex::StringId& lhs, const char* rhs) {
3601 return CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues(get_string(lhs), rhs) < 0;
3602 };
3603
3604 // '=' follows '<'
3605 static_assert('<' + 1 == '=', "Unexpected character relation");
3606 const auto angle_end = std::lower_bound(first, last, "=", compare);
3607 init_indices_.angle_bracket_end_index = angle_end - first;
3608
3609 const auto angle_start = std::lower_bound(first, angle_end, "<", compare);
3610 init_indices_.angle_bracket_start_index = angle_start - first;
3611 if (angle_start == angle_end) {
3612 // No strings starting with '<'.
3613 init_indices_.angle_init_angle_index = std::numeric_limits<size_t>::max();
3614 init_indices_.angle_clinit_angle_index = std::numeric_limits<size_t>::max();
3615 return;
3616 }
3617
3618 {
3619 constexpr const char* kClinit = "<clinit>";
3620 const auto it = std::lower_bound(angle_start, angle_end, kClinit, compare);
3621 if (it != angle_end && strcmp(get_string(*it), kClinit) == 0) {
3622 init_indices_.angle_clinit_angle_index = it - first;
3623 } else {
3624 init_indices_.angle_clinit_angle_index = std::numeric_limits<size_t>::max();
3625 }
3626 }
3627 {
3628 constexpr const char* kInit = "<init>";
3629 const auto it = std::lower_bound(angle_start, angle_end, kInit, compare);
3630 if (it != angle_end && strcmp(get_string(*it), kInit) == 0) {
3631 init_indices_.angle_init_angle_index = it - first;
3632 } else {
3633 init_indices_.angle_init_angle_index = std::numeric_limits<size_t>::max();
3634 }
3635 }
3636 }
3637
CheckMethodAccessFlags(uint32_t method_index,uint32_t method_access_flags,uint32_t class_access_flags,uint32_t constructor_flags_by_name,bool has_code,bool expect_direct,std::string * error_msg)3638 bool DexFileVerifier::CheckMethodAccessFlags(uint32_t method_index,
3639 uint32_t method_access_flags,
3640 uint32_t class_access_flags,
3641 uint32_t constructor_flags_by_name,
3642 bool has_code,
3643 bool expect_direct,
3644 std::string* error_msg) {
3645 // Generally sort out >16-bit flags, except dex knows Constructor and DeclaredSynchronized.
3646 constexpr uint32_t kAllMethodFlags =
3647 kAccJavaFlagsMask | kAccConstructor | kAccDeclaredSynchronized;
3648 if ((method_access_flags & ~kAllMethodFlags) != 0) {
3649 *error_msg = StringPrintf("Bad method access_flags for %s: %x",
3650 GetMethodDescription(method_index).c_str(),
3651 method_access_flags);
3652 return false;
3653 }
3654
3655 // Flags allowed on methods, in general. Other lower-16-bit flags are to be ignored.
3656 constexpr uint32_t kMethodAccessFlags = kAccPublic |
3657 kAccPrivate |
3658 kAccProtected |
3659 kAccStatic |
3660 kAccFinal |
3661 kAccSynthetic |
3662 kAccSynchronized |
3663 kAccBridge |
3664 kAccVarargs |
3665 kAccNative |
3666 kAccAbstract |
3667 kAccStrict;
3668
3669 // Methods may have only one of public/protected/final.
3670 if (!CheckAtMostOneOfPublicProtectedPrivate(method_access_flags)) {
3671 *error_msg = StringPrintf("Method may have only one of public/protected/private, %s: %x",
3672 GetMethodDescription(method_index).c_str(),
3673 method_access_flags);
3674 return false;
3675 }
3676
3677 constexpr uint32_t kConstructorFlags = kAccStatic | kAccConstructor;
3678 const bool is_constructor_by_name = (constructor_flags_by_name & kConstructorFlags) != 0;
3679 const bool is_clinit_by_name = constructor_flags_by_name == kConstructorFlags;
3680
3681 // Only methods named "<clinit>" or "<init>" may be marked constructor. Note: we cannot enforce
3682 // the reverse for backwards compatibility reasons.
3683 if (((method_access_flags & kAccConstructor) != 0) && !is_constructor_by_name) {
3684 *error_msg =
3685 StringPrintf("Method %" PRIu32 "(%s) is marked constructor, but doesn't match name",
3686 method_index,
3687 GetMethodDescription(method_index).c_str());
3688 return false;
3689 }
3690
3691 if (is_constructor_by_name) {
3692 // Check that the static constructor (= static initializer) is named "<clinit>" and that the
3693 // instance constructor is called "<init>".
3694 bool is_static = (method_access_flags & kAccStatic) != 0;
3695 if (is_static ^ is_clinit_by_name) {
3696 *error_msg = StringPrintf("Constructor %" PRIu32 "(%s) is not flagged correctly wrt/ static.",
3697 method_index,
3698 GetMethodDescription(method_index).c_str());
3699 if (dex_file_->SupportsDefaultMethods()) {
3700 return false;
3701 } else {
3702 // Allow in older versions, but warn.
3703 LOG(WARNING) << "This dex file is invalid and will be rejected in the future. Error is: "
3704 << *error_msg;
3705 }
3706 }
3707 }
3708
3709 // Check that static and private methods, as well as constructors, are in the direct methods list,
3710 // and other methods in the virtual methods list.
3711 bool is_direct = ((method_access_flags & (kAccStatic | kAccPrivate)) != 0) ||
3712 is_constructor_by_name;
3713 if (is_direct != expect_direct) {
3714 *error_msg = StringPrintf("Direct/virtual method %" PRIu32 "(%s) not in expected list %d",
3715 method_index,
3716 GetMethodDescription(method_index).c_str(),
3717 expect_direct);
3718 return false;
3719 }
3720
3721 // From here on out it is easier to mask out the bits we're supposed to ignore.
3722 method_access_flags &= kMethodAccessFlags;
3723
3724 // Interfaces are special.
3725 if ((class_access_flags & kAccInterface) != 0) {
3726 // Non-static interface methods must be public or private.
3727 uint32_t desired_flags = (kAccPublic | kAccStatic);
3728 if (dex_file_->SupportsDefaultMethods()) {
3729 desired_flags |= kAccPrivate;
3730 }
3731 if ((method_access_flags & desired_flags) == 0) {
3732 *error_msg = StringPrintf("Interface virtual method %" PRIu32 "(%s) is not public",
3733 method_index,
3734 GetMethodDescription(method_index).c_str());
3735 if (dex_file_->SupportsDefaultMethods()) {
3736 return false;
3737 } else {
3738 // Allow in older versions, but warn.
3739 LOG(WARNING) << "This dex file is invalid and will be rejected in the future. Error is: "
3740 << *error_msg;
3741 }
3742 }
3743 }
3744
3745 // If there aren't any instructions, make sure that's expected.
3746 if (!has_code) {
3747 // Only native or abstract methods may not have code.
3748 if ((method_access_flags & (kAccNative | kAccAbstract)) == 0) {
3749 *error_msg = StringPrintf("Method %" PRIu32 "(%s) has no code, but is not marked native or "
3750 "abstract",
3751 method_index,
3752 GetMethodDescription(method_index).c_str());
3753 return false;
3754 }
3755 // Constructors must always have code.
3756 if (is_constructor_by_name) {
3757 *error_msg = StringPrintf("Constructor %u(%s) must not be abstract or native",
3758 method_index,
3759 GetMethodDescription(method_index).c_str());
3760 if (dex_file_->SupportsDefaultMethods()) {
3761 return false;
3762 } else {
3763 // Allow in older versions, but warn.
3764 LOG(WARNING) << "This dex file is invalid and will be rejected in the future. Error is: "
3765 << *error_msg;
3766 }
3767 }
3768 if ((method_access_flags & kAccAbstract) != 0) {
3769 // Abstract methods are not allowed to have the following flags.
3770 constexpr uint32_t kForbidden =
3771 kAccPrivate | kAccStatic | kAccFinal | kAccNative | kAccStrict | kAccSynchronized;
3772 if ((method_access_flags & kForbidden) != 0) {
3773 *error_msg = StringPrintf("Abstract method %" PRIu32 "(%s) has disallowed access flags %x",
3774 method_index,
3775 GetMethodDescription(method_index).c_str(),
3776 method_access_flags);
3777 return false;
3778 }
3779 // Abstract methods should be in an abstract class or interface.
3780 if ((class_access_flags & (kAccInterface | kAccAbstract)) == 0) {
3781 LOG(WARNING) << "Method " << GetMethodDescription(method_index)
3782 << " is abstract, but the declaring class is neither abstract nor an "
3783 << "interface in dex file "
3784 << dex_file_->GetLocation();
3785 }
3786 }
3787 // Interfaces are special.
3788 if ((class_access_flags & kAccInterface) != 0) {
3789 // Interface methods without code must be abstract.
3790 if ((method_access_flags & (kAccPublic | kAccAbstract)) != (kAccPublic | kAccAbstract)) {
3791 *error_msg = StringPrintf("Interface method %" PRIu32 "(%s) is not public and abstract",
3792 method_index,
3793 GetMethodDescription(method_index).c_str());
3794 if (dex_file_->SupportsDefaultMethods()) {
3795 return false;
3796 } else {
3797 // Allow in older versions, but warn.
3798 LOG(WARNING) << "This dex file is invalid and will be rejected in the future. Error is: "
3799 << *error_msg;
3800 }
3801 }
3802 // At this point, we know the method is public and abstract. This means that all the checks
3803 // for invalid combinations above applies. In addition, interface methods must not be
3804 // protected. This is caught by the check for only-one-of-public-protected-private.
3805 }
3806 return true;
3807 }
3808
3809 // When there's code, the method must not be native or abstract.
3810 if ((method_access_flags & (kAccNative | kAccAbstract)) != 0) {
3811 *error_msg = StringPrintf("Method %" PRIu32 "(%s) has code, but is marked native or abstract",
3812 method_index,
3813 GetMethodDescription(method_index).c_str());
3814 return false;
3815 }
3816
3817 // Instance constructors must not be synchronized and a few other flags.
3818 if (constructor_flags_by_name == kAccConstructor) {
3819 static constexpr uint32_t kInitAllowed =
3820 kAccPrivate | kAccProtected | kAccPublic | kAccStrict | kAccVarargs | kAccSynthetic;
3821 if ((method_access_flags & ~kInitAllowed) != 0) {
3822 *error_msg = StringPrintf("Constructor %" PRIu32 "(%s) flagged inappropriately %x",
3823 method_index,
3824 GetMethodDescription(method_index).c_str(),
3825 method_access_flags);
3826 return false;
3827 }
3828 }
3829
3830 return true;
3831 }
3832
CheckConstructorProperties(uint32_t method_index,uint32_t constructor_flags)3833 bool DexFileVerifier::CheckConstructorProperties(
3834 uint32_t method_index,
3835 uint32_t constructor_flags) {
3836 DCHECK(constructor_flags == kAccConstructor ||
3837 constructor_flags == (kAccConstructor | kAccStatic));
3838
3839 // Check signature matches expectations.
3840 // The `method_index` has already been checked in `CheckIntraClassDataItemMethods()`.
3841 CHECK_LT(method_index, header_->method_ids_size_);
3842 const dex::MethodId& method_id = dex_file_->GetMethodId(method_index);
3843
3844 // The `method_id.proto_idx_` has already been checked in `CheckIntraMethodIdItem()`
3845 DCHECK_LE(method_id.proto_idx_.index_, header_->proto_ids_size_);
3846
3847 Signature signature = dex_file_->GetMethodSignature(method_id);
3848 if (constructor_flags == (kAccStatic | kAccConstructor)) {
3849 if (!signature.IsVoid() || signature.GetNumberOfParameters() != 0) {
3850 ErrorStringPrintf("<clinit> must have descriptor ()V");
3851 return false;
3852 }
3853 } else if (!signature.IsVoid()) {
3854 ErrorStringPrintf("Constructor %u(%s) must be void",
3855 method_index,
3856 GetMethodDescription(method_index).c_str());
3857 return false;
3858 }
3859
3860 return true;
3861 }
3862
Verify(const DexFile * dex_file,const char * location,bool verify_checksum,std::string * error_msg)3863 bool Verify(const DexFile* dex_file,
3864 const char* location,
3865 bool verify_checksum,
3866 std::string* error_msg) {
3867 std::unique_ptr<DexFileVerifier> verifier(
3868 new DexFileVerifier(dex_file, location, verify_checksum));
3869 if (!verifier->Verify()) {
3870 *error_msg = verifier->FailureReason();
3871 return false;
3872 }
3873 return true;
3874 }
3875
3876 } // namespace dex
3877 } // namespace art
3878