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