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 count = item->insnsSize; 1813 insns = item->insns; 1814 CHECK_LIST_SIZE(insns, count, sizeof(u2)); 1815 1816 while (count--) { 1817 *insns = SWAP2(*insns); 1818 insns++; 1819 } 1820 1821 if (item->triesSize == 0) { 1822 ptr = insns; 1823 } else { 1824 if ((((u4) insns) & 3) != 0) { 1825 // Four-byte alignment for the tries. Verify the spacer is a 0. 1826 if (*insns != 0) { 1827 LOGE("Non-zero padding: 0x%x\n", (u4) *insns); 1828 return NULL; 1829 } 1830 } 1831 1832 ptr = swapTriesAndCatches(state, item); 1833 } 1834 1835 return ptr; 1836 } 1837 1838 /* Perform intra-item verification on string_data_item. */ 1839 static void* intraVerifyStringDataItem(const CheckState* state, void* ptr) { 1840 const u1* fileEnd = state->fileEnd; 1841 const u1* data = ptr; 1842 bool okay = true; 1843 u4 utf16Size = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 1844 u4 i; 1845 1846 if (!okay) { 1847 LOGE("Bogus utf16_size\n"); 1848 return NULL; 1849 } 1850 1851 for (i = 0; i < utf16Size; i++) { 1852 if (data >= fileEnd) { 1853 LOGE("String data would go beyond end-of-file\n"); 1854 return NULL; 1855 } 1856 1857 u1 byte1 = *(data++); 1858 1859 // Switch on the high four bits. 1860 switch (byte1 >> 4) { 1861 case 0x00: { 1862 // Special case of bit pattern 0xxx. 1863 if (byte1 == 0) { 1864 LOGE("String shorter than indicated utf16_size 0x%x\n", 1865 utf16Size); 1866 return NULL; 1867 } 1868 break; 1869 } 1870 case 0x01: 1871 case 0x02: 1872 case 0x03: 1873 case 0x04: 1874 case 0x05: 1875 case 0x06: 1876 case 0x07: { 1877 // Bit pattern 0xxx. No need for any extra bytes or checks. 1878 break; 1879 } 1880 case 0x08: 1881 case 0x09: 1882 case 0x0a: 1883 case 0x0b: 1884 case 0x0f: { 1885 /* 1886 * Bit pattern 10xx or 1111, which are illegal start bytes. 1887 * Note: 1111 is valid for normal UTF-8, but not the 1888 * modified UTF-8 used here. 1889 */ 1890 LOGE("Illegal start byte 0x%x\n", byte1); 1891 return NULL; 1892 } 1893 case 0x0e: { 1894 // Bit pattern 1110, so there are two additional bytes. 1895 u1 byte2 = *(data++); 1896 if ((byte2 & 0xc0) != 0x80) { 1897 LOGE("Illegal continuation byte 0x%x\n", byte2); 1898 return NULL; 1899 } 1900 u1 byte3 = *(data++); 1901 if ((byte3 & 0xc0) != 0x80) { 1902 LOGE("Illegal continuation byte 0x%x\n", byte3); 1903 return NULL; 1904 } 1905 u2 value = ((byte1 & 0x0f) << 12) | ((byte2 & 0x3f) << 6) 1906 | (byte3 & 0x3f); 1907 if (value < 0x800) { 1908 LOGE("Illegal representation for value %x\n", value); 1909 return NULL; 1910 } 1911 break; 1912 } 1913 case 0x0c: 1914 case 0x0d: { 1915 // Bit pattern 110x, so there is one additional byte. 1916 u1 byte2 = *(data++); 1917 if ((byte2 & 0xc0) != 0x80) { 1918 LOGE("Illegal continuation byte 0x%x\n", byte2); 1919 return NULL; 1920 } 1921 u2 value = ((byte1 & 0x1f) << 6) | (byte2 & 0x3f); 1922 if ((value != 0) && (value < 0x80)) { 1923 LOGE("Illegal representation for value %x\n", value); 1924 return NULL; 1925 } 1926 break; 1927 } 1928 } 1929 } 1930 1931 if (*(data++) != '\0') { 1932 LOGE("String longer than indicated utf16_size 0x%x\n", utf16Size); 1933 return NULL; 1934 } 1935 1936 return (void*) data; 1937 } 1938 1939 /* Perform intra-item verification on debug_info_item. */ 1940 static void* intraVerifyDebugInfoItem(const CheckState* state, void* ptr) { 1941 const u1* fileEnd = state->fileEnd; 1942 const u1* data = ptr; 1943 bool okay = true; 1944 u4 i; 1945 1946 readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 1947 1948 if (!okay) { 1949 LOGE("Bogus line_start\n"); 1950 return NULL; 1951 } 1952 1953 u4 parametersSize = 1954 readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 1955 1956 if (!okay) { 1957 LOGE("Bogus parameters_size\n"); 1958 return NULL; 1959 } 1960 1961 if (parametersSize > 65536) { 1962 LOGE("Invalid parameters_size: 0x%x\n", parametersSize); 1963 return NULL; 1964 } 1965 1966 for (i = 0; i < parametersSize; i++) { 1967 u4 parameterName = 1968 readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 1969 1970 if (!okay) { 1971 LOGE("Bogus parameter_name\n"); 1972 return NULL; 1973 } 1974 1975 if (parameterName != 0) { 1976 parameterName--; 1977 CHECK_INDEX(parameterName, state->pHeader->stringIdsSize); 1978 } 1979 } 1980 1981 bool done = false; 1982 while (!done) { 1983 u1 opcode = *(data++); 1984 1985 switch (opcode) { 1986 case DBG_END_SEQUENCE: { 1987 done = true; 1988 break; 1989 } 1990 case DBG_ADVANCE_PC: { 1991 readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 1992 break; 1993 } 1994 case DBG_ADVANCE_LINE: { 1995 readAndVerifySignedLeb128(&data, fileEnd, &okay); 1996 break; 1997 } 1998 case DBG_START_LOCAL: { 1999 u4 idx; 2000 u4 regNum = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 2001 if (!okay) break; 2002 if (regNum >= 65536) { 2003 okay = false; 2004 break; 2005 } 2006 idx = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 2007 if (!okay) break; 2008 if (idx != 0) { 2009 idx--; 2010 CHECK_INDEX(idx, state->pHeader->stringIdsSize); 2011 } 2012 idx = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 2013 if (!okay) break; 2014 if (idx != 0) { 2015 idx--; 2016 CHECK_INDEX(idx, state->pHeader->stringIdsSize); 2017 } 2018 break; 2019 } 2020 case DBG_END_LOCAL: 2021 case DBG_RESTART_LOCAL: { 2022 u4 regNum = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 2023 if (!okay) break; 2024 if (regNum >= 65536) { 2025 okay = false; 2026 break; 2027 } 2028 break; 2029 } 2030 case DBG_START_LOCAL_EXTENDED: { 2031 u4 idx; 2032 u4 regNum = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 2033 if (!okay) break; 2034 if (regNum >= 65536) { 2035 okay = false; 2036 break; 2037 } 2038 idx = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 2039 if (!okay) break; 2040 if (idx != 0) { 2041 idx--; 2042 CHECK_INDEX(idx, state->pHeader->stringIdsSize); 2043 } 2044 idx = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 2045 if (!okay) break; 2046 if (idx != 0) { 2047 idx--; 2048 CHECK_INDEX(idx, state->pHeader->stringIdsSize); 2049 } 2050 idx = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 2051 if (!okay) break; 2052 if (idx != 0) { 2053 idx--; 2054 CHECK_INDEX(idx, state->pHeader->stringIdsSize); 2055 } 2056 break; 2057 } 2058 case DBG_SET_FILE: { 2059 u4 idx = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 2060 if (!okay) break; 2061 if (idx != 0) { 2062 idx--; 2063 CHECK_INDEX(idx, state->pHeader->stringIdsSize); 2064 } 2065 break; 2066 } 2067 default: { 2068 // No arguments to parse for anything else. 2069 } 2070 } 2071 2072 if (!okay) { 2073 LOGE("Bogus syntax for opcode %02x\n", opcode); 2074 return NULL; 2075 } 2076 } 2077 2078 return (void*) data; 2079 } 2080 2081 /* defined below */ 2082 static const u1* verifyEncodedValue(const CheckState* state, const u1* data, 2083 bool crossVerify); 2084 static const u1* verifyEncodedAnnotation(const CheckState* state, 2085 const u1* data, bool crossVerify); 2086 2087 /* Helper for verifyEncodedValue(), which reads a 1- to 4- byte unsigned 2088 * little endian value. */ 2089 static u4 readUnsignedLittleEndian(const CheckState* state, const u1** pData, 2090 u4 size) { 2091 const u1* data = *pData; 2092 u4 result = 0; 2093 u4 i; 2094 2095 CHECK_PTR_RANGE(data, data + size); 2096 2097 for (i = 0; i < size; i++) { 2098 result |= ((u4) *(data++)) << (i * 8); 2099 } 2100 2101 *pData = data; 2102 return result; 2103 } 2104 2105 /* Helper for *VerifyAnnotationItem() and *VerifyEncodedArrayItem(), which 2106 * verifies an encoded_array. */ 2107 static const u1* verifyEncodedArray(const CheckState* state, 2108 const u1* data, bool crossVerify) { 2109 bool okay = true; 2110 u4 size = readAndVerifyUnsignedLeb128(&data, state->fileEnd, &okay); 2111 2112 if (!okay) { 2113 LOGE("Bogus encoded_array size\n"); 2114 return NULL; 2115 } 2116 2117 while (size--) { 2118 data = verifyEncodedValue(state, data, crossVerify); 2119 if (data == NULL) { 2120 LOGE("Bogus encoded_array value\n"); 2121 return NULL; 2122 } 2123 } 2124 2125 return data; 2126 } 2127 2128 /* Helper for *VerifyAnnotationItem() and *VerifyEncodedArrayItem(), which 2129 * verifies an encoded_value. */ 2130 static const u1* verifyEncodedValue(const CheckState* state, 2131 const u1* data, bool crossVerify) { 2132 CHECK_PTR_RANGE(data, data + 1); 2133 2134 u1 headerByte = *(data++); 2135 u4 valueType = headerByte & kDexAnnotationValueTypeMask; 2136 u4 valueArg = headerByte >> kDexAnnotationValueArgShift; 2137 2138 switch (valueType) { 2139 case kDexAnnotationByte: { 2140 if (valueArg != 0) { 2141 LOGE("Bogus byte size 0x%x\n", valueArg); 2142 return NULL; 2143 } 2144 data++; 2145 break; 2146 } 2147 case kDexAnnotationShort: 2148 case kDexAnnotationChar: { 2149 if (valueArg > 1) { 2150 LOGE("Bogus char/short size 0x%x\n", valueArg); 2151 return NULL; 2152 } 2153 data += valueArg + 1; 2154 break; 2155 } 2156 case kDexAnnotationInt: 2157 case kDexAnnotationFloat: { 2158 if (valueArg > 3) { 2159 LOGE("Bogus int/float size 0x%x\n", valueArg); 2160 return NULL; 2161 } 2162 data += valueArg + 1; 2163 break; 2164 } 2165 case kDexAnnotationLong: 2166 case kDexAnnotationDouble: { 2167 data += valueArg + 1; 2168 break; 2169 } 2170 case kDexAnnotationString: { 2171 if (valueArg > 3) { 2172 LOGE("Bogus string size 0x%x\n", valueArg); 2173 return NULL; 2174 } 2175 u4 idx = readUnsignedLittleEndian(state, &data, valueArg + 1); 2176 CHECK_INDEX(idx, state->pHeader->stringIdsSize); 2177 break; 2178 } 2179 case kDexAnnotationType: { 2180 if (valueArg > 3) { 2181 LOGE("Bogus type size 0x%x\n", valueArg); 2182 return NULL; 2183 } 2184 u4 idx = readUnsignedLittleEndian(state, &data, valueArg + 1); 2185 CHECK_INDEX(idx, state->pHeader->typeIdsSize); 2186 break; 2187 } 2188 case kDexAnnotationField: 2189 case kDexAnnotationEnum: { 2190 if (valueArg > 3) { 2191 LOGE("Bogus field/enum size 0x%x\n", valueArg); 2192 return NULL; 2193 } 2194 u4 idx = readUnsignedLittleEndian(state, &data, valueArg + 1); 2195 CHECK_INDEX(idx, state->pHeader->fieldIdsSize); 2196 break; 2197 } 2198 case kDexAnnotationMethod: { 2199 if (valueArg > 3) { 2200 LOGE("Bogus method size 0x%x\n", valueArg); 2201 return NULL; 2202 } 2203 u4 idx = readUnsignedLittleEndian(state, &data, valueArg + 1); 2204 CHECK_INDEX(idx, state->pHeader->methodIdsSize); 2205 break; 2206 } 2207 case kDexAnnotationArray: { 2208 if (valueArg != 0) { 2209 LOGE("Bogus array value_arg 0x%x\n", valueArg); 2210 return NULL; 2211 } 2212 data = verifyEncodedArray(state, data, crossVerify); 2213 break; 2214 } 2215 case kDexAnnotationAnnotation: { 2216 if (valueArg != 0) { 2217 LOGE("Bogus annotation value_arg 0x%x\n", valueArg); 2218 return NULL; 2219 } 2220 data = verifyEncodedAnnotation(state, data, crossVerify); 2221 break; 2222 } 2223 case kDexAnnotationNull: { 2224 if (valueArg != 0) { 2225 LOGE("Bogus null value_arg 0x%x\n", valueArg); 2226 return NULL; 2227 } 2228 // Nothing else to do for this type. 2229 break; 2230 } 2231 case kDexAnnotationBoolean: { 2232 if (valueArg > 1) { 2233 LOGE("Bogus boolean value_arg 0x%x\n", valueArg); 2234 return NULL; 2235 } 2236 // Nothing else to do for this type. 2237 break; 2238 } 2239 default: { 2240 LOGE("Bogus value_type 0x%x\n", valueType); 2241 return NULL; 2242 } 2243 } 2244 2245 return data; 2246 } 2247 2248 /* Helper for *VerifyAnnotationItem() and *VerifyEncodedArrayItem(), which 2249 * verifies an encoded_annotation. */ 2250 static const u1* verifyEncodedAnnotation(const CheckState* state, 2251 const u1* data, bool crossVerify) { 2252 const u1* fileEnd = state->fileEnd; 2253 bool okay = true; 2254 u4 idx = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 2255 2256 if (!okay) { 2257 LOGE("Bogus encoded_annotation type_idx\n"); 2258 return NULL; 2259 } 2260 2261 CHECK_INDEX(idx, state->pHeader->typeIdsSize); 2262 2263 if (crossVerify) { 2264 const char* descriptor = dexStringByTypeIdx(state->pDexFile, idx); 2265 if (!dexIsClassDescriptor(descriptor)) { 2266 LOGE("Bogus annotation type: '%s'\n", descriptor); 2267 return NULL; 2268 } 2269 } 2270 2271 u4 size = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 2272 u4 lastIdx = 0; 2273 bool first = true; 2274 2275 if (!okay) { 2276 LOGE("Bogus encoded_annotation size\n"); 2277 return NULL; 2278 } 2279 2280 while (size--) { 2281 idx = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 2282 2283 if (!okay) { 2284 LOGE("Bogus encoded_annotation name_idx\n"); 2285 return NULL; 2286 } 2287 2288 CHECK_INDEX(idx, state->pHeader->stringIdsSize); 2289 2290 if (crossVerify) { 2291 const char* name = dexStringById(state->pDexFile, idx); 2292 if (!dexIsValidMemberName(name)) { 2293 LOGE("Bogus annotation member name: '%s'\n", name); 2294 return NULL; 2295 } 2296 } 2297 2298 if (first) { 2299 first = false; 2300 } else if (lastIdx >= idx) { 2301 LOGE("Out-of-order encoded_annotation name_idx: 0x%x then 0x%x\n", 2302 lastIdx, idx); 2303 return NULL; 2304 } 2305 2306 data = verifyEncodedValue(state, data, crossVerify); 2307 lastIdx = idx; 2308 2309 if (data == NULL) { 2310 return NULL; 2311 } 2312 } 2313 2314 return data; 2315 } 2316 2317 /* Perform intra-item verification on encoded_array_item. */ 2318 static void* intraVerifyEncodedArrayItem(const CheckState* state, void* ptr) { 2319 return (void*) verifyEncodedArray(state, (const u1*) ptr, false); 2320 } 2321 2322 /* Perform intra-item verification on annotation_item. */ 2323 static void* intraVerifyAnnotationItem(const CheckState* state, void* ptr) { 2324 const u1* data = ptr; 2325 2326 CHECK_PTR_RANGE(data, data + 1); 2327 2328 switch (*(data++)) { 2329 case kDexVisibilityBuild: 2330 case kDexVisibilityRuntime: 2331 case kDexVisibilitySystem: { 2332 break; 2333 } 2334 default: { 2335 LOGE("Bogus annotation visibility: 0x%x\n", *data); 2336 return NULL; 2337 } 2338 } 2339 2340 return (void*) verifyEncodedAnnotation(state, data, false); 2341 } 2342 2343 /* Perform cross-item verification on annotation_item. */ 2344 static void* crossVerifyAnnotationItem(const CheckState* state, void* ptr) { 2345 const u1* data = ptr; 2346 2347 // Skip the visibility byte. 2348 data++; 2349 2350 return (void*) verifyEncodedAnnotation(state, data, true); 2351 } 2352 2353 2354 2355 2356 /* 2357 * Function to visit an individual top-level item type. 2358 */ 2359 typedef void* ItemVisitorFunction(const CheckState* state, void* ptr); 2360 2361 /* 2362 * Iterate over all the items in a section, optionally updating the 2363 * data map (done if mapType is passed as non-negative). The section 2364 * must consist of concatenated items of the same type. 2365 */ 2366 static bool iterateSectionWithOptionalUpdate(CheckState* state, 2367 u4 offset, u4 count, ItemVisitorFunction* func, u4 alignment, 2368 u4* nextOffset, int mapType) { 2369 u4 alignmentMask = alignment - 1; 2370 u4 i; 2371 2372 state->previousItem = NULL; 2373 2374 for (i = 0; i < count; i++) { 2375 u4 newOffset = (offset + alignmentMask) & ~alignmentMask; 2376 u1* ptr = filePointer(state, newOffset); 2377 2378 if (offset < newOffset) { 2379 ptr = filePointer(state, offset); 2380 if (offset < newOffset) { 2381 CHECK_OFFSET_RANGE(offset, newOffset); 2382 while (offset < newOffset) { 2383 if (*ptr != '\0') { 2384 LOGE("Non-zero padding 0x%02x @ %x\n", *ptr, offset); 2385 return false; 2386 } 2387 ptr++; 2388 offset++; 2389 } 2390 } 2391 } 2392 2393 u1* newPtr = (u1*) func(state, ptr); 2394 newOffset = fileOffset(state, newPtr); 2395 2396 if (newPtr == NULL) { 2397 LOGE("Trouble with item %d @ offset 0x%x\n", i, offset); 2398 return false; 2399 } 2400 2401 if (newOffset > state->fileLen) { 2402 LOGE("Item %d @ offset 0x%x ends out of bounds\n", i, offset); 2403 return false; 2404 } 2405 2406 if (mapType >= 0) { 2407 dexDataMapAdd(state->pDataMap, offset, mapType); 2408 } 2409 2410 state->previousItem = ptr; 2411 offset = newOffset; 2412 } 2413 2414 if (nextOffset != NULL) { 2415 *nextOffset = offset; 2416 } 2417 2418 return true; 2419 } 2420 2421 /* 2422 * Iterate over all the items in a section. The section must consist of 2423 * concatenated items of the same type. This variant will not update the data 2424 * map. 2425 */ 2426 static bool iterateSection(CheckState* state, u4 offset, u4 count, 2427 ItemVisitorFunction* func, u4 alignment, u4* nextOffset) { 2428 return iterateSectionWithOptionalUpdate(state, offset, count, func, 2429 alignment, nextOffset, -1); 2430 } 2431 2432 /* 2433 * Like iterateSection(), but also check that the offset and count match 2434 * a given pair of expected values. 2435 */ 2436 static bool checkBoundsAndIterateSection(CheckState* state, 2437 u4 offset, u4 count, u4 expectedOffset, u4 expectedCount, 2438 ItemVisitorFunction* func, u4 alignment, u4* nextOffset) { 2439 if (offset != expectedOffset) { 2440 LOGE("Bogus offset for section: got 0x%x; expected 0x%x\n", 2441 offset, expectedOffset); 2442 return false; 2443 } 2444 2445 if (count != expectedCount) { 2446 LOGE("Bogus size for section: got 0x%x; expected 0x%x\n", 2447 count, expectedCount); 2448 return false; 2449 } 2450 2451 return iterateSection(state, offset, count, func, alignment, nextOffset); 2452 } 2453 2454 /* 2455 * Like iterateSection(), but also update the data section map and 2456 * check that all the items fall within the data section. 2457 */ 2458 static bool iterateDataSection(CheckState* state, u4 offset, u4 count, 2459 ItemVisitorFunction* func, u4 alignment, u4* nextOffset, int mapType) { 2460 u4 dataStart = state->pHeader->dataOff; 2461 u4 dataEnd = dataStart + state->pHeader->dataSize; 2462 2463 assert(nextOffset != NULL); 2464 2465 if ((offset < dataStart) || (offset >= dataEnd)) { 2466 LOGE("Bogus offset for data subsection: 0x%x\n", offset); 2467 return false; 2468 } 2469 2470 if (!iterateSectionWithOptionalUpdate(state, offset, count, func, 2471 alignment, nextOffset, mapType)) { 2472 return false; 2473 } 2474 2475 if (*nextOffset > dataEnd) { 2476 LOGE("Out-of-bounds end of data subsection: 0x%x\n", *nextOffset); 2477 return false; 2478 } 2479 2480 return true; 2481 } 2482 2483 /* 2484 * Byte-swap all items in the given map except the header and the map 2485 * itself, both of which should have already gotten swapped. This also 2486 * does all possible intra-item verification, that is, verification 2487 * that doesn't need to assume the sanctity of the contents of *other* 2488 * items. The intra-item limitation is because at the time an item is 2489 * asked to verify itself, it can't assume that the items it refers to 2490 * have been byte-swapped and verified. 2491 */ 2492 static bool swapEverythingButHeaderAndMap(CheckState* state, 2493 DexMapList* pMap) { 2494 const DexMapItem* item = pMap->list; 2495 u4 lastOffset = 0; 2496 u4 count = pMap->size; 2497 bool okay = true; 2498 2499 while (okay && count--) { 2500 u4 sectionOffset = item->offset; 2501 u4 sectionCount = item->size; 2502 u2 type = item->type; 2503 2504 if (lastOffset < sectionOffset) { 2505 CHECK_OFFSET_RANGE(lastOffset, sectionOffset); 2506 const u1* ptr = filePointer(state, lastOffset); 2507 while (lastOffset < sectionOffset) { 2508 if (*ptr != '\0') { 2509 LOGE("Non-zero padding 0x%02x before section start @ %x\n", 2510 *ptr, lastOffset); 2511 okay = false; 2512 break; 2513 } 2514 ptr++; 2515 lastOffset++; 2516 } 2517 } else if (lastOffset > sectionOffset) { 2518 LOGE("Section overlap or out-of-order map: %x, %x\n", 2519 lastOffset, sectionOffset); 2520 okay = false; 2521 } 2522 2523 if (!okay) { 2524 break; 2525 } 2526 2527 switch (type) { 2528 case kDexTypeHeaderItem: { 2529 /* 2530 * The header got swapped very early on, but do some 2531 * additional sanity checking here. 2532 */ 2533 okay = checkHeaderSection(state, sectionOffset, sectionCount, 2534 &lastOffset); 2535 break; 2536 } 2537 case kDexTypeStringIdItem: { 2538 okay = checkBoundsAndIterateSection(state, sectionOffset, 2539 sectionCount, state->pHeader->stringIdsOff, 2540 state->pHeader->stringIdsSize, swapStringIdItem, 2541 sizeof(u4), &lastOffset); 2542 break; 2543 } 2544 case kDexTypeTypeIdItem: { 2545 okay = checkBoundsAndIterateSection(state, sectionOffset, 2546 sectionCount, state->pHeader->typeIdsOff, 2547 state->pHeader->typeIdsSize, swapTypeIdItem, 2548 sizeof(u4), &lastOffset); 2549 break; 2550 } 2551 case kDexTypeProtoIdItem: { 2552 okay = checkBoundsAndIterateSection(state, sectionOffset, 2553 sectionCount, state->pHeader->protoIdsOff, 2554 state->pHeader->protoIdsSize, swapProtoIdItem, 2555 sizeof(u4), &lastOffset); 2556 break; 2557 } 2558 case kDexTypeFieldIdItem: { 2559 okay = checkBoundsAndIterateSection(state, sectionOffset, 2560 sectionCount, state->pHeader->fieldIdsOff, 2561 state->pHeader->fieldIdsSize, swapFieldIdItem, 2562 sizeof(u4), &lastOffset); 2563 break; 2564 } 2565 case kDexTypeMethodIdItem: { 2566 okay = checkBoundsAndIterateSection(state, sectionOffset, 2567 sectionCount, state->pHeader->methodIdsOff, 2568 state->pHeader->methodIdsSize, swapMethodIdItem, 2569 sizeof(u4), &lastOffset); 2570 break; 2571 } 2572 case kDexTypeClassDefItem: { 2573 okay = checkBoundsAndIterateSection(state, sectionOffset, 2574 sectionCount, state->pHeader->classDefsOff, 2575 state->pHeader->classDefsSize, swapClassDefItem, 2576 sizeof(u4), &lastOffset); 2577 break; 2578 } 2579 case kDexTypeMapList: { 2580 /* 2581 * The map section was swapped early on, but do some 2582 * additional sanity checking here. 2583 */ 2584 okay = checkMapSection(state, sectionOffset, sectionCount, 2585 &lastOffset); 2586 break; 2587 } 2588 case kDexTypeTypeList: { 2589 okay = iterateDataSection(state, sectionOffset, sectionCount, 2590 swapTypeList, sizeof(u4), &lastOffset, type); 2591 break; 2592 } 2593 case kDexTypeAnnotationSetRefList: { 2594 okay = iterateDataSection(state, sectionOffset, sectionCount, 2595 swapAnnotationSetRefList, sizeof(u4), &lastOffset, 2596 type); 2597 break; 2598 } 2599 case kDexTypeAnnotationSetItem: { 2600 okay = iterateDataSection(state, sectionOffset, sectionCount, 2601 swapAnnotationSetItem, sizeof(u4), &lastOffset, type); 2602 break; 2603 } 2604 case kDexTypeClassDataItem: { 2605 okay = iterateDataSection(state, sectionOffset, sectionCount, 2606 intraVerifyClassDataItem, sizeof(u1), &lastOffset, 2607 type); 2608 break; 2609 } 2610 case kDexTypeCodeItem: { 2611 okay = iterateDataSection(state, sectionOffset, sectionCount, 2612 swapCodeItem, sizeof(u4), &lastOffset, type); 2613 break; 2614 } 2615 case kDexTypeStringDataItem: { 2616 okay = iterateDataSection(state, sectionOffset, sectionCount, 2617 intraVerifyStringDataItem, sizeof(u1), &lastOffset, 2618 type); 2619 break; 2620 } 2621 case kDexTypeDebugInfoItem: { 2622 okay = iterateDataSection(state, sectionOffset, sectionCount, 2623 intraVerifyDebugInfoItem, sizeof(u1), &lastOffset, 2624 type); 2625 break; 2626 } 2627 case kDexTypeAnnotationItem: { 2628 okay = iterateDataSection(state, sectionOffset, sectionCount, 2629 intraVerifyAnnotationItem, sizeof(u1), &lastOffset, 2630 type); 2631 break; 2632 } 2633 case kDexTypeEncodedArrayItem: { 2634 okay = iterateDataSection(state, sectionOffset, sectionCount, 2635 intraVerifyEncodedArrayItem, sizeof(u1), &lastOffset, 2636 type); 2637 break; 2638 } 2639 case kDexTypeAnnotationsDirectoryItem: { 2640 okay = iterateDataSection(state, sectionOffset, sectionCount, 2641 swapAnnotationsDirectoryItem, sizeof(u4), &lastOffset, 2642 type); 2643 break; 2644 } 2645 default: { 2646 LOGE("Unknown map item type %04x\n", type); 2647 return false; 2648 } 2649 } 2650 2651 if (!okay) { 2652 LOGE("Swap of section type %04x failed\n", type); 2653 } 2654 2655 item++; 2656 } 2657 2658 return okay; 2659 } 2660 2661 /* 2662 * Perform cross-item verification on everything that needs it. This 2663 * pass is only called after all items are byte-swapped and 2664 * intra-verified (checked for internal consistency). 2665 */ 2666 static bool crossVerifyEverything(CheckState* state, DexMapList* pMap) 2667 { 2668 const DexMapItem* item = pMap->list; 2669 u4 count = pMap->size; 2670 bool okay = true; 2671 2672 while (okay && count--) { 2673 u4 sectionOffset = item->offset; 2674 u4 sectionCount = item->size; 2675 2676 switch (item->type) { 2677 case kDexTypeHeaderItem: 2678 case kDexTypeMapList: 2679 case kDexTypeTypeList: 2680 case kDexTypeCodeItem: 2681 case kDexTypeStringDataItem: 2682 case kDexTypeDebugInfoItem: 2683 case kDexTypeAnnotationItem: 2684 case kDexTypeEncodedArrayItem: { 2685 // There is no need for cross-item verification for these. 2686 break; 2687 } 2688 case kDexTypeStringIdItem: { 2689 okay = iterateSection(state, sectionOffset, sectionCount, 2690 crossVerifyStringIdItem, sizeof(u4), NULL); 2691 break; 2692 } 2693 case kDexTypeTypeIdItem: { 2694 okay = iterateSection(state, sectionOffset, sectionCount, 2695 crossVerifyTypeIdItem, sizeof(u4), NULL); 2696 break; 2697 } 2698 case kDexTypeProtoIdItem: { 2699 okay = iterateSection(state, sectionOffset, sectionCount, 2700 crossVerifyProtoIdItem, sizeof(u4), NULL); 2701 break; 2702 } 2703 case kDexTypeFieldIdItem: { 2704 okay = iterateSection(state, sectionOffset, sectionCount, 2705 crossVerifyFieldIdItem, sizeof(u4), NULL); 2706 break; 2707 } 2708 case kDexTypeMethodIdItem: { 2709 okay = iterateSection(state, sectionOffset, sectionCount, 2710 crossVerifyMethodIdItem, sizeof(u4), NULL); 2711 break; 2712 } 2713 case kDexTypeClassDefItem: { 2714 // Allocate (on the stack) the "observed class_def" bits. 2715 size_t arraySize = calcDefinedClassBitsSize(state); 2716 u4 definedClassBits[arraySize]; 2717 memset(definedClassBits, 0, arraySize * sizeof(u4)); 2718 state->pDefinedClassBits = definedClassBits; 2719 2720 okay = iterateSection(state, sectionOffset, sectionCount, 2721 crossVerifyClassDefItem, sizeof(u4), NULL); 2722 2723 state->pDefinedClassBits = NULL; 2724 break; 2725 } 2726 case kDexTypeAnnotationSetRefList: { 2727 okay = iterateSection(state, sectionOffset, sectionCount, 2728 crossVerifyAnnotationSetRefList, sizeof(u4), NULL); 2729 break; 2730 } 2731 case kDexTypeAnnotationSetItem: { 2732 okay = iterateSection(state, sectionOffset, sectionCount, 2733 crossVerifyAnnotationSetItem, sizeof(u4), NULL); 2734 break; 2735 } 2736 case kDexTypeClassDataItem: { 2737 okay = iterateSection(state, sectionOffset, sectionCount, 2738 crossVerifyClassDataItem, sizeof(u1), NULL); 2739 break; 2740 } 2741 case kDexTypeAnnotationsDirectoryItem: { 2742 okay = iterateSection(state, sectionOffset, sectionCount, 2743 crossVerifyAnnotationsDirectoryItem, sizeof(u4), NULL); 2744 break; 2745 } 2746 default: { 2747 LOGE("Unknown map item type %04x\n", item->type); 2748 return false; 2749 } 2750 } 2751 2752 if (!okay) { 2753 LOGE("Cross-item verify of section type %04x failed\n", 2754 item->type); 2755 } 2756 2757 item++; 2758 } 2759 2760 return okay; 2761 } 2762 2763 /* 2764 * Fix the byte ordering of all fields in the DEX file, and do structural 2765 * verification. 2766 * 2767 * While we're at it, make sure that the file offsets all refer to locations 2768 * within the file. 2769 * 2770 * Returns 0 on success, nonzero on failure. 2771 */ 2772 int dexFixByteOrdering(u1* addr, int len) 2773 { 2774 DexHeader* pHeader; 2775 CheckState state; 2776 bool okay = true; 2777 2778 memset(&state, 0, sizeof(state)); 2779 LOGV("+++ swapping and verifying\n"); 2780 2781 /* 2782 * Start by verifying the magic number. The caller verified that "len" 2783 * says we have at least a header's worth of data. 2784 */ 2785 pHeader = (DexHeader*) addr; 2786 if (memcmp(pHeader->magic, DEX_MAGIC, 4) != 0) { 2787 /* really shouldn't be here -- this is weird */ 2788 LOGE("ERROR: Can't byte swap: bad magic number " 2789 "(0x%02x %02x %02x %02x)\n", 2790 pHeader->magic[0], pHeader->magic[1], 2791 pHeader->magic[2], pHeader->magic[3]); 2792 okay = false; 2793 } 2794 2795 if (okay && memcmp(pHeader->magic+4, DEX_MAGIC_VERS, 4) != 0) { 2796 /* older or newer version we don't know how to read */ 2797 LOGE("ERROR: Can't byte swap: bad dex version " 2798 "(0x%02x %02x %02x %02x)\n", 2799 pHeader->magic[4], pHeader->magic[5], 2800 pHeader->magic[6], pHeader->magic[7]); 2801 okay = false; 2802 } 2803 2804 if (okay) { 2805 int expectedLen = (int) SWAP4(pHeader->fileSize); 2806 if (len < expectedLen) { 2807 LOGE("ERROR: Bad length: expected %d, got %d\n", expectedLen, len); 2808 okay = false; 2809 } else if (len != expectedLen) { 2810 LOGW("WARNING: Odd length: expected %d, got %d\n", expectedLen, 2811 len); 2812 // keep going 2813 } 2814 } 2815 2816 if (okay) { 2817 /* 2818 * Compute the adler32 checksum and compare it to what's stored in 2819 * the file. This isn't free, but chances are good that we just 2820 * unpacked this from a jar file and have all of the pages sitting 2821 * in memory, so it's pretty quick. 2822 * 2823 * This might be a big-endian system, so we need to do this before 2824 * we byte-swap the header. 2825 */ 2826 uLong adler = adler32(0L, Z_NULL, 0); 2827 const int nonSum = sizeof(pHeader->magic) + sizeof(pHeader->checksum); 2828 u4 storedFileSize = SWAP4(pHeader->fileSize); 2829 u4 expectedChecksum = SWAP4(pHeader->checksum); 2830 2831 adler = adler32(adler, ((const u1*) pHeader) + nonSum, 2832 storedFileSize - nonSum); 2833 2834 if (adler != expectedChecksum) { 2835 LOGE("ERROR: bad checksum (%08lx, expected %08x)\n", 2836 adler, expectedChecksum); 2837 okay = false; 2838 } 2839 } 2840 2841 if (okay) { 2842 state.fileStart = addr; 2843 state.fileEnd = addr + len; 2844 state.fileLen = len; 2845 state.pDexFile = NULL; 2846 state.pDataMap = NULL; 2847 state.pDefinedClassBits = NULL; 2848 state.previousItem = NULL; 2849 2850 /* 2851 * Swap the header and check the contents. 2852 */ 2853 okay = swapDexHeader(&state, pHeader); 2854 } 2855 2856 if (okay) { 2857 state.pHeader = pHeader; 2858 2859 if (pHeader->headerSize < sizeof(DexHeader)) { 2860 LOGE("ERROR: Small header size %d, struct %d\n", 2861 pHeader->headerSize, (int) sizeof(DexHeader)); 2862 okay = false; 2863 } else if (pHeader->headerSize > sizeof(DexHeader)) { 2864 LOGW("WARNING: Large header size %d, struct %d\n", 2865 pHeader->headerSize, (int) sizeof(DexHeader)); 2866 // keep going? 2867 } 2868 } 2869 2870 if (okay) { 2871 /* 2872 * Look for the map. Swap it and then use it to find and swap 2873 * everything else. 2874 */ 2875 if (pHeader->mapOff != 0) { 2876 DexFile dexFile; 2877 DexMapList* pDexMap = (DexMapList*) (addr + pHeader->mapOff); 2878 2879 okay = okay && swapMap(&state, pDexMap); 2880 okay = okay && swapEverythingButHeaderAndMap(&state, pDexMap); 2881 2882 dexFileSetupBasicPointers(&dexFile, addr); 2883 state.pDexFile = &dexFile; 2884 2885 okay = okay && crossVerifyEverything(&state, pDexMap); 2886 } else { 2887 LOGE("ERROR: No map found; impossible to byte-swap and verify"); 2888 okay = false; 2889 } 2890 } 2891 2892 if (!okay) { 2893 LOGE("ERROR: Byte swap + verify failed\n"); 2894 } 2895 2896 if (state.pDataMap != NULL) { 2897 dexDataMapFree(state.pDataMap); 2898 } 2899 2900 return !okay; // 0 == success 2901 } 2902