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