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