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