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