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