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 <= 3 && 1072 item->fieldOrMethodIdx >= state->pHeader->fieldIdsSize) { 1073 // 0-3 are field accessors. 1074 ALOGE("Method handle has invalid field id: %u\n", item->fieldOrMethodIdx); 1075 return NULL; 1076 } 1077 if (item->methodHandleType >= 4 && 1078 item->methodHandleType <= 6 && 1079 item->fieldOrMethodIdx >= state->pHeader->methodIdsSize) { 1080 // 4-6 are method invocations. 1081 ALOGE("Method handle has invalid method id: %u\n", item->fieldOrMethodIdx); 1082 return NULL; 1083 } 1084 if (item->methodHandleType >= 7) { 1085 ALOGE("Unknown method handle type: %u", item->methodHandleType); 1086 return NULL; 1087 } 1088 return (void*) (item + 1); 1089 } 1090 1091 /* Helper for swapAnnotationsDirectoryItem(), which performs 1092 * byte-swapping and intra-item verification on an 1093 * annotation_directory_item's field elements. */ 1094 static u1* swapFieldAnnotations(const CheckState* state, u4 count, u1* addr) { 1095 DexFieldAnnotationsItem* item = (DexFieldAnnotationsItem*) addr; 1096 bool first = true; 1097 u4 lastIdx = 0; 1098 1099 const u4 sizeOfItem = (u4) sizeof(DexFieldAnnotationsItem); 1100 CHECK_LIST_SIZE(item, count, sizeOfItem); 1101 1102 while (count--) { 1103 SWAP_INDEX4(item->fieldIdx, state->pHeader->fieldIdsSize); 1104 SWAP_OFFSET4(item->annotationsOff); 1105 1106 if (first) { 1107 first = false; 1108 } else if (lastIdx >= item->fieldIdx) { 1109 ALOGE("Out-of-order field_idx: %#x then %#x", lastIdx, 1110 item->fieldIdx); 1111 return NULL; 1112 } 1113 1114 lastIdx = item->fieldIdx; 1115 item++; 1116 } 1117 1118 return (u1*) item; 1119 } 1120 1121 /* Helper for swapAnnotationsDirectoryItem(), which performs 1122 * byte-swapping and intra-item verification on an 1123 * annotation_directory_item's method elements. */ 1124 static u1* swapMethodAnnotations(const CheckState* state, u4 count, u1* addr) { 1125 DexMethodAnnotationsItem* item = (DexMethodAnnotationsItem*) addr; 1126 bool first = true; 1127 u4 lastIdx = 0; 1128 1129 const u4 sizeOfItem = (u4) sizeof(DexMethodAnnotationsItem); 1130 CHECK_LIST_SIZE(item, count, sizeOfItem); 1131 1132 while (count--) { 1133 SWAP_INDEX4(item->methodIdx, state->pHeader->methodIdsSize); 1134 SWAP_OFFSET4(item->annotationsOff); 1135 1136 if (first) { 1137 first = false; 1138 } else if (lastIdx >= item->methodIdx) { 1139 ALOGE("Out-of-order method_idx: %#x then %#x", lastIdx, 1140 item->methodIdx); 1141 return NULL; 1142 } 1143 1144 lastIdx = item->methodIdx; 1145 item++; 1146 } 1147 1148 return (u1*) item; 1149 } 1150 1151 /* Helper for swapAnnotationsDirectoryItem(), which performs 1152 * byte-swapping and intra-item verification on an 1153 * annotation_directory_item's parameter elements. */ 1154 static u1* swapParameterAnnotations(const CheckState* state, u4 count, 1155 u1* addr) { 1156 DexParameterAnnotationsItem* item = (DexParameterAnnotationsItem*) addr; 1157 bool first = true; 1158 u4 lastIdx = 0; 1159 1160 const u4 sizeOfItem = (u4) sizeof(DexParameterAnnotationsItem); 1161 CHECK_LIST_SIZE(item, count, sizeOfItem); 1162 1163 while (count--) { 1164 SWAP_INDEX4(item->methodIdx, state->pHeader->methodIdsSize); 1165 SWAP_OFFSET4(item->annotationsOff); 1166 1167 if (first) { 1168 first = false; 1169 } else if (lastIdx >= item->methodIdx) { 1170 ALOGE("Out-of-order method_idx: %#x then %#x", lastIdx, 1171 item->methodIdx); 1172 return NULL; 1173 } 1174 1175 lastIdx = item->methodIdx; 1176 item++; 1177 } 1178 1179 return (u1*) item; 1180 } 1181 1182 /* Perform byte-swapping and intra-item verification on 1183 * annotations_directory_item. */ 1184 static void* swapAnnotationsDirectoryItem(const CheckState* state, void* ptr) { 1185 DexAnnotationsDirectoryItem* item = (DexAnnotationsDirectoryItem*) ptr; 1186 1187 CHECK_PTR_RANGE(item, item + 1); 1188 SWAP_OFFSET4(item->classAnnotationsOff); 1189 SWAP_FIELD4(item->fieldsSize); 1190 SWAP_FIELD4(item->methodsSize); 1191 SWAP_FIELD4(item->parametersSize); 1192 1193 u1* addr = (u1*) (item + 1); 1194 1195 if (item->fieldsSize != 0) { 1196 addr = swapFieldAnnotations(state, item->fieldsSize, addr); 1197 if (addr == NULL) { 1198 return NULL; 1199 } 1200 } 1201 1202 if (item->methodsSize != 0) { 1203 addr = swapMethodAnnotations(state, item->methodsSize, addr); 1204 if (addr == NULL) { 1205 return NULL; 1206 } 1207 } 1208 1209 if (item->parametersSize != 0) { 1210 addr = swapParameterAnnotations(state, item->parametersSize, addr); 1211 if (addr == NULL) { 1212 return NULL; 1213 } 1214 } 1215 1216 return addr; 1217 } 1218 1219 static void* swapCallSiteId(const CheckState* state, void* ptr) { 1220 DexCallSiteId* item = (DexCallSiteId*) ptr; 1221 1222 CHECK_PTR_RANGE(item, item + 1); 1223 SWAP_OFFSET4(item->callSiteOff); 1224 1225 return (item + 1); 1226 } 1227 1228 static void* swapMethodHandleItem(const CheckState* state, void* ptr) { 1229 DexMethodHandleItem* item = (DexMethodHandleItem*) ptr; 1230 1231 CHECK_PTR_RANGE(item, item + 1); 1232 SWAP_FIELD2(item->methodHandleType); 1233 SWAP_FIELD2(item->fieldOrMethodIdx); 1234 1235 return (item + 1); 1236 } 1237 1238 1239 /* Helper for crossVerifyAnnotationsDirectoryItem(), which checks the 1240 * field elements. */ 1241 static const u1* crossVerifyFieldAnnotations(const CheckState* state, u4 count, 1242 const u1* addr, u4 definingClass) { 1243 const DexFieldAnnotationsItem* item = (DexFieldAnnotationsItem*) addr; 1244 1245 while (count--) { 1246 if (!verifyFieldDefiner(state, definingClass, item->fieldIdx)) { 1247 return NULL; 1248 } 1249 if (!dexDataMapVerify(state->pDataMap, item->annotationsOff, 1250 kDexTypeAnnotationSetItem)) { 1251 return NULL; 1252 } 1253 item++; 1254 } 1255 1256 return (const u1*) item; 1257 } 1258 1259 /* Helper for crossVerifyAnnotationsDirectoryItem(), which checks the 1260 * method elements. */ 1261 static const u1* crossVerifyMethodAnnotations(const CheckState* state, 1262 u4 count, const u1* addr, u4 definingClass) { 1263 const DexMethodAnnotationsItem* item = (DexMethodAnnotationsItem*) addr; 1264 1265 while (count--) { 1266 if (!verifyMethodDefiner(state, definingClass, item->methodIdx)) { 1267 return NULL; 1268 } 1269 if (!dexDataMapVerify(state->pDataMap, item->annotationsOff, 1270 kDexTypeAnnotationSetItem)) { 1271 return NULL; 1272 } 1273 item++; 1274 } 1275 1276 return (const u1*) item; 1277 } 1278 1279 /* Helper for crossVerifyAnnotationsDirectoryItem(), which checks the 1280 * parameter elements. */ 1281 static const u1* crossVerifyParameterAnnotations(const CheckState* state, 1282 u4 count, const u1* addr, u4 definingClass) { 1283 const DexParameterAnnotationsItem* item = 1284 (DexParameterAnnotationsItem*) addr; 1285 1286 while (count--) { 1287 if (!verifyMethodDefiner(state, definingClass, item->methodIdx)) { 1288 return NULL; 1289 } 1290 if (!dexDataMapVerify(state->pDataMap, item->annotationsOff, 1291 kDexTypeAnnotationSetRefList)) { 1292 return NULL; 1293 } 1294 item++; 1295 } 1296 1297 return (const u1*) item; 1298 } 1299 1300 /* Helper for crossVerifyClassDefItem() and 1301 * crossVerifyAnnotationsDirectoryItem(), which finds the type_idx of 1302 * the definer of the first item in the data. */ 1303 static u4 findFirstAnnotationsDirectoryDefiner(const CheckState* state, 1304 const DexAnnotationsDirectoryItem* dir) { 1305 if (dir->fieldsSize != 0) { 1306 const DexFieldAnnotationsItem* fields = 1307 dexGetFieldAnnotations(state->pDexFile, dir); 1308 const DexFieldId* field = 1309 dexGetFieldId(state->pDexFile, fields[0].fieldIdx); 1310 return field->classIdx; 1311 } 1312 1313 if (dir->methodsSize != 0) { 1314 const DexMethodAnnotationsItem* methods = 1315 dexGetMethodAnnotations(state->pDexFile, dir); 1316 const DexMethodId* method = 1317 dexGetMethodId(state->pDexFile, methods[0].methodIdx); 1318 return method->classIdx; 1319 } 1320 1321 if (dir->parametersSize != 0) { 1322 const DexParameterAnnotationsItem* parameters = 1323 dexGetParameterAnnotations(state->pDexFile, dir); 1324 const DexMethodId* method = 1325 dexGetMethodId(state->pDexFile, parameters[0].methodIdx); 1326 return method->classIdx; 1327 } 1328 1329 return kDexNoIndex; 1330 } 1331 1332 /* Perform cross-item verification of annotations_directory_item. */ 1333 static void* crossVerifyAnnotationsDirectoryItem(const CheckState* state, 1334 void* ptr) { 1335 const DexAnnotationsDirectoryItem* item = (const DexAnnotationsDirectoryItem*) ptr; 1336 u4 definingClass = findFirstAnnotationsDirectoryDefiner(state, item); 1337 1338 if (!dexDataMapVerify0Ok(state->pDataMap, 1339 item->classAnnotationsOff, kDexTypeAnnotationSetItem)) { 1340 return NULL; 1341 } 1342 1343 const u1* addr = (const u1*) (item + 1); 1344 1345 if (item->fieldsSize != 0) { 1346 addr = crossVerifyFieldAnnotations(state, item->fieldsSize, addr, 1347 definingClass); 1348 if (addr == NULL) { 1349 return NULL; 1350 } 1351 } 1352 1353 if (item->methodsSize != 0) { 1354 addr = crossVerifyMethodAnnotations(state, item->methodsSize, addr, 1355 definingClass); 1356 if (addr == NULL) { 1357 return NULL; 1358 } 1359 } 1360 1361 if (item->parametersSize != 0) { 1362 addr = crossVerifyParameterAnnotations(state, item->parametersSize, 1363 addr, definingClass); 1364 if (addr == NULL) { 1365 return NULL; 1366 } 1367 } 1368 1369 return (void*) addr; 1370 } 1371 1372 /* Perform byte-swapping and intra-item verification on type_list. */ 1373 static void* swapTypeList(const CheckState* state, void* ptr) 1374 { 1375 DexTypeList* pTypeList = (DexTypeList*) ptr; 1376 DexTypeItem* pType; 1377 u4 count; 1378 1379 CHECK_PTR_RANGE(pTypeList, pTypeList + 1); 1380 SWAP_FIELD4(pTypeList->size); 1381 count = pTypeList->size; 1382 pType = pTypeList->list; 1383 1384 const u4 sizeOfItem = (u4) sizeof(DexTypeItem); 1385 CHECK_LIST_SIZE(pType, count, sizeOfItem); 1386 1387 while (count--) { 1388 SWAP_INDEX2(pType->typeIdx, state->pHeader->typeIdsSize); 1389 pType++; 1390 } 1391 1392 return pType; 1393 } 1394 1395 /* Perform byte-swapping and intra-item verification on 1396 * annotation_set_ref_list. */ 1397 static void* swapAnnotationSetRefList(const CheckState* state, void* ptr) { 1398 DexAnnotationSetRefList* list = (DexAnnotationSetRefList*) ptr; 1399 DexAnnotationSetRefItem* item; 1400 u4 count; 1401 1402 CHECK_PTR_RANGE(list, list + 1); 1403 SWAP_FIELD4(list->size); 1404 count = list->size; 1405 item = list->list; 1406 1407 const u4 sizeOfItem = (u4) sizeof(DexAnnotationSetRefItem); 1408 CHECK_LIST_SIZE(item, count, sizeOfItem); 1409 1410 while (count--) { 1411 SWAP_OFFSET4(item->annotationsOff); 1412 item++; 1413 } 1414 1415 return item; 1416 } 1417 1418 /* Perform cross-item verification of annotation_set_ref_list. */ 1419 static void* crossVerifyAnnotationSetRefList(const CheckState* state, 1420 void* ptr) { 1421 const DexAnnotationSetRefList* list = (const DexAnnotationSetRefList*) ptr; 1422 const DexAnnotationSetRefItem* item = list->list; 1423 int count = list->size; 1424 1425 while (count--) { 1426 if (!dexDataMapVerify0Ok(state->pDataMap, 1427 item->annotationsOff, kDexTypeAnnotationSetItem)) { 1428 return NULL; 1429 } 1430 item++; 1431 } 1432 1433 return (void*) item; 1434 } 1435 1436 /* Perform byte-swapping and intra-item verification on 1437 * annotation_set_item. */ 1438 static void* swapAnnotationSetItem(const CheckState* state, void* ptr) { 1439 DexAnnotationSetItem* set = (DexAnnotationSetItem*) ptr; 1440 u4* item; 1441 u4 count; 1442 1443 CHECK_PTR_RANGE(set, set + 1); 1444 SWAP_FIELD4(set->size); 1445 count = set->size; 1446 item = set->entries; 1447 1448 const u4 sizeOfItem = (u4) sizeof(u4); 1449 CHECK_LIST_SIZE(item, count, sizeOfItem); 1450 1451 while (count--) { 1452 SWAP_OFFSET4(*item); 1453 item++; 1454 } 1455 1456 return item; 1457 } 1458 1459 /* Helper for crossVerifyAnnotationSetItem(), which extracts the type_idx 1460 * out of an annotation_item. */ 1461 static u4 annotationItemTypeIdx(const DexAnnotationItem* item) { 1462 const u1* data = item->annotation; 1463 return readUnsignedLeb128(&data); 1464 } 1465 1466 /* Perform cross-item verification of annotation_set_item. */ 1467 static void* crossVerifyAnnotationSetItem(const CheckState* state, void* ptr) { 1468 const DexAnnotationSetItem* set = (const DexAnnotationSetItem*) ptr; 1469 int count = set->size; 1470 u4 lastIdx = 0; 1471 bool first = true; 1472 int i; 1473 1474 for (i = 0; i < count; i++) { 1475 if (!dexDataMapVerify0Ok(state->pDataMap, 1476 dexGetAnnotationOff(set, i), kDexTypeAnnotationItem)) { 1477 return NULL; 1478 } 1479 1480 const DexAnnotationItem* annotation = 1481 dexGetAnnotationItem(state->pDexFile, set, i); 1482 u4 idx = annotationItemTypeIdx(annotation); 1483 1484 if (first) { 1485 first = false; 1486 } else if (lastIdx >= idx) { 1487 ALOGE("Out-of-order entry types: %#x then %#x", 1488 lastIdx, idx); 1489 return NULL; 1490 } 1491 1492 lastIdx = idx; 1493 } 1494 1495 return (void*) (set->entries + count); 1496 } 1497 1498 /* Helper for verifyClassDataItem(), which checks a list of fields. */ 1499 static bool verifyFields(const CheckState* state, u4 size, 1500 DexField* fields, bool expectStatic) { 1501 u4 i; 1502 1503 for (i = 0; i < size; i++) { 1504 DexField* field = &fields[i]; 1505 u4 accessFlags = field->accessFlags; 1506 bool isStatic = (accessFlags & ACC_STATIC) != 0; 1507 1508 CHECK_INDEX(field->fieldIdx, state->pHeader->fieldIdsSize); 1509 1510 if (isStatic != expectStatic) { 1511 ALOGE("Field in wrong list @ %d", i); 1512 return false; 1513 } 1514 1515 if ((accessFlags & ~ACC_FIELD_MASK) != 0) { 1516 // The VM specification says that unknown flags should be ignored. 1517 ALOGV("Bogus field access flags %x @ %d", accessFlags, i); 1518 field->accessFlags &= ACC_FIELD_MASK; 1519 } 1520 } 1521 1522 return true; 1523 } 1524 1525 /* Helper for verifyClassDataItem(), which checks a list of methods. */ 1526 static bool verifyMethods(const CheckState* state, u4 size, 1527 DexMethod* methods, bool expectDirect) { 1528 u4 i; 1529 1530 for (i = 0; i < size; i++) { 1531 DexMethod* method = &methods[i]; 1532 1533 CHECK_INDEX(method->methodIdx, state->pHeader->methodIdsSize); 1534 1535 u4 accessFlags = method->accessFlags; 1536 bool isDirect = 1537 (accessFlags & (ACC_STATIC | ACC_PRIVATE | ACC_CONSTRUCTOR)) != 0; 1538 bool expectCode = (accessFlags & (ACC_NATIVE | ACC_ABSTRACT)) == 0; 1539 bool isSynchronized = (accessFlags & ACC_SYNCHRONIZED) != 0; 1540 bool allowSynchronized = (accessFlags & ACC_NATIVE) != 0; 1541 1542 if (isDirect != expectDirect) { 1543 ALOGE("Method in wrong list @ %d", i); 1544 return false; 1545 } 1546 1547 if (isSynchronized && !allowSynchronized) { 1548 ALOGE("Bogus method access flags (synchronization) %x @ %d", accessFlags, i); 1549 return false; 1550 } 1551 1552 if ((accessFlags & ~ACC_METHOD_MASK) != 0) { 1553 // The VM specification says that unknown flags should be ignored. 1554 ALOGV("Bogus method access flags %x @ %d", accessFlags, i); 1555 method->accessFlags &= ACC_METHOD_MASK; 1556 } 1557 1558 if (expectCode) { 1559 if (method->codeOff == 0) { 1560 ALOGE("Unexpected zero code_off for access_flags %x", 1561 accessFlags); 1562 return false; 1563 } 1564 } else if (method->codeOff != 0) { 1565 ALOGE("Unexpected non-zero code_off %#x for access_flags %x", 1566 method->codeOff, accessFlags); 1567 return false; 1568 } 1569 } 1570 1571 return true; 1572 } 1573 1574 /* Helper for verifyClassDataItem(), which does most of the work. */ 1575 static bool verifyClassDataItem0(const CheckState* state, 1576 DexClassData* classData) { 1577 bool okay; 1578 1579 okay = verifyFields(state, classData->header.staticFieldsSize, 1580 classData->staticFields, true); 1581 1582 if (!okay) { 1583 ALOGE("Trouble with static fields"); 1584 return false; 1585 } 1586 1587 verifyFields(state, classData->header.instanceFieldsSize, 1588 classData->instanceFields, false); 1589 1590 if (!okay) { 1591 ALOGE("Trouble with instance fields"); 1592 return false; 1593 } 1594 1595 okay = verifyMethods(state, classData->header.directMethodsSize, 1596 classData->directMethods, true); 1597 1598 if (!okay) { 1599 ALOGE("Trouble with direct methods"); 1600 return false; 1601 } 1602 1603 okay = verifyMethods(state, classData->header.virtualMethodsSize, 1604 classData->virtualMethods, false); 1605 1606 if (!okay) { 1607 ALOGE("Trouble with virtual methods"); 1608 return false; 1609 } 1610 1611 return true; 1612 } 1613 1614 /* Perform intra-item verification on class_data_item. */ 1615 static void* intraVerifyClassDataItem(const CheckState* state, void* ptr) { 1616 const u1* data = (const u1*) ptr; 1617 DexClassData* classData = dexReadAndVerifyClassData(&data, state->fileEnd); 1618 1619 if (classData == NULL) { 1620 ALOGE("Unable to parse class_data_item"); 1621 return NULL; 1622 } 1623 1624 bool okay = verifyClassDataItem0(state, classData); 1625 1626 free(classData); 1627 1628 if (!okay) { 1629 return NULL; 1630 } 1631 1632 return (void*) data; 1633 } 1634 1635 /* Helper for crossVerifyClassDefItem() and 1636 * crossVerifyClassDataItem(), which finds the type_idx of the definer 1637 * of the first item in the data. */ 1638 static u4 findFirstClassDataDefiner(const CheckState* state, 1639 DexClassData* classData) { 1640 if (classData->header.staticFieldsSize != 0) { 1641 u4 fieldIdx = classData->staticFields[0].fieldIdx; 1642 const DexFieldId* field = dexGetFieldId(state->pDexFile, fieldIdx); 1643 return field->classIdx; 1644 } 1645 1646 if (classData->header.instanceFieldsSize != 0) { 1647 u4 fieldIdx = classData->instanceFields[0].fieldIdx; 1648 const DexFieldId* field = dexGetFieldId(state->pDexFile, fieldIdx); 1649 return field->classIdx; 1650 } 1651 1652 if (classData->header.directMethodsSize != 0) { 1653 u4 methodIdx = classData->directMethods[0].methodIdx; 1654 const DexMethodId* meth = dexGetMethodId(state->pDexFile, methodIdx); 1655 return meth->classIdx; 1656 } 1657 1658 if (classData->header.virtualMethodsSize != 0) { 1659 u4 methodIdx = classData->virtualMethods[0].methodIdx; 1660 const DexMethodId* meth = dexGetMethodId(state->pDexFile, methodIdx); 1661 return meth->classIdx; 1662 } 1663 1664 return kDexNoIndex; 1665 } 1666 1667 /* Perform cross-item verification of class_data_item. */ 1668 static void* crossVerifyClassDataItem(const CheckState* state, void* ptr) { 1669 const u1* data = (const u1*) ptr; 1670 DexClassData* classData = dexReadAndVerifyClassData(&data, state->fileEnd); 1671 u4 definingClass = findFirstClassDataDefiner(state, classData); 1672 bool okay = true; 1673 u4 i; 1674 1675 for (i = classData->header.staticFieldsSize; okay && (i > 0); /*i*/) { 1676 i--; 1677 const DexField* field = &classData->staticFields[i]; 1678 okay = verifyFieldDefiner(state, definingClass, field->fieldIdx); 1679 } 1680 1681 for (i = classData->header.instanceFieldsSize; okay && (i > 0); /*i*/) { 1682 i--; 1683 const DexField* field = &classData->instanceFields[i]; 1684 okay = verifyFieldDefiner(state, definingClass, field->fieldIdx); 1685 } 1686 1687 for (i = classData->header.directMethodsSize; okay && (i > 0); /*i*/) { 1688 i--; 1689 const DexMethod* meth = &classData->directMethods[i]; 1690 okay = dexDataMapVerify0Ok(state->pDataMap, meth->codeOff, 1691 kDexTypeCodeItem) 1692 && verifyMethodDefiner(state, definingClass, meth->methodIdx); 1693 } 1694 1695 for (i = classData->header.virtualMethodsSize; okay && (i > 0); /*i*/) { 1696 i--; 1697 const DexMethod* meth = &classData->virtualMethods[i]; 1698 okay = dexDataMapVerify0Ok(state->pDataMap, meth->codeOff, 1699 kDexTypeCodeItem) 1700 && verifyMethodDefiner(state, definingClass, meth->methodIdx); 1701 } 1702 1703 free(classData); 1704 1705 if (!okay) { 1706 return NULL; 1707 } 1708 1709 return (void*) data; 1710 } 1711 1712 /* Helper for swapCodeItem(), which fills an array with all the valid 1713 * handlerOff values for catch handlers and also verifies the handler 1714 * contents. */ 1715 static u4 setHandlerOffsAndVerify(const CheckState* state, 1716 DexCode* code, u4 firstOffset, u4 handlersSize, u4* handlerOffs) { 1717 const u1* fileEnd = state->fileEnd; 1718 const u1* handlersBase = dexGetCatchHandlerData(code); 1719 u4 offset = firstOffset; 1720 bool okay = true; 1721 u4 i; 1722 1723 for (i = 0; i < handlersSize; i++) { 1724 const u1* ptr = handlersBase + offset; 1725 int size = readAndVerifySignedLeb128(&ptr, fileEnd, &okay); 1726 bool catchAll; 1727 1728 if (!okay) { 1729 ALOGE("Bogus size"); 1730 return 0; 1731 } 1732 1733 if ((size < -65536) || (size > 65536)) { 1734 ALOGE("Invalid size: %d", size); 1735 return 0; 1736 } 1737 1738 if (size <= 0) { 1739 catchAll = true; 1740 size = -size; 1741 } else { 1742 catchAll = false; 1743 } 1744 1745 handlerOffs[i] = offset; 1746 1747 while (size-- > 0) { 1748 u4 typeIdx = 1749 readAndVerifyUnsignedLeb128(&ptr, fileEnd, &okay); 1750 1751 if (!okay) { 1752 ALOGE("Bogus type_idx"); 1753 return 0; 1754 } 1755 1756 CHECK_INDEX(typeIdx, state->pHeader->typeIdsSize); 1757 1758 u4 addr = readAndVerifyUnsignedLeb128(&ptr, fileEnd, &okay); 1759 1760 if (!okay) { 1761 ALOGE("Bogus addr"); 1762 return 0; 1763 } 1764 1765 if (addr >= code->insnsSize) { 1766 ALOGE("Invalid addr: %#x", addr); 1767 return 0; 1768 } 1769 } 1770 1771 if (catchAll) { 1772 u4 addr = readAndVerifyUnsignedLeb128(&ptr, fileEnd, &okay); 1773 1774 if (!okay) { 1775 ALOGE("Bogus catch_all_addr"); 1776 return 0; 1777 } 1778 1779 if (addr >= code->insnsSize) { 1780 ALOGE("Invalid catch_all_addr: %#x", addr); 1781 return 0; 1782 } 1783 } 1784 1785 offset = ptr - handlersBase; 1786 } 1787 1788 return offset; 1789 } 1790 1791 /* Helper for swapCodeItem(), which does all the try-catch related 1792 * swapping and verification. */ 1793 static void* swapTriesAndCatches(const CheckState* state, DexCode* code) { 1794 const u1* encodedHandlers = dexGetCatchHandlerData(code); 1795 const u1* encodedPtr = encodedHandlers; 1796 bool okay = true; 1797 u4 handlersSize = 1798 readAndVerifyUnsignedLeb128(&encodedPtr, state->fileEnd, &okay); 1799 1800 if (!okay) { 1801 ALOGE("Bogus handlers_size"); 1802 return NULL; 1803 } 1804 1805 if ((handlersSize == 0) || (handlersSize >= 65536)) { 1806 ALOGE("Invalid handlers_size: %d", handlersSize); 1807 return NULL; 1808 } 1809 1810 u4 handlerOffs[handlersSize]; // list of valid handlerOff values 1811 u4 endOffset = setHandlerOffsAndVerify(state, code, 1812 encodedPtr - encodedHandlers, 1813 handlersSize, handlerOffs); 1814 1815 if (endOffset == 0) { 1816 return NULL; 1817 } 1818 1819 DexTry* tries = (DexTry*) dexGetTries(code); 1820 u4 count = code->triesSize; 1821 u4 lastEnd = 0; 1822 1823 const u4 sizeOfItem = (u4) sizeof(DexTry); 1824 CHECK_LIST_SIZE(tries, count, sizeOfItem); 1825 1826 while (count--) { 1827 u4 i; 1828 1829 SWAP_FIELD4(tries->startAddr); 1830 SWAP_FIELD2(tries->insnCount); 1831 SWAP_FIELD2(tries->handlerOff); 1832 1833 if (tries->startAddr < lastEnd) { 1834 ALOGE("Out-of-order try"); 1835 return NULL; 1836 } 1837 1838 if (tries->startAddr >= code->insnsSize) { 1839 ALOGE("Invalid start_addr: %#x", tries->startAddr); 1840 return NULL; 1841 } 1842 1843 for (i = 0; i < handlersSize; i++) { 1844 if (tries->handlerOff == handlerOffs[i]) { 1845 break; 1846 } 1847 } 1848 1849 if (i == handlersSize) { 1850 ALOGE("Bogus handler offset: %#x", tries->handlerOff); 1851 return NULL; 1852 } 1853 1854 lastEnd = tries->startAddr + tries->insnCount; 1855 1856 if (lastEnd > code->insnsSize) { 1857 ALOGE("Invalid insn_count: %#x (end addr %#x)", 1858 tries->insnCount, lastEnd); 1859 return NULL; 1860 } 1861 1862 tries++; 1863 } 1864 1865 return (u1*) encodedHandlers + endOffset; 1866 } 1867 1868 /* Perform byte-swapping and intra-item verification on code_item. */ 1869 static void* swapCodeItem(const CheckState* state, void* ptr) { 1870 DexCode* item = (DexCode*) ptr; 1871 u2* insns; 1872 u4 count; 1873 1874 CHECK_PTR_RANGE(item, item + 1); 1875 SWAP_FIELD2(item->registersSize); 1876 SWAP_FIELD2(item->insSize); 1877 SWAP_FIELD2(item->outsSize); 1878 SWAP_FIELD2(item->triesSize); 1879 SWAP_OFFSET4(item->debugInfoOff); 1880 SWAP_FIELD4(item->insnsSize); 1881 1882 if (item->insSize > item->registersSize) { 1883 ALOGE("insSize (%u) > registersSize (%u)", item->insSize, 1884 item->registersSize); 1885 return NULL; 1886 } 1887 1888 if ((item->outsSize > 5) && (item->outsSize > item->registersSize)) { 1889 /* 1890 * It's okay for outsSize to be up to five, even if registersSize 1891 * is smaller, since the short forms of method invocation allow 1892 * repetition of a register multiple times within a single parameter 1893 * list. Longer parameter lists, though, need to be represented 1894 * in-order in the register file. 1895 */ 1896 ALOGE("outsSize (%u) > registersSize (%u)", item->outsSize, 1897 item->registersSize); 1898 return NULL; 1899 } 1900 1901 count = item->insnsSize; 1902 insns = item->insns; 1903 1904 const u4 sizeOfItem = (u4) sizeof(u2); 1905 CHECK_LIST_SIZE(insns, count, sizeOfItem); 1906 1907 while (count--) { 1908 *insns = SWAP2(*insns); 1909 insns++; 1910 } 1911 1912 if (item->triesSize == 0) { 1913 ptr = insns; 1914 } else { 1915 if ((((uintptr_t) insns) & 3) != 0) { 1916 // Four-byte alignment for the tries. Verify the spacer is a 0. 1917 if (*insns != 0) { 1918 ALOGE("Non-zero padding: %#x", (u4) *insns); 1919 return NULL; 1920 } 1921 } 1922 1923 ptr = swapTriesAndCatches(state, item); 1924 } 1925 1926 return ptr; 1927 } 1928 1929 /* Perform intra-item verification on string_data_item. */ 1930 static void* intraVerifyStringDataItem(const CheckState* state, void* ptr) { 1931 const u1* fileEnd = state->fileEnd; 1932 const u1* data = (const u1*) ptr; 1933 bool okay = true; 1934 u4 utf16Size = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 1935 u4 i; 1936 1937 if (!okay) { 1938 ALOGE("Bogus utf16_size"); 1939 return NULL; 1940 } 1941 1942 for (i = 0; i < utf16Size; i++) { 1943 if (data >= fileEnd) { 1944 ALOGE("String data would go beyond end-of-file"); 1945 return NULL; 1946 } 1947 1948 u1 byte1 = *(data++); 1949 1950 // Switch on the high four bits. 1951 switch (byte1 >> 4) { 1952 case 0x00: { 1953 // Special case of bit pattern 0xxx. 1954 if (byte1 == 0) { 1955 ALOGE("String shorter than indicated utf16_size %#x", 1956 utf16Size); 1957 return NULL; 1958 } 1959 break; 1960 } 1961 case 0x01: 1962 case 0x02: 1963 case 0x03: 1964 case 0x04: 1965 case 0x05: 1966 case 0x06: 1967 case 0x07: { 1968 // Bit pattern 0xxx. No need for any extra bytes or checks. 1969 break; 1970 } 1971 case 0x08: 1972 case 0x09: 1973 case 0x0a: 1974 case 0x0b: 1975 case 0x0f: { 1976 /* 1977 * Bit pattern 10xx or 1111, which are illegal start bytes. 1978 * Note: 1111 is valid for normal UTF-8, but not the 1979 * modified UTF-8 used here. 1980 */ 1981 ALOGE("Illegal start byte %#x", byte1); 1982 return NULL; 1983 } 1984 case 0x0e: { 1985 // Bit pattern 1110, so there are two additional bytes. 1986 u1 byte2 = *(data++); 1987 if ((byte2 & 0xc0) != 0x80) { 1988 ALOGE("Illegal continuation byte %#x", byte2); 1989 return NULL; 1990 } 1991 u1 byte3 = *(data++); 1992 if ((byte3 & 0xc0) != 0x80) { 1993 ALOGE("Illegal continuation byte %#x", byte3); 1994 return NULL; 1995 } 1996 u2 value = ((byte1 & 0x0f) << 12) | ((byte2 & 0x3f) << 6) 1997 | (byte3 & 0x3f); 1998 if (value < 0x800) { 1999 ALOGE("Illegal representation for value %x", value); 2000 return NULL; 2001 } 2002 break; 2003 } 2004 case 0x0c: 2005 case 0x0d: { 2006 // Bit pattern 110x, so there is one additional byte. 2007 u1 byte2 = *(data++); 2008 if ((byte2 & 0xc0) != 0x80) { 2009 ALOGE("Illegal continuation byte %#x", byte2); 2010 return NULL; 2011 } 2012 u2 value = ((byte1 & 0x1f) << 6) | (byte2 & 0x3f); 2013 if ((value != 0) && (value < 0x80)) { 2014 ALOGE("Illegal representation for value %x", value); 2015 return NULL; 2016 } 2017 break; 2018 } 2019 } 2020 } 2021 2022 if (*(data++) != '\0') { 2023 ALOGE("String longer than indicated utf16_size %#x", utf16Size); 2024 return NULL; 2025 } 2026 2027 return (void*) data; 2028 } 2029 2030 /* Perform intra-item verification on debug_info_item. */ 2031 static void* intraVerifyDebugInfoItem(const CheckState* state, void* ptr) { 2032 const u1* fileEnd = state->fileEnd; 2033 const u1* data = (const u1*) ptr; 2034 bool okay = true; 2035 u4 i; 2036 2037 readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 2038 2039 if (!okay) { 2040 ALOGE("Bogus line_start"); 2041 return NULL; 2042 } 2043 2044 u4 parametersSize = 2045 readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 2046 2047 if (!okay) { 2048 ALOGE("Bogus parameters_size"); 2049 return NULL; 2050 } 2051 2052 if (parametersSize > 65536) { 2053 ALOGE("Invalid parameters_size: %#x", parametersSize); 2054 return NULL; 2055 } 2056 2057 for (i = 0; i < parametersSize; i++) { 2058 u4 parameterName = 2059 readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 2060 2061 if (!okay) { 2062 ALOGE("Bogus parameter_name"); 2063 return NULL; 2064 } 2065 2066 if (parameterName != 0) { 2067 parameterName--; 2068 CHECK_INDEX(parameterName, state->pHeader->stringIdsSize); 2069 } 2070 } 2071 2072 bool done = false; 2073 while (!done) { 2074 u1 opcode = *(data++); 2075 2076 switch (opcode) { 2077 case DBG_END_SEQUENCE: { 2078 done = true; 2079 break; 2080 } 2081 case DBG_ADVANCE_PC: { 2082 readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 2083 break; 2084 } 2085 case DBG_ADVANCE_LINE: { 2086 readAndVerifySignedLeb128(&data, fileEnd, &okay); 2087 break; 2088 } 2089 case DBG_START_LOCAL: { 2090 u4 idx; 2091 u4 regNum = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 2092 if (!okay) break; 2093 if (regNum >= 65536) { 2094 okay = false; 2095 break; 2096 } 2097 idx = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 2098 if (!okay) break; 2099 if (idx != 0) { 2100 idx--; 2101 CHECK_INDEX(idx, state->pHeader->stringIdsSize); 2102 } 2103 idx = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 2104 if (!okay) break; 2105 if (idx != 0) { 2106 idx--; 2107 CHECK_INDEX(idx, state->pHeader->stringIdsSize); 2108 } 2109 break; 2110 } 2111 case DBG_END_LOCAL: 2112 case DBG_RESTART_LOCAL: { 2113 u4 regNum = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 2114 if (!okay) break; 2115 if (regNum >= 65536) { 2116 okay = false; 2117 break; 2118 } 2119 break; 2120 } 2121 case DBG_START_LOCAL_EXTENDED: { 2122 u4 idx; 2123 u4 regNum = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 2124 if (!okay) break; 2125 if (regNum >= 65536) { 2126 okay = false; 2127 break; 2128 } 2129 idx = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 2130 if (!okay) break; 2131 if (idx != 0) { 2132 idx--; 2133 CHECK_INDEX(idx, state->pHeader->stringIdsSize); 2134 } 2135 idx = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 2136 if (!okay) break; 2137 if (idx != 0) { 2138 idx--; 2139 CHECK_INDEX(idx, state->pHeader->stringIdsSize); 2140 } 2141 idx = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 2142 if (!okay) break; 2143 if (idx != 0) { 2144 idx--; 2145 CHECK_INDEX(idx, state->pHeader->stringIdsSize); 2146 } 2147 break; 2148 } 2149 case DBG_SET_FILE: { 2150 u4 idx = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 2151 if (!okay) break; 2152 if (idx != 0) { 2153 idx--; 2154 CHECK_INDEX(idx, state->pHeader->stringIdsSize); 2155 } 2156 break; 2157 } 2158 default: { 2159 // No arguments to parse for anything else. 2160 } 2161 } 2162 2163 if (!okay) { 2164 ALOGE("Bogus syntax for opcode %02x", opcode); 2165 return NULL; 2166 } 2167 } 2168 2169 return (void*) data; 2170 } 2171 2172 /* defined below */ 2173 static const u1* verifyEncodedValue(const CheckState* state, const u1* data, 2174 bool crossVerify); 2175 static const u1* verifyEncodedAnnotation(const CheckState* state, 2176 const u1* data, bool crossVerify); 2177 2178 /* Helper for verifyEncodedValue(), which reads a 1- to 4- byte unsigned 2179 * little endian value. */ 2180 static u4 readUnsignedLittleEndian(const CheckState* state, const u1** pData, 2181 u4 size) { 2182 const u1* data = *pData; 2183 u4 result = 0; 2184 u4 i; 2185 2186 CHECK_PTR_RANGE(data, data + size); 2187 2188 for (i = 0; i < size; i++) { 2189 result |= ((u4) *(data++)) << (i * 8); 2190 } 2191 2192 *pData = data; 2193 return result; 2194 } 2195 2196 /* Helper for *VerifyAnnotationItem() and *VerifyEncodedArrayItem(), which 2197 * verifies an encoded_array. */ 2198 static const u1* verifyEncodedArray(const CheckState* state, 2199 const u1* data, bool crossVerify) { 2200 bool okay = true; 2201 u4 size = readAndVerifyUnsignedLeb128(&data, state->fileEnd, &okay); 2202 2203 if (!okay) { 2204 ALOGE("Bogus encoded_array size"); 2205 return NULL; 2206 } 2207 2208 while (size--) { 2209 data = verifyEncodedValue(state, data, crossVerify); 2210 if (data == NULL) { 2211 ALOGE("Bogus encoded_array value"); 2212 return NULL; 2213 } 2214 } 2215 2216 return data; 2217 } 2218 2219 static u4 numberOfMethodHandles(const CheckState* state) { 2220 if (state->pMethodHandleItems != nullptr) { 2221 return state->pMethodHandleItems->size; 2222 } 2223 return 0; 2224 } 2225 2226 /* Helper for *VerifyAnnotationItem() and *VerifyEncodedArrayItem(), which 2227 * verifies an encoded_value. */ 2228 static const u1* verifyEncodedValue(const CheckState* state, 2229 const u1* data, bool crossVerify) { 2230 CHECK_PTR_RANGE(data, data + 1); 2231 2232 u1 headerByte = *(data++); 2233 u4 valueType = headerByte & kDexAnnotationValueTypeMask; 2234 u4 valueArg = headerByte >> kDexAnnotationValueArgShift; 2235 2236 switch (valueType) { 2237 case kDexAnnotationByte: { 2238 if (valueArg != 0) { 2239 ALOGE("Bogus byte size %#x", valueArg); 2240 return NULL; 2241 } 2242 data++; 2243 break; 2244 } 2245 case kDexAnnotationShort: 2246 case kDexAnnotationChar: { 2247 if (valueArg > 1) { 2248 ALOGE("Bogus char/short size %#x", valueArg); 2249 return NULL; 2250 } 2251 data += valueArg + 1; 2252 break; 2253 } 2254 case kDexAnnotationInt: 2255 case kDexAnnotationFloat: { 2256 if (valueArg > 3) { 2257 ALOGE("Bogus int/float size %#x", valueArg); 2258 return NULL; 2259 } 2260 data += valueArg + 1; 2261 break; 2262 } 2263 case kDexAnnotationLong: 2264 case kDexAnnotationDouble: { 2265 data += valueArg + 1; 2266 break; 2267 } 2268 case kDexAnnotationMethodType: { 2269 if (valueArg > 3) { 2270 ALOGE("Bogus method type size %#x", valueArg); 2271 return NULL; 2272 } 2273 u4 idx = readUnsignedLittleEndian(state, &data, valueArg + 1); 2274 CHECK_INDEX(idx, state->pHeader->protoIdsSize); 2275 break; 2276 } 2277 case kDexAnnotationMethodHandle: { 2278 if (valueArg > 3) { 2279 ALOGE("Bogus method type size %#x", valueArg); 2280 return NULL; 2281 } 2282 u4 idx = readUnsignedLittleEndian(state, &data, valueArg + 1); 2283 CHECK_INDEX(idx, numberOfMethodHandles(state)); 2284 break; 2285 } 2286 case kDexAnnotationString: { 2287 if (valueArg > 3) { 2288 ALOGE("Bogus string size %#x", valueArg); 2289 return NULL; 2290 } 2291 u4 idx = readUnsignedLittleEndian(state, &data, valueArg + 1); 2292 CHECK_INDEX(idx, state->pHeader->stringIdsSize); 2293 break; 2294 } 2295 case kDexAnnotationType: { 2296 if (valueArg > 3) { 2297 ALOGE("Bogus type size %#x", valueArg); 2298 return NULL; 2299 } 2300 u4 idx = readUnsignedLittleEndian(state, &data, valueArg + 1); 2301 CHECK_INDEX(idx, state->pHeader->typeIdsSize); 2302 break; 2303 } 2304 case kDexAnnotationField: 2305 case kDexAnnotationEnum: { 2306 if (valueArg > 3) { 2307 ALOGE("Bogus field/enum size %#x", valueArg); 2308 return NULL; 2309 } 2310 u4 idx = readUnsignedLittleEndian(state, &data, valueArg + 1); 2311 CHECK_INDEX(idx, state->pHeader->fieldIdsSize); 2312 break; 2313 } 2314 case kDexAnnotationMethod: { 2315 if (valueArg > 3) { 2316 ALOGE("Bogus method size %#x", valueArg); 2317 return NULL; 2318 } 2319 u4 idx = readUnsignedLittleEndian(state, &data, valueArg + 1); 2320 CHECK_INDEX(idx, state->pHeader->methodIdsSize); 2321 break; 2322 } 2323 case kDexAnnotationArray: { 2324 if (valueArg != 0) { 2325 ALOGE("Bogus array value_arg %#x", valueArg); 2326 return NULL; 2327 } 2328 data = verifyEncodedArray(state, data, crossVerify); 2329 break; 2330 } 2331 case kDexAnnotationAnnotation: { 2332 if (valueArg != 0) { 2333 ALOGE("Bogus annotation value_arg %#x", valueArg); 2334 return NULL; 2335 } 2336 data = verifyEncodedAnnotation(state, data, crossVerify); 2337 break; 2338 } 2339 case kDexAnnotationNull: { 2340 if (valueArg != 0) { 2341 ALOGE("Bogus null value_arg %#x", valueArg); 2342 return NULL; 2343 } 2344 // Nothing else to do for this type. 2345 break; 2346 } 2347 case kDexAnnotationBoolean: { 2348 if (valueArg > 1) { 2349 ALOGE("Bogus boolean value_arg %#x", valueArg); 2350 return NULL; 2351 } 2352 // Nothing else to do for this type. 2353 break; 2354 } 2355 default: { 2356 ALOGE("Bogus value_type %#x", valueType); 2357 return NULL; 2358 } 2359 } 2360 2361 return data; 2362 } 2363 2364 /* Helper for *VerifyAnnotationItem() and *VerifyEncodedArrayItem(), which 2365 * verifies an encoded_annotation. */ 2366 static const u1* verifyEncodedAnnotation(const CheckState* state, 2367 const u1* data, bool crossVerify) { 2368 const u1* fileEnd = state->fileEnd; 2369 bool okay = true; 2370 u4 idx = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 2371 2372 if (!okay) { 2373 ALOGE("Bogus encoded_annotation type_idx"); 2374 return NULL; 2375 } 2376 2377 CHECK_INDEX(idx, state->pHeader->typeIdsSize); 2378 2379 if (crossVerify) { 2380 const char* descriptor = dexStringByTypeIdx(state->pDexFile, idx); 2381 if (!dexIsClassDescriptor(descriptor)) { 2382 ALOGE("Bogus annotation type: '%s'", descriptor); 2383 return NULL; 2384 } 2385 } 2386 2387 u4 size = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 2388 u4 lastIdx = 0; 2389 bool first = true; 2390 2391 if (!okay) { 2392 ALOGE("Bogus encoded_annotation size"); 2393 return NULL; 2394 } 2395 2396 while (size--) { 2397 idx = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 2398 2399 if (!okay) { 2400 ALOGE("Bogus encoded_annotation name_idx"); 2401 return NULL; 2402 } 2403 2404 CHECK_INDEX(idx, state->pHeader->stringIdsSize); 2405 2406 if (crossVerify) { 2407 const char* name = dexStringById(state->pDexFile, idx); 2408 if (!dexIsValidMemberName(name)) { 2409 ALOGE("Bogus annotation member name: '%s'", name); 2410 return NULL; 2411 } 2412 } 2413 2414 if (first) { 2415 first = false; 2416 } else if (lastIdx >= idx) { 2417 ALOGE("Out-of-order encoded_annotation name_idx: %#x then %#x", 2418 lastIdx, idx); 2419 return NULL; 2420 } 2421 2422 data = verifyEncodedValue(state, data, crossVerify); 2423 lastIdx = idx; 2424 2425 if (data == NULL) { 2426 return NULL; 2427 } 2428 } 2429 2430 return data; 2431 } 2432 2433 /* Perform intra-item verification on encoded_array_item. */ 2434 static void* intraVerifyEncodedArrayItem(const CheckState* state, void* ptr) { 2435 return (void*) verifyEncodedArray(state, (const u1*) ptr, false); 2436 } 2437 2438 /* Perform intra-item verification on annotation_item. */ 2439 static void* intraVerifyAnnotationItem(const CheckState* state, void* ptr) { 2440 const u1* data = (const u1*) ptr; 2441 2442 CHECK_PTR_RANGE(data, data + 1); 2443 2444 switch (*(data++)) { 2445 case kDexVisibilityBuild: 2446 case kDexVisibilityRuntime: 2447 case kDexVisibilitySystem: { 2448 break; 2449 } 2450 default: { 2451 ALOGE("Bogus annotation visibility: %#x", *data); 2452 return NULL; 2453 } 2454 } 2455 2456 return (void*) verifyEncodedAnnotation(state, data, false); 2457 } 2458 2459 /* Perform cross-item verification on annotation_item. */ 2460 static void* crossVerifyAnnotationItem(const CheckState* state, void* ptr) { 2461 const u1* data = (const u1*) ptr; 2462 2463 // Skip the visibility byte. 2464 data++; 2465 2466 return (void*) verifyEncodedAnnotation(state, data, true); 2467 } 2468 2469 2470 2471 2472 /* 2473 * Function to visit an individual top-level item type. 2474 */ 2475 typedef void* ItemVisitorFunction(const CheckState* state, void* ptr); 2476 2477 /* 2478 * Iterate over all the items in a section, optionally updating the 2479 * data map (done if mapType is passed as non-negative). The section 2480 * must consist of concatenated items of the same type. 2481 */ 2482 static bool iterateSectionWithOptionalUpdate(CheckState* state, 2483 u4 offset, u4 count, ItemVisitorFunction* func, u4 alignment, 2484 u4* nextOffset, int mapType) { 2485 u4 alignmentMask = alignment - 1; 2486 u4 i; 2487 2488 state->previousItem = NULL; 2489 2490 for (i = 0; i < count; i++) { 2491 u4 newOffset = (offset + alignmentMask) & ~alignmentMask; 2492 u1* ptr = (u1*) filePointer(state, newOffset); 2493 2494 if (offset < newOffset) { 2495 ptr = (u1*) filePointer(state, offset); 2496 if (offset < newOffset) { 2497 CHECK_OFFSET_RANGE(offset, newOffset); 2498 while (offset < newOffset) { 2499 if (*ptr != '\0') { 2500 ALOGE("Non-zero padding 0x%02x @ %x", *ptr, offset); 2501 return false; 2502 } 2503 ptr++; 2504 offset++; 2505 } 2506 } 2507 } 2508 2509 u1* newPtr = (u1*) func(state, ptr); 2510 newOffset = fileOffset(state, newPtr); 2511 2512 if (newPtr == NULL) { 2513 ALOGE("Trouble with item %d @ offset %#x", i, offset); 2514 return false; 2515 } 2516 2517 if (newOffset > state->fileLen) { 2518 ALOGE("Item %d @ offset %#x ends out of bounds", i, offset); 2519 return false; 2520 } 2521 2522 if (mapType >= 0) { 2523 dexDataMapAdd(state->pDataMap, offset, mapType); 2524 } 2525 2526 state->previousItem = ptr; 2527 offset = newOffset; 2528 } 2529 2530 if (nextOffset != NULL) { 2531 *nextOffset = offset; 2532 } 2533 2534 return true; 2535 } 2536 2537 /* 2538 * Iterate over all the items in a section. The section must consist of 2539 * concatenated items of the same type. This variant will not update the data 2540 * map. 2541 */ 2542 static bool iterateSection(CheckState* state, u4 offset, u4 count, 2543 ItemVisitorFunction* func, u4 alignment, u4* nextOffset) { 2544 return iterateSectionWithOptionalUpdate(state, offset, count, func, 2545 alignment, nextOffset, -1); 2546 } 2547 2548 /* 2549 * Like iterateSection(), but also check that the offset and count match 2550 * a given pair of expected values. 2551 */ 2552 static bool checkBoundsAndIterateSection(CheckState* state, 2553 u4 offset, u4 count, u4 expectedOffset, u4 expectedCount, 2554 ItemVisitorFunction* func, u4 alignment, u4* nextOffset) { 2555 if (offset != expectedOffset) { 2556 ALOGE("Bogus offset for section: got %#x; expected %#x", 2557 offset, expectedOffset); 2558 return false; 2559 } 2560 2561 if (count != expectedCount) { 2562 ALOGE("Bogus size for section: got %#x; expected %#x", 2563 count, expectedCount); 2564 return false; 2565 } 2566 2567 return iterateSection(state, offset, count, func, alignment, nextOffset); 2568 } 2569 2570 /* 2571 * Like iterateSection(), but also update the data section map and 2572 * check that all the items fall within the data section. 2573 */ 2574 static bool iterateDataSection(CheckState* state, u4 offset, u4 count, 2575 ItemVisitorFunction* func, u4 alignment, u4* nextOffset, int mapType) { 2576 u4 dataStart = state->pHeader->dataOff; 2577 u4 dataEnd = dataStart + state->pHeader->dataSize; 2578 2579 assert(nextOffset != NULL); 2580 2581 if ((offset < dataStart) || (offset >= dataEnd)) { 2582 ALOGE("Bogus offset for data subsection: %#x", offset); 2583 return false; 2584 } 2585 2586 if (!iterateSectionWithOptionalUpdate(state, offset, count, func, 2587 alignment, nextOffset, mapType)) { 2588 return false; 2589 } 2590 2591 if (*nextOffset > dataEnd) { 2592 ALOGE("Out-of-bounds end of data subsection: %#x", *nextOffset); 2593 return false; 2594 } 2595 2596 return true; 2597 } 2598 2599 /* 2600 * Byte-swap all items in the given map except the header and the map 2601 * itself, both of which should have already gotten swapped. This also 2602 * does all possible intra-item verification, that is, verification 2603 * that doesn't need to assume the sanctity of the contents of *other* 2604 * items. The intra-item limitation is because at the time an item is 2605 * asked to verify itself, it can't assume that the items it refers to 2606 * have been byte-swapped and verified. 2607 */ 2608 static bool swapEverythingButHeaderAndMap(CheckState* state, 2609 DexMapList* pMap) { 2610 const DexMapItem* item = pMap->list; 2611 u4 lastOffset = 0; 2612 u4 count = pMap->size; 2613 bool okay = true; 2614 2615 while (okay && count--) { 2616 u4 sectionOffset = item->offset; 2617 u4 sectionCount = item->size; 2618 u2 type = item->type; 2619 2620 if (lastOffset < sectionOffset) { 2621 CHECK_OFFSET_RANGE(lastOffset, sectionOffset); 2622 const u1* ptr = (const u1*) filePointer(state, lastOffset); 2623 while (lastOffset < sectionOffset) { 2624 if (*ptr != '\0') { 2625 ALOGE("Non-zero padding 0x%02x before section start @ %x", 2626 *ptr, lastOffset); 2627 okay = false; 2628 break; 2629 } 2630 ptr++; 2631 lastOffset++; 2632 } 2633 } else if (lastOffset > sectionOffset) { 2634 ALOGE("Section overlap or out-of-order map: %x, %x", 2635 lastOffset, sectionOffset); 2636 okay = false; 2637 } 2638 2639 if (!okay) { 2640 break; 2641 } 2642 2643 switch (type) { 2644 case kDexTypeHeaderItem: { 2645 /* 2646 * The header got swapped very early on, but do some 2647 * additional sanity checking here. 2648 */ 2649 okay = checkHeaderSection(state, sectionOffset, sectionCount, 2650 &lastOffset); 2651 break; 2652 } 2653 case kDexTypeStringIdItem: { 2654 okay = checkBoundsAndIterateSection(state, sectionOffset, 2655 sectionCount, state->pHeader->stringIdsOff, 2656 state->pHeader->stringIdsSize, swapStringIdItem, 2657 sizeof(u4), &lastOffset); 2658 break; 2659 } 2660 case kDexTypeTypeIdItem: { 2661 okay = checkBoundsAndIterateSection(state, sectionOffset, 2662 sectionCount, state->pHeader->typeIdsOff, 2663 state->pHeader->typeIdsSize, swapTypeIdItem, 2664 sizeof(u4), &lastOffset); 2665 break; 2666 } 2667 case kDexTypeProtoIdItem: { 2668 okay = checkBoundsAndIterateSection(state, sectionOffset, 2669 sectionCount, state->pHeader->protoIdsOff, 2670 state->pHeader->protoIdsSize, swapProtoIdItem, 2671 sizeof(u4), &lastOffset); 2672 break; 2673 } 2674 case kDexTypeFieldIdItem: { 2675 okay = checkBoundsAndIterateSection(state, sectionOffset, 2676 sectionCount, state->pHeader->fieldIdsOff, 2677 state->pHeader->fieldIdsSize, swapFieldIdItem, 2678 sizeof(u4), &lastOffset); 2679 break; 2680 } 2681 case kDexTypeMethodIdItem: { 2682 okay = checkBoundsAndIterateSection(state, sectionOffset, 2683 sectionCount, state->pHeader->methodIdsOff, 2684 state->pHeader->methodIdsSize, swapMethodIdItem, 2685 sizeof(u4), &lastOffset); 2686 break; 2687 } 2688 case kDexTypeClassDefItem: { 2689 okay = checkBoundsAndIterateSection(state, sectionOffset, 2690 sectionCount, state->pHeader->classDefsOff, 2691 state->pHeader->classDefsSize, swapClassDefItem, 2692 sizeof(u4), &lastOffset); 2693 break; 2694 } 2695 case kDexTypeCallSiteIdItem: { 2696 okay = checkBoundsAndIterateSection(state, sectionOffset, 2697 sectionCount, sectionOffset, sectionCount, 2698 swapCallSiteId, sizeof(u4), &lastOffset); 2699 break; 2700 } 2701 case kDexTypeMethodHandleItem: { 2702 okay = checkBoundsAndIterateSection(state, sectionOffset, 2703 sectionCount, sectionOffset, sectionCount, 2704 swapMethodHandleItem, sizeof(u4), &lastOffset); 2705 break; 2706 } 2707 case kDexTypeMapList: { 2708 /* 2709 * The map section was swapped early on, but do some 2710 * additional sanity checking here. 2711 */ 2712 okay = checkMapSection(state, sectionOffset, sectionCount, 2713 &lastOffset); 2714 break; 2715 } 2716 case kDexTypeTypeList: { 2717 okay = iterateDataSection(state, sectionOffset, sectionCount, 2718 swapTypeList, sizeof(u4), &lastOffset, type); 2719 break; 2720 } 2721 case kDexTypeAnnotationSetRefList: { 2722 okay = iterateDataSection(state, sectionOffset, sectionCount, 2723 swapAnnotationSetRefList, sizeof(u4), &lastOffset, 2724 type); 2725 break; 2726 } 2727 case kDexTypeAnnotationSetItem: { 2728 okay = iterateDataSection(state, sectionOffset, sectionCount, 2729 swapAnnotationSetItem, sizeof(u4), &lastOffset, type); 2730 break; 2731 } 2732 case kDexTypeClassDataItem: { 2733 okay = iterateDataSection(state, sectionOffset, sectionCount, 2734 intraVerifyClassDataItem, sizeof(u1), &lastOffset, 2735 type); 2736 break; 2737 } 2738 case kDexTypeCodeItem: { 2739 okay = iterateDataSection(state, sectionOffset, sectionCount, 2740 swapCodeItem, sizeof(u4), &lastOffset, type); 2741 break; 2742 } 2743 case kDexTypeStringDataItem: { 2744 okay = iterateDataSection(state, sectionOffset, sectionCount, 2745 intraVerifyStringDataItem, sizeof(u1), &lastOffset, 2746 type); 2747 break; 2748 } 2749 case kDexTypeDebugInfoItem: { 2750 okay = iterateDataSection(state, sectionOffset, sectionCount, 2751 intraVerifyDebugInfoItem, sizeof(u1), &lastOffset, 2752 type); 2753 break; 2754 } 2755 case kDexTypeAnnotationItem: { 2756 okay = iterateDataSection(state, sectionOffset, sectionCount, 2757 intraVerifyAnnotationItem, sizeof(u1), &lastOffset, 2758 type); 2759 break; 2760 } 2761 case kDexTypeEncodedArrayItem: { 2762 okay = iterateDataSection(state, sectionOffset, sectionCount, 2763 intraVerifyEncodedArrayItem, sizeof(u1), &lastOffset, 2764 type); 2765 break; 2766 } 2767 case kDexTypeAnnotationsDirectoryItem: { 2768 okay = iterateDataSection(state, sectionOffset, sectionCount, 2769 swapAnnotationsDirectoryItem, sizeof(u4), &lastOffset, 2770 type); 2771 break; 2772 } 2773 default: { 2774 ALOGE("Unknown map item type %04x", type); 2775 return false; 2776 } 2777 } 2778 2779 if (!okay) { 2780 ALOGE("Swap of section type %04x failed", type); 2781 } 2782 2783 item++; 2784 } 2785 2786 return okay; 2787 } 2788 2789 /* 2790 * Perform cross-item verification on everything that needs it. This 2791 * pass is only called after all items are byte-swapped and 2792 * intra-verified (checked for internal consistency). 2793 */ 2794 static bool crossVerifyEverything(CheckState* state, DexMapList* pMap) 2795 { 2796 const DexMapItem* item = pMap->list; 2797 u4 count = pMap->size; 2798 bool okay = true; 2799 2800 while (okay && count--) { 2801 u4 sectionOffset = item->offset; 2802 u4 sectionCount = item->size; 2803 2804 switch (item->type) { 2805 case kDexTypeHeaderItem: 2806 case kDexTypeMapList: 2807 case kDexTypeTypeList: 2808 case kDexTypeCodeItem: 2809 case kDexTypeStringDataItem: 2810 case kDexTypeDebugInfoItem: 2811 case kDexTypeAnnotationItem: 2812 case kDexTypeEncodedArrayItem: { 2813 // There is no need for cross-item verification for these. 2814 break; 2815 } 2816 case kDexTypeStringIdItem: { 2817 okay = iterateSection(state, sectionOffset, sectionCount, 2818 crossVerifyStringIdItem, sizeof(u4), NULL); 2819 break; 2820 } 2821 case kDexTypeTypeIdItem: { 2822 okay = iterateSection(state, sectionOffset, sectionCount, 2823 crossVerifyTypeIdItem, sizeof(u4), NULL); 2824 break; 2825 } 2826 case kDexTypeProtoIdItem: { 2827 okay = iterateSection(state, sectionOffset, sectionCount, 2828 crossVerifyProtoIdItem, sizeof(u4), NULL); 2829 break; 2830 } 2831 case kDexTypeFieldIdItem: { 2832 okay = iterateSection(state, sectionOffset, sectionCount, 2833 crossVerifyFieldIdItem, sizeof(u4), NULL); 2834 break; 2835 } 2836 case kDexTypeMethodIdItem: { 2837 okay = iterateSection(state, sectionOffset, sectionCount, 2838 crossVerifyMethodIdItem, sizeof(u4), NULL); 2839 break; 2840 } 2841 case kDexTypeClassDefItem: { 2842 // Allocate (on the stack) the "observed class_def" bits. 2843 size_t arraySize = calcDefinedClassBitsSize(state); 2844 u4 definedClassBits[arraySize]; 2845 memset(definedClassBits, 0, arraySize * sizeof(u4)); 2846 state->pDefinedClassBits = definedClassBits; 2847 2848 okay = iterateSection(state, sectionOffset, sectionCount, 2849 crossVerifyClassDefItem, sizeof(u4), NULL); 2850 2851 state->pDefinedClassBits = NULL; 2852 break; 2853 } 2854 case kDexTypeCallSiteIdItem: { 2855 okay = iterateSection(state, sectionOffset, sectionCount, 2856 crossVerifyCallSiteId, sizeof(u4), NULL); 2857 break; 2858 } 2859 case kDexTypeMethodHandleItem: { 2860 okay = iterateSection(state, sectionOffset, sectionCount, 2861 crossVerifyMethodHandleItem, sizeof(u4), NULL); 2862 break; 2863 } 2864 case kDexTypeAnnotationSetRefList: { 2865 okay = iterateSection(state, sectionOffset, sectionCount, 2866 crossVerifyAnnotationSetRefList, sizeof(u4), NULL); 2867 break; 2868 } 2869 case kDexTypeAnnotationSetItem: { 2870 okay = iterateSection(state, sectionOffset, sectionCount, 2871 crossVerifyAnnotationSetItem, sizeof(u4), NULL); 2872 break; 2873 } 2874 case kDexTypeClassDataItem: { 2875 okay = iterateSection(state, sectionOffset, sectionCount, 2876 crossVerifyClassDataItem, sizeof(u1), NULL); 2877 break; 2878 } 2879 case kDexTypeAnnotationsDirectoryItem: { 2880 okay = iterateSection(state, sectionOffset, sectionCount, 2881 crossVerifyAnnotationsDirectoryItem, sizeof(u4), NULL); 2882 break; 2883 } 2884 default: { 2885 ALOGE("Unknown map item type %04x", item->type); 2886 return false; 2887 } 2888 } 2889 2890 if (!okay) { 2891 ALOGE("Cross-item verify of section type %04x failed", 2892 item->type); 2893 } 2894 2895 item++; 2896 } 2897 2898 return okay; 2899 } 2900 2901 /* (documented in header file) */ 2902 bool dexHasValidMagic(const DexHeader* pHeader) 2903 { 2904 const u1* magic = pHeader->magic; 2905 const u1* version = &magic[4]; 2906 2907 if (memcmp(magic, DEX_MAGIC, 4) != 0) { 2908 ALOGE("ERROR: unrecognized magic number (%02x %02x %02x %02x)", 2909 magic[0], magic[1], magic[2], magic[3]); 2910 return false; 2911 } 2912 2913 if ((memcmp(version, DEX_MAGIC_VERS, 4) != 0) && 2914 (memcmp(version, DEX_MAGIC_VERS_API_13, 4) != 0) && 2915 (memcmp(version, DEX_MAGIC_VERS_37, 4) != 0) && 2916 (memcmp(version, DEX_MAGIC_VERS_38, 4) != 0)) { 2917 /* 2918 * Magic was correct, but this is an unsupported older or 2919 * newer format variant. 2920 */ 2921 ALOGE("ERROR: unsupported dex version (%02x %02x %02x %02x)", 2922 version[0], version[1], version[2], version[3]); 2923 return false; 2924 } 2925 2926 return true; 2927 } 2928 2929 /* 2930 * Fix the byte ordering of all fields in the DEX file, and do 2931 * structural verification. This is only required for code that opens 2932 * "raw" DEX files, such as the DEX optimizer. 2933 * 2934 * Returns 0 on success, nonzero on failure. 2935 */ 2936 int dexSwapAndVerify(u1* addr, size_t len) 2937 { 2938 DexHeader* pHeader; 2939 CheckState state; 2940 bool okay = true; 2941 2942 memset(&state, 0, sizeof(state)); 2943 ALOGV("+++ swapping and verifying"); 2944 2945 /* 2946 * Note: The caller must have verified that "len" is at least as 2947 * large as a dex file header. 2948 */ 2949 pHeader = (DexHeader*) addr; 2950 2951 if (!dexHasValidMagic(pHeader)) { 2952 okay = false; 2953 } 2954 2955 if (okay) { 2956 u4 expectedLen = SWAP4(pHeader->fileSize); 2957 if (len != expectedLen) { 2958 ALOGE("ERROR: Bad length: expected %u, got %zu", expectedLen, len); 2959 okay = false; 2960 } 2961 } 2962 2963 if (okay) { 2964 /* 2965 * Compute the adler32 checksum and compare it to what's stored in 2966 * the file. This isn't free, but chances are good that we just 2967 * unpacked this from a jar file and have all of the pages sitting 2968 * in memory, so it's pretty quick. 2969 * 2970 * This might be a big-endian system, so we need to do this before 2971 * we byte-swap the header. 2972 */ 2973 uLong adler = adler32(0L, Z_NULL, 0); 2974 const int nonSum = sizeof(pHeader->magic) + sizeof(pHeader->checksum); 2975 u4 storedFileSize = SWAP4(pHeader->fileSize); 2976 u4 expectedChecksum = SWAP4(pHeader->checksum); 2977 2978 adler = adler32(adler, ((const u1*) pHeader) + nonSum, 2979 storedFileSize - nonSum); 2980 2981 if (adler != expectedChecksum) { 2982 ALOGE("ERROR: bad checksum (%08lx, expected %08x)", 2983 adler, expectedChecksum); 2984 okay = false; 2985 } 2986 } 2987 2988 if (okay) { 2989 state.fileStart = addr; 2990 state.fileEnd = addr + len; 2991 state.fileLen = len; 2992 state.pDexFile = NULL; 2993 state.pDataMap = NULL; 2994 state.pDefinedClassBits = NULL; 2995 state.previousItem = NULL; 2996 2997 /* 2998 * Swap the header and check the contents. 2999 */ 3000 okay = swapDexHeader(&state, pHeader); 3001 } 3002 3003 if (okay) { 3004 state.pHeader = pHeader; 3005 3006 if (pHeader->headerSize < sizeof(DexHeader)) { 3007 ALOGE("ERROR: Small header size %d, struct %d", 3008 pHeader->headerSize, (int) sizeof(DexHeader)); 3009 okay = false; 3010 } else if (pHeader->headerSize > sizeof(DexHeader)) { 3011 ALOGW("WARNING: Large header size %d, struct %d", 3012 pHeader->headerSize, (int) sizeof(DexHeader)); 3013 // keep going? 3014 } 3015 } 3016 3017 if (okay) { 3018 /* 3019 * Look for the map. Swap it and then use it to find and swap 3020 * everything else. 3021 */ 3022 if (pHeader->mapOff != 0) { 3023 DexFile dexFile; 3024 DexMapList* pDexMap = (DexMapList*) (addr + pHeader->mapOff); 3025 3026 okay = okay && swapMap(&state, pDexMap); 3027 okay = okay && swapEverythingButHeaderAndMap(&state, pDexMap); 3028 3029 dexFileSetupBasicPointers(&dexFile, addr); 3030 state.pDexFile = &dexFile; 3031 3032 okay = okay && crossVerifyEverything(&state, pDexMap); 3033 } else { 3034 ALOGE("ERROR: No map found; impossible to byte-swap and verify"); 3035 okay = false; 3036 } 3037 } 3038 3039 if (!okay) { 3040 ALOGE("ERROR: Byte swap + verify failed"); 3041 } 3042 3043 if (state.pDataMap != NULL) { 3044 dexDataMapFree(state.pDataMap); 3045 } 3046 3047 return !okay; // 0 == success 3048 } 3049 3050 /* 3051 * Detect the file type of the given memory buffer via magic number. 3052 * Call dexSwapAndVerify() on an unoptimized DEX file, do nothing 3053 * but return successfully on an optimized DEX file, and report an 3054 * error for all other cases. 3055 * 3056 * Returns 0 on success, nonzero on failure. 3057 */ 3058 int dexSwapAndVerifyIfNecessary(u1* addr, size_t len) 3059 { 3060 if (memcmp(addr, DEX_OPT_MAGIC, 4) == 0) { 3061 // It is an optimized dex file. 3062 return 0; 3063 } 3064 3065 if (memcmp(addr, DEX_MAGIC, 4) == 0) { 3066 // It is an unoptimized dex file. 3067 return dexSwapAndVerify(addr, len); 3068 } 3069 3070 ALOGE("ERROR: Bad magic number (0x%02x %02x %02x %02x)", 3071 addr[0], addr[1], addr[2], addr[3]); 3072 3073 return 1; 3074 } 3075