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 "Leb128.h" 26 27 #include <safe_iop.h> 28 #include <zlib.h> 29 30 #include <stdlib.h> 31 #include <string.h> 32 33 #ifndef __BYTE_ORDER 34 # error "byte ordering not defined" 35 #endif 36 37 #if __BYTE_ORDER == __LITTLE_ENDIAN 38 # define SWAP2(_value) (_value) 39 # define SWAP4(_value) (_value) 40 # define SWAP8(_value) (_value) 41 #else 42 # define SWAP2(_value) endianSwapU2((_value)) 43 # define SWAP4(_value) endianSwapU4((_value)) 44 # define SWAP8(_value) endianSwapU8((_value)) 45 static u2 endianSwapU2(u2 value) { 46 return (value >> 8) | (value << 8); 47 } 48 static u4 endianSwapU4(u4 value) { 49 /* ABCD --> CDAB --> DCBA */ 50 value = (value >> 16) | (value << 16); 51 return ((value & 0xff00ff00) >> 8) | ((value << 8) & 0xff00ff00); 52 } 53 static u8 endianSwapU8(u8 value) { 54 /* ABCDEFGH --> EFGHABCD --> GHEFCDAB --> HGFEDCBA */ 55 value = (value >> 32) | (value << 32); 56 value = ((value & 0xffff0000ffff0000ULL) >> 16) | 57 ((value << 16) & 0xffff0000ffff0000ULL); 58 return ((value & 0xff00ff00ff00ff00ULL) >> 8) | 59 ((value << 8) & 0xff00ff00ff00ff00ULL); 60 } 61 #endif 62 63 #define SWAP_FIELD2(_field) (_field) = SWAP2(_field) 64 #define SWAP_FIELD4(_field) (_field) = SWAP4(_field) 65 #define SWAP_FIELD8(_field) (_field) = SWAP8(_field) 66 67 /* 68 * Some information we pass around to help verify values. 69 */ 70 typedef struct CheckState { 71 const DexHeader* pHeader; 72 const u1* fileStart; 73 const u1* fileEnd; // points to fileStart + fileLen 74 u4 fileLen; 75 DexDataMap* pDataMap; // set after map verification 76 const DexFile* pDexFile; // set after intraitem verification 77 78 /* 79 * bitmap of type_id indices that have been used to define classes; 80 * initialized immediately before class_def cross-verification, and 81 * freed immediately after it 82 */ 83 u4* pDefinedClassBits; 84 85 const void* previousItem; // set during section iteration 86 } CheckState; 87 88 /* 89 * Return the file offset of the given pointer. 90 */ 91 static inline u4 fileOffset(const CheckState* state, const void* ptr) { 92 return ((const u1*) ptr) - state->fileStart; 93 } 94 95 /* 96 * Return a pointer for the given file offset. 97 */ 98 static inline void* filePointer(const CheckState* state, u4 offset) { 99 return (void*) (state->fileStart + offset); 100 } 101 102 /* 103 * Verify that a pointer range, start inclusive to end exclusive, only 104 * covers bytes in the file and doesn't point beyond the end of the 105 * file. That is, the start must indicate a valid byte or may point at 106 * the byte just past the end of the file (but no further), and the 107 * end must be no less than the start and must also not point beyond 108 * the byte just past the end of the file. 109 */ 110 static inline bool checkPtrRange(const CheckState* state, 111 const void* start, const void* end, const char* label) { 112 const void* fileStart = state->fileStart; 113 const void* fileEnd = state->fileEnd; 114 if ((start < fileStart) || (start > fileEnd) 115 || (end < start) || (end > fileEnd)) { 116 LOGW("Bad offset range for %s: 0x%x..0x%x\n", label, 117 fileOffset(state, start), fileOffset(state, end)); 118 return false; 119 } 120 return true; 121 } 122 123 /* 124 * Verify that a range of offsets, start inclusive to end exclusive, 125 * are all valid. That is, the start must indicate a valid byte or may 126 * point at the byte just past the end of the file (but no further), 127 * and the end must be no less than the start and must also not point 128 * beyond the byte just past the end of the file. 129 * 130 * Assumes "const CheckState* state". 131 */ 132 #define CHECK_OFFSET_RANGE(_start, _end) { \ 133 const u1* _startPtr = filePointer(state, (_start)); \ 134 const u1* _endPtr = filePointer(state, (_end)); \ 135 if (!checkPtrRange(state, _startPtr, _endPtr, \ 136 #_start ".." #_end)) { \ 137 return 0; \ 138 } \ 139 } 140 141 /* 142 * Verify that a pointer range, start inclusive to end exclusive, only 143 * covers bytes in the file and doesn't point beyond the end of the 144 * file. That is, the start must indicate a valid byte or may point at 145 * the byte just past the end of the file (but no further), and the 146 * end must be no less than the start and must also not point beyond 147 * the byte just past the end of the file. 148 * 149 * Assumes "const CheckState* state". 150 */ 151 #define CHECK_PTR_RANGE(_start, _end) { \ 152 if (!checkPtrRange(state, (_start), (_end), #_start ".." #_end)) { \ 153 return 0; \ 154 } \ 155 } 156 157 /* 158 * Make sure a list of items fits entirely within the file. 159 * 160 * Assumes "const CheckState* state" and "typeof(_count) == typeof(_elemSize)" 161 * If the type sizes or signs are mismatched, this will return 0. 162 */ 163 #define CHECK_LIST_SIZE(_ptr, _count, _elemSize) { \ 164 const u1* _start = (const u1*) (_ptr); \ 165 const u1* _end = _start + ((_count) * (_elemSize)); \ 166 if (!safe_mul(NULL, (_count), (_elemSize)) || \ 167 !checkPtrRange(state, _start, _end, #_ptr)) { \ 168 return 0; \ 169 } \ 170 } 171 172 /* 173 * Swap a field that is known to hold an absolute DEX file offset. Note: 174 * This does not check to see that the swapped offset points within the 175 * mapped file, since that should be handled (with even more rigor) by 176 * the cross-verification phase. 177 * 178 * Assumes "const CheckState* state". 179 */ 180 #define SWAP_OFFSET4(_field) { \ 181 SWAP_FIELD4((_field)); \ 182 } 183 184 /* 185 * Verify that an index falls in a valid range. 186 */ 187 #define CHECK_INDEX(_field, _limit) { \ 188 if ((_field) >= (_limit)) { \ 189 LOGW("Bad index: %s(%u) > %s(%u)\n", \ 190 #_field, (u4)(_field), #_limit, (u4)(_limit)); \ 191 return 0; \ 192 } \ 193 } 194 195 /* 196 * Swap an index, and verify that it falls in a valid range. 197 */ 198 #define SWAP_INDEX2(_field, _limit) { \ 199 SWAP_FIELD2((_field)); \ 200 CHECK_INDEX((_field), (_limit)); \ 201 } 202 203 /* 204 * Verify that an index falls in a valid range or is kDexNoIndex. 205 */ 206 #define CHECK_INDEX_OR_NOINDEX(_field, _limit) { \ 207 if ((_field) != kDexNoIndex && (_field) >= (_limit)) { \ 208 LOGW("Bad index: %s(%u) > %s(%u)\n", \ 209 #_field, (u4)(_field), #_limit, (u4)(_limit)); \ 210 return 0; \ 211 } \ 212 } 213 214 /* 215 * Swap an index, and verify that it falls in a valid range. 216 */ 217 #define SWAP_INDEX4(_field, _limit) { \ 218 SWAP_FIELD4((_field)); \ 219 CHECK_INDEX((_field), (_limit)); \ 220 } 221 222 /* 223 * Swap an index, and verify that it falls in a valid range or is 224 * kDexNoIndex. 225 */ 226 #define SWAP_INDEX4_OR_NOINDEX(_field, _limit) { \ 227 SWAP_FIELD4((_field)); \ 228 CHECK_INDEX_OR_NOINDEX((_field), (_limit)); \ 229 } 230 231 /* Verify the definer of a given field_idx. */ 232 static bool verifyFieldDefiner(const CheckState* state, u4 definingClass, 233 u4 fieldIdx) { 234 const DexFieldId* field = dexGetFieldId(state->pDexFile, fieldIdx); 235 return field->classIdx == definingClass; 236 } 237 238 /* Verify the definer of a given method_idx. */ 239 static bool verifyMethodDefiner(const CheckState* state, u4 definingClass, 240 u4 methodIdx) { 241 const DexMethodId* meth = dexGetMethodId(state->pDexFile, methodIdx); 242 return meth->classIdx == definingClass; 243 } 244 245 /* 246 * Calculate the required size (in elements) of the array pointed at by 247 * pDefinedClassBits. 248 */ 249 static size_t calcDefinedClassBitsSize(const CheckState* state) 250 { 251 // Divide typeIdsSize by 32 (0x20), rounding up. 252 return (state->pHeader->typeIdsSize + 0x1f) >> 5; 253 } 254 255 /* 256 * Set the given bit in pDefinedClassBits, returning its former value. 257 */ 258 static bool setDefinedClassBit(const CheckState* state, u4 typeIdx) { 259 u4 arrayIdx = typeIdx >> 5; 260 u4 bit = 1 << (typeIdx & 0x1f); 261 u4* element = &state->pDefinedClassBits[arrayIdx]; 262 bool result = (*element & bit) != 0; 263 264 *element |= bit; 265 266 return result; 267 } 268 269 /* 270 * Swap the header_item. 271 */ 272 static bool swapDexHeader(const CheckState* state, DexHeader* pHeader) 273 { 274 CHECK_PTR_RANGE(pHeader, pHeader + 1); 275 276 // magic is ok 277 SWAP_FIELD4(pHeader->checksum); 278 // signature is ok 279 SWAP_FIELD4(pHeader->fileSize); 280 SWAP_FIELD4(pHeader->headerSize); 281 SWAP_FIELD4(pHeader->endianTag); 282 SWAP_FIELD4(pHeader->linkSize); 283 SWAP_OFFSET4(pHeader->linkOff); 284 SWAP_OFFSET4(pHeader->mapOff); 285 SWAP_FIELD4(pHeader->stringIdsSize); 286 SWAP_OFFSET4(pHeader->stringIdsOff); 287 SWAP_FIELD4(pHeader->typeIdsSize); 288 SWAP_OFFSET4(pHeader->typeIdsOff); 289 SWAP_FIELD4(pHeader->fieldIdsSize); 290 SWAP_OFFSET4(pHeader->fieldIdsOff); 291 SWAP_FIELD4(pHeader->methodIdsSize); 292 SWAP_OFFSET4(pHeader->methodIdsOff); 293 SWAP_FIELD4(pHeader->protoIdsSize); 294 SWAP_OFFSET4(pHeader->protoIdsOff); 295 SWAP_FIELD4(pHeader->classDefsSize); 296 SWAP_OFFSET4(pHeader->classDefsOff); 297 SWAP_FIELD4(pHeader->dataSize); 298 SWAP_OFFSET4(pHeader->dataOff); 299 300 if (pHeader->endianTag != kDexEndianConstant) { 301 LOGE("Unexpected endian_tag: 0x%x\n", pHeader->endianTag); 302 return false; 303 } 304 305 // Assign variables so the diagnostic is prettier. (Hooray for macros.) 306 u4 linkOff = pHeader->linkOff; 307 u4 linkEnd = linkOff + pHeader->linkSize; 308 u4 dataOff = pHeader->dataOff; 309 u4 dataEnd = dataOff + pHeader->dataSize; 310 CHECK_OFFSET_RANGE(linkOff, linkEnd); 311 CHECK_OFFSET_RANGE(dataOff, dataEnd); 312 313 /* 314 * Note: The offsets and ranges of the other header items end up getting 315 * checked during the first iteration over the map. 316 */ 317 318 return true; 319 } 320 321 /* Check the header section for sanity. */ 322 static bool checkHeaderSection(const CheckState* state, u4 sectionOffset, 323 u4 sectionCount, u4* endOffset) { 324 if (sectionCount != 1) { 325 LOGE("Multiple header items\n"); 326 return false; 327 } 328 329 if (sectionOffset != 0) { 330 LOGE("Header at 0x%x; not at start of file\n", sectionOffset); 331 return false; 332 } 333 334 const DexHeader* pHeader = filePointer(state, 0); 335 *endOffset = pHeader->headerSize; 336 return true; 337 } 338 339 /* 340 * Helper for swapMap(), which turns a map type constant into a small 341 * one-bit-on integer, suitable for use in an int-sized bit set. 342 */ 343 static u4 mapTypeToBitMask(int mapType) { 344 switch (mapType) { 345 case kDexTypeHeaderItem: return 1 << 0; 346 case kDexTypeStringIdItem: return 1 << 1; 347 case kDexTypeTypeIdItem: return 1 << 2; 348 case kDexTypeProtoIdItem: return 1 << 3; 349 case kDexTypeFieldIdItem: return 1 << 4; 350 case kDexTypeMethodIdItem: return 1 << 5; 351 case kDexTypeClassDefItem: return 1 << 6; 352 case kDexTypeMapList: return 1 << 7; 353 case kDexTypeTypeList: return 1 << 8; 354 case kDexTypeAnnotationSetRefList: return 1 << 9; 355 case kDexTypeAnnotationSetItem: return 1 << 10; 356 case kDexTypeClassDataItem: return 1 << 11; 357 case kDexTypeCodeItem: return 1 << 12; 358 case kDexTypeStringDataItem: return 1 << 13; 359 case kDexTypeDebugInfoItem: return 1 << 14; 360 case kDexTypeAnnotationItem: return 1 << 15; 361 case kDexTypeEncodedArrayItem: return 1 << 16; 362 case kDexTypeAnnotationsDirectoryItem: return 1 << 17; 363 default: { 364 LOGE("Unknown map item type %04x\n", mapType); 365 return 0; 366 } 367 } 368 } 369 370 /* 371 * Helper for swapMap(), which indicates if an item type should appear 372 * in the data section. 373 */ 374 static bool isDataSectionType(int mapType) { 375 switch (mapType) { 376 case kDexTypeHeaderItem: 377 case kDexTypeStringIdItem: 378 case kDexTypeTypeIdItem: 379 case kDexTypeProtoIdItem: 380 case kDexTypeFieldIdItem: 381 case kDexTypeMethodIdItem: 382 case kDexTypeClassDefItem: { 383 return false; 384 } 385 } 386 387 return true; 388 } 389 390 /* 391 * Swap the map_list and verify what we can about it. Also, if verification 392 * passes, allocate the state's DexDataMap. 393 */ 394 static bool swapMap(CheckState* state, DexMapList* pMap) 395 { 396 DexMapItem* item = pMap->list; 397 u4 count; 398 u4 dataItemCount = 0; // Total count of items in the data section. 399 u4 dataItemsLeft = state->pHeader->dataSize; // See use below. 400 u4 usedBits = 0; // Bit set: one bit per section 401 bool first = true; 402 u4 lastOffset = 0; 403 404 SWAP_FIELD4(pMap->size); 405 count = pMap->size; 406 407 CHECK_LIST_SIZE(item, count, sizeof(DexMapItem)); 408 409 while (count--) { 410 SWAP_FIELD2(item->type); 411 SWAP_FIELD2(item->unused); 412 SWAP_FIELD4(item->size); 413 SWAP_OFFSET4(item->offset); 414 415 if (first) { 416 first = false; 417 } else if (lastOffset >= item->offset) { 418 LOGE("Out-of-order map item: 0x%x then 0x%x\n", 419 lastOffset, item->offset); 420 return false; 421 } 422 423 if (item->offset >= state->pHeader->fileSize) { 424 LOGE("Map item after end of file: %x, size 0x%x\n", 425 item->offset, state->pHeader->fileSize); 426 return false; 427 } 428 429 if (isDataSectionType(item->type)) { 430 u4 icount = item->size; 431 432 /* 433 * This sanity check on the data section items ensures that 434 * there are no more items than the number of bytes in 435 * the data section. 436 */ 437 if (icount > dataItemsLeft) { 438 LOGE("Unrealistically many items in the data section: " 439 "at least %d\n", dataItemCount + icount); 440 return false; 441 } 442 443 dataItemsLeft -= icount; 444 dataItemCount += icount; 445 } 446 447 u4 bit = mapTypeToBitMask(item->type); 448 449 if (bit == 0) { 450 return false; 451 } 452 453 if ((usedBits & bit) != 0) { 454 LOGE("Duplicate map section of type 0x%x\n", item->type); 455 return false; 456 } 457 458 usedBits |= bit; 459 lastOffset = item->offset; 460 item++; 461 } 462 463 if ((usedBits & mapTypeToBitMask(kDexTypeHeaderItem)) == 0) { 464 LOGE("Map is missing header entry\n"); 465 return false; 466 } 467 468 if ((usedBits & mapTypeToBitMask(kDexTypeMapList)) == 0) { 469 LOGE("Map is missing map_list entry\n"); 470 return false; 471 } 472 473 if (((usedBits & mapTypeToBitMask(kDexTypeStringIdItem)) == 0) 474 && ((state->pHeader->stringIdsOff != 0) 475 || (state->pHeader->stringIdsSize != 0))) { 476 LOGE("Map is missing string_ids entry\n"); 477 return false; 478 } 479 480 if (((usedBits & mapTypeToBitMask(kDexTypeTypeIdItem)) == 0) 481 && ((state->pHeader->typeIdsOff != 0) 482 || (state->pHeader->typeIdsSize != 0))) { 483 LOGE("Map is missing type_ids entry\n"); 484 return false; 485 } 486 487 if (((usedBits & mapTypeToBitMask(kDexTypeProtoIdItem)) == 0) 488 && ((state->pHeader->protoIdsOff != 0) 489 || (state->pHeader->protoIdsSize != 0))) { 490 LOGE("Map is missing proto_ids entry\n"); 491 return false; 492 } 493 494 if (((usedBits & mapTypeToBitMask(kDexTypeFieldIdItem)) == 0) 495 && ((state->pHeader->fieldIdsOff != 0) 496 || (state->pHeader->fieldIdsSize != 0))) { 497 LOGE("Map is missing field_ids entry\n"); 498 return false; 499 } 500 501 if (((usedBits & mapTypeToBitMask(kDexTypeMethodIdItem)) == 0) 502 && ((state->pHeader->methodIdsOff != 0) 503 || (state->pHeader->methodIdsSize != 0))) { 504 LOGE("Map is missing method_ids entry\n"); 505 return false; 506 } 507 508 if (((usedBits & mapTypeToBitMask(kDexTypeClassDefItem)) == 0) 509 && ((state->pHeader->classDefsOff != 0) 510 || (state->pHeader->classDefsSize != 0))) { 511 LOGE("Map is missing class_defs entry\n"); 512 return false; 513 } 514 515 state->pDataMap = dexDataMapAlloc(dataItemCount); 516 if (state->pDataMap == NULL) { 517 LOGE("Unable to allocate data map (size 0x%x)\n", dataItemCount); 518 return false; 519 } 520 521 return true; 522 } 523 524 /* Check the map section for sanity. */ 525 static bool checkMapSection(const CheckState* state, u4 sectionOffset, 526 u4 sectionCount, u4* endOffset) { 527 if (sectionCount != 1) { 528 LOGE("Multiple map list items"); 529 return false; 530 } 531 532 if (sectionOffset != state->pHeader->mapOff) { 533 LOGE("Map not at header-defined offset: 0x%x, expected 0x%x\n", 534 sectionOffset, state->pHeader->mapOff); 535 return false; 536 } 537 538 const DexMapList* pMap = filePointer(state, sectionOffset); 539 540 *endOffset = 541 sectionOffset + sizeof(u4) + (pMap->size * sizeof(DexMapItem)); 542 return true; 543 } 544 545 /* Perform byte-swapping and intra-item verification on string_id_item. */ 546 static void* swapStringIdItem(const CheckState* state, void* ptr) { 547 DexStringId* item = ptr; 548 549 CHECK_PTR_RANGE(item, item + 1); 550 SWAP_OFFSET4(item->stringDataOff); 551 552 return item + 1; 553 } 554 555 /* Perform cross-item verification of string_id_item. */ 556 static void* crossVerifyStringIdItem(const CheckState* state, void* ptr) { 557 const DexStringId* item = ptr; 558 559 if (!dexDataMapVerify(state->pDataMap, 560 item->stringDataOff, kDexTypeStringDataItem)) { 561 return NULL; 562 } 563 564 const DexStringId* item0 = state->previousItem; 565 if (item0 != NULL) { 566 // Check ordering. 567 const char* s0 = dexGetStringData(state->pDexFile, item0); 568 const char* s1 = dexGetStringData(state->pDexFile, item); 569 if (dexUtf8Cmp(s0, s1) >= 0) { 570 LOGE("Out-of-order string_ids: '%s' then '%s'\n", s0, s1); 571 return NULL; 572 } 573 } 574 575 return (void*) (item + 1); 576 } 577 578 /* Perform byte-swapping and intra-item verification on type_id_item. */ 579 static void* swapTypeIdItem(const CheckState* state, void* ptr) { 580 DexTypeId* item = ptr; 581 582 CHECK_PTR_RANGE(item, item + 1); 583 SWAP_INDEX4(item->descriptorIdx, state->pHeader->stringIdsSize); 584 585 return item + 1; 586 } 587 588 /* Perform cross-item verification of type_id_item. */ 589 static void* crossVerifyTypeIdItem(const CheckState* state, void* ptr) { 590 const DexTypeId* item = ptr; 591 const char* descriptor = 592 dexStringById(state->pDexFile, item->descriptorIdx); 593 594 if (!dexIsValidTypeDescriptor(descriptor)) { 595 LOGE("Invalid type descriptor: '%s'\n", descriptor); 596 return NULL; 597 } 598 599 const DexTypeId* item0 = state->previousItem; 600 if (item0 != NULL) { 601 // Check ordering. This relies on string_ids being in order. 602 if (item0->descriptorIdx >= item->descriptorIdx) { 603 LOGE("Out-of-order type_ids: 0x%x then 0x%x\n", 604 item0->descriptorIdx, item->descriptorIdx); 605 return NULL; 606 } 607 } 608 609 return (void*) (item + 1); 610 } 611 612 /* Perform byte-swapping and intra-item verification on proto_id_item. */ 613 static void* swapProtoIdItem(const CheckState* state, void* ptr) { 614 DexProtoId* item = ptr; 615 616 CHECK_PTR_RANGE(item, item + 1); 617 SWAP_INDEX4(item->shortyIdx, state->pHeader->stringIdsSize); 618 SWAP_INDEX4(item->returnTypeIdx, state->pHeader->typeIdsSize); 619 SWAP_OFFSET4(item->parametersOff); 620 621 return item + 1; 622 } 623 624 /* Helper for crossVerifyProtoIdItem(), which checks a shorty character 625 * to see if it is compatible with a type descriptor. Returns true if 626 * so, false if not. */ 627 static bool shortyDescMatch(char shorty, const char* descriptor, bool 628 isReturnType) { 629 switch (shorty) { 630 case 'V': { 631 if (!isReturnType) { 632 LOGE("Invalid use of void\n"); 633 return false; 634 } 635 // Fall through. 636 } 637 case 'B': 638 case 'C': 639 case 'D': 640 case 'F': 641 case 'I': 642 case 'J': 643 case 'S': 644 case 'Z': { 645 if ((descriptor[0] != shorty) || (descriptor[1] != '\0')) { 646 LOGE("Shorty vs. primitive type mismatch: '%c', '%s'\n", 647 shorty, descriptor); 648 return false; 649 } 650 break; 651 } 652 case 'L': { 653 if ((descriptor[0] != 'L') && (descriptor[0] != '[')) { 654 LOGE("Shorty vs. type mismatch: '%c', '%s'\n", 655 shorty, descriptor); 656 return false; 657 } 658 break; 659 } 660 default: { 661 LOGE("Bogus shorty: '%c'\n", shorty); 662 return false; 663 } 664 } 665 666 return true; 667 } 668 669 /* Perform cross-item verification of proto_id_item. */ 670 static void* crossVerifyProtoIdItem(const CheckState* state, void* ptr) { 671 const DexProtoId* item = ptr; 672 const char* shorty = 673 dexStringById(state->pDexFile, item->shortyIdx); 674 675 if (!dexDataMapVerify0Ok(state->pDataMap, 676 item->parametersOff, kDexTypeTypeList)) { 677 return NULL; 678 } 679 680 if (!shortyDescMatch(*shorty, 681 dexStringByTypeIdx(state->pDexFile, item->returnTypeIdx), 682 true)) { 683 return NULL; 684 } 685 686 u4 protoIdx = item - state->pDexFile->pProtoIds; 687 DexProto proto = { state->pDexFile, protoIdx }; 688 DexParameterIterator iterator; 689 690 dexParameterIteratorInit(&iterator, &proto); 691 shorty++; // Skip the return type. 692 693 for (;;) { 694 const char *desc = dexParameterIteratorNextDescriptor(&iterator); 695 696 if (desc == NULL) { 697 break; 698 } 699 700 if (*shorty == '\0') { 701 LOGE("Shorty is too short\n"); 702 return NULL; 703 } 704 705 if (!shortyDescMatch(*shorty, desc, false)) { 706 return NULL; 707 } 708 709 shorty++; 710 } 711 712 if (*shorty != '\0') { 713 LOGE("Shorty is too long\n"); 714 return NULL; 715 } 716 717 const DexProtoId* item0 = state->previousItem; 718 if (item0 != NULL) { 719 // Check ordering. This relies on type_ids being in order. 720 if (item0->returnTypeIdx > item->returnTypeIdx) { 721 LOGE("Out-of-order proto_id return types\n"); 722 return NULL; 723 } else if (item0->returnTypeIdx == item->returnTypeIdx) { 724 bool badOrder = false; 725 DexProto proto0 = { state->pDexFile, protoIdx - 1 }; 726 DexParameterIterator iterator0; 727 728 dexParameterIteratorInit(&iterator, &proto); 729 dexParameterIteratorInit(&iterator0, &proto0); 730 731 for (;;) { 732 u4 idx0 = dexParameterIteratorNextIndex(&iterator0); 733 u4 idx1 = dexParameterIteratorNextIndex(&iterator); 734 735 if (idx1 == kDexNoIndex) { 736 badOrder = true; 737 break; 738 } 739 740 if (idx0 == kDexNoIndex) { 741 break; 742 } 743 744 if (idx0 < idx1) { 745 break; 746 } else if (idx0 > idx1) { 747 badOrder = true; 748 break; 749 } 750 } 751 752 if (badOrder) { 753 LOGE("Out-of-order proto_id arguments\n"); 754 return NULL; 755 } 756 } 757 } 758 759 return (void*) (item + 1); 760 } 761 762 /* Perform byte-swapping and intra-item verification on field_id_item. */ 763 static void* swapFieldIdItem(const CheckState* state, void* ptr) { 764 DexFieldId* item = ptr; 765 766 CHECK_PTR_RANGE(item, item + 1); 767 SWAP_INDEX2(item->classIdx, state->pHeader->typeIdsSize); 768 SWAP_INDEX2(item->typeIdx, state->pHeader->typeIdsSize); 769 SWAP_INDEX4(item->nameIdx, state->pHeader->stringIdsSize); 770 771 return item + 1; 772 } 773 774 /* Perform cross-item verification of field_id_item. */ 775 static void* crossVerifyFieldIdItem(const CheckState* state, void* ptr) { 776 const DexFieldId* item = ptr; 777 const char* s; 778 779 s = dexStringByTypeIdx(state->pDexFile, item->classIdx); 780 if (!dexIsClassDescriptor(s)) { 781 LOGE("Invalid descriptor for class_idx: '%s'\n", s); 782 return NULL; 783 } 784 785 s = dexStringByTypeIdx(state->pDexFile, item->typeIdx); 786 if (!dexIsFieldDescriptor(s)) { 787 LOGE("Invalid descriptor for type_idx: '%s'\n", s); 788 return NULL; 789 } 790 791 s = dexStringById(state->pDexFile, item->nameIdx); 792 if (!dexIsValidMemberName(s)) { 793 LOGE("Invalid name: '%s'\n", s); 794 return NULL; 795 } 796 797 const DexFieldId* item0 = state->previousItem; 798 if (item0 != NULL) { 799 // Check ordering. This relies on the other sections being in order. 800 bool done = false; 801 bool bogus = false; 802 803 if (item0->classIdx > item->classIdx) { 804 bogus = true; 805 done = true; 806 } else if (item0->classIdx < item->classIdx) { 807 done = true; 808 } 809 810 if (!done) { 811 if (item0->nameIdx > item->nameIdx) { 812 bogus = true; 813 done = true; 814 } else if (item0->nameIdx < item->nameIdx) { 815 done = true; 816 } 817 } 818 819 if (!done) { 820 if (item0->typeIdx >= item->typeIdx) { 821 bogus = true; 822 } 823 } 824 825 if (bogus) { 826 LOGE("Out-of-order field_ids\n"); 827 return NULL; 828 } 829 } 830 831 return (void*) (item + 1); 832 } 833 834 /* Perform byte-swapping and intra-item verification on method_id_item. */ 835 static void* swapMethodIdItem(const CheckState* state, void* ptr) { 836 DexMethodId* item = ptr; 837 838 CHECK_PTR_RANGE(item, item + 1); 839 SWAP_INDEX2(item->classIdx, state->pHeader->typeIdsSize); 840 SWAP_INDEX2(item->protoIdx, state->pHeader->protoIdsSize); 841 SWAP_INDEX4(item->nameIdx, state->pHeader->stringIdsSize); 842 843 return item + 1; 844 } 845 846 /* Perform cross-item verification of method_id_item. */ 847 static void* crossVerifyMethodIdItem(const CheckState* state, void* ptr) { 848 const DexMethodId* item = ptr; 849 const char* s; 850 851 s = dexStringByTypeIdx(state->pDexFile, item->classIdx); 852 if (!dexIsReferenceDescriptor(s)) { 853 LOGE("Invalid descriptor for class_idx: '%s'\n", s); 854 return NULL; 855 } 856 857 s = dexStringById(state->pDexFile, item->nameIdx); 858 if (!dexIsValidMemberName(s)) { 859 LOGE("Invalid name: '%s'\n", s); 860 return NULL; 861 } 862 863 const DexMethodId* item0 = state->previousItem; 864 if (item0 != NULL) { 865 // Check ordering. This relies on the other sections being in order. 866 bool done = false; 867 bool bogus = false; 868 869 if (item0->classIdx > item->classIdx) { 870 bogus = true; 871 done = true; 872 } else if (item0->classIdx < item->classIdx) { 873 done = true; 874 } 875 876 if (!done) { 877 if (item0->nameIdx > item->nameIdx) { 878 bogus = true; 879 done = true; 880 } else if (item0->nameIdx < item->nameIdx) { 881 done = true; 882 } 883 } 884 885 if (!done) { 886 if (item0->protoIdx >= item->protoIdx) { 887 bogus = true; 888 } 889 } 890 891 if (bogus) { 892 LOGE("Out-of-order method_ids\n"); 893 return NULL; 894 } 895 } 896 897 return (void*) (item + 1); 898 } 899 900 /* Perform byte-swapping and intra-item verification on class_def_item. */ 901 static void* swapClassDefItem(const CheckState* state, void* ptr) { 902 DexClassDef* item = ptr; 903 904 CHECK_PTR_RANGE(item, item + 1); 905 SWAP_INDEX4(item->classIdx, state->pHeader->typeIdsSize); 906 SWAP_FIELD4(item->accessFlags); 907 SWAP_INDEX4_OR_NOINDEX(item->superclassIdx, state->pHeader->typeIdsSize); 908 SWAP_OFFSET4(item->interfacesOff); 909 SWAP_INDEX4_OR_NOINDEX(item->sourceFileIdx, state->pHeader->stringIdsSize); 910 SWAP_OFFSET4(item->annotationsOff); 911 SWAP_OFFSET4(item->classDataOff); 912 913 return item + 1; 914 } 915 916 /* defined below */ 917 static u4 findFirstClassDataDefiner(const CheckState* state, 918 DexClassData* classData); 919 static u4 findFirstAnnotationsDirectoryDefiner(const CheckState* state, 920 const DexAnnotationsDirectoryItem* dir); 921 922 /* Helper for crossVerifyClassDefItem(), which checks a class_data_item to 923 * make sure all its references are to a given class. */ 924 static bool verifyClassDataIsForDef(const CheckState* state, u4 offset, 925 u4 definerIdx) { 926 if (offset == 0) { 927 return true; 928 } 929 930 const u1* data = filePointer(state, offset); 931 DexClassData* classData = dexReadAndVerifyClassData(&data, NULL); 932 933 if (classData == NULL) { 934 // Shouldn't happen, but bail here just in case. 935 return false; 936 } 937 938 /* 939 * The class_data_item verification ensures that 940 * it consistently refers to the same definer, so all we need to 941 * do is check the first one. 942 */ 943 u4 dataDefiner = findFirstClassDataDefiner(state, classData); 944 bool result = (dataDefiner == definerIdx) || (dataDefiner == kDexNoIndex); 945 946 free(classData); 947 return result; 948 } 949 950 /* Helper for crossVerifyClassDefItem(), which checks an 951 * annotations_directory_item to make sure all its references are to a 952 * given class. */ 953 static bool verifyAnnotationsDirectoryIsForDef(const CheckState* state, 954 u4 offset, u4 definerIdx) { 955 if (offset == 0) { 956 return true; 957 } 958 959 const DexAnnotationsDirectoryItem* dir = filePointer(state, offset); 960 u4 annoDefiner = findFirstAnnotationsDirectoryDefiner(state, dir); 961 962 return (annoDefiner == definerIdx) || (annoDefiner == kDexNoIndex); 963 } 964 965 /* Perform cross-item verification of class_def_item. */ 966 static void* crossVerifyClassDefItem(const CheckState* state, void* ptr) { 967 const DexClassDef* item = ptr; 968 u4 classIdx = item->classIdx; 969 const char* descriptor = dexStringByTypeIdx(state->pDexFile, classIdx); 970 971 if (!dexIsClassDescriptor(descriptor)) { 972 LOGE("Invalid class: '%s'\n", descriptor); 973 return NULL; 974 } 975 976 if (setDefinedClassBit(state, classIdx)) { 977 LOGE("Duplicate class definition: '%s'\n", descriptor); 978 return NULL; 979 } 980 981 bool okay = 982 dexDataMapVerify0Ok(state->pDataMap, 983 item->interfacesOff, kDexTypeTypeList) 984 && dexDataMapVerify0Ok(state->pDataMap, 985 item->annotationsOff, kDexTypeAnnotationsDirectoryItem) 986 && dexDataMapVerify0Ok(state->pDataMap, 987 item->classDataOff, kDexTypeClassDataItem) 988 && dexDataMapVerify0Ok(state->pDataMap, 989 item->staticValuesOff, kDexTypeEncodedArrayItem); 990 991 if (!okay) { 992 return NULL; 993 } 994 995 if (item->superclassIdx != kDexNoIndex) { 996 descriptor = dexStringByTypeIdx(state->pDexFile, item->superclassIdx); 997 if (!dexIsClassDescriptor(descriptor)) { 998 LOGE("Invalid superclass: '%s'\n", descriptor); 999 return NULL; 1000 } 1001 } 1002 1003 const DexTypeList* interfaces = 1004 dexGetInterfacesList(state->pDexFile, item); 1005 if (interfaces != NULL) { 1006 u4 size = interfaces->size; 1007 u4 i; 1008 1009 /* 1010 * Ensure that all interfaces refer to classes (not arrays or 1011 * primitives). 1012 */ 1013 for (i = 0; i < size; i++) { 1014 descriptor = dexStringByTypeIdx(state->pDexFile, 1015 dexTypeListGetIdx(interfaces, i)); 1016 if (!dexIsClassDescriptor(descriptor)) { 1017 LOGE("Invalid interface: '%s'\n", descriptor); 1018 return NULL; 1019 } 1020 } 1021 1022 /* 1023 * Ensure that there are no duplicates. This is an O(N^2) test, 1024 * but in practice the number of interfaces implemented by any 1025 * given class is low. I will buy a milkshake for the 1026 * first person to show me a realistic case for which this test 1027 * would be unacceptably slow. 1028 */ 1029 for (i = 1; i < size; i++) { 1030 u4 idx1 = dexTypeListGetIdx(interfaces, i); 1031 u4 j; 1032 for (j = 0; j < i; j++) { 1033 u4 idx2 = dexTypeListGetIdx(interfaces, j); 1034 if (idx1 == idx2) { 1035 LOGE("Duplicate interface: '%s'\n", 1036 dexStringByTypeIdx(state->pDexFile, idx1)); 1037 return NULL; 1038 } 1039 } 1040 } 1041 } 1042 1043 if (!verifyClassDataIsForDef(state, item->classDataOff, item->classIdx)) { 1044 LOGE("Invalid class_data_item\n"); 1045 return NULL; 1046 } 1047 1048 if (!verifyAnnotationsDirectoryIsForDef(state, item->annotationsOff, 1049 item->classIdx)) { 1050 LOGE("Invalid annotations_directory_item\n"); 1051 return NULL; 1052 } 1053 1054 return (void*) (item + 1); 1055 } 1056 1057 /* Helper for swapAnnotationsDirectoryItem(), which performs 1058 * byte-swapping and intra-item verification on an 1059 * annotation_directory_item's field elements. */ 1060 static u1* swapFieldAnnotations(const CheckState* state, u4 count, u1* addr) { 1061 DexFieldAnnotationsItem* item = (DexFieldAnnotationsItem*) addr; 1062 bool first = true; 1063 u4 lastIdx = 0; 1064 1065 CHECK_LIST_SIZE(item, count, sizeof(DexFieldAnnotationsItem)); 1066 1067 while (count--) { 1068 SWAP_INDEX4(item->fieldIdx, state->pHeader->fieldIdsSize); 1069 SWAP_OFFSET4(item->annotationsOff); 1070 1071 if (first) { 1072 first = false; 1073 } else if (lastIdx >= item->fieldIdx) { 1074 LOGE("Out-of-order field_idx: 0x%x then 0x%x\n", lastIdx, 1075 item->fieldIdx); 1076 return NULL; 1077 } 1078 1079 lastIdx = item->fieldIdx; 1080 item++; 1081 } 1082 1083 return (u1*) item; 1084 } 1085 1086 /* Helper for swapAnnotationsDirectoryItem(), which performs 1087 * byte-swapping and intra-item verification on an 1088 * annotation_directory_item's method elements. */ 1089 static u1* swapMethodAnnotations(const CheckState* state, u4 count, u1* addr) { 1090 DexMethodAnnotationsItem* item = (DexMethodAnnotationsItem*) addr; 1091 bool first = true; 1092 u4 lastIdx = 0; 1093 1094 CHECK_LIST_SIZE(item, count, sizeof(DexMethodAnnotationsItem)); 1095 1096 while (count--) { 1097 SWAP_INDEX4(item->methodIdx, state->pHeader->methodIdsSize); 1098 SWAP_OFFSET4(item->annotationsOff); 1099 1100 if (first) { 1101 first = false; 1102 } else if (lastIdx >= item->methodIdx) { 1103 LOGE("Out-of-order method_idx: 0x%x then 0x%x\n", lastIdx, 1104 item->methodIdx); 1105 return NULL; 1106 } 1107 1108 lastIdx = item->methodIdx; 1109 item++; 1110 } 1111 1112 return (u1*) item; 1113 } 1114 1115 /* Helper for swapAnnotationsDirectoryItem(), which performs 1116 * byte-swapping and intra-item verification on an 1117 * annotation_directory_item's parameter elements. */ 1118 static u1* swapParameterAnnotations(const CheckState* state, u4 count, 1119 u1* addr) { 1120 DexParameterAnnotationsItem* item = (DexParameterAnnotationsItem*) addr; 1121 bool first = true; 1122 u4 lastIdx = 0; 1123 1124 CHECK_LIST_SIZE(item, count, sizeof(DexParameterAnnotationsItem)); 1125 1126 while (count--) { 1127 SWAP_INDEX4(item->methodIdx, state->pHeader->methodIdsSize); 1128 SWAP_OFFSET4(item->annotationsOff); 1129 1130 if (first) { 1131 first = false; 1132 } else if (lastIdx >= item->methodIdx) { 1133 LOGE("Out-of-order method_idx: 0x%x then 0x%x\n", lastIdx, 1134 item->methodIdx); 1135 return NULL; 1136 } 1137 1138 lastIdx = item->methodIdx; 1139 item++; 1140 } 1141 1142 return (u1*) item; 1143 } 1144 1145 /* Perform byte-swapping and intra-item verification on 1146 * annotations_directory_item. */ 1147 static void* swapAnnotationsDirectoryItem(const CheckState* state, void* ptr) { 1148 DexAnnotationsDirectoryItem* item = ptr; 1149 1150 CHECK_PTR_RANGE(item, item + 1); 1151 SWAP_OFFSET4(item->classAnnotationsOff); 1152 SWAP_FIELD4(item->fieldsSize); 1153 SWAP_FIELD4(item->methodsSize); 1154 SWAP_FIELD4(item->parametersSize); 1155 1156 u1* addr = (u1*) (item + 1); 1157 1158 if (item->fieldsSize != 0) { 1159 addr = swapFieldAnnotations(state, item->fieldsSize, addr); 1160 if (addr == NULL) { 1161 return NULL; 1162 } 1163 } 1164 1165 if (item->methodsSize != 0) { 1166 addr = swapMethodAnnotations(state, item->methodsSize, addr); 1167 if (addr == NULL) { 1168 return NULL; 1169 } 1170 } 1171 1172 if (item->parametersSize != 0) { 1173 addr = swapParameterAnnotations(state, item->parametersSize, addr); 1174 if (addr == NULL) { 1175 return NULL; 1176 } 1177 } 1178 1179 return addr; 1180 } 1181 1182 /* Helper for crossVerifyAnnotationsDirectoryItem(), which checks the 1183 * field elements. */ 1184 static const u1* crossVerifyFieldAnnotations(const CheckState* state, u4 count, 1185 const u1* addr, u4 definingClass) { 1186 const DexFieldAnnotationsItem* item = (DexFieldAnnotationsItem*) addr; 1187 1188 while (count--) { 1189 if (!verifyFieldDefiner(state, definingClass, item->fieldIdx)) { 1190 return NULL; 1191 } 1192 if (!dexDataMapVerify(state->pDataMap, item->annotationsOff, 1193 kDexTypeAnnotationSetItem)) { 1194 return NULL; 1195 } 1196 item++; 1197 } 1198 1199 return (const u1*) item; 1200 } 1201 1202 /* Helper for crossVerifyAnnotationsDirectoryItem(), which checks the 1203 * method elements. */ 1204 static const u1* crossVerifyMethodAnnotations(const CheckState* state, 1205 u4 count, const u1* addr, u4 definingClass) { 1206 const DexMethodAnnotationsItem* item = (DexMethodAnnotationsItem*) addr; 1207 1208 while (count--) { 1209 if (!verifyMethodDefiner(state, definingClass, item->methodIdx)) { 1210 return NULL; 1211 } 1212 if (!dexDataMapVerify(state->pDataMap, item->annotationsOff, 1213 kDexTypeAnnotationSetItem)) { 1214 return NULL; 1215 } 1216 item++; 1217 } 1218 1219 return (const u1*) item; 1220 } 1221 1222 /* Helper for crossVerifyAnnotationsDirectoryItem(), which checks the 1223 * parameter elements. */ 1224 static const u1* crossVerifyParameterAnnotations(const CheckState* state, 1225 u4 count, const u1* addr, u4 definingClass) { 1226 const DexParameterAnnotationsItem* item = 1227 (DexParameterAnnotationsItem*) addr; 1228 1229 while (count--) { 1230 if (!verifyMethodDefiner(state, definingClass, item->methodIdx)) { 1231 return NULL; 1232 } 1233 if (!dexDataMapVerify(state->pDataMap, item->annotationsOff, 1234 kDexTypeAnnotationSetRefList)) { 1235 return NULL; 1236 } 1237 item++; 1238 } 1239 1240 return (const u1*) item; 1241 } 1242 1243 /* Helper for crossVerifyClassDefItem() and 1244 * crossVerifyAnnotationsDirectoryItem(), which finds the type_idx of 1245 * the definer of the first item in the data. */ 1246 static u4 findFirstAnnotationsDirectoryDefiner(const CheckState* state, 1247 const DexAnnotationsDirectoryItem* dir) { 1248 if (dir->fieldsSize != 0) { 1249 const DexFieldAnnotationsItem* fields = 1250 dexGetFieldAnnotations(state->pDexFile, dir); 1251 const DexFieldId* field = 1252 dexGetFieldId(state->pDexFile, fields[0].fieldIdx); 1253 return field->classIdx; 1254 } 1255 1256 if (dir->methodsSize != 0) { 1257 const DexMethodAnnotationsItem* methods = 1258 dexGetMethodAnnotations(state->pDexFile, dir); 1259 const DexMethodId* method = 1260 dexGetMethodId(state->pDexFile, methods[0].methodIdx); 1261 return method->classIdx; 1262 } 1263 1264 if (dir->parametersSize != 0) { 1265 const DexParameterAnnotationsItem* parameters = 1266 dexGetParameterAnnotations(state->pDexFile, dir); 1267 const DexMethodId* method = 1268 dexGetMethodId(state->pDexFile, parameters[0].methodIdx); 1269 return method->classIdx; 1270 } 1271 1272 return kDexNoIndex; 1273 } 1274 1275 /* Perform cross-item verification of annotations_directory_item. */ 1276 static void* crossVerifyAnnotationsDirectoryItem(const CheckState* state, 1277 void* ptr) { 1278 const DexAnnotationsDirectoryItem* item = ptr; 1279 u4 definingClass = findFirstAnnotationsDirectoryDefiner(state, item); 1280 1281 if (!dexDataMapVerify0Ok(state->pDataMap, 1282 item->classAnnotationsOff, kDexTypeAnnotationSetItem)) { 1283 return NULL; 1284 } 1285 1286 const u1* addr = (const u1*) (item + 1); 1287 1288 if (item->fieldsSize != 0) { 1289 addr = crossVerifyFieldAnnotations(state, item->fieldsSize, addr, 1290 definingClass); 1291 if (addr == NULL) { 1292 return NULL; 1293 } 1294 } 1295 1296 if (item->methodsSize != 0) { 1297 addr = crossVerifyMethodAnnotations(state, item->methodsSize, addr, 1298 definingClass); 1299 if (addr == NULL) { 1300 return NULL; 1301 } 1302 } 1303 1304 if (item->parametersSize != 0) { 1305 addr = crossVerifyParameterAnnotations(state, item->parametersSize, 1306 addr, definingClass); 1307 if (addr == NULL) { 1308 return NULL; 1309 } 1310 } 1311 1312 return (void*) addr; 1313 } 1314 1315 /* Perform byte-swapping and intra-item verification on type_list. */ 1316 static void* swapTypeList(const CheckState* state, void* ptr) 1317 { 1318 DexTypeList* pTypeList = ptr; 1319 DexTypeItem* pType; 1320 u4 count; 1321 1322 CHECK_PTR_RANGE(pTypeList, pTypeList + 1); 1323 SWAP_FIELD4(pTypeList->size); 1324 count = pTypeList->size; 1325 pType = pTypeList->list; 1326 CHECK_LIST_SIZE(pType, count, sizeof(DexTypeItem)); 1327 1328 while (count--) { 1329 SWAP_INDEX2(pType->typeIdx, state->pHeader->typeIdsSize); 1330 pType++; 1331 } 1332 1333 return pType; 1334 } 1335 1336 /* Perform byte-swapping and intra-item verification on 1337 * annotation_set_ref_list. */ 1338 static void* swapAnnotationSetRefList(const CheckState* state, void* ptr) { 1339 DexAnnotationSetRefList* list = ptr; 1340 DexAnnotationSetRefItem* item; 1341 u4 count; 1342 1343 CHECK_PTR_RANGE(list, list + 1); 1344 SWAP_FIELD4(list->size); 1345 count = list->size; 1346 item = list->list; 1347 CHECK_LIST_SIZE(item, count, sizeof(DexAnnotationSetRefItem)); 1348 1349 while (count--) { 1350 SWAP_OFFSET4(item->annotationsOff); 1351 item++; 1352 } 1353 1354 return item; 1355 } 1356 1357 /* Perform cross-item verification of annotation_set_ref_list. */ 1358 static void* crossVerifyAnnotationSetRefList(const CheckState* state, 1359 void* ptr) { 1360 const DexAnnotationSetRefList* list = ptr; 1361 const DexAnnotationSetRefItem* item = list->list; 1362 int count = list->size; 1363 1364 while (count--) { 1365 if (!dexDataMapVerify0Ok(state->pDataMap, 1366 item->annotationsOff, kDexTypeAnnotationSetItem)) { 1367 return NULL; 1368 } 1369 item++; 1370 } 1371 1372 return (void*) item; 1373 } 1374 1375 /* Perform byte-swapping and intra-item verification on 1376 * annotation_set_item. */ 1377 static void* swapAnnotationSetItem(const CheckState* state, void* ptr) { 1378 DexAnnotationSetItem* set = ptr; 1379 u4* item; 1380 u4 count; 1381 1382 CHECK_PTR_RANGE(set, set + 1); 1383 SWAP_FIELD4(set->size); 1384 count = set->size; 1385 item = set->entries; 1386 CHECK_LIST_SIZE(item, count, sizeof(u4)); 1387 1388 while (count--) { 1389 SWAP_OFFSET4(*item); 1390 item++; 1391 } 1392 1393 return item; 1394 } 1395 1396 /* Helper for crossVerifyAnnotationSetItem(), which extracts the type_idx 1397 * out of an annotation_item. */ 1398 static u4 annotationItemTypeIdx(const DexAnnotationItem* item) { 1399 const u1* data = item->annotation; 1400 return readUnsignedLeb128(&data); 1401 } 1402 1403 /* Perform cross-item verification of annotation_set_item. */ 1404 static void* crossVerifyAnnotationSetItem(const CheckState* state, void* ptr) { 1405 const DexAnnotationSetItem* set = ptr; 1406 int count = set->size; 1407 u4 lastIdx = 0; 1408 bool first = true; 1409 int i; 1410 1411 for (i = 0; i < count; i++) { 1412 if (!dexDataMapVerify0Ok(state->pDataMap, 1413 dexGetAnnotationOff(set, i), kDexTypeAnnotationItem)) { 1414 return NULL; 1415 } 1416 1417 const DexAnnotationItem* annotation = 1418 dexGetAnnotationItem(state->pDexFile, set, i); 1419 u4 idx = annotationItemTypeIdx(annotation); 1420 1421 if (first) { 1422 first = false; 1423 } else if (lastIdx >= idx) { 1424 LOGE("Out-of-order entry types: 0x%x then 0x%x\n", 1425 lastIdx, idx); 1426 return NULL; 1427 } 1428 1429 lastIdx = idx; 1430 } 1431 1432 return (void*) (set->entries + count); 1433 } 1434 1435 /* Helper for verifyClassDataItem(), which checks a list of fields. */ 1436 static bool verifyFields(const CheckState* state, u4 size, 1437 DexField* fields, bool expectStatic) { 1438 u4 i; 1439 1440 for (i = 0; i < size; i++) { 1441 DexField* field = &fields[i]; 1442 u4 accessFlags = field->accessFlags; 1443 bool isStatic = (accessFlags & ACC_STATIC) != 0; 1444 1445 CHECK_INDEX(field->fieldIdx, state->pHeader->fieldIdsSize); 1446 1447 if (isStatic != expectStatic) { 1448 LOGE("Field in wrong list @ %d\n", i); 1449 return false; 1450 } 1451 1452 if ((accessFlags & ~ACC_FIELD_MASK) != 0) { 1453 LOGE("Bogus field access flags %x @ %d\n", accessFlags, i); 1454 return false; 1455 } 1456 } 1457 1458 return true; 1459 } 1460 1461 /* Helper for verifyClassDataItem(), which checks a list of methods. */ 1462 static bool verifyMethods(const CheckState* state, u4 size, 1463 DexMethod* methods, bool expectDirect) { 1464 u4 i; 1465 1466 for (i = 0; i < size; i++) { 1467 DexMethod* method = &methods[i]; 1468 1469 CHECK_INDEX(method->methodIdx, state->pHeader->methodIdsSize); 1470 1471 u4 accessFlags = method->accessFlags; 1472 bool isDirect = 1473 (accessFlags & (ACC_STATIC | ACC_PRIVATE | ACC_CONSTRUCTOR)) != 0; 1474 bool expectCode = (accessFlags & (ACC_NATIVE | ACC_ABSTRACT)) == 0; 1475 bool isSynchronized = (accessFlags & ACC_SYNCHRONIZED) != 0; 1476 bool allowSynchronized = (accessFlags & ACC_NATIVE) != 0; 1477 1478 if (isDirect != expectDirect) { 1479 LOGE("Method in wrong list @ %d\n", i); 1480 return false; 1481 } 1482 1483 if (((accessFlags & ~ACC_METHOD_MASK) != 0) 1484 || (isSynchronized && !allowSynchronized)) { 1485 LOGE("Bogus method access flags %x @ %d\n", accessFlags, i); 1486 return false; 1487 } 1488 1489 if (expectCode) { 1490 if (method->codeOff == 0) { 1491 LOGE("Unexpected zero code_off for access_flags %x\n", 1492 accessFlags); 1493 return false; 1494 } 1495 } else if (method->codeOff != 0) { 1496 LOGE("Unexpected non-zero code_off 0x%x for access_flags %x\n", 1497 method->codeOff, accessFlags); 1498 return false; 1499 } 1500 } 1501 1502 return true; 1503 } 1504 1505 /* Helper for verifyClassDataItem(), which does most of the work. */ 1506 static bool verifyClassDataItem0(const CheckState* state, 1507 DexClassData* classData) { 1508 bool okay; 1509 1510 okay = verifyFields(state, classData->header.staticFieldsSize, 1511 classData->staticFields, true); 1512 1513 if (!okay) { 1514 LOGE("Trouble with static fields\n"); 1515 return false; 1516 } 1517 1518 verifyFields(state, classData->header.instanceFieldsSize, 1519 classData->instanceFields, false); 1520 1521 if (!okay) { 1522 LOGE("Trouble with instance fields\n"); 1523 return false; 1524 } 1525 1526 okay = verifyMethods(state, classData->header.directMethodsSize, 1527 classData->directMethods, true); 1528 1529 if (!okay) { 1530 LOGE("Trouble with direct methods\n"); 1531 return false; 1532 } 1533 1534 okay = verifyMethods(state, classData->header.virtualMethodsSize, 1535 classData->virtualMethods, false); 1536 1537 if (!okay) { 1538 LOGE("Trouble with virtual methods\n"); 1539 return false; 1540 } 1541 1542 return true; 1543 } 1544 1545 /* Perform intra-item verification on class_data_item. */ 1546 static void* intraVerifyClassDataItem(const CheckState* state, void* ptr) { 1547 const u1* data = ptr; 1548 DexClassData* classData = dexReadAndVerifyClassData(&data, state->fileEnd); 1549 1550 if (classData == NULL) { 1551 LOGE("Unable to parse class_data_item\n"); 1552 return NULL; 1553 } 1554 1555 bool okay = verifyClassDataItem0(state, classData); 1556 1557 free(classData); 1558 1559 if (!okay) { 1560 return NULL; 1561 } 1562 1563 return (void*) data; 1564 } 1565 1566 /* Helper for crossVerifyClassDefItem() and 1567 * crossVerifyClassDataItem(), which finds the type_idx of the definer 1568 * of the first item in the data. */ 1569 static u4 findFirstClassDataDefiner(const CheckState* state, 1570 DexClassData* classData) { 1571 if (classData->header.staticFieldsSize != 0) { 1572 u4 fieldIdx = classData->staticFields[0].fieldIdx; 1573 const DexFieldId* field = dexGetFieldId(state->pDexFile, fieldIdx); 1574 return field->classIdx; 1575 } 1576 1577 if (classData->header.instanceFieldsSize != 0) { 1578 u4 fieldIdx = classData->instanceFields[0].fieldIdx; 1579 const DexFieldId* field = dexGetFieldId(state->pDexFile, fieldIdx); 1580 return field->classIdx; 1581 } 1582 1583 if (classData->header.directMethodsSize != 0) { 1584 u4 methodIdx = classData->directMethods[0].methodIdx; 1585 const DexMethodId* meth = dexGetMethodId(state->pDexFile, methodIdx); 1586 return meth->classIdx; 1587 } 1588 1589 if (classData->header.virtualMethodsSize != 0) { 1590 u4 methodIdx = classData->virtualMethods[0].methodIdx; 1591 const DexMethodId* meth = dexGetMethodId(state->pDexFile, methodIdx); 1592 return meth->classIdx; 1593 } 1594 1595 return kDexNoIndex; 1596 } 1597 1598 /* Perform cross-item verification of class_data_item. */ 1599 static void* crossVerifyClassDataItem(const CheckState* state, void* ptr) { 1600 const u1* data = ptr; 1601 DexClassData* classData = dexReadAndVerifyClassData(&data, state->fileEnd); 1602 u4 definingClass = findFirstClassDataDefiner(state, classData); 1603 bool okay = true; 1604 u4 i; 1605 1606 for (i = classData->header.staticFieldsSize; okay && (i > 0); /*i*/) { 1607 i--; 1608 const DexField* field = &classData->staticFields[i]; 1609 okay = verifyFieldDefiner(state, definingClass, field->fieldIdx); 1610 } 1611 1612 for (i = classData->header.instanceFieldsSize; okay && (i > 0); /*i*/) { 1613 i--; 1614 const DexField* field = &classData->instanceFields[i]; 1615 okay = verifyFieldDefiner(state, definingClass, field->fieldIdx); 1616 } 1617 1618 for (i = classData->header.directMethodsSize; okay && (i > 0); /*i*/) { 1619 i--; 1620 const DexMethod* meth = &classData->directMethods[i]; 1621 okay = dexDataMapVerify0Ok(state->pDataMap, meth->codeOff, 1622 kDexTypeCodeItem) 1623 && verifyMethodDefiner(state, definingClass, meth->methodIdx); 1624 } 1625 1626 for (i = classData->header.virtualMethodsSize; okay && (i > 0); /*i*/) { 1627 i--; 1628 const DexMethod* meth = &classData->virtualMethods[i]; 1629 okay = dexDataMapVerify0Ok(state->pDataMap, meth->codeOff, 1630 kDexTypeCodeItem) 1631 && verifyMethodDefiner(state, definingClass, meth->methodIdx); 1632 } 1633 1634 free(classData); 1635 1636 if (!okay) { 1637 return NULL; 1638 } 1639 1640 return (void*) data; 1641 } 1642 1643 /* Helper for swapCodeItem(), which fills an array with all the valid 1644 * handlerOff values for catch handlers and also verifies the handler 1645 * contents. */ 1646 static u4 setHandlerOffsAndVerify(const CheckState* state, 1647 DexCode* code, u4 firstOffset, u4 handlersSize, u4* handlerOffs) { 1648 const u1* fileEnd = state->fileEnd; 1649 const u1* handlersBase = dexGetCatchHandlerData(code); 1650 u4 offset = firstOffset; 1651 bool okay = true; 1652 u4 i; 1653 1654 for (i = 0; i < handlersSize; i++) { 1655 const u1* ptr = handlersBase + offset; 1656 int size = readAndVerifySignedLeb128(&ptr, fileEnd, &okay); 1657 bool catchAll; 1658 1659 if (!okay) { 1660 LOGE("Bogus size\n"); 1661 return 0; 1662 } 1663 1664 if ((size < -65536) || (size > 65536)) { 1665 LOGE("Invalid size: %d\n", size); 1666 return 0; 1667 } 1668 1669 if (size <= 0) { 1670 catchAll = true; 1671 size = -size; 1672 } else { 1673 catchAll = false; 1674 } 1675 1676 handlerOffs[i] = offset; 1677 1678 while (size-- > 0) { 1679 u4 typeIdx = 1680 readAndVerifyUnsignedLeb128(&ptr, fileEnd, &okay); 1681 1682 if (!okay) { 1683 LOGE("Bogus type_idx"); 1684 return 0; 1685 } 1686 1687 CHECK_INDEX(typeIdx, state->pHeader->typeIdsSize); 1688 1689 u4 addr = readAndVerifyUnsignedLeb128(&ptr, fileEnd, &okay); 1690 1691 if (!okay) { 1692 LOGE("Bogus addr"); 1693 return 0; 1694 } 1695 1696 if (addr >= code->insnsSize) { 1697 LOGE("Invalid addr: 0x%x", addr); 1698 return 0; 1699 } 1700 } 1701 1702 if (catchAll) { 1703 u4 addr = readAndVerifyUnsignedLeb128(&ptr, fileEnd, &okay); 1704 1705 if (!okay) { 1706 LOGE("Bogus catch_all_addr"); 1707 return 0; 1708 } 1709 1710 if (addr >= code->insnsSize) { 1711 LOGE("Invalid catch_all_addr: 0x%x", addr); 1712 return 0; 1713 } 1714 } 1715 1716 offset = ptr - handlersBase; 1717 } 1718 1719 return offset; 1720 } 1721 1722 /* Helper for swapCodeItem(), which does all the try-catch related 1723 * swapping and verification. */ 1724 static void* swapTriesAndCatches(const CheckState* state, DexCode* code) { 1725 const u1* encodedHandlers = dexGetCatchHandlerData(code); 1726 const u1* encodedPtr = encodedHandlers; 1727 bool okay = true; 1728 u4 handlersSize = 1729 readAndVerifyUnsignedLeb128(&encodedPtr, state->fileEnd, &okay); 1730 1731 if (!okay) { 1732 LOGE("Bogus handlers_size\n"); 1733 return NULL; 1734 } 1735 1736 if ((handlersSize == 0) || (handlersSize >= 65536)) { 1737 LOGE("Invalid handlers_size: %d\n", handlersSize); 1738 return NULL; 1739 } 1740 1741 u4 handlerOffs[handlersSize]; // list of valid handlerOff values 1742 u4 endOffset = setHandlerOffsAndVerify(state, code, 1743 encodedPtr - encodedHandlers, 1744 handlersSize, handlerOffs); 1745 1746 if (endOffset == 0) { 1747 return NULL; 1748 } 1749 1750 DexTry* tries = (DexTry*) dexGetTries(code); 1751 u4 count = code->triesSize; 1752 u4 lastEnd = 0; 1753 1754 CHECK_LIST_SIZE(tries, count, sizeof(DexTry)); 1755 1756 while (count--) { 1757 u4 i; 1758 1759 SWAP_FIELD4(tries->startAddr); 1760 SWAP_FIELD2(tries->insnCount); 1761 SWAP_FIELD2(tries->handlerOff); 1762 1763 if (tries->startAddr < lastEnd) { 1764 LOGE("Out-of-order try\n"); 1765 return NULL; 1766 } 1767 1768 if (tries->startAddr >= code->insnsSize) { 1769 LOGE("Invalid start_addr: 0x%x\n", tries->startAddr); 1770 return NULL; 1771 } 1772 1773 for (i = 0; i < handlersSize; i++) { 1774 if (tries->handlerOff == handlerOffs[i]) { 1775 break; 1776 } 1777 } 1778 1779 if (i == handlersSize) { 1780 LOGE("Bogus handler offset: 0x%x\n", tries->handlerOff); 1781 return NULL; 1782 } 1783 1784 lastEnd = tries->startAddr + tries->insnCount; 1785 1786 if (lastEnd > code->insnsSize) { 1787 LOGE("Invalid insn_count: 0x%x (end addr 0x%x)\n", 1788 tries->insnCount, lastEnd); 1789 return NULL; 1790 } 1791 1792 tries++; 1793 } 1794 1795 return (u1*) encodedHandlers + endOffset; 1796 } 1797 1798 /* Perform byte-swapping and intra-item verification on code_item. */ 1799 static void* swapCodeItem(const CheckState* state, void* ptr) { 1800 DexCode* item = ptr; 1801 u2* insns; 1802 u4 count; 1803 1804 CHECK_PTR_RANGE(item, item + 1); 1805 SWAP_FIELD2(item->registersSize); 1806 SWAP_FIELD2(item->insSize); 1807 SWAP_FIELD2(item->outsSize); 1808 SWAP_FIELD2(item->triesSize); 1809 SWAP_OFFSET4(item->debugInfoOff); 1810 SWAP_FIELD4(item->insnsSize); 1811 1812 if (item->insSize > item->registersSize) { 1813 LOGE("insSize (%u) > registersSize (%u)\n", item->insSize, 1814 item->registersSize); 1815 return NULL; 1816 } 1817 1818 if ((item->outsSize > 5) && (item->outsSize > item->registersSize)) { 1819 /* 1820 * It's okay for outsSize to be up to five, even if registersSize 1821 * is smaller, since the short forms of method invocation allow 1822 * repetition of a register multiple times within a single parameter 1823 * list. Longer parameter lists, though, need to be represented 1824 * in-order in the register file. 1825 */ 1826 LOGE("outsSize (%u) > registersSize (%u)\n", item->outsSize, 1827 item->registersSize); 1828 return NULL; 1829 } 1830 1831 count = item->insnsSize; 1832 insns = item->insns; 1833 CHECK_LIST_SIZE(insns, count, sizeof(u2)); 1834 1835 while (count--) { 1836 *insns = SWAP2(*insns); 1837 insns++; 1838 } 1839 1840 if (item->triesSize == 0) { 1841 ptr = insns; 1842 } else { 1843 if ((((u4) insns) & 3) != 0) { 1844 // Four-byte alignment for the tries. Verify the spacer is a 0. 1845 if (*insns != 0) { 1846 LOGE("Non-zero padding: 0x%x\n", (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 = ptr; 1861 bool okay = true; 1862 u4 utf16Size = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 1863 u4 i; 1864 1865 if (!okay) { 1866 LOGE("Bogus utf16_size\n"); 1867 return NULL; 1868 } 1869 1870 for (i = 0; i < utf16Size; i++) { 1871 if (data >= fileEnd) { 1872 LOGE("String data would go beyond end-of-file\n"); 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 LOGE("String shorter than indicated utf16_size 0x%x\n", 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 LOGE("Illegal start byte 0x%x\n", 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 LOGE("Illegal continuation byte 0x%x\n", byte2); 1917 return NULL; 1918 } 1919 u1 byte3 = *(data++); 1920 if ((byte3 & 0xc0) != 0x80) { 1921 LOGE("Illegal continuation byte 0x%x\n", byte3); 1922 return NULL; 1923 } 1924 u2 value = ((byte1 & 0x0f) << 12) | ((byte2 & 0x3f) << 6) 1925 | (byte3 & 0x3f); 1926 if (value < 0x800) { 1927 LOGE("Illegal representation for value %x\n", 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 LOGE("Illegal continuation byte 0x%x\n", byte2); 1938 return NULL; 1939 } 1940 u2 value = ((byte1 & 0x1f) << 6) | (byte2 & 0x3f); 1941 if ((value != 0) && (value < 0x80)) { 1942 LOGE("Illegal representation for value %x\n", value); 1943 return NULL; 1944 } 1945 break; 1946 } 1947 } 1948 } 1949 1950 if (*(data++) != '\0') { 1951 LOGE("String longer than indicated utf16_size 0x%x\n", 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 = ptr; 1962 bool okay = true; 1963 u4 i; 1964 1965 readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 1966 1967 if (!okay) { 1968 LOGE("Bogus line_start\n"); 1969 return NULL; 1970 } 1971 1972 u4 parametersSize = 1973 readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 1974 1975 if (!okay) { 1976 LOGE("Bogus parameters_size\n"); 1977 return NULL; 1978 } 1979 1980 if (parametersSize > 65536) { 1981 LOGE("Invalid parameters_size: 0x%x\n", 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 LOGE("Bogus parameter_name\n"); 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 LOGE("Bogus syntax for opcode %02x\n", 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 LOGE("Bogus encoded_array size\n"); 2133 return NULL; 2134 } 2135 2136 while (size--) { 2137 data = verifyEncodedValue(state, data, crossVerify); 2138 if (data == NULL) { 2139 LOGE("Bogus encoded_array value\n"); 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 LOGE("Bogus byte size 0x%x\n", valueArg); 2161 return NULL; 2162 } 2163 data++; 2164 break; 2165 } 2166 case kDexAnnotationShort: 2167 case kDexAnnotationChar: { 2168 if (valueArg > 1) { 2169 LOGE("Bogus char/short size 0x%x\n", valueArg); 2170 return NULL; 2171 } 2172 data += valueArg + 1; 2173 break; 2174 } 2175 case kDexAnnotationInt: 2176 case kDexAnnotationFloat: { 2177 if (valueArg > 3) { 2178 LOGE("Bogus int/float size 0x%x\n", 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 LOGE("Bogus string size 0x%x\n", 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 LOGE("Bogus type size 0x%x\n", 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 LOGE("Bogus field/enum size 0x%x\n", 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 LOGE("Bogus method size 0x%x\n", 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 LOGE("Bogus array value_arg 0x%x\n", valueArg); 2229 return NULL; 2230 } 2231 data = verifyEncodedArray(state, data, crossVerify); 2232 break; 2233 } 2234 case kDexAnnotationAnnotation: { 2235 if (valueArg != 0) { 2236 LOGE("Bogus annotation value_arg 0x%x\n", valueArg); 2237 return NULL; 2238 } 2239 data = verifyEncodedAnnotation(state, data, crossVerify); 2240 break; 2241 } 2242 case kDexAnnotationNull: { 2243 if (valueArg != 0) { 2244 LOGE("Bogus null value_arg 0x%x\n", valueArg); 2245 return NULL; 2246 } 2247 // Nothing else to do for this type. 2248 break; 2249 } 2250 case kDexAnnotationBoolean: { 2251 if (valueArg > 1) { 2252 LOGE("Bogus boolean value_arg 0x%x\n", valueArg); 2253 return NULL; 2254 } 2255 // Nothing else to do for this type. 2256 break; 2257 } 2258 default: { 2259 LOGE("Bogus value_type 0x%x\n", 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 LOGE("Bogus encoded_annotation type_idx\n"); 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 LOGE("Bogus annotation type: '%s'\n", 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 LOGE("Bogus encoded_annotation size\n"); 2296 return NULL; 2297 } 2298 2299 while (size--) { 2300 idx = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 2301 2302 if (!okay) { 2303 LOGE("Bogus encoded_annotation name_idx\n"); 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 LOGE("Bogus annotation member name: '%s'\n", name); 2313 return NULL; 2314 } 2315 } 2316 2317 if (first) { 2318 first = false; 2319 } else if (lastIdx >= idx) { 2320 LOGE("Out-of-order encoded_annotation name_idx: 0x%x then 0x%x\n", 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 = 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 LOGE("Bogus annotation visibility: 0x%x\n", *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 = 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 = filePointer(state, newOffset); 2396 2397 if (offset < newOffset) { 2398 ptr = filePointer(state, offset); 2399 if (offset < newOffset) { 2400 CHECK_OFFSET_RANGE(offset, newOffset); 2401 while (offset < newOffset) { 2402 if (*ptr != '\0') { 2403 LOGE("Non-zero padding 0x%02x @ %x\n", *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 LOGE("Trouble with item %d @ offset 0x%x\n", i, offset); 2417 return false; 2418 } 2419 2420 if (newOffset > state->fileLen) { 2421 LOGE("Item %d @ offset 0x%x ends out of bounds\n", 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 LOGE("Bogus offset for section: got 0x%x; expected 0x%x\n", 2460 offset, expectedOffset); 2461 return false; 2462 } 2463 2464 if (count != expectedCount) { 2465 LOGE("Bogus size for section: got 0x%x; expected 0x%x\n", 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 LOGE("Bogus offset for data subsection: 0x%x\n", 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 LOGE("Out-of-bounds end of data subsection: 0x%x\n", *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 = filePointer(state, lastOffset); 2526 while (lastOffset < sectionOffset) { 2527 if (*ptr != '\0') { 2528 LOGE("Non-zero padding 0x%02x before section start @ %x\n", 2529 *ptr, lastOffset); 2530 okay = false; 2531 break; 2532 } 2533 ptr++; 2534 lastOffset++; 2535 } 2536 } else if (lastOffset > sectionOffset) { 2537 LOGE("Section overlap or out-of-order map: %x, %x\n", 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 LOGE("Unknown map item type %04x\n", type); 2666 return false; 2667 } 2668 } 2669 2670 if (!okay) { 2671 LOGE("Swap of section type %04x failed\n", 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 LOGE("Unknown map item type %04x\n", item->type); 2767 return false; 2768 } 2769 } 2770 2771 if (!okay) { 2772 LOGE("Cross-item verify of section type %04x failed\n", 2773 item->type); 2774 } 2775 2776 item++; 2777 } 2778 2779 return okay; 2780 } 2781 2782 /* 2783 * Fix the byte ordering of all fields in the DEX file, and do 2784 * structural verification. This is only required for code that opens 2785 * "raw" DEX files, such as the DEX optimizer. 2786 * 2787 * Returns 0 on success, nonzero on failure. 2788 */ 2789 int dexSwapAndVerify(u1* addr, int len) 2790 { 2791 DexHeader* pHeader; 2792 CheckState state; 2793 bool okay = true; 2794 2795 memset(&state, 0, sizeof(state)); 2796 LOGV("+++ swapping and verifying\n"); 2797 2798 /* 2799 * Start by verifying the magic number. The caller verified that "len" 2800 * says we have at least a header's worth of data. 2801 */ 2802 pHeader = (DexHeader*) addr; 2803 if (memcmp(pHeader->magic, DEX_MAGIC, 4) != 0) { 2804 /* really shouldn't be here -- this is weird */ 2805 LOGE("ERROR: Can't byte swap: bad magic number " 2806 "(0x%02x %02x %02x %02x)\n", 2807 pHeader->magic[0], pHeader->magic[1], 2808 pHeader->magic[2], pHeader->magic[3]); 2809 okay = false; 2810 } 2811 2812 if (okay && memcmp(pHeader->magic+4, DEX_MAGIC_VERS, 4) != 0) { 2813 /* older or newer version we don't know how to read */ 2814 LOGE("ERROR: Can't byte swap: bad dex version " 2815 "(0x%02x %02x %02x %02x)\n", 2816 pHeader->magic[4], pHeader->magic[5], 2817 pHeader->magic[6], pHeader->magic[7]); 2818 okay = false; 2819 } 2820 2821 if (okay) { 2822 int expectedLen = (int) SWAP4(pHeader->fileSize); 2823 if (len < expectedLen) { 2824 LOGE("ERROR: Bad length: expected %d, got %d\n", expectedLen, len); 2825 okay = false; 2826 } else if (len != expectedLen) { 2827 LOGW("WARNING: Odd length: expected %d, got %d\n", expectedLen, 2828 len); 2829 // keep going 2830 } 2831 } 2832 2833 if (okay) { 2834 /* 2835 * Compute the adler32 checksum and compare it to what's stored in 2836 * the file. This isn't free, but chances are good that we just 2837 * unpacked this from a jar file and have all of the pages sitting 2838 * in memory, so it's pretty quick. 2839 * 2840 * This might be a big-endian system, so we need to do this before 2841 * we byte-swap the header. 2842 */ 2843 uLong adler = adler32(0L, Z_NULL, 0); 2844 const int nonSum = sizeof(pHeader->magic) + sizeof(pHeader->checksum); 2845 u4 storedFileSize = SWAP4(pHeader->fileSize); 2846 u4 expectedChecksum = SWAP4(pHeader->checksum); 2847 2848 adler = adler32(adler, ((const u1*) pHeader) + nonSum, 2849 storedFileSize - nonSum); 2850 2851 if (adler != expectedChecksum) { 2852 LOGE("ERROR: bad checksum (%08lx, expected %08x)\n", 2853 adler, expectedChecksum); 2854 okay = false; 2855 } 2856 } 2857 2858 if (okay) { 2859 state.fileStart = addr; 2860 state.fileEnd = addr + len; 2861 state.fileLen = len; 2862 state.pDexFile = NULL; 2863 state.pDataMap = NULL; 2864 state.pDefinedClassBits = NULL; 2865 state.previousItem = NULL; 2866 2867 /* 2868 * Swap the header and check the contents. 2869 */ 2870 okay = swapDexHeader(&state, pHeader); 2871 } 2872 2873 if (okay) { 2874 state.pHeader = pHeader; 2875 2876 if (pHeader->headerSize < sizeof(DexHeader)) { 2877 LOGE("ERROR: Small header size %d, struct %d\n", 2878 pHeader->headerSize, (int) sizeof(DexHeader)); 2879 okay = false; 2880 } else if (pHeader->headerSize > sizeof(DexHeader)) { 2881 LOGW("WARNING: Large header size %d, struct %d\n", 2882 pHeader->headerSize, (int) sizeof(DexHeader)); 2883 // keep going? 2884 } 2885 } 2886 2887 if (okay) { 2888 /* 2889 * Look for the map. Swap it and then use it to find and swap 2890 * everything else. 2891 */ 2892 if (pHeader->mapOff != 0) { 2893 DexFile dexFile; 2894 DexMapList* pDexMap = (DexMapList*) (addr + pHeader->mapOff); 2895 2896 okay = okay && swapMap(&state, pDexMap); 2897 okay = okay && swapEverythingButHeaderAndMap(&state, pDexMap); 2898 2899 dexFileSetupBasicPointers(&dexFile, addr); 2900 state.pDexFile = &dexFile; 2901 2902 okay = okay && crossVerifyEverything(&state, pDexMap); 2903 } else { 2904 LOGE("ERROR: No map found; impossible to byte-swap and verify"); 2905 okay = false; 2906 } 2907 } 2908 2909 if (!okay) { 2910 LOGE("ERROR: Byte swap + verify failed\n"); 2911 } 2912 2913 if (state.pDataMap != NULL) { 2914 dexDataMapFree(state.pDataMap); 2915 } 2916 2917 return !okay; // 0 == success 2918 } 2919 2920 /* 2921 * Detect the file type of the given memory buffer via magic number. 2922 * Call dexSwapAndVerify() on an unoptimized DEX file, do nothing 2923 * but return successfully on an optimized DEX file, and report an 2924 * error for all other cases. 2925 * 2926 * Returns 0 on success, nonzero on failure. 2927 */ 2928 int dexSwapAndVerifyIfNecessary(u1* addr, int len) 2929 { 2930 if (memcmp(addr, DEX_OPT_MAGIC, 4) == 0) { 2931 // It is an optimized dex file. 2932 return 0; 2933 } 2934 2935 if (memcmp(addr, DEX_MAGIC, 4) == 0) { 2936 // It is an unoptimized dex file. 2937 return dexSwapAndVerify(addr, len); 2938 } 2939 2940 LOGE("ERROR: Bad magic number (0x%02x %02x %02x %02x)\n", 2941 addr[0], addr[1], addr[2], addr[3]); 2942 2943 return 1; 2944 } 2945