1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 /* 18 * Byte-swapping and verification of dex files. 19 */ 20 21 #include "DexFile.h" 22 #include "DexClass.h" 23 #include "DexDataMap.h" 24 #include "DexProto.h" 25 #include "DexUtf.h" 26 #include "Leb128.h" 27 28 #include <safe_iop.h> 29 #include <zlib.h> 30 31 #include <stdlib.h> 32 #include <string.h> 33 34 #ifndef __BYTE_ORDER 35 # error "byte ordering not defined" 36 #endif 37 38 #if __BYTE_ORDER == __LITTLE_ENDIAN 39 # define SWAP2(_value) (_value) 40 # define SWAP4(_value) (_value) 41 # define SWAP8(_value) (_value) 42 #else 43 # define SWAP2(_value) endianSwapU2((_value)) 44 # define SWAP4(_value) endianSwapU4((_value)) 45 # define SWAP8(_value) endianSwapU8((_value)) 46 static u2 endianSwapU2(u2 value) { 47 return (value >> 8) | (value << 8); 48 } 49 static u4 endianSwapU4(u4 value) { 50 /* ABCD --> CDAB --> DCBA */ 51 value = (value >> 16) | (value << 16); 52 return ((value & 0xff00ff00) >> 8) | ((value << 8) & 0xff00ff00); 53 } 54 static u8 endianSwapU8(u8 value) { 55 /* ABCDEFGH --> EFGHABCD --> GHEFCDAB --> HGFEDCBA */ 56 value = (value >> 32) | (value << 32); 57 value = ((value & 0xffff0000ffff0000ULL) >> 16) | 58 ((value << 16) & 0xffff0000ffff0000ULL); 59 return ((value & 0xff00ff00ff00ff00ULL) >> 8) | 60 ((value << 8) & 0xff00ff00ff00ff00ULL); 61 } 62 #endif 63 64 #define SWAP_FIELD2(_field) (_field) = SWAP2(_field) 65 #define SWAP_FIELD4(_field) (_field) = SWAP4(_field) 66 #define SWAP_FIELD8(_field) (_field) = SWAP8(_field) 67 68 /* 69 * Some information we pass around to help verify values. 70 */ 71 struct CheckState { 72 const DexHeader* pHeader; 73 const u1* fileStart; 74 const u1* fileEnd; // points to fileStart + fileLen 75 u4 fileLen; 76 DexDataMap* pDataMap; // set after map verification 77 const DexFile* pDexFile; // set after intraitem verification 78 79 /* 80 * bitmap of type_id indices that have been used to define classes; 81 * initialized immediately before class_def cross-verification, and 82 * freed immediately after it 83 */ 84 u4* pDefinedClassBits; 85 86 const void* previousItem; // set during section iteration 87 }; 88 89 /* 90 * Return the file offset of the given pointer. 91 */ 92 static inline u4 fileOffset(const CheckState* state, const void* ptr) { 93 return ((const u1*) ptr) - state->fileStart; 94 } 95 96 /* 97 * Return a pointer for the given file offset. 98 */ 99 static inline void* filePointer(const CheckState* state, u4 offset) { 100 return (void*) (state->fileStart + offset); 101 } 102 103 /* 104 * Verify that a pointer range, start inclusive to end exclusive, only 105 * covers bytes in the file and doesn't point beyond the end of the 106 * file. That is, the start must indicate a valid byte or may point at 107 * the byte just past the end of the file (but no further), and the 108 * end must be no less than the start and must also not point beyond 109 * the byte just past the end of the file. 110 */ 111 static inline bool checkPtrRange(const CheckState* state, 112 const void* start, const void* end, const char* label) { 113 const void* fileStart = state->fileStart; 114 const void* fileEnd = state->fileEnd; 115 if ((start < fileStart) || (start > fileEnd) 116 || (end < start) || (end > fileEnd)) { 117 ALOGW("Bad offset range for %s: %#x..%#x", label, 118 fileOffset(state, start), fileOffset(state, end)); 119 return false; 120 } 121 return true; 122 } 123 124 /* 125 * Verify that a range of offsets, start inclusive to end exclusive, 126 * are all valid. That is, the start must indicate a valid byte or may 127 * point at the byte just past the end of the file (but no further), 128 * and the end must be no less than the start and must also not point 129 * beyond the byte just past the end of the file. 130 * 131 * Assumes "const CheckState* state". 132 */ 133 #define CHECK_OFFSET_RANGE(_start, _end) { \ 134 const u1* _startPtr = (const u1*) filePointer(state, (_start)); \ 135 const u1* _endPtr = (const u1*) filePointer(state, (_end)); \ 136 if (!checkPtrRange(state, _startPtr, _endPtr, \ 137 #_start ".." #_end)) { \ 138 return 0; \ 139 } \ 140 } 141 142 /* 143 * Verify that a pointer range, start inclusive to end exclusive, only 144 * covers bytes in the file and doesn't point beyond the end of the 145 * file. That is, the start must indicate a valid byte or may point at 146 * the byte just past the end of the file (but no further), and the 147 * end must be no less than the start and must also not point beyond 148 * the byte just past the end of the file. 149 * 150 * Assumes "const CheckState* state". 151 */ 152 #define CHECK_PTR_RANGE(_start, _end) { \ 153 if (!checkPtrRange(state, (_start), (_end), #_start ".." #_end)) { \ 154 return 0; \ 155 } \ 156 } 157 158 /* 159 * Make sure a list of items fits entirely within the file. 160 * 161 * Assumes "const CheckState* state" and "typeof(_count) == typeof(_elemSize)" 162 * If the type sizes or signs are mismatched, this will return 0. 163 */ 164 #define CHECK_LIST_SIZE(_ptr, _count, _elemSize) { \ 165 const u1* _start = (const u1*) (_ptr); \ 166 const u1* _end = _start + ((_count) * (_elemSize)); \ 167 if (!safe_mul(NULL, (_count), (_elemSize)) || \ 168 !checkPtrRange(state, _start, _end, #_ptr)) { \ 169 return 0; \ 170 } \ 171 } 172 173 /* 174 * Swap a field that is known to hold an absolute DEX file offset. Note: 175 * This does not check to see that the swapped offset points within the 176 * mapped file, since that should be handled (with even more rigor) by 177 * the cross-verification phase. 178 * 179 * Assumes "const CheckState* state". 180 */ 181 #define SWAP_OFFSET4(_field) { \ 182 SWAP_FIELD4((_field)); \ 183 } 184 185 /* 186 * Verify that an index falls in a valid range. 187 */ 188 #define CHECK_INDEX(_field, _limit) { \ 189 if ((_field) >= (_limit)) { \ 190 ALOGW("Bad index: %s(%u) > %s(%u)", \ 191 #_field, (u4)(_field), #_limit, (u4)(_limit)); \ 192 return 0; \ 193 } \ 194 } 195 196 /* 197 * Swap an index, and verify that it falls in a valid range. 198 */ 199 #define SWAP_INDEX2(_field, _limit) { \ 200 SWAP_FIELD2((_field)); \ 201 CHECK_INDEX((_field), (_limit)); \ 202 } 203 204 /* 205 * Verify that an index falls in a valid range or is kDexNoIndex. 206 */ 207 #define CHECK_INDEX_OR_NOINDEX(_field, _limit) { \ 208 if ((_field) != kDexNoIndex && (_field) >= (_limit)) { \ 209 ALOGW("Bad index: %s(%u) > %s(%u)", \ 210 #_field, (u4)(_field), #_limit, (u4)(_limit)); \ 211 return 0; \ 212 } \ 213 } 214 215 /* 216 * Swap an index, and verify that it falls in a valid range. 217 */ 218 #define SWAP_INDEX4(_field, _limit) { \ 219 SWAP_FIELD4((_field)); \ 220 CHECK_INDEX((_field), (_limit)); \ 221 } 222 223 /* 224 * Swap an index, and verify that it falls in a valid range or is 225 * kDexNoIndex. 226 */ 227 #define SWAP_INDEX4_OR_NOINDEX(_field, _limit) { \ 228 SWAP_FIELD4((_field)); \ 229 CHECK_INDEX_OR_NOINDEX((_field), (_limit)); \ 230 } 231 232 /* Verify the definer of a given field_idx. */ 233 static bool verifyFieldDefiner(const CheckState* state, u4 definingClass, 234 u4 fieldIdx) { 235 const DexFieldId* field = dexGetFieldId(state->pDexFile, fieldIdx); 236 return field->classIdx == definingClass; 237 } 238 239 /* Verify the definer of a given method_idx. */ 240 static bool verifyMethodDefiner(const CheckState* state, u4 definingClass, 241 u4 methodIdx) { 242 const DexMethodId* meth = dexGetMethodId(state->pDexFile, methodIdx); 243 return meth->classIdx == definingClass; 244 } 245 246 /* 247 * Calculate the required size (in elements) of the array pointed at by 248 * pDefinedClassBits. 249 */ 250 static size_t calcDefinedClassBitsSize(const CheckState* state) 251 { 252 // Divide typeIdsSize by 32 (0x20), rounding up. 253 return (state->pHeader->typeIdsSize + 0x1f) >> 5; 254 } 255 256 /* 257 * Set the given bit in pDefinedClassBits, returning its former value. 258 */ 259 static bool setDefinedClassBit(const CheckState* state, u4 typeIdx) { 260 u4 arrayIdx = typeIdx >> 5; 261 u4 bit = 1 << (typeIdx & 0x1f); 262 u4* element = &state->pDefinedClassBits[arrayIdx]; 263 bool result = (*element & bit) != 0; 264 265 *element |= bit; 266 267 return result; 268 } 269 270 /* 271 * Swap the header_item. 272 */ 273 static bool swapDexHeader(const CheckState* state, DexHeader* pHeader) 274 { 275 CHECK_PTR_RANGE(pHeader, pHeader + 1); 276 277 // magic is ok 278 SWAP_FIELD4(pHeader->checksum); 279 // signature is ok 280 SWAP_FIELD4(pHeader->fileSize); 281 SWAP_FIELD4(pHeader->headerSize); 282 SWAP_FIELD4(pHeader->endianTag); 283 SWAP_FIELD4(pHeader->linkSize); 284 SWAP_OFFSET4(pHeader->linkOff); 285 SWAP_OFFSET4(pHeader->mapOff); 286 SWAP_FIELD4(pHeader->stringIdsSize); 287 SWAP_OFFSET4(pHeader->stringIdsOff); 288 SWAP_FIELD4(pHeader->typeIdsSize); 289 SWAP_OFFSET4(pHeader->typeIdsOff); 290 SWAP_FIELD4(pHeader->fieldIdsSize); 291 SWAP_OFFSET4(pHeader->fieldIdsOff); 292 SWAP_FIELD4(pHeader->methodIdsSize); 293 SWAP_OFFSET4(pHeader->methodIdsOff); 294 SWAP_FIELD4(pHeader->protoIdsSize); 295 SWAP_OFFSET4(pHeader->protoIdsOff); 296 SWAP_FIELD4(pHeader->classDefsSize); 297 SWAP_OFFSET4(pHeader->classDefsOff); 298 SWAP_FIELD4(pHeader->dataSize); 299 SWAP_OFFSET4(pHeader->dataOff); 300 301 if (pHeader->endianTag != kDexEndianConstant) { 302 ALOGE("Unexpected endian_tag: %#x", pHeader->endianTag); 303 return false; 304 } 305 306 // Assign variables so the diagnostic is prettier. (Hooray for macros.) 307 u4 linkOff = pHeader->linkOff; 308 u4 linkEnd = linkOff + pHeader->linkSize; 309 u4 dataOff = pHeader->dataOff; 310 u4 dataEnd = dataOff + pHeader->dataSize; 311 CHECK_OFFSET_RANGE(linkOff, linkEnd); 312 CHECK_OFFSET_RANGE(dataOff, dataEnd); 313 314 /* 315 * Note: The offsets and ranges of the other header items end up getting 316 * checked during the first iteration over the map. 317 */ 318 319 return true; 320 } 321 322 /* Check the header section for sanity. */ 323 static bool checkHeaderSection(const CheckState* state, u4 sectionOffset, 324 u4 sectionCount, u4* endOffset) { 325 if (sectionCount != 1) { 326 ALOGE("Multiple header items"); 327 return false; 328 } 329 330 if (sectionOffset != 0) { 331 ALOGE("Header at %#x; not at start of file", sectionOffset); 332 return false; 333 } 334 335 const DexHeader* pHeader = (const DexHeader*) filePointer(state, 0); 336 *endOffset = pHeader->headerSize; 337 return true; 338 } 339 340 /* 341 * Helper for swapMap(), which turns a map type constant into a small 342 * one-bit-on integer, suitable for use in an int-sized bit set. 343 */ 344 static u4 mapTypeToBitMask(int mapType) { 345 switch (mapType) { 346 case kDexTypeHeaderItem: return 1 << 0; 347 case kDexTypeStringIdItem: return 1 << 1; 348 case kDexTypeTypeIdItem: return 1 << 2; 349 case kDexTypeProtoIdItem: return 1 << 3; 350 case kDexTypeFieldIdItem: return 1 << 4; 351 case kDexTypeMethodIdItem: return 1 << 5; 352 case kDexTypeClassDefItem: return 1 << 6; 353 case kDexTypeMapList: return 1 << 7; 354 case kDexTypeTypeList: return 1 << 8; 355 case kDexTypeAnnotationSetRefList: return 1 << 9; 356 case kDexTypeAnnotationSetItem: return 1 << 10; 357 case kDexTypeClassDataItem: return 1 << 11; 358 case kDexTypeCodeItem: return 1 << 12; 359 case kDexTypeStringDataItem: return 1 << 13; 360 case kDexTypeDebugInfoItem: return 1 << 14; 361 case kDexTypeAnnotationItem: return 1 << 15; 362 case kDexTypeEncodedArrayItem: return 1 << 16; 363 case kDexTypeAnnotationsDirectoryItem: return 1 << 17; 364 default: { 365 ALOGE("Unknown map item type %04x", mapType); 366 return 0; 367 } 368 } 369 } 370 371 /* 372 * Helper for swapMap(), which indicates if an item type should appear 373 * in the data section. 374 */ 375 static bool isDataSectionType(int mapType) { 376 switch (mapType) { 377 case kDexTypeHeaderItem: 378 case kDexTypeStringIdItem: 379 case kDexTypeTypeIdItem: 380 case kDexTypeProtoIdItem: 381 case kDexTypeFieldIdItem: 382 case kDexTypeMethodIdItem: 383 case kDexTypeClassDefItem: { 384 return false; 385 } 386 } 387 388 return true; 389 } 390 391 /* 392 * Swap the map_list and verify what we can about it. Also, if verification 393 * passes, allocate the state's DexDataMap. 394 */ 395 static bool swapMap(CheckState* state, DexMapList* pMap) 396 { 397 DexMapItem* item = pMap->list; 398 u4 count; 399 u4 dataItemCount = 0; // Total count of items in the data section. 400 u4 dataItemsLeft = state->pHeader->dataSize; // See use below. 401 u4 usedBits = 0; // Bit set: one bit per section 402 bool first = true; 403 u4 lastOffset = 0; 404 405 SWAP_FIELD4(pMap->size); 406 count = pMap->size; 407 408 CHECK_LIST_SIZE(item, count, sizeof(DexMapItem)); 409 410 while (count--) { 411 SWAP_FIELD2(item->type); 412 SWAP_FIELD2(item->unused); 413 SWAP_FIELD4(item->size); 414 SWAP_OFFSET4(item->offset); 415 416 if (first) { 417 first = false; 418 } else if (lastOffset >= item->offset) { 419 ALOGE("Out-of-order map item: %#x then %#x", 420 lastOffset, item->offset); 421 return false; 422 } 423 424 if (item->offset >= state->pHeader->fileSize) { 425 ALOGE("Map item after end of file: %x, size %#x", 426 item->offset, state->pHeader->fileSize); 427 return false; 428 } 429 430 if (isDataSectionType(item->type)) { 431 u4 icount = item->size; 432 433 /* 434 * This sanity check on the data section items ensures that 435 * there are no more items than the number of bytes in 436 * the data section. 437 */ 438 if (icount > dataItemsLeft) { 439 ALOGE("Unrealistically many items in the data section: " 440 "at least %d", dataItemCount + icount); 441 return false; 442 } 443 444 dataItemsLeft -= icount; 445 dataItemCount += icount; 446 } 447 448 u4 bit = mapTypeToBitMask(item->type); 449 450 if (bit == 0) { 451 return false; 452 } 453 454 if ((usedBits & bit) != 0) { 455 ALOGE("Duplicate map section of type %#x", item->type); 456 return false; 457 } 458 459 usedBits |= bit; 460 lastOffset = item->offset; 461 item++; 462 } 463 464 if ((usedBits & mapTypeToBitMask(kDexTypeHeaderItem)) == 0) { 465 ALOGE("Map is missing header entry"); 466 return false; 467 } 468 469 if ((usedBits & mapTypeToBitMask(kDexTypeMapList)) == 0) { 470 ALOGE("Map is missing map_list entry"); 471 return false; 472 } 473 474 if (((usedBits & mapTypeToBitMask(kDexTypeStringIdItem)) == 0) 475 && ((state->pHeader->stringIdsOff != 0) 476 || (state->pHeader->stringIdsSize != 0))) { 477 ALOGE("Map is missing string_ids entry"); 478 return false; 479 } 480 481 if (((usedBits & mapTypeToBitMask(kDexTypeTypeIdItem)) == 0) 482 && ((state->pHeader->typeIdsOff != 0) 483 || (state->pHeader->typeIdsSize != 0))) { 484 ALOGE("Map is missing type_ids entry"); 485 return false; 486 } 487 488 if (((usedBits & mapTypeToBitMask(kDexTypeProtoIdItem)) == 0) 489 && ((state->pHeader->protoIdsOff != 0) 490 || (state->pHeader->protoIdsSize != 0))) { 491 ALOGE("Map is missing proto_ids entry"); 492 return false; 493 } 494 495 if (((usedBits & mapTypeToBitMask(kDexTypeFieldIdItem)) == 0) 496 && ((state->pHeader->fieldIdsOff != 0) 497 || (state->pHeader->fieldIdsSize != 0))) { 498 ALOGE("Map is missing field_ids entry"); 499 return false; 500 } 501 502 if (((usedBits & mapTypeToBitMask(kDexTypeMethodIdItem)) == 0) 503 && ((state->pHeader->methodIdsOff != 0) 504 || (state->pHeader->methodIdsSize != 0))) { 505 ALOGE("Map is missing method_ids entry"); 506 return false; 507 } 508 509 if (((usedBits & mapTypeToBitMask(kDexTypeClassDefItem)) == 0) 510 && ((state->pHeader->classDefsOff != 0) 511 || (state->pHeader->classDefsSize != 0))) { 512 ALOGE("Map is missing class_defs entry"); 513 return false; 514 } 515 516 state->pDataMap = dexDataMapAlloc(dataItemCount); 517 if (state->pDataMap == NULL) { 518 ALOGE("Unable to allocate data map (size %#x)", dataItemCount); 519 return false; 520 } 521 522 return true; 523 } 524 525 /* Check the map section for sanity. */ 526 static bool checkMapSection(const CheckState* state, u4 sectionOffset, 527 u4 sectionCount, u4* endOffset) { 528 if (sectionCount != 1) { 529 ALOGE("Multiple map list items"); 530 return false; 531 } 532 533 if (sectionOffset != state->pHeader->mapOff) { 534 ALOGE("Map not at header-defined offset: %#x, expected %#x", 535 sectionOffset, state->pHeader->mapOff); 536 return false; 537 } 538 539 const DexMapList* pMap = (const DexMapList*) filePointer(state, sectionOffset); 540 541 *endOffset = 542 sectionOffset + sizeof(u4) + (pMap->size * sizeof(DexMapItem)); 543 return true; 544 } 545 546 /* Perform byte-swapping and intra-item verification on string_id_item. */ 547 static void* swapStringIdItem(const CheckState* state, void* ptr) { 548 DexStringId* item = (DexStringId*) ptr; 549 550 CHECK_PTR_RANGE(item, item + 1); 551 SWAP_OFFSET4(item->stringDataOff); 552 553 return item + 1; 554 } 555 556 /* Perform cross-item verification of string_id_item. */ 557 static void* crossVerifyStringIdItem(const CheckState* state, void* ptr) { 558 const DexStringId* item = (const DexStringId*) ptr; 559 560 if (!dexDataMapVerify(state->pDataMap, 561 item->stringDataOff, kDexTypeStringDataItem)) { 562 return NULL; 563 } 564 565 const DexStringId* item0 = (const DexStringId*) state->previousItem; 566 if (item0 != NULL) { 567 // Check ordering. 568 const char* s0 = dexGetStringData(state->pDexFile, item0); 569 const char* s1 = dexGetStringData(state->pDexFile, item); 570 if (dexUtf8Cmp(s0, s1) >= 0) { 571 ALOGE("Out-of-order string_ids: '%s' then '%s'", s0, s1); 572 return NULL; 573 } 574 } 575 576 return (void*) (item + 1); 577 } 578 579 /* Perform byte-swapping and intra-item verification on type_id_item. */ 580 static void* swapTypeIdItem(const CheckState* state, void* ptr) { 581 DexTypeId* item = (DexTypeId*) ptr; 582 583 CHECK_PTR_RANGE(item, item + 1); 584 SWAP_INDEX4(item->descriptorIdx, state->pHeader->stringIdsSize); 585 586 return item + 1; 587 } 588 589 /* Perform cross-item verification of type_id_item. */ 590 static void* crossVerifyTypeIdItem(const CheckState* state, void* ptr) { 591 const DexTypeId* item = (const DexTypeId*) ptr; 592 const char* descriptor = 593 dexStringById(state->pDexFile, item->descriptorIdx); 594 595 if (!dexIsValidTypeDescriptor(descriptor)) { 596 ALOGE("Invalid type descriptor: '%s'", descriptor); 597 return NULL; 598 } 599 600 const DexTypeId* item0 = (const DexTypeId*) state->previousItem; 601 if (item0 != NULL) { 602 // Check ordering. This relies on string_ids being in order. 603 if (item0->descriptorIdx >= item->descriptorIdx) { 604 ALOGE("Out-of-order type_ids: %#x then %#x", 605 item0->descriptorIdx, item->descriptorIdx); 606 return NULL; 607 } 608 } 609 610 return (void*) (item + 1); 611 } 612 613 /* Perform byte-swapping and intra-item verification on proto_id_item. */ 614 static void* swapProtoIdItem(const CheckState* state, void* ptr) { 615 DexProtoId* item = (DexProtoId*) ptr; 616 617 CHECK_PTR_RANGE(item, item + 1); 618 SWAP_INDEX4(item->shortyIdx, state->pHeader->stringIdsSize); 619 SWAP_INDEX4(item->returnTypeIdx, state->pHeader->typeIdsSize); 620 SWAP_OFFSET4(item->parametersOff); 621 622 return item + 1; 623 } 624 625 /* Helper for crossVerifyProtoIdItem(), which checks a shorty character 626 * to see if it is compatible with a type descriptor. Returns true if 627 * so, false if not. */ 628 static bool shortyDescMatch(char shorty, const char* descriptor, bool 629 isReturnType) { 630 switch (shorty) { 631 case 'V': { 632 if (!isReturnType) { 633 ALOGE("Invalid use of void"); 634 return false; 635 } 636 // Fall through. 637 } 638 case 'B': 639 case 'C': 640 case 'D': 641 case 'F': 642 case 'I': 643 case 'J': 644 case 'S': 645 case 'Z': { 646 if ((descriptor[0] != shorty) || (descriptor[1] != '\0')) { 647 ALOGE("Shorty vs. primitive type mismatch: '%c', '%s'", 648 shorty, descriptor); 649 return false; 650 } 651 break; 652 } 653 case 'L': { 654 if ((descriptor[0] != 'L') && (descriptor[0] != '[')) { 655 ALOGE("Shorty vs. type mismatch: '%c', '%s'", 656 shorty, descriptor); 657 return false; 658 } 659 break; 660 } 661 default: { 662 ALOGE("Bogus shorty: '%c'", shorty); 663 return false; 664 } 665 } 666 667 return true; 668 } 669 670 /* Perform cross-item verification of proto_id_item. */ 671 static void* crossVerifyProtoIdItem(const CheckState* state, void* ptr) { 672 const DexProtoId* item = (const DexProtoId*) ptr; 673 const char* shorty = 674 dexStringById(state->pDexFile, item->shortyIdx); 675 676 if (!dexDataMapVerify0Ok(state->pDataMap, 677 item->parametersOff, kDexTypeTypeList)) { 678 return NULL; 679 } 680 681 if (!shortyDescMatch(*shorty, 682 dexStringByTypeIdx(state->pDexFile, item->returnTypeIdx), 683 true)) { 684 return NULL; 685 } 686 687 u4 protoIdx = item - state->pDexFile->pProtoIds; 688 DexProto proto = { state->pDexFile, protoIdx }; 689 DexParameterIterator iterator; 690 691 dexParameterIteratorInit(&iterator, &proto); 692 shorty++; // Skip the return type. 693 694 for (;;) { 695 const char *desc = dexParameterIteratorNextDescriptor(&iterator); 696 697 if (desc == NULL) { 698 break; 699 } 700 701 if (*shorty == '\0') { 702 ALOGE("Shorty is too short"); 703 return NULL; 704 } 705 706 if (!shortyDescMatch(*shorty, desc, false)) { 707 return NULL; 708 } 709 710 shorty++; 711 } 712 713 if (*shorty != '\0') { 714 ALOGE("Shorty is too long"); 715 return NULL; 716 } 717 718 const DexProtoId* item0 = (const DexProtoId*) state->previousItem; 719 if (item0 != NULL) { 720 // Check ordering. This relies on type_ids being in order. 721 if (item0->returnTypeIdx > item->returnTypeIdx) { 722 ALOGE("Out-of-order proto_id return types"); 723 return NULL; 724 } else if (item0->returnTypeIdx == item->returnTypeIdx) { 725 bool badOrder = false; 726 DexProto proto0 = { state->pDexFile, protoIdx - 1 }; 727 DexParameterIterator iterator0; 728 729 dexParameterIteratorInit(&iterator, &proto); 730 dexParameterIteratorInit(&iterator0, &proto0); 731 732 for (;;) { 733 u4 idx0 = dexParameterIteratorNextIndex(&iterator0); 734 u4 idx1 = dexParameterIteratorNextIndex(&iterator); 735 736 if (idx1 == kDexNoIndex) { 737 badOrder = true; 738 break; 739 } 740 741 if (idx0 == kDexNoIndex) { 742 break; 743 } 744 745 if (idx0 < idx1) { 746 break; 747 } else if (idx0 > idx1) { 748 badOrder = true; 749 break; 750 } 751 } 752 753 if (badOrder) { 754 ALOGE("Out-of-order proto_id arguments"); 755 return NULL; 756 } 757 } 758 } 759 760 return (void*) (item + 1); 761 } 762 763 /* Perform byte-swapping and intra-item verification on field_id_item. */ 764 static void* swapFieldIdItem(const CheckState* state, void* ptr) { 765 DexFieldId* item = (DexFieldId*) ptr; 766 767 CHECK_PTR_RANGE(item, item + 1); 768 SWAP_INDEX2(item->classIdx, state->pHeader->typeIdsSize); 769 SWAP_INDEX2(item->typeIdx, state->pHeader->typeIdsSize); 770 SWAP_INDEX4(item->nameIdx, state->pHeader->stringIdsSize); 771 772 return item + 1; 773 } 774 775 /* Perform cross-item verification of field_id_item. */ 776 static void* crossVerifyFieldIdItem(const CheckState* state, void* ptr) { 777 const DexFieldId* item = (const DexFieldId*) ptr; 778 const char* s; 779 780 s = dexStringByTypeIdx(state->pDexFile, item->classIdx); 781 if (!dexIsClassDescriptor(s)) { 782 ALOGE("Invalid descriptor for class_idx: '%s'", s); 783 return NULL; 784 } 785 786 s = dexStringByTypeIdx(state->pDexFile, item->typeIdx); 787 if (!dexIsFieldDescriptor(s)) { 788 ALOGE("Invalid descriptor for type_idx: '%s'", s); 789 return NULL; 790 } 791 792 s = dexStringById(state->pDexFile, item->nameIdx); 793 if (!dexIsValidMemberName(s)) { 794 ALOGE("Invalid name: '%s'", s); 795 return NULL; 796 } 797 798 const DexFieldId* item0 = (const DexFieldId*) state->previousItem; 799 if (item0 != NULL) { 800 // Check ordering. This relies on the other sections being in order. 801 bool done = false; 802 bool bogus = false; 803 804 if (item0->classIdx > item->classIdx) { 805 bogus = true; 806 done = true; 807 } else if (item0->classIdx < item->classIdx) { 808 done = true; 809 } 810 811 if (!done) { 812 if (item0->nameIdx > item->nameIdx) { 813 bogus = true; 814 done = true; 815 } else if (item0->nameIdx < item->nameIdx) { 816 done = true; 817 } 818 } 819 820 if (!done) { 821 if (item0->typeIdx >= item->typeIdx) { 822 bogus = true; 823 } 824 } 825 826 if (bogus) { 827 ALOGE("Out-of-order field_ids"); 828 return NULL; 829 } 830 } 831 832 return (void*) (item + 1); 833 } 834 835 /* Perform byte-swapping and intra-item verification on method_id_item. */ 836 static void* swapMethodIdItem(const CheckState* state, void* ptr) { 837 DexMethodId* item = (DexMethodId*) ptr; 838 839 CHECK_PTR_RANGE(item, item + 1); 840 SWAP_INDEX2(item->classIdx, state->pHeader->typeIdsSize); 841 SWAP_INDEX2(item->protoIdx, state->pHeader->protoIdsSize); 842 SWAP_INDEX4(item->nameIdx, state->pHeader->stringIdsSize); 843 844 return item + 1; 845 } 846 847 /* Perform cross-item verification of method_id_item. */ 848 static void* crossVerifyMethodIdItem(const CheckState* state, void* ptr) { 849 const DexMethodId* item = (const DexMethodId*) ptr; 850 const char* s; 851 852 s = dexStringByTypeIdx(state->pDexFile, item->classIdx); 853 if (!dexIsReferenceDescriptor(s)) { 854 ALOGE("Invalid descriptor for class_idx: '%s'", s); 855 return NULL; 856 } 857 858 s = dexStringById(state->pDexFile, item->nameIdx); 859 if (!dexIsValidMemberName(s)) { 860 ALOGE("Invalid name: '%s'", s); 861 return NULL; 862 } 863 864 const DexMethodId* item0 = (const DexMethodId*) state->previousItem; 865 if (item0 != NULL) { 866 // Check ordering. This relies on the other sections being in order. 867 bool done = false; 868 bool bogus = false; 869 870 if (item0->classIdx > item->classIdx) { 871 bogus = true; 872 done = true; 873 } else if (item0->classIdx < item->classIdx) { 874 done = true; 875 } 876 877 if (!done) { 878 if (item0->nameIdx > item->nameIdx) { 879 bogus = true; 880 done = true; 881 } else if (item0->nameIdx < item->nameIdx) { 882 done = true; 883 } 884 } 885 886 if (!done) { 887 if (item0->protoIdx >= item->protoIdx) { 888 bogus = true; 889 } 890 } 891 892 if (bogus) { 893 ALOGE("Out-of-order method_ids"); 894 return NULL; 895 } 896 } 897 898 return (void*) (item + 1); 899 } 900 901 /* Perform byte-swapping and intra-item verification on class_def_item. */ 902 static void* swapClassDefItem(const CheckState* state, void* ptr) { 903 DexClassDef* item = (DexClassDef*) ptr; 904 905 CHECK_PTR_RANGE(item, item + 1); 906 SWAP_INDEX4(item->classIdx, state->pHeader->typeIdsSize); 907 SWAP_FIELD4(item->accessFlags); 908 SWAP_INDEX4_OR_NOINDEX(item->superclassIdx, state->pHeader->typeIdsSize); 909 SWAP_OFFSET4(item->interfacesOff); 910 SWAP_INDEX4_OR_NOINDEX(item->sourceFileIdx, state->pHeader->stringIdsSize); 911 SWAP_OFFSET4(item->annotationsOff); 912 SWAP_OFFSET4(item->classDataOff); 913 914 if ((item->accessFlags & ~ACC_CLASS_MASK) != 0) { 915 // The VM specification says that unknown flags should be ignored. 916 ALOGV("Bogus class access flags %x", item->accessFlags); 917 item->accessFlags &= ACC_CLASS_MASK; 918 } 919 920 return item + 1; 921 } 922 923 /* defined below */ 924 static u4 findFirstClassDataDefiner(const CheckState* state, 925 DexClassData* classData); 926 static u4 findFirstAnnotationsDirectoryDefiner(const CheckState* state, 927 const DexAnnotationsDirectoryItem* dir); 928 929 /* Helper for crossVerifyClassDefItem(), which checks a class_data_item to 930 * make sure all its references are to a given class. */ 931 static bool verifyClassDataIsForDef(const CheckState* state, u4 offset, 932 u4 definerIdx) { 933 if (offset == 0) { 934 return true; 935 } 936 937 const u1* data = (const u1*) filePointer(state, offset); 938 DexClassData* classData = dexReadAndVerifyClassData(&data, NULL); 939 940 if (classData == NULL) { 941 // Shouldn't happen, but bail here just in case. 942 return false; 943 } 944 945 /* 946 * The class_data_item verification ensures that 947 * it consistently refers to the same definer, so all we need to 948 * do is check the first one. 949 */ 950 u4 dataDefiner = findFirstClassDataDefiner(state, classData); 951 bool result = (dataDefiner == definerIdx) || (dataDefiner == kDexNoIndex); 952 953 free(classData); 954 return result; 955 } 956 957 /* Helper for crossVerifyClassDefItem(), which checks an 958 * annotations_directory_item to make sure all its references are to a 959 * given class. */ 960 static bool verifyAnnotationsDirectoryIsForDef(const CheckState* state, 961 u4 offset, u4 definerIdx) { 962 if (offset == 0) { 963 return true; 964 } 965 966 const DexAnnotationsDirectoryItem* dir = 967 (const DexAnnotationsDirectoryItem*) filePointer(state, offset); 968 u4 annoDefiner = findFirstAnnotationsDirectoryDefiner(state, dir); 969 970 return (annoDefiner == definerIdx) || (annoDefiner == kDexNoIndex); 971 } 972 973 /* Perform cross-item verification of class_def_item. */ 974 static void* crossVerifyClassDefItem(const CheckState* state, void* ptr) { 975 const DexClassDef* item = (const DexClassDef*) ptr; 976 u4 classIdx = item->classIdx; 977 const char* descriptor = dexStringByTypeIdx(state->pDexFile, classIdx); 978 979 if (!dexIsClassDescriptor(descriptor)) { 980 ALOGE("Invalid class: '%s'", descriptor); 981 return NULL; 982 } 983 984 if (setDefinedClassBit(state, classIdx)) { 985 ALOGE("Duplicate class definition: '%s'", descriptor); 986 return NULL; 987 } 988 989 bool okay = 990 dexDataMapVerify0Ok(state->pDataMap, 991 item->interfacesOff, kDexTypeTypeList) 992 && dexDataMapVerify0Ok(state->pDataMap, 993 item->annotationsOff, kDexTypeAnnotationsDirectoryItem) 994 && dexDataMapVerify0Ok(state->pDataMap, 995 item->classDataOff, kDexTypeClassDataItem) 996 && dexDataMapVerify0Ok(state->pDataMap, 997 item->staticValuesOff, kDexTypeEncodedArrayItem); 998 999 if (!okay) { 1000 return NULL; 1001 } 1002 1003 if (item->superclassIdx != kDexNoIndex) { 1004 descriptor = dexStringByTypeIdx(state->pDexFile, item->superclassIdx); 1005 if (!dexIsClassDescriptor(descriptor)) { 1006 ALOGE("Invalid superclass: '%s'", descriptor); 1007 return NULL; 1008 } 1009 } 1010 1011 const DexTypeList* interfaces = 1012 dexGetInterfacesList(state->pDexFile, item); 1013 if (interfaces != NULL) { 1014 u4 size = interfaces->size; 1015 u4 i; 1016 1017 /* 1018 * Ensure that all interfaces refer to classes (not arrays or 1019 * primitives). 1020 */ 1021 for (i = 0; i < size; i++) { 1022 descriptor = dexStringByTypeIdx(state->pDexFile, 1023 dexTypeListGetIdx(interfaces, i)); 1024 if (!dexIsClassDescriptor(descriptor)) { 1025 ALOGE("Invalid interface: '%s'", descriptor); 1026 return NULL; 1027 } 1028 } 1029 1030 /* 1031 * Ensure that there are no duplicates. This is an O(N^2) test, 1032 * but in practice the number of interfaces implemented by any 1033 * given class is low. I will buy a milkshake for the 1034 * first person to show me a realistic case for which this test 1035 * would be unacceptably slow. 1036 */ 1037 for (i = 1; i < size; i++) { 1038 u4 idx1 = dexTypeListGetIdx(interfaces, i); 1039 u4 j; 1040 for (j = 0; j < i; j++) { 1041 u4 idx2 = dexTypeListGetIdx(interfaces, j); 1042 if (idx1 == idx2) { 1043 ALOGE("Duplicate interface: '%s'", 1044 dexStringByTypeIdx(state->pDexFile, idx1)); 1045 return NULL; 1046 } 1047 } 1048 } 1049 } 1050 1051 if (!verifyClassDataIsForDef(state, item->classDataOff, item->classIdx)) { 1052 ALOGE("Invalid class_data_item"); 1053 return NULL; 1054 } 1055 1056 if (!verifyAnnotationsDirectoryIsForDef(state, item->annotationsOff, 1057 item->classIdx)) { 1058 ALOGE("Invalid annotations_directory_item"); 1059 return NULL; 1060 } 1061 1062 return (void*) (item + 1); 1063 } 1064 1065 /* Helper for swapAnnotationsDirectoryItem(), which performs 1066 * byte-swapping and intra-item verification on an 1067 * annotation_directory_item's field elements. */ 1068 static u1* swapFieldAnnotations(const CheckState* state, u4 count, u1* addr) { 1069 DexFieldAnnotationsItem* item = (DexFieldAnnotationsItem*) addr; 1070 bool first = true; 1071 u4 lastIdx = 0; 1072 1073 CHECK_LIST_SIZE(item, count, sizeof(DexFieldAnnotationsItem)); 1074 1075 while (count--) { 1076 SWAP_INDEX4(item->fieldIdx, state->pHeader->fieldIdsSize); 1077 SWAP_OFFSET4(item->annotationsOff); 1078 1079 if (first) { 1080 first = false; 1081 } else if (lastIdx >= item->fieldIdx) { 1082 ALOGE("Out-of-order field_idx: %#x then %#x", lastIdx, 1083 item->fieldIdx); 1084 return NULL; 1085 } 1086 1087 lastIdx = item->fieldIdx; 1088 item++; 1089 } 1090 1091 return (u1*) item; 1092 } 1093 1094 /* Helper for swapAnnotationsDirectoryItem(), which performs 1095 * byte-swapping and intra-item verification on an 1096 * annotation_directory_item's method elements. */ 1097 static u1* swapMethodAnnotations(const CheckState* state, u4 count, u1* addr) { 1098 DexMethodAnnotationsItem* item = (DexMethodAnnotationsItem*) addr; 1099 bool first = true; 1100 u4 lastIdx = 0; 1101 1102 CHECK_LIST_SIZE(item, count, sizeof(DexMethodAnnotationsItem)); 1103 1104 while (count--) { 1105 SWAP_INDEX4(item->methodIdx, state->pHeader->methodIdsSize); 1106 SWAP_OFFSET4(item->annotationsOff); 1107 1108 if (first) { 1109 first = false; 1110 } else if (lastIdx >= item->methodIdx) { 1111 ALOGE("Out-of-order method_idx: %#x then %#x", lastIdx, 1112 item->methodIdx); 1113 return NULL; 1114 } 1115 1116 lastIdx = item->methodIdx; 1117 item++; 1118 } 1119 1120 return (u1*) item; 1121 } 1122 1123 /* Helper for swapAnnotationsDirectoryItem(), which performs 1124 * byte-swapping and intra-item verification on an 1125 * annotation_directory_item's parameter elements. */ 1126 static u1* swapParameterAnnotations(const CheckState* state, u4 count, 1127 u1* addr) { 1128 DexParameterAnnotationsItem* item = (DexParameterAnnotationsItem*) addr; 1129 bool first = true; 1130 u4 lastIdx = 0; 1131 1132 CHECK_LIST_SIZE(item, count, sizeof(DexParameterAnnotationsItem)); 1133 1134 while (count--) { 1135 SWAP_INDEX4(item->methodIdx, state->pHeader->methodIdsSize); 1136 SWAP_OFFSET4(item->annotationsOff); 1137 1138 if (first) { 1139 first = false; 1140 } else if (lastIdx >= item->methodIdx) { 1141 ALOGE("Out-of-order method_idx: %#x then %#x", lastIdx, 1142 item->methodIdx); 1143 return NULL; 1144 } 1145 1146 lastIdx = item->methodIdx; 1147 item++; 1148 } 1149 1150 return (u1*) item; 1151 } 1152 1153 /* Perform byte-swapping and intra-item verification on 1154 * annotations_directory_item. */ 1155 static void* swapAnnotationsDirectoryItem(const CheckState* state, void* ptr) { 1156 DexAnnotationsDirectoryItem* item = (DexAnnotationsDirectoryItem*) ptr; 1157 1158 CHECK_PTR_RANGE(item, item + 1); 1159 SWAP_OFFSET4(item->classAnnotationsOff); 1160 SWAP_FIELD4(item->fieldsSize); 1161 SWAP_FIELD4(item->methodsSize); 1162 SWAP_FIELD4(item->parametersSize); 1163 1164 u1* addr = (u1*) (item + 1); 1165 1166 if (item->fieldsSize != 0) { 1167 addr = swapFieldAnnotations(state, item->fieldsSize, addr); 1168 if (addr == NULL) { 1169 return NULL; 1170 } 1171 } 1172 1173 if (item->methodsSize != 0) { 1174 addr = swapMethodAnnotations(state, item->methodsSize, addr); 1175 if (addr == NULL) { 1176 return NULL; 1177 } 1178 } 1179 1180 if (item->parametersSize != 0) { 1181 addr = swapParameterAnnotations(state, item->parametersSize, addr); 1182 if (addr == NULL) { 1183 return NULL; 1184 } 1185 } 1186 1187 return addr; 1188 } 1189 1190 /* Helper for crossVerifyAnnotationsDirectoryItem(), which checks the 1191 * field elements. */ 1192 static const u1* crossVerifyFieldAnnotations(const CheckState* state, u4 count, 1193 const u1* addr, u4 definingClass) { 1194 const DexFieldAnnotationsItem* item = (DexFieldAnnotationsItem*) addr; 1195 1196 while (count--) { 1197 if (!verifyFieldDefiner(state, definingClass, item->fieldIdx)) { 1198 return NULL; 1199 } 1200 if (!dexDataMapVerify(state->pDataMap, item->annotationsOff, 1201 kDexTypeAnnotationSetItem)) { 1202 return NULL; 1203 } 1204 item++; 1205 } 1206 1207 return (const u1*) item; 1208 } 1209 1210 /* Helper for crossVerifyAnnotationsDirectoryItem(), which checks the 1211 * method elements. */ 1212 static const u1* crossVerifyMethodAnnotations(const CheckState* state, 1213 u4 count, const u1* addr, u4 definingClass) { 1214 const DexMethodAnnotationsItem* item = (DexMethodAnnotationsItem*) addr; 1215 1216 while (count--) { 1217 if (!verifyMethodDefiner(state, definingClass, item->methodIdx)) { 1218 return NULL; 1219 } 1220 if (!dexDataMapVerify(state->pDataMap, item->annotationsOff, 1221 kDexTypeAnnotationSetItem)) { 1222 return NULL; 1223 } 1224 item++; 1225 } 1226 1227 return (const u1*) item; 1228 } 1229 1230 /* Helper for crossVerifyAnnotationsDirectoryItem(), which checks the 1231 * parameter elements. */ 1232 static const u1* crossVerifyParameterAnnotations(const CheckState* state, 1233 u4 count, const u1* addr, u4 definingClass) { 1234 const DexParameterAnnotationsItem* item = 1235 (DexParameterAnnotationsItem*) addr; 1236 1237 while (count--) { 1238 if (!verifyMethodDefiner(state, definingClass, item->methodIdx)) { 1239 return NULL; 1240 } 1241 if (!dexDataMapVerify(state->pDataMap, item->annotationsOff, 1242 kDexTypeAnnotationSetRefList)) { 1243 return NULL; 1244 } 1245 item++; 1246 } 1247 1248 return (const u1*) item; 1249 } 1250 1251 /* Helper for crossVerifyClassDefItem() and 1252 * crossVerifyAnnotationsDirectoryItem(), which finds the type_idx of 1253 * the definer of the first item in the data. */ 1254 static u4 findFirstAnnotationsDirectoryDefiner(const CheckState* state, 1255 const DexAnnotationsDirectoryItem* dir) { 1256 if (dir->fieldsSize != 0) { 1257 const DexFieldAnnotationsItem* fields = 1258 dexGetFieldAnnotations(state->pDexFile, dir); 1259 const DexFieldId* field = 1260 dexGetFieldId(state->pDexFile, fields[0].fieldIdx); 1261 return field->classIdx; 1262 } 1263 1264 if (dir->methodsSize != 0) { 1265 const DexMethodAnnotationsItem* methods = 1266 dexGetMethodAnnotations(state->pDexFile, dir); 1267 const DexMethodId* method = 1268 dexGetMethodId(state->pDexFile, methods[0].methodIdx); 1269 return method->classIdx; 1270 } 1271 1272 if (dir->parametersSize != 0) { 1273 const DexParameterAnnotationsItem* parameters = 1274 dexGetParameterAnnotations(state->pDexFile, dir); 1275 const DexMethodId* method = 1276 dexGetMethodId(state->pDexFile, parameters[0].methodIdx); 1277 return method->classIdx; 1278 } 1279 1280 return kDexNoIndex; 1281 } 1282 1283 /* Perform cross-item verification of annotations_directory_item. */ 1284 static void* crossVerifyAnnotationsDirectoryItem(const CheckState* state, 1285 void* ptr) { 1286 const DexAnnotationsDirectoryItem* item = (const DexAnnotationsDirectoryItem*) ptr; 1287 u4 definingClass = findFirstAnnotationsDirectoryDefiner(state, item); 1288 1289 if (!dexDataMapVerify0Ok(state->pDataMap, 1290 item->classAnnotationsOff, kDexTypeAnnotationSetItem)) { 1291 return NULL; 1292 } 1293 1294 const u1* addr = (const u1*) (item + 1); 1295 1296 if (item->fieldsSize != 0) { 1297 addr = crossVerifyFieldAnnotations(state, item->fieldsSize, addr, 1298 definingClass); 1299 if (addr == NULL) { 1300 return NULL; 1301 } 1302 } 1303 1304 if (item->methodsSize != 0) { 1305 addr = crossVerifyMethodAnnotations(state, item->methodsSize, addr, 1306 definingClass); 1307 if (addr == NULL) { 1308 return NULL; 1309 } 1310 } 1311 1312 if (item->parametersSize != 0) { 1313 addr = crossVerifyParameterAnnotations(state, item->parametersSize, 1314 addr, definingClass); 1315 if (addr == NULL) { 1316 return NULL; 1317 } 1318 } 1319 1320 return (void*) addr; 1321 } 1322 1323 /* Perform byte-swapping and intra-item verification on type_list. */ 1324 static void* swapTypeList(const CheckState* state, void* ptr) 1325 { 1326 DexTypeList* pTypeList = (DexTypeList*) ptr; 1327 DexTypeItem* pType; 1328 u4 count; 1329 1330 CHECK_PTR_RANGE(pTypeList, pTypeList + 1); 1331 SWAP_FIELD4(pTypeList->size); 1332 count = pTypeList->size; 1333 pType = pTypeList->list; 1334 CHECK_LIST_SIZE(pType, count, sizeof(DexTypeItem)); 1335 1336 while (count--) { 1337 SWAP_INDEX2(pType->typeIdx, state->pHeader->typeIdsSize); 1338 pType++; 1339 } 1340 1341 return pType; 1342 } 1343 1344 /* Perform byte-swapping and intra-item verification on 1345 * annotation_set_ref_list. */ 1346 static void* swapAnnotationSetRefList(const CheckState* state, void* ptr) { 1347 DexAnnotationSetRefList* list = (DexAnnotationSetRefList*) ptr; 1348 DexAnnotationSetRefItem* item; 1349 u4 count; 1350 1351 CHECK_PTR_RANGE(list, list + 1); 1352 SWAP_FIELD4(list->size); 1353 count = list->size; 1354 item = list->list; 1355 CHECK_LIST_SIZE(item, count, sizeof(DexAnnotationSetRefItem)); 1356 1357 while (count--) { 1358 SWAP_OFFSET4(item->annotationsOff); 1359 item++; 1360 } 1361 1362 return item; 1363 } 1364 1365 /* Perform cross-item verification of annotation_set_ref_list. */ 1366 static void* crossVerifyAnnotationSetRefList(const CheckState* state, 1367 void* ptr) { 1368 const DexAnnotationSetRefList* list = (const DexAnnotationSetRefList*) ptr; 1369 const DexAnnotationSetRefItem* item = list->list; 1370 int count = list->size; 1371 1372 while (count--) { 1373 if (!dexDataMapVerify0Ok(state->pDataMap, 1374 item->annotationsOff, kDexTypeAnnotationSetItem)) { 1375 return NULL; 1376 } 1377 item++; 1378 } 1379 1380 return (void*) item; 1381 } 1382 1383 /* Perform byte-swapping and intra-item verification on 1384 * annotation_set_item. */ 1385 static void* swapAnnotationSetItem(const CheckState* state, void* ptr) { 1386 DexAnnotationSetItem* set = (DexAnnotationSetItem*) ptr; 1387 u4* item; 1388 u4 count; 1389 1390 CHECK_PTR_RANGE(set, set + 1); 1391 SWAP_FIELD4(set->size); 1392 count = set->size; 1393 item = set->entries; 1394 CHECK_LIST_SIZE(item, count, sizeof(u4)); 1395 1396 while (count--) { 1397 SWAP_OFFSET4(*item); 1398 item++; 1399 } 1400 1401 return item; 1402 } 1403 1404 /* Helper for crossVerifyAnnotationSetItem(), which extracts the type_idx 1405 * out of an annotation_item. */ 1406 static u4 annotationItemTypeIdx(const DexAnnotationItem* item) { 1407 const u1* data = item->annotation; 1408 return readUnsignedLeb128(&data); 1409 } 1410 1411 /* Perform cross-item verification of annotation_set_item. */ 1412 static void* crossVerifyAnnotationSetItem(const CheckState* state, void* ptr) { 1413 const DexAnnotationSetItem* set = (const DexAnnotationSetItem*) ptr; 1414 int count = set->size; 1415 u4 lastIdx = 0; 1416 bool first = true; 1417 int i; 1418 1419 for (i = 0; i < count; i++) { 1420 if (!dexDataMapVerify0Ok(state->pDataMap, 1421 dexGetAnnotationOff(set, i), kDexTypeAnnotationItem)) { 1422 return NULL; 1423 } 1424 1425 const DexAnnotationItem* annotation = 1426 dexGetAnnotationItem(state->pDexFile, set, i); 1427 u4 idx = annotationItemTypeIdx(annotation); 1428 1429 if (first) { 1430 first = false; 1431 } else if (lastIdx >= idx) { 1432 ALOGE("Out-of-order entry types: %#x then %#x", 1433 lastIdx, idx); 1434 return NULL; 1435 } 1436 1437 lastIdx = idx; 1438 } 1439 1440 return (void*) (set->entries + count); 1441 } 1442 1443 /* Helper for verifyClassDataItem(), which checks a list of fields. */ 1444 static bool verifyFields(const CheckState* state, u4 size, 1445 DexField* fields, bool expectStatic) { 1446 u4 i; 1447 1448 for (i = 0; i < size; i++) { 1449 DexField* field = &fields[i]; 1450 u4 accessFlags = field->accessFlags; 1451 bool isStatic = (accessFlags & ACC_STATIC) != 0; 1452 1453 CHECK_INDEX(field->fieldIdx, state->pHeader->fieldIdsSize); 1454 1455 if (isStatic != expectStatic) { 1456 ALOGE("Field in wrong list @ %d", i); 1457 return false; 1458 } 1459 1460 if ((accessFlags & ~ACC_FIELD_MASK) != 0) { 1461 // The VM specification says that unknown flags should be ignored. 1462 ALOGV("Bogus field access flags %x @ %d", accessFlags, i); 1463 field->accessFlags &= ACC_FIELD_MASK; 1464 } 1465 } 1466 1467 return true; 1468 } 1469 1470 /* Helper for verifyClassDataItem(), which checks a list of methods. */ 1471 static bool verifyMethods(const CheckState* state, u4 size, 1472 DexMethod* methods, bool expectDirect) { 1473 u4 i; 1474 1475 for (i = 0; i < size; i++) { 1476 DexMethod* method = &methods[i]; 1477 1478 CHECK_INDEX(method->methodIdx, state->pHeader->methodIdsSize); 1479 1480 u4 accessFlags = method->accessFlags; 1481 bool isDirect = 1482 (accessFlags & (ACC_STATIC | ACC_PRIVATE | ACC_CONSTRUCTOR)) != 0; 1483 bool expectCode = (accessFlags & (ACC_NATIVE | ACC_ABSTRACT)) == 0; 1484 bool isSynchronized = (accessFlags & ACC_SYNCHRONIZED) != 0; 1485 bool allowSynchronized = (accessFlags & ACC_NATIVE) != 0; 1486 1487 if (isDirect != expectDirect) { 1488 ALOGE("Method in wrong list @ %d", i); 1489 return false; 1490 } 1491 1492 if (isSynchronized && !allowSynchronized) { 1493 ALOGE("Bogus method access flags (synchronization) %x @ %d", accessFlags, i); 1494 return false; 1495 } 1496 1497 if ((accessFlags & ~ACC_METHOD_MASK) != 0) { 1498 // The VM specification says that unknown flags should be ignored. 1499 ALOGV("Bogus method access flags %x @ %d", accessFlags, i); 1500 method->accessFlags &= ACC_METHOD_MASK; 1501 } 1502 1503 if (expectCode) { 1504 if (method->codeOff == 0) { 1505 ALOGE("Unexpected zero code_off for access_flags %x", 1506 accessFlags); 1507 return false; 1508 } 1509 } else if (method->codeOff != 0) { 1510 ALOGE("Unexpected non-zero code_off %#x for access_flags %x", 1511 method->codeOff, accessFlags); 1512 return false; 1513 } 1514 } 1515 1516 return true; 1517 } 1518 1519 /* Helper for verifyClassDataItem(), which does most of the work. */ 1520 static bool verifyClassDataItem0(const CheckState* state, 1521 DexClassData* classData) { 1522 bool okay; 1523 1524 okay = verifyFields(state, classData->header.staticFieldsSize, 1525 classData->staticFields, true); 1526 1527 if (!okay) { 1528 ALOGE("Trouble with static fields"); 1529 return false; 1530 } 1531 1532 verifyFields(state, classData->header.instanceFieldsSize, 1533 classData->instanceFields, false); 1534 1535 if (!okay) { 1536 ALOGE("Trouble with instance fields"); 1537 return false; 1538 } 1539 1540 okay = verifyMethods(state, classData->header.directMethodsSize, 1541 classData->directMethods, true); 1542 1543 if (!okay) { 1544 ALOGE("Trouble with direct methods"); 1545 return false; 1546 } 1547 1548 okay = verifyMethods(state, classData->header.virtualMethodsSize, 1549 classData->virtualMethods, false); 1550 1551 if (!okay) { 1552 ALOGE("Trouble with virtual methods"); 1553 return false; 1554 } 1555 1556 return true; 1557 } 1558 1559 /* Perform intra-item verification on class_data_item. */ 1560 static void* intraVerifyClassDataItem(const CheckState* state, void* ptr) { 1561 const u1* data = (const u1*) ptr; 1562 DexClassData* classData = dexReadAndVerifyClassData(&data, state->fileEnd); 1563 1564 if (classData == NULL) { 1565 ALOGE("Unable to parse class_data_item"); 1566 return NULL; 1567 } 1568 1569 bool okay = verifyClassDataItem0(state, classData); 1570 1571 free(classData); 1572 1573 if (!okay) { 1574 return NULL; 1575 } 1576 1577 return (void*) data; 1578 } 1579 1580 /* Helper for crossVerifyClassDefItem() and 1581 * crossVerifyClassDataItem(), which finds the type_idx of the definer 1582 * of the first item in the data. */ 1583 static u4 findFirstClassDataDefiner(const CheckState* state, 1584 DexClassData* classData) { 1585 if (classData->header.staticFieldsSize != 0) { 1586 u4 fieldIdx = classData->staticFields[0].fieldIdx; 1587 const DexFieldId* field = dexGetFieldId(state->pDexFile, fieldIdx); 1588 return field->classIdx; 1589 } 1590 1591 if (classData->header.instanceFieldsSize != 0) { 1592 u4 fieldIdx = classData->instanceFields[0].fieldIdx; 1593 const DexFieldId* field = dexGetFieldId(state->pDexFile, fieldIdx); 1594 return field->classIdx; 1595 } 1596 1597 if (classData->header.directMethodsSize != 0) { 1598 u4 methodIdx = classData->directMethods[0].methodIdx; 1599 const DexMethodId* meth = dexGetMethodId(state->pDexFile, methodIdx); 1600 return meth->classIdx; 1601 } 1602 1603 if (classData->header.virtualMethodsSize != 0) { 1604 u4 methodIdx = classData->virtualMethods[0].methodIdx; 1605 const DexMethodId* meth = dexGetMethodId(state->pDexFile, methodIdx); 1606 return meth->classIdx; 1607 } 1608 1609 return kDexNoIndex; 1610 } 1611 1612 /* Perform cross-item verification of class_data_item. */ 1613 static void* crossVerifyClassDataItem(const CheckState* state, void* ptr) { 1614 const u1* data = (const u1*) ptr; 1615 DexClassData* classData = dexReadAndVerifyClassData(&data, state->fileEnd); 1616 u4 definingClass = findFirstClassDataDefiner(state, classData); 1617 bool okay = true; 1618 u4 i; 1619 1620 for (i = classData->header.staticFieldsSize; okay && (i > 0); /*i*/) { 1621 i--; 1622 const DexField* field = &classData->staticFields[i]; 1623 okay = verifyFieldDefiner(state, definingClass, field->fieldIdx); 1624 } 1625 1626 for (i = classData->header.instanceFieldsSize; okay && (i > 0); /*i*/) { 1627 i--; 1628 const DexField* field = &classData->instanceFields[i]; 1629 okay = verifyFieldDefiner(state, definingClass, field->fieldIdx); 1630 } 1631 1632 for (i = classData->header.directMethodsSize; okay && (i > 0); /*i*/) { 1633 i--; 1634 const DexMethod* meth = &classData->directMethods[i]; 1635 okay = dexDataMapVerify0Ok(state->pDataMap, meth->codeOff, 1636 kDexTypeCodeItem) 1637 && verifyMethodDefiner(state, definingClass, meth->methodIdx); 1638 } 1639 1640 for (i = classData->header.virtualMethodsSize; okay && (i > 0); /*i*/) { 1641 i--; 1642 const DexMethod* meth = &classData->virtualMethods[i]; 1643 okay = dexDataMapVerify0Ok(state->pDataMap, meth->codeOff, 1644 kDexTypeCodeItem) 1645 && verifyMethodDefiner(state, definingClass, meth->methodIdx); 1646 } 1647 1648 free(classData); 1649 1650 if (!okay) { 1651 return NULL; 1652 } 1653 1654 return (void*) data; 1655 } 1656 1657 /* Helper for swapCodeItem(), which fills an array with all the valid 1658 * handlerOff values for catch handlers and also verifies the handler 1659 * contents. */ 1660 static u4 setHandlerOffsAndVerify(const CheckState* state, 1661 DexCode* code, u4 firstOffset, u4 handlersSize, u4* handlerOffs) { 1662 const u1* fileEnd = state->fileEnd; 1663 const u1* handlersBase = dexGetCatchHandlerData(code); 1664 u4 offset = firstOffset; 1665 bool okay = true; 1666 u4 i; 1667 1668 for (i = 0; i < handlersSize; i++) { 1669 const u1* ptr = handlersBase + offset; 1670 int size = readAndVerifySignedLeb128(&ptr, fileEnd, &okay); 1671 bool catchAll; 1672 1673 if (!okay) { 1674 ALOGE("Bogus size"); 1675 return 0; 1676 } 1677 1678 if ((size < -65536) || (size > 65536)) { 1679 ALOGE("Invalid size: %d", size); 1680 return 0; 1681 } 1682 1683 if (size <= 0) { 1684 catchAll = true; 1685 size = -size; 1686 } else { 1687 catchAll = false; 1688 } 1689 1690 handlerOffs[i] = offset; 1691 1692 while (size-- > 0) { 1693 u4 typeIdx = 1694 readAndVerifyUnsignedLeb128(&ptr, fileEnd, &okay); 1695 1696 if (!okay) { 1697 ALOGE("Bogus type_idx"); 1698 return 0; 1699 } 1700 1701 CHECK_INDEX(typeIdx, state->pHeader->typeIdsSize); 1702 1703 u4 addr = readAndVerifyUnsignedLeb128(&ptr, fileEnd, &okay); 1704 1705 if (!okay) { 1706 ALOGE("Bogus addr"); 1707 return 0; 1708 } 1709 1710 if (addr >= code->insnsSize) { 1711 ALOGE("Invalid addr: %#x", addr); 1712 return 0; 1713 } 1714 } 1715 1716 if (catchAll) { 1717 u4 addr = readAndVerifyUnsignedLeb128(&ptr, fileEnd, &okay); 1718 1719 if (!okay) { 1720 ALOGE("Bogus catch_all_addr"); 1721 return 0; 1722 } 1723 1724 if (addr >= code->insnsSize) { 1725 ALOGE("Invalid catch_all_addr: %#x", addr); 1726 return 0; 1727 } 1728 } 1729 1730 offset = ptr - handlersBase; 1731 } 1732 1733 return offset; 1734 } 1735 1736 /* Helper for swapCodeItem(), which does all the try-catch related 1737 * swapping and verification. */ 1738 static void* swapTriesAndCatches(const CheckState* state, DexCode* code) { 1739 const u1* encodedHandlers = dexGetCatchHandlerData(code); 1740 const u1* encodedPtr = encodedHandlers; 1741 bool okay = true; 1742 u4 handlersSize = 1743 readAndVerifyUnsignedLeb128(&encodedPtr, state->fileEnd, &okay); 1744 1745 if (!okay) { 1746 ALOGE("Bogus handlers_size"); 1747 return NULL; 1748 } 1749 1750 if ((handlersSize == 0) || (handlersSize >= 65536)) { 1751 ALOGE("Invalid handlers_size: %d", handlersSize); 1752 return NULL; 1753 } 1754 1755 u4 handlerOffs[handlersSize]; // list of valid handlerOff values 1756 u4 endOffset = setHandlerOffsAndVerify(state, code, 1757 encodedPtr - encodedHandlers, 1758 handlersSize, handlerOffs); 1759 1760 if (endOffset == 0) { 1761 return NULL; 1762 } 1763 1764 DexTry* tries = (DexTry*) dexGetTries(code); 1765 u4 count = code->triesSize; 1766 u4 lastEnd = 0; 1767 1768 CHECK_LIST_SIZE(tries, count, sizeof(DexTry)); 1769 1770 while (count--) { 1771 u4 i; 1772 1773 SWAP_FIELD4(tries->startAddr); 1774 SWAP_FIELD2(tries->insnCount); 1775 SWAP_FIELD2(tries->handlerOff); 1776 1777 if (tries->startAddr < lastEnd) { 1778 ALOGE("Out-of-order try"); 1779 return NULL; 1780 } 1781 1782 if (tries->startAddr >= code->insnsSize) { 1783 ALOGE("Invalid start_addr: %#x", tries->startAddr); 1784 return NULL; 1785 } 1786 1787 for (i = 0; i < handlersSize; i++) { 1788 if (tries->handlerOff == handlerOffs[i]) { 1789 break; 1790 } 1791 } 1792 1793 if (i == handlersSize) { 1794 ALOGE("Bogus handler offset: %#x", tries->handlerOff); 1795 return NULL; 1796 } 1797 1798 lastEnd = tries->startAddr + tries->insnCount; 1799 1800 if (lastEnd > code->insnsSize) { 1801 ALOGE("Invalid insn_count: %#x (end addr %#x)", 1802 tries->insnCount, lastEnd); 1803 return NULL; 1804 } 1805 1806 tries++; 1807 } 1808 1809 return (u1*) encodedHandlers + endOffset; 1810 } 1811 1812 /* Perform byte-swapping and intra-item verification on code_item. */ 1813 static void* swapCodeItem(const CheckState* state, void* ptr) { 1814 DexCode* item = (DexCode*) ptr; 1815 u2* insns; 1816 u4 count; 1817 1818 CHECK_PTR_RANGE(item, item + 1); 1819 SWAP_FIELD2(item->registersSize); 1820 SWAP_FIELD2(item->insSize); 1821 SWAP_FIELD2(item->outsSize); 1822 SWAP_FIELD2(item->triesSize); 1823 SWAP_OFFSET4(item->debugInfoOff); 1824 SWAP_FIELD4(item->insnsSize); 1825 1826 if (item->insSize > item->registersSize) { 1827 ALOGE("insSize (%u) > registersSize (%u)", item->insSize, 1828 item->registersSize); 1829 return NULL; 1830 } 1831 1832 if ((item->outsSize > 5) && (item->outsSize > item->registersSize)) { 1833 /* 1834 * It's okay for outsSize to be up to five, even if registersSize 1835 * is smaller, since the short forms of method invocation allow 1836 * repetition of a register multiple times within a single parameter 1837 * list. Longer parameter lists, though, need to be represented 1838 * in-order in the register file. 1839 */ 1840 ALOGE("outsSize (%u) > registersSize (%u)", item->outsSize, 1841 item->registersSize); 1842 return NULL; 1843 } 1844 1845 count = item->insnsSize; 1846 insns = item->insns; 1847 CHECK_LIST_SIZE(insns, count, sizeof(u2)); 1848 1849 while (count--) { 1850 *insns = SWAP2(*insns); 1851 insns++; 1852 } 1853 1854 if (item->triesSize == 0) { 1855 ptr = insns; 1856 } else { 1857 if ((((uintptr_t) insns) & 3) != 0) { 1858 // Four-byte alignment for the tries. Verify the spacer is a 0. 1859 if (*insns != 0) { 1860 ALOGE("Non-zero padding: %#x", (u4) *insns); 1861 return NULL; 1862 } 1863 } 1864 1865 ptr = swapTriesAndCatches(state, item); 1866 } 1867 1868 return ptr; 1869 } 1870 1871 /* Perform intra-item verification on string_data_item. */ 1872 static void* intraVerifyStringDataItem(const CheckState* state, void* ptr) { 1873 const u1* fileEnd = state->fileEnd; 1874 const u1* data = (const u1*) ptr; 1875 bool okay = true; 1876 u4 utf16Size = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 1877 u4 i; 1878 1879 if (!okay) { 1880 ALOGE("Bogus utf16_size"); 1881 return NULL; 1882 } 1883 1884 for (i = 0; i < utf16Size; i++) { 1885 if (data >= fileEnd) { 1886 ALOGE("String data would go beyond end-of-file"); 1887 return NULL; 1888 } 1889 1890 u1 byte1 = *(data++); 1891 1892 // Switch on the high four bits. 1893 switch (byte1 >> 4) { 1894 case 0x00: { 1895 // Special case of bit pattern 0xxx. 1896 if (byte1 == 0) { 1897 ALOGE("String shorter than indicated utf16_size %#x", 1898 utf16Size); 1899 return NULL; 1900 } 1901 break; 1902 } 1903 case 0x01: 1904 case 0x02: 1905 case 0x03: 1906 case 0x04: 1907 case 0x05: 1908 case 0x06: 1909 case 0x07: { 1910 // Bit pattern 0xxx. No need for any extra bytes or checks. 1911 break; 1912 } 1913 case 0x08: 1914 case 0x09: 1915 case 0x0a: 1916 case 0x0b: 1917 case 0x0f: { 1918 /* 1919 * Bit pattern 10xx or 1111, which are illegal start bytes. 1920 * Note: 1111 is valid for normal UTF-8, but not the 1921 * modified UTF-8 used here. 1922 */ 1923 ALOGE("Illegal start byte %#x", byte1); 1924 return NULL; 1925 } 1926 case 0x0e: { 1927 // Bit pattern 1110, so there are two additional bytes. 1928 u1 byte2 = *(data++); 1929 if ((byte2 & 0xc0) != 0x80) { 1930 ALOGE("Illegal continuation byte %#x", byte2); 1931 return NULL; 1932 } 1933 u1 byte3 = *(data++); 1934 if ((byte3 & 0xc0) != 0x80) { 1935 ALOGE("Illegal continuation byte %#x", byte3); 1936 return NULL; 1937 } 1938 u2 value = ((byte1 & 0x0f) << 12) | ((byte2 & 0x3f) << 6) 1939 | (byte3 & 0x3f); 1940 if (value < 0x800) { 1941 ALOGE("Illegal representation for value %x", value); 1942 return NULL; 1943 } 1944 break; 1945 } 1946 case 0x0c: 1947 case 0x0d: { 1948 // Bit pattern 110x, so there is one additional byte. 1949 u1 byte2 = *(data++); 1950 if ((byte2 & 0xc0) != 0x80) { 1951 ALOGE("Illegal continuation byte %#x", byte2); 1952 return NULL; 1953 } 1954 u2 value = ((byte1 & 0x1f) << 6) | (byte2 & 0x3f); 1955 if ((value != 0) && (value < 0x80)) { 1956 ALOGE("Illegal representation for value %x", value); 1957 return NULL; 1958 } 1959 break; 1960 } 1961 } 1962 } 1963 1964 if (*(data++) != '\0') { 1965 ALOGE("String longer than indicated utf16_size %#x", utf16Size); 1966 return NULL; 1967 } 1968 1969 return (void*) data; 1970 } 1971 1972 /* Perform intra-item verification on debug_info_item. */ 1973 static void* intraVerifyDebugInfoItem(const CheckState* state, void* ptr) { 1974 const u1* fileEnd = state->fileEnd; 1975 const u1* data = (const u1*) ptr; 1976 bool okay = true; 1977 u4 i; 1978 1979 readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 1980 1981 if (!okay) { 1982 ALOGE("Bogus line_start"); 1983 return NULL; 1984 } 1985 1986 u4 parametersSize = 1987 readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 1988 1989 if (!okay) { 1990 ALOGE("Bogus parameters_size"); 1991 return NULL; 1992 } 1993 1994 if (parametersSize > 65536) { 1995 ALOGE("Invalid parameters_size: %#x", parametersSize); 1996 return NULL; 1997 } 1998 1999 for (i = 0; i < parametersSize; i++) { 2000 u4 parameterName = 2001 readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 2002 2003 if (!okay) { 2004 ALOGE("Bogus parameter_name"); 2005 return NULL; 2006 } 2007 2008 if (parameterName != 0) { 2009 parameterName--; 2010 CHECK_INDEX(parameterName, state->pHeader->stringIdsSize); 2011 } 2012 } 2013 2014 bool done = false; 2015 while (!done) { 2016 u1 opcode = *(data++); 2017 2018 switch (opcode) { 2019 case DBG_END_SEQUENCE: { 2020 done = true; 2021 break; 2022 } 2023 case DBG_ADVANCE_PC: { 2024 readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 2025 break; 2026 } 2027 case DBG_ADVANCE_LINE: { 2028 readAndVerifySignedLeb128(&data, fileEnd, &okay); 2029 break; 2030 } 2031 case DBG_START_LOCAL: { 2032 u4 idx; 2033 u4 regNum = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 2034 if (!okay) break; 2035 if (regNum >= 65536) { 2036 okay = false; 2037 break; 2038 } 2039 idx = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 2040 if (!okay) break; 2041 if (idx != 0) { 2042 idx--; 2043 CHECK_INDEX(idx, state->pHeader->stringIdsSize); 2044 } 2045 idx = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 2046 if (!okay) break; 2047 if (idx != 0) { 2048 idx--; 2049 CHECK_INDEX(idx, state->pHeader->stringIdsSize); 2050 } 2051 break; 2052 } 2053 case DBG_END_LOCAL: 2054 case DBG_RESTART_LOCAL: { 2055 u4 regNum = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 2056 if (!okay) break; 2057 if (regNum >= 65536) { 2058 okay = false; 2059 break; 2060 } 2061 break; 2062 } 2063 case DBG_START_LOCAL_EXTENDED: { 2064 u4 idx; 2065 u4 regNum = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 2066 if (!okay) break; 2067 if (regNum >= 65536) { 2068 okay = false; 2069 break; 2070 } 2071 idx = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 2072 if (!okay) break; 2073 if (idx != 0) { 2074 idx--; 2075 CHECK_INDEX(idx, state->pHeader->stringIdsSize); 2076 } 2077 idx = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 2078 if (!okay) break; 2079 if (idx != 0) { 2080 idx--; 2081 CHECK_INDEX(idx, state->pHeader->stringIdsSize); 2082 } 2083 idx = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 2084 if (!okay) break; 2085 if (idx != 0) { 2086 idx--; 2087 CHECK_INDEX(idx, state->pHeader->stringIdsSize); 2088 } 2089 break; 2090 } 2091 case DBG_SET_FILE: { 2092 u4 idx = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 2093 if (!okay) break; 2094 if (idx != 0) { 2095 idx--; 2096 CHECK_INDEX(idx, state->pHeader->stringIdsSize); 2097 } 2098 break; 2099 } 2100 default: { 2101 // No arguments to parse for anything else. 2102 } 2103 } 2104 2105 if (!okay) { 2106 ALOGE("Bogus syntax for opcode %02x", opcode); 2107 return NULL; 2108 } 2109 } 2110 2111 return (void*) data; 2112 } 2113 2114 /* defined below */ 2115 static const u1* verifyEncodedValue(const CheckState* state, const u1* data, 2116 bool crossVerify); 2117 static const u1* verifyEncodedAnnotation(const CheckState* state, 2118 const u1* data, bool crossVerify); 2119 2120 /* Helper for verifyEncodedValue(), which reads a 1- to 4- byte unsigned 2121 * little endian value. */ 2122 static u4 readUnsignedLittleEndian(const CheckState* state, const u1** pData, 2123 u4 size) { 2124 const u1* data = *pData; 2125 u4 result = 0; 2126 u4 i; 2127 2128 CHECK_PTR_RANGE(data, data + size); 2129 2130 for (i = 0; i < size; i++) { 2131 result |= ((u4) *(data++)) << (i * 8); 2132 } 2133 2134 *pData = data; 2135 return result; 2136 } 2137 2138 /* Helper for *VerifyAnnotationItem() and *VerifyEncodedArrayItem(), which 2139 * verifies an encoded_array. */ 2140 static const u1* verifyEncodedArray(const CheckState* state, 2141 const u1* data, bool crossVerify) { 2142 bool okay = true; 2143 u4 size = readAndVerifyUnsignedLeb128(&data, state->fileEnd, &okay); 2144 2145 if (!okay) { 2146 ALOGE("Bogus encoded_array size"); 2147 return NULL; 2148 } 2149 2150 while (size--) { 2151 data = verifyEncodedValue(state, data, crossVerify); 2152 if (data == NULL) { 2153 ALOGE("Bogus encoded_array value"); 2154 return NULL; 2155 } 2156 } 2157 2158 return data; 2159 } 2160 2161 /* Helper for *VerifyAnnotationItem() and *VerifyEncodedArrayItem(), which 2162 * verifies an encoded_value. */ 2163 static const u1* verifyEncodedValue(const CheckState* state, 2164 const u1* data, bool crossVerify) { 2165 CHECK_PTR_RANGE(data, data + 1); 2166 2167 u1 headerByte = *(data++); 2168 u4 valueType = headerByte & kDexAnnotationValueTypeMask; 2169 u4 valueArg = headerByte >> kDexAnnotationValueArgShift; 2170 2171 switch (valueType) { 2172 case kDexAnnotationByte: { 2173 if (valueArg != 0) { 2174 ALOGE("Bogus byte size %#x", valueArg); 2175 return NULL; 2176 } 2177 data++; 2178 break; 2179 } 2180 case kDexAnnotationShort: 2181 case kDexAnnotationChar: { 2182 if (valueArg > 1) { 2183 ALOGE("Bogus char/short size %#x", valueArg); 2184 return NULL; 2185 } 2186 data += valueArg + 1; 2187 break; 2188 } 2189 case kDexAnnotationInt: 2190 case kDexAnnotationFloat: { 2191 if (valueArg > 3) { 2192 ALOGE("Bogus int/float size %#x", valueArg); 2193 return NULL; 2194 } 2195 data += valueArg + 1; 2196 break; 2197 } 2198 case kDexAnnotationLong: 2199 case kDexAnnotationDouble: { 2200 data += valueArg + 1; 2201 break; 2202 } 2203 case kDexAnnotationString: { 2204 if (valueArg > 3) { 2205 ALOGE("Bogus string size %#x", valueArg); 2206 return NULL; 2207 } 2208 u4 idx = readUnsignedLittleEndian(state, &data, valueArg + 1); 2209 CHECK_INDEX(idx, state->pHeader->stringIdsSize); 2210 break; 2211 } 2212 case kDexAnnotationType: { 2213 if (valueArg > 3) { 2214 ALOGE("Bogus type size %#x", valueArg); 2215 return NULL; 2216 } 2217 u4 idx = readUnsignedLittleEndian(state, &data, valueArg + 1); 2218 CHECK_INDEX(idx, state->pHeader->typeIdsSize); 2219 break; 2220 } 2221 case kDexAnnotationField: 2222 case kDexAnnotationEnum: { 2223 if (valueArg > 3) { 2224 ALOGE("Bogus field/enum size %#x", valueArg); 2225 return NULL; 2226 } 2227 u4 idx = readUnsignedLittleEndian(state, &data, valueArg + 1); 2228 CHECK_INDEX(idx, state->pHeader->fieldIdsSize); 2229 break; 2230 } 2231 case kDexAnnotationMethod: { 2232 if (valueArg > 3) { 2233 ALOGE("Bogus method size %#x", valueArg); 2234 return NULL; 2235 } 2236 u4 idx = readUnsignedLittleEndian(state, &data, valueArg + 1); 2237 CHECK_INDEX(idx, state->pHeader->methodIdsSize); 2238 break; 2239 } 2240 case kDexAnnotationArray: { 2241 if (valueArg != 0) { 2242 ALOGE("Bogus array value_arg %#x", valueArg); 2243 return NULL; 2244 } 2245 data = verifyEncodedArray(state, data, crossVerify); 2246 break; 2247 } 2248 case kDexAnnotationAnnotation: { 2249 if (valueArg != 0) { 2250 ALOGE("Bogus annotation value_arg %#x", valueArg); 2251 return NULL; 2252 } 2253 data = verifyEncodedAnnotation(state, data, crossVerify); 2254 break; 2255 } 2256 case kDexAnnotationNull: { 2257 if (valueArg != 0) { 2258 ALOGE("Bogus null value_arg %#x", valueArg); 2259 return NULL; 2260 } 2261 // Nothing else to do for this type. 2262 break; 2263 } 2264 case kDexAnnotationBoolean: { 2265 if (valueArg > 1) { 2266 ALOGE("Bogus boolean value_arg %#x", valueArg); 2267 return NULL; 2268 } 2269 // Nothing else to do for this type. 2270 break; 2271 } 2272 default: { 2273 ALOGE("Bogus value_type %#x", valueType); 2274 return NULL; 2275 } 2276 } 2277 2278 return data; 2279 } 2280 2281 /* Helper for *VerifyAnnotationItem() and *VerifyEncodedArrayItem(), which 2282 * verifies an encoded_annotation. */ 2283 static const u1* verifyEncodedAnnotation(const CheckState* state, 2284 const u1* data, bool crossVerify) { 2285 const u1* fileEnd = state->fileEnd; 2286 bool okay = true; 2287 u4 idx = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 2288 2289 if (!okay) { 2290 ALOGE("Bogus encoded_annotation type_idx"); 2291 return NULL; 2292 } 2293 2294 CHECK_INDEX(idx, state->pHeader->typeIdsSize); 2295 2296 if (crossVerify) { 2297 const char* descriptor = dexStringByTypeIdx(state->pDexFile, idx); 2298 if (!dexIsClassDescriptor(descriptor)) { 2299 ALOGE("Bogus annotation type: '%s'", descriptor); 2300 return NULL; 2301 } 2302 } 2303 2304 u4 size = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 2305 u4 lastIdx = 0; 2306 bool first = true; 2307 2308 if (!okay) { 2309 ALOGE("Bogus encoded_annotation size"); 2310 return NULL; 2311 } 2312 2313 while (size--) { 2314 idx = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 2315 2316 if (!okay) { 2317 ALOGE("Bogus encoded_annotation name_idx"); 2318 return NULL; 2319 } 2320 2321 CHECK_INDEX(idx, state->pHeader->stringIdsSize); 2322 2323 if (crossVerify) { 2324 const char* name = dexStringById(state->pDexFile, idx); 2325 if (!dexIsValidMemberName(name)) { 2326 ALOGE("Bogus annotation member name: '%s'", name); 2327 return NULL; 2328 } 2329 } 2330 2331 if (first) { 2332 first = false; 2333 } else if (lastIdx >= idx) { 2334 ALOGE("Out-of-order encoded_annotation name_idx: %#x then %#x", 2335 lastIdx, idx); 2336 return NULL; 2337 } 2338 2339 data = verifyEncodedValue(state, data, crossVerify); 2340 lastIdx = idx; 2341 2342 if (data == NULL) { 2343 return NULL; 2344 } 2345 } 2346 2347 return data; 2348 } 2349 2350 /* Perform intra-item verification on encoded_array_item. */ 2351 static void* intraVerifyEncodedArrayItem(const CheckState* state, void* ptr) { 2352 return (void*) verifyEncodedArray(state, (const u1*) ptr, false); 2353 } 2354 2355 /* Perform intra-item verification on annotation_item. */ 2356 static void* intraVerifyAnnotationItem(const CheckState* state, void* ptr) { 2357 const u1* data = (const u1*) ptr; 2358 2359 CHECK_PTR_RANGE(data, data + 1); 2360 2361 switch (*(data++)) { 2362 case kDexVisibilityBuild: 2363 case kDexVisibilityRuntime: 2364 case kDexVisibilitySystem: { 2365 break; 2366 } 2367 default: { 2368 ALOGE("Bogus annotation visibility: %#x", *data); 2369 return NULL; 2370 } 2371 } 2372 2373 return (void*) verifyEncodedAnnotation(state, data, false); 2374 } 2375 2376 /* Perform cross-item verification on annotation_item. */ 2377 static void* crossVerifyAnnotationItem(const CheckState* state, void* ptr) { 2378 const u1* data = (const u1*) ptr; 2379 2380 // Skip the visibility byte. 2381 data++; 2382 2383 return (void*) verifyEncodedAnnotation(state, data, true); 2384 } 2385 2386 2387 2388 2389 /* 2390 * Function to visit an individual top-level item type. 2391 */ 2392 typedef void* ItemVisitorFunction(const CheckState* state, void* ptr); 2393 2394 /* 2395 * Iterate over all the items in a section, optionally updating the 2396 * data map (done if mapType is passed as non-negative). The section 2397 * must consist of concatenated items of the same type. 2398 */ 2399 static bool iterateSectionWithOptionalUpdate(CheckState* state, 2400 u4 offset, u4 count, ItemVisitorFunction* func, u4 alignment, 2401 u4* nextOffset, int mapType) { 2402 u4 alignmentMask = alignment - 1; 2403 u4 i; 2404 2405 state->previousItem = NULL; 2406 2407 for (i = 0; i < count; i++) { 2408 u4 newOffset = (offset + alignmentMask) & ~alignmentMask; 2409 u1* ptr = (u1*) filePointer(state, newOffset); 2410 2411 if (offset < newOffset) { 2412 ptr = (u1*) filePointer(state, offset); 2413 if (offset < newOffset) { 2414 CHECK_OFFSET_RANGE(offset, newOffset); 2415 while (offset < newOffset) { 2416 if (*ptr != '\0') { 2417 ALOGE("Non-zero padding 0x%02x @ %x", *ptr, offset); 2418 return false; 2419 } 2420 ptr++; 2421 offset++; 2422 } 2423 } 2424 } 2425 2426 u1* newPtr = (u1*) func(state, ptr); 2427 newOffset = fileOffset(state, newPtr); 2428 2429 if (newPtr == NULL) { 2430 ALOGE("Trouble with item %d @ offset %#x", i, offset); 2431 return false; 2432 } 2433 2434 if (newOffset > state->fileLen) { 2435 ALOGE("Item %d @ offset %#x ends out of bounds", i, offset); 2436 return false; 2437 } 2438 2439 if (mapType >= 0) { 2440 dexDataMapAdd(state->pDataMap, offset, mapType); 2441 } 2442 2443 state->previousItem = ptr; 2444 offset = newOffset; 2445 } 2446 2447 if (nextOffset != NULL) { 2448 *nextOffset = offset; 2449 } 2450 2451 return true; 2452 } 2453 2454 /* 2455 * Iterate over all the items in a section. The section must consist of 2456 * concatenated items of the same type. This variant will not update the data 2457 * map. 2458 */ 2459 static bool iterateSection(CheckState* state, u4 offset, u4 count, 2460 ItemVisitorFunction* func, u4 alignment, u4* nextOffset) { 2461 return iterateSectionWithOptionalUpdate(state, offset, count, func, 2462 alignment, nextOffset, -1); 2463 } 2464 2465 /* 2466 * Like iterateSection(), but also check that the offset and count match 2467 * a given pair of expected values. 2468 */ 2469 static bool checkBoundsAndIterateSection(CheckState* state, 2470 u4 offset, u4 count, u4 expectedOffset, u4 expectedCount, 2471 ItemVisitorFunction* func, u4 alignment, u4* nextOffset) { 2472 if (offset != expectedOffset) { 2473 ALOGE("Bogus offset for section: got %#x; expected %#x", 2474 offset, expectedOffset); 2475 return false; 2476 } 2477 2478 if (count != expectedCount) { 2479 ALOGE("Bogus size for section: got %#x; expected %#x", 2480 count, expectedCount); 2481 return false; 2482 } 2483 2484 return iterateSection(state, offset, count, func, alignment, nextOffset); 2485 } 2486 2487 /* 2488 * Like iterateSection(), but also update the data section map and 2489 * check that all the items fall within the data section. 2490 */ 2491 static bool iterateDataSection(CheckState* state, u4 offset, u4 count, 2492 ItemVisitorFunction* func, u4 alignment, u4* nextOffset, int mapType) { 2493 u4 dataStart = state->pHeader->dataOff; 2494 u4 dataEnd = dataStart + state->pHeader->dataSize; 2495 2496 assert(nextOffset != NULL); 2497 2498 if ((offset < dataStart) || (offset >= dataEnd)) { 2499 ALOGE("Bogus offset for data subsection: %#x", offset); 2500 return false; 2501 } 2502 2503 if (!iterateSectionWithOptionalUpdate(state, offset, count, func, 2504 alignment, nextOffset, mapType)) { 2505 return false; 2506 } 2507 2508 if (*nextOffset > dataEnd) { 2509 ALOGE("Out-of-bounds end of data subsection: %#x", *nextOffset); 2510 return false; 2511 } 2512 2513 return true; 2514 } 2515 2516 /* 2517 * Byte-swap all items in the given map except the header and the map 2518 * itself, both of which should have already gotten swapped. This also 2519 * does all possible intra-item verification, that is, verification 2520 * that doesn't need to assume the sanctity of the contents of *other* 2521 * items. The intra-item limitation is because at the time an item is 2522 * asked to verify itself, it can't assume that the items it refers to 2523 * have been byte-swapped and verified. 2524 */ 2525 static bool swapEverythingButHeaderAndMap(CheckState* state, 2526 DexMapList* pMap) { 2527 const DexMapItem* item = pMap->list; 2528 u4 lastOffset = 0; 2529 u4 count = pMap->size; 2530 bool okay = true; 2531 2532 while (okay && count--) { 2533 u4 sectionOffset = item->offset; 2534 u4 sectionCount = item->size; 2535 u2 type = item->type; 2536 2537 if (lastOffset < sectionOffset) { 2538 CHECK_OFFSET_RANGE(lastOffset, sectionOffset); 2539 const u1* ptr = (const u1*) filePointer(state, lastOffset); 2540 while (lastOffset < sectionOffset) { 2541 if (*ptr != '\0') { 2542 ALOGE("Non-zero padding 0x%02x before section start @ %x", 2543 *ptr, lastOffset); 2544 okay = false; 2545 break; 2546 } 2547 ptr++; 2548 lastOffset++; 2549 } 2550 } else if (lastOffset > sectionOffset) { 2551 ALOGE("Section overlap or out-of-order map: %x, %x", 2552 lastOffset, sectionOffset); 2553 okay = false; 2554 } 2555 2556 if (!okay) { 2557 break; 2558 } 2559 2560 switch (type) { 2561 case kDexTypeHeaderItem: { 2562 /* 2563 * The header got swapped very early on, but do some 2564 * additional sanity checking here. 2565 */ 2566 okay = checkHeaderSection(state, sectionOffset, sectionCount, 2567 &lastOffset); 2568 break; 2569 } 2570 case kDexTypeStringIdItem: { 2571 okay = checkBoundsAndIterateSection(state, sectionOffset, 2572 sectionCount, state->pHeader->stringIdsOff, 2573 state->pHeader->stringIdsSize, swapStringIdItem, 2574 sizeof(u4), &lastOffset); 2575 break; 2576 } 2577 case kDexTypeTypeIdItem: { 2578 okay = checkBoundsAndIterateSection(state, sectionOffset, 2579 sectionCount, state->pHeader->typeIdsOff, 2580 state->pHeader->typeIdsSize, swapTypeIdItem, 2581 sizeof(u4), &lastOffset); 2582 break; 2583 } 2584 case kDexTypeProtoIdItem: { 2585 okay = checkBoundsAndIterateSection(state, sectionOffset, 2586 sectionCount, state->pHeader->protoIdsOff, 2587 state->pHeader->protoIdsSize, swapProtoIdItem, 2588 sizeof(u4), &lastOffset); 2589 break; 2590 } 2591 case kDexTypeFieldIdItem: { 2592 okay = checkBoundsAndIterateSection(state, sectionOffset, 2593 sectionCount, state->pHeader->fieldIdsOff, 2594 state->pHeader->fieldIdsSize, swapFieldIdItem, 2595 sizeof(u4), &lastOffset); 2596 break; 2597 } 2598 case kDexTypeMethodIdItem: { 2599 okay = checkBoundsAndIterateSection(state, sectionOffset, 2600 sectionCount, state->pHeader->methodIdsOff, 2601 state->pHeader->methodIdsSize, swapMethodIdItem, 2602 sizeof(u4), &lastOffset); 2603 break; 2604 } 2605 case kDexTypeClassDefItem: { 2606 okay = checkBoundsAndIterateSection(state, sectionOffset, 2607 sectionCount, state->pHeader->classDefsOff, 2608 state->pHeader->classDefsSize, swapClassDefItem, 2609 sizeof(u4), &lastOffset); 2610 break; 2611 } 2612 case kDexTypeMapList: { 2613 /* 2614 * The map section was swapped early on, but do some 2615 * additional sanity checking here. 2616 */ 2617 okay = checkMapSection(state, sectionOffset, sectionCount, 2618 &lastOffset); 2619 break; 2620 } 2621 case kDexTypeTypeList: { 2622 okay = iterateDataSection(state, sectionOffset, sectionCount, 2623 swapTypeList, sizeof(u4), &lastOffset, type); 2624 break; 2625 } 2626 case kDexTypeAnnotationSetRefList: { 2627 okay = iterateDataSection(state, sectionOffset, sectionCount, 2628 swapAnnotationSetRefList, sizeof(u4), &lastOffset, 2629 type); 2630 break; 2631 } 2632 case kDexTypeAnnotationSetItem: { 2633 okay = iterateDataSection(state, sectionOffset, sectionCount, 2634 swapAnnotationSetItem, sizeof(u4), &lastOffset, type); 2635 break; 2636 } 2637 case kDexTypeClassDataItem: { 2638 okay = iterateDataSection(state, sectionOffset, sectionCount, 2639 intraVerifyClassDataItem, sizeof(u1), &lastOffset, 2640 type); 2641 break; 2642 } 2643 case kDexTypeCodeItem: { 2644 okay = iterateDataSection(state, sectionOffset, sectionCount, 2645 swapCodeItem, sizeof(u4), &lastOffset, type); 2646 break; 2647 } 2648 case kDexTypeStringDataItem: { 2649 okay = iterateDataSection(state, sectionOffset, sectionCount, 2650 intraVerifyStringDataItem, sizeof(u1), &lastOffset, 2651 type); 2652 break; 2653 } 2654 case kDexTypeDebugInfoItem: { 2655 okay = iterateDataSection(state, sectionOffset, sectionCount, 2656 intraVerifyDebugInfoItem, sizeof(u1), &lastOffset, 2657 type); 2658 break; 2659 } 2660 case kDexTypeAnnotationItem: { 2661 okay = iterateDataSection(state, sectionOffset, sectionCount, 2662 intraVerifyAnnotationItem, sizeof(u1), &lastOffset, 2663 type); 2664 break; 2665 } 2666 case kDexTypeEncodedArrayItem: { 2667 okay = iterateDataSection(state, sectionOffset, sectionCount, 2668 intraVerifyEncodedArrayItem, sizeof(u1), &lastOffset, 2669 type); 2670 break; 2671 } 2672 case kDexTypeAnnotationsDirectoryItem: { 2673 okay = iterateDataSection(state, sectionOffset, sectionCount, 2674 swapAnnotationsDirectoryItem, sizeof(u4), &lastOffset, 2675 type); 2676 break; 2677 } 2678 default: { 2679 ALOGE("Unknown map item type %04x", type); 2680 return false; 2681 } 2682 } 2683 2684 if (!okay) { 2685 ALOGE("Swap of section type %04x failed", type); 2686 } 2687 2688 item++; 2689 } 2690 2691 return okay; 2692 } 2693 2694 /* 2695 * Perform cross-item verification on everything that needs it. This 2696 * pass is only called after all items are byte-swapped and 2697 * intra-verified (checked for internal consistency). 2698 */ 2699 static bool crossVerifyEverything(CheckState* state, DexMapList* pMap) 2700 { 2701 const DexMapItem* item = pMap->list; 2702 u4 count = pMap->size; 2703 bool okay = true; 2704 2705 while (okay && count--) { 2706 u4 sectionOffset = item->offset; 2707 u4 sectionCount = item->size; 2708 2709 switch (item->type) { 2710 case kDexTypeHeaderItem: 2711 case kDexTypeMapList: 2712 case kDexTypeTypeList: 2713 case kDexTypeCodeItem: 2714 case kDexTypeStringDataItem: 2715 case kDexTypeDebugInfoItem: 2716 case kDexTypeAnnotationItem: 2717 case kDexTypeEncodedArrayItem: { 2718 // There is no need for cross-item verification for these. 2719 break; 2720 } 2721 case kDexTypeStringIdItem: { 2722 okay = iterateSection(state, sectionOffset, sectionCount, 2723 crossVerifyStringIdItem, sizeof(u4), NULL); 2724 break; 2725 } 2726 case kDexTypeTypeIdItem: { 2727 okay = iterateSection(state, sectionOffset, sectionCount, 2728 crossVerifyTypeIdItem, sizeof(u4), NULL); 2729 break; 2730 } 2731 case kDexTypeProtoIdItem: { 2732 okay = iterateSection(state, sectionOffset, sectionCount, 2733 crossVerifyProtoIdItem, sizeof(u4), NULL); 2734 break; 2735 } 2736 case kDexTypeFieldIdItem: { 2737 okay = iterateSection(state, sectionOffset, sectionCount, 2738 crossVerifyFieldIdItem, sizeof(u4), NULL); 2739 break; 2740 } 2741 case kDexTypeMethodIdItem: { 2742 okay = iterateSection(state, sectionOffset, sectionCount, 2743 crossVerifyMethodIdItem, sizeof(u4), NULL); 2744 break; 2745 } 2746 case kDexTypeClassDefItem: { 2747 // Allocate (on the stack) the "observed class_def" bits. 2748 size_t arraySize = calcDefinedClassBitsSize(state); 2749 u4 definedClassBits[arraySize]; 2750 memset(definedClassBits, 0, arraySize * sizeof(u4)); 2751 state->pDefinedClassBits = definedClassBits; 2752 2753 okay = iterateSection(state, sectionOffset, sectionCount, 2754 crossVerifyClassDefItem, sizeof(u4), NULL); 2755 2756 state->pDefinedClassBits = NULL; 2757 break; 2758 } 2759 case kDexTypeAnnotationSetRefList: { 2760 okay = iterateSection(state, sectionOffset, sectionCount, 2761 crossVerifyAnnotationSetRefList, sizeof(u4), NULL); 2762 break; 2763 } 2764 case kDexTypeAnnotationSetItem: { 2765 okay = iterateSection(state, sectionOffset, sectionCount, 2766 crossVerifyAnnotationSetItem, sizeof(u4), NULL); 2767 break; 2768 } 2769 case kDexTypeClassDataItem: { 2770 okay = iterateSection(state, sectionOffset, sectionCount, 2771 crossVerifyClassDataItem, sizeof(u1), NULL); 2772 break; 2773 } 2774 case kDexTypeAnnotationsDirectoryItem: { 2775 okay = iterateSection(state, sectionOffset, sectionCount, 2776 crossVerifyAnnotationsDirectoryItem, sizeof(u4), NULL); 2777 break; 2778 } 2779 default: { 2780 ALOGE("Unknown map item type %04x", item->type); 2781 return false; 2782 } 2783 } 2784 2785 if (!okay) { 2786 ALOGE("Cross-item verify of section type %04x failed", 2787 item->type); 2788 } 2789 2790 item++; 2791 } 2792 2793 return okay; 2794 } 2795 2796 /* (documented in header file) */ 2797 bool dexHasValidMagic(const DexHeader* pHeader) 2798 { 2799 const u1* magic = pHeader->magic; 2800 const u1* version = &magic[4]; 2801 2802 if (memcmp(magic, DEX_MAGIC, 4) != 0) { 2803 ALOGE("ERROR: unrecognized magic number (%02x %02x %02x %02x)", 2804 magic[0], magic[1], magic[2], magic[3]); 2805 return false; 2806 } 2807 2808 if ((memcmp(version, DEX_MAGIC_VERS, 4) != 0) && 2809 (memcmp(version, DEX_MAGIC_VERS_API_13, 4) != 0)) { 2810 /* 2811 * Magic was correct, but this is an unsupported older or 2812 * newer format variant. 2813 */ 2814 ALOGE("ERROR: unsupported dex version (%02x %02x %02x %02x)", 2815 version[0], version[1], version[2], version[3]); 2816 return false; 2817 } 2818 2819 return true; 2820 } 2821 2822 /* 2823 * Fix the byte ordering of all fields in the DEX file, and do 2824 * structural verification. This is only required for code that opens 2825 * "raw" DEX files, such as the DEX optimizer. 2826 * 2827 * Returns 0 on success, nonzero on failure. 2828 */ 2829 int dexSwapAndVerify(u1* addr, int len) 2830 { 2831 DexHeader* pHeader; 2832 CheckState state; 2833 bool okay = true; 2834 2835 memset(&state, 0, sizeof(state)); 2836 ALOGV("+++ swapping and verifying"); 2837 2838 /* 2839 * Note: The caller must have verified that "len" is at least as 2840 * large as a dex file header. 2841 */ 2842 pHeader = (DexHeader*) addr; 2843 2844 if (!dexHasValidMagic(pHeader)) { 2845 okay = false; 2846 } 2847 2848 if (okay) { 2849 int expectedLen = (int) SWAP4(pHeader->fileSize); 2850 if (len < expectedLen) { 2851 ALOGE("ERROR: Bad length: expected %d, got %d", expectedLen, len); 2852 okay = false; 2853 } else if (len != expectedLen) { 2854 ALOGW("WARNING: Odd length: expected %d, got %d", expectedLen, 2855 len); 2856 // keep going 2857 } 2858 } 2859 2860 if (okay) { 2861 /* 2862 * Compute the adler32 checksum and compare it to what's stored in 2863 * the file. This isn't free, but chances are good that we just 2864 * unpacked this from a jar file and have all of the pages sitting 2865 * in memory, so it's pretty quick. 2866 * 2867 * This might be a big-endian system, so we need to do this before 2868 * we byte-swap the header. 2869 */ 2870 uLong adler = adler32(0L, Z_NULL, 0); 2871 const int nonSum = sizeof(pHeader->magic) + sizeof(pHeader->checksum); 2872 u4 storedFileSize = SWAP4(pHeader->fileSize); 2873 u4 expectedChecksum = SWAP4(pHeader->checksum); 2874 2875 adler = adler32(adler, ((const u1*) pHeader) + nonSum, 2876 storedFileSize - nonSum); 2877 2878 if (adler != expectedChecksum) { 2879 ALOGE("ERROR: bad checksum (%08lx, expected %08x)", 2880 adler, expectedChecksum); 2881 okay = false; 2882 } 2883 } 2884 2885 if (okay) { 2886 state.fileStart = addr; 2887 state.fileEnd = addr + len; 2888 state.fileLen = len; 2889 state.pDexFile = NULL; 2890 state.pDataMap = NULL; 2891 state.pDefinedClassBits = NULL; 2892 state.previousItem = NULL; 2893 2894 /* 2895 * Swap the header and check the contents. 2896 */ 2897 okay = swapDexHeader(&state, pHeader); 2898 } 2899 2900 if (okay) { 2901 state.pHeader = pHeader; 2902 2903 if (pHeader->headerSize < sizeof(DexHeader)) { 2904 ALOGE("ERROR: Small header size %d, struct %d", 2905 pHeader->headerSize, (int) sizeof(DexHeader)); 2906 okay = false; 2907 } else if (pHeader->headerSize > sizeof(DexHeader)) { 2908 ALOGW("WARNING: Large header size %d, struct %d", 2909 pHeader->headerSize, (int) sizeof(DexHeader)); 2910 // keep going? 2911 } 2912 } 2913 2914 if (okay) { 2915 /* 2916 * Look for the map. Swap it and then use it to find and swap 2917 * everything else. 2918 */ 2919 if (pHeader->mapOff != 0) { 2920 DexFile dexFile; 2921 DexMapList* pDexMap = (DexMapList*) (addr + pHeader->mapOff); 2922 2923 okay = okay && swapMap(&state, pDexMap); 2924 okay = okay && swapEverythingButHeaderAndMap(&state, pDexMap); 2925 2926 dexFileSetupBasicPointers(&dexFile, addr); 2927 state.pDexFile = &dexFile; 2928 2929 okay = okay && crossVerifyEverything(&state, pDexMap); 2930 } else { 2931 ALOGE("ERROR: No map found; impossible to byte-swap and verify"); 2932 okay = false; 2933 } 2934 } 2935 2936 if (!okay) { 2937 ALOGE("ERROR: Byte swap + verify failed"); 2938 } 2939 2940 if (state.pDataMap != NULL) { 2941 dexDataMapFree(state.pDataMap); 2942 } 2943 2944 return !okay; // 0 == success 2945 } 2946 2947 /* 2948 * Detect the file type of the given memory buffer via magic number. 2949 * Call dexSwapAndVerify() on an unoptimized DEX file, do nothing 2950 * but return successfully on an optimized DEX file, and report an 2951 * error for all other cases. 2952 * 2953 * Returns 0 on success, nonzero on failure. 2954 */ 2955 int dexSwapAndVerifyIfNecessary(u1* addr, int len) 2956 { 2957 if (memcmp(addr, DEX_OPT_MAGIC, 4) == 0) { 2958 // It is an optimized dex file. 2959 return 0; 2960 } 2961 2962 if (memcmp(addr, DEX_MAGIC, 4) == 0) { 2963 // It is an unoptimized dex file. 2964 return dexSwapAndVerify(addr, len); 2965 } 2966 2967 ALOGE("ERROR: Bad magic number (0x%02x %02x %02x %02x)", 2968 addr[0], addr[1], addr[2], addr[3]); 2969 2970 return 1; 2971 } 2972