DexSwapVerify.cpp revision c2e9a5b2b70d69c027964c9a4d07a4bdf723dd36
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 if ((item->accessFlags & ~ACC_CLASS_MASK) != 0) { 915 ALOGE("Bogus class access flags %x", item->accessFlags); 916 return NULL; 917 } 918 919 return item + 1; 920} 921 922/* defined below */ 923static u4 findFirstClassDataDefiner(const CheckState* state, 924 DexClassData* classData); 925static u4 findFirstAnnotationsDirectoryDefiner(const CheckState* state, 926 const DexAnnotationsDirectoryItem* dir); 927 928/* Helper for crossVerifyClassDefItem(), which checks a class_data_item to 929 * make sure all its references are to a given class. */ 930static bool verifyClassDataIsForDef(const CheckState* state, u4 offset, 931 u4 definerIdx) { 932 if (offset == 0) { 933 return true; 934 } 935 936 const u1* data = (const u1*) filePointer(state, offset); 937 DexClassData* classData = dexReadAndVerifyClassData(&data, NULL); 938 939 if (classData == NULL) { 940 // Shouldn't happen, but bail here just in case. 941 return false; 942 } 943 944 /* 945 * The class_data_item verification ensures that 946 * it consistently refers to the same definer, so all we need to 947 * do is check the first one. 948 */ 949 u4 dataDefiner = findFirstClassDataDefiner(state, classData); 950 bool result = (dataDefiner == definerIdx) || (dataDefiner == kDexNoIndex); 951 952 free(classData); 953 return result; 954} 955 956/* Helper for crossVerifyClassDefItem(), which checks an 957 * annotations_directory_item to make sure all its references are to a 958 * given class. */ 959static bool verifyAnnotationsDirectoryIsForDef(const CheckState* state, 960 u4 offset, u4 definerIdx) { 961 if (offset == 0) { 962 return true; 963 } 964 965 const DexAnnotationsDirectoryItem* dir = 966 (const DexAnnotationsDirectoryItem*) filePointer(state, offset); 967 u4 annoDefiner = findFirstAnnotationsDirectoryDefiner(state, dir); 968 969 return (annoDefiner == definerIdx) || (annoDefiner == kDexNoIndex); 970} 971 972/* Perform cross-item verification of class_def_item. */ 973static void* crossVerifyClassDefItem(const CheckState* state, void* ptr) { 974 const DexClassDef* item = (const DexClassDef*) ptr; 975 u4 classIdx = item->classIdx; 976 const char* descriptor = dexStringByTypeIdx(state->pDexFile, classIdx); 977 978 if (!dexIsClassDescriptor(descriptor)) { 979 ALOGE("Invalid class: '%s'", descriptor); 980 return NULL; 981 } 982 983 if (setDefinedClassBit(state, classIdx)) { 984 ALOGE("Duplicate class definition: '%s'", descriptor); 985 return NULL; 986 } 987 988 bool okay = 989 dexDataMapVerify0Ok(state->pDataMap, 990 item->interfacesOff, kDexTypeTypeList) 991 && dexDataMapVerify0Ok(state->pDataMap, 992 item->annotationsOff, kDexTypeAnnotationsDirectoryItem) 993 && dexDataMapVerify0Ok(state->pDataMap, 994 item->classDataOff, kDexTypeClassDataItem) 995 && dexDataMapVerify0Ok(state->pDataMap, 996 item->staticValuesOff, kDexTypeEncodedArrayItem); 997 998 if (!okay) { 999 return NULL; 1000 } 1001 1002 if (item->superclassIdx != kDexNoIndex) { 1003 descriptor = dexStringByTypeIdx(state->pDexFile, item->superclassIdx); 1004 if (!dexIsClassDescriptor(descriptor)) { 1005 ALOGE("Invalid superclass: '%s'", descriptor); 1006 return NULL; 1007 } 1008 } 1009 1010 const DexTypeList* interfaces = 1011 dexGetInterfacesList(state->pDexFile, item); 1012 if (interfaces != NULL) { 1013 u4 size = interfaces->size; 1014 u4 i; 1015 1016 /* 1017 * Ensure that all interfaces refer to classes (not arrays or 1018 * primitives). 1019 */ 1020 for (i = 0; i < size; i++) { 1021 descriptor = dexStringByTypeIdx(state->pDexFile, 1022 dexTypeListGetIdx(interfaces, i)); 1023 if (!dexIsClassDescriptor(descriptor)) { 1024 ALOGE("Invalid interface: '%s'", descriptor); 1025 return NULL; 1026 } 1027 } 1028 1029 /* 1030 * Ensure that there are no duplicates. This is an O(N^2) test, 1031 * but in practice the number of interfaces implemented by any 1032 * given class is low. I will buy a milkshake for the 1033 * first person to show me a realistic case for which this test 1034 * would be unacceptably slow. 1035 */ 1036 for (i = 1; i < size; i++) { 1037 u4 idx1 = dexTypeListGetIdx(interfaces, i); 1038 u4 j; 1039 for (j = 0; j < i; j++) { 1040 u4 idx2 = dexTypeListGetIdx(interfaces, j); 1041 if (idx1 == idx2) { 1042 ALOGE("Duplicate interface: '%s'", 1043 dexStringByTypeIdx(state->pDexFile, idx1)); 1044 return NULL; 1045 } 1046 } 1047 } 1048 } 1049 1050 if (!verifyClassDataIsForDef(state, item->classDataOff, item->classIdx)) { 1051 ALOGE("Invalid class_data_item"); 1052 return NULL; 1053 } 1054 1055 if (!verifyAnnotationsDirectoryIsForDef(state, item->annotationsOff, 1056 item->classIdx)) { 1057 ALOGE("Invalid annotations_directory_item"); 1058 return NULL; 1059 } 1060 1061 return (void*) (item + 1); 1062} 1063 1064/* Helper for swapAnnotationsDirectoryItem(), which performs 1065 * byte-swapping and intra-item verification on an 1066 * annotation_directory_item's field elements. */ 1067static u1* swapFieldAnnotations(const CheckState* state, u4 count, u1* addr) { 1068 DexFieldAnnotationsItem* item = (DexFieldAnnotationsItem*) addr; 1069 bool first = true; 1070 u4 lastIdx = 0; 1071 1072 CHECK_LIST_SIZE(item, count, sizeof(DexFieldAnnotationsItem)); 1073 1074 while (count--) { 1075 SWAP_INDEX4(item->fieldIdx, state->pHeader->fieldIdsSize); 1076 SWAP_OFFSET4(item->annotationsOff); 1077 1078 if (first) { 1079 first = false; 1080 } else if (lastIdx >= item->fieldIdx) { 1081 ALOGE("Out-of-order field_idx: %#x then %#x", lastIdx, 1082 item->fieldIdx); 1083 return NULL; 1084 } 1085 1086 lastIdx = item->fieldIdx; 1087 item++; 1088 } 1089 1090 return (u1*) item; 1091} 1092 1093/* Helper for swapAnnotationsDirectoryItem(), which performs 1094 * byte-swapping and intra-item verification on an 1095 * annotation_directory_item's method elements. */ 1096static u1* swapMethodAnnotations(const CheckState* state, u4 count, u1* addr) { 1097 DexMethodAnnotationsItem* item = (DexMethodAnnotationsItem*) addr; 1098 bool first = true; 1099 u4 lastIdx = 0; 1100 1101 CHECK_LIST_SIZE(item, count, sizeof(DexMethodAnnotationsItem)); 1102 1103 while (count--) { 1104 SWAP_INDEX4(item->methodIdx, state->pHeader->methodIdsSize); 1105 SWAP_OFFSET4(item->annotationsOff); 1106 1107 if (first) { 1108 first = false; 1109 } else if (lastIdx >= item->methodIdx) { 1110 ALOGE("Out-of-order method_idx: %#x then %#x", lastIdx, 1111 item->methodIdx); 1112 return NULL; 1113 } 1114 1115 lastIdx = item->methodIdx; 1116 item++; 1117 } 1118 1119 return (u1*) item; 1120} 1121 1122/* Helper for swapAnnotationsDirectoryItem(), which performs 1123 * byte-swapping and intra-item verification on an 1124 * annotation_directory_item's parameter elements. */ 1125static u1* swapParameterAnnotations(const CheckState* state, u4 count, 1126 u1* addr) { 1127 DexParameterAnnotationsItem* item = (DexParameterAnnotationsItem*) addr; 1128 bool first = true; 1129 u4 lastIdx = 0; 1130 1131 CHECK_LIST_SIZE(item, count, sizeof(DexParameterAnnotationsItem)); 1132 1133 while (count--) { 1134 SWAP_INDEX4(item->methodIdx, state->pHeader->methodIdsSize); 1135 SWAP_OFFSET4(item->annotationsOff); 1136 1137 if (first) { 1138 first = false; 1139 } else if (lastIdx >= item->methodIdx) { 1140 ALOGE("Out-of-order method_idx: %#x then %#x", lastIdx, 1141 item->methodIdx); 1142 return NULL; 1143 } 1144 1145 lastIdx = item->methodIdx; 1146 item++; 1147 } 1148 1149 return (u1*) item; 1150} 1151 1152/* Perform byte-swapping and intra-item verification on 1153 * annotations_directory_item. */ 1154static void* swapAnnotationsDirectoryItem(const CheckState* state, void* ptr) { 1155 DexAnnotationsDirectoryItem* item = (DexAnnotationsDirectoryItem*) ptr; 1156 1157 CHECK_PTR_RANGE(item, item + 1); 1158 SWAP_OFFSET4(item->classAnnotationsOff); 1159 SWAP_FIELD4(item->fieldsSize); 1160 SWAP_FIELD4(item->methodsSize); 1161 SWAP_FIELD4(item->parametersSize); 1162 1163 u1* addr = (u1*) (item + 1); 1164 1165 if (item->fieldsSize != 0) { 1166 addr = swapFieldAnnotations(state, item->fieldsSize, addr); 1167 if (addr == NULL) { 1168 return NULL; 1169 } 1170 } 1171 1172 if (item->methodsSize != 0) { 1173 addr = swapMethodAnnotations(state, item->methodsSize, addr); 1174 if (addr == NULL) { 1175 return NULL; 1176 } 1177 } 1178 1179 if (item->parametersSize != 0) { 1180 addr = swapParameterAnnotations(state, item->parametersSize, addr); 1181 if (addr == NULL) { 1182 return NULL; 1183 } 1184 } 1185 1186 return addr; 1187} 1188 1189/* Helper for crossVerifyAnnotationsDirectoryItem(), which checks the 1190 * field elements. */ 1191static const u1* crossVerifyFieldAnnotations(const CheckState* state, u4 count, 1192 const u1* addr, u4 definingClass) { 1193 const DexFieldAnnotationsItem* item = (DexFieldAnnotationsItem*) addr; 1194 1195 while (count--) { 1196 if (!verifyFieldDefiner(state, definingClass, item->fieldIdx)) { 1197 return NULL; 1198 } 1199 if (!dexDataMapVerify(state->pDataMap, item->annotationsOff, 1200 kDexTypeAnnotationSetItem)) { 1201 return NULL; 1202 } 1203 item++; 1204 } 1205 1206 return (const u1*) item; 1207} 1208 1209/* Helper for crossVerifyAnnotationsDirectoryItem(), which checks the 1210 * method elements. */ 1211static const u1* crossVerifyMethodAnnotations(const CheckState* state, 1212 u4 count, const u1* addr, u4 definingClass) { 1213 const DexMethodAnnotationsItem* item = (DexMethodAnnotationsItem*) addr; 1214 1215 while (count--) { 1216 if (!verifyMethodDefiner(state, definingClass, item->methodIdx)) { 1217 return NULL; 1218 } 1219 if (!dexDataMapVerify(state->pDataMap, item->annotationsOff, 1220 kDexTypeAnnotationSetItem)) { 1221 return NULL; 1222 } 1223 item++; 1224 } 1225 1226 return (const u1*) item; 1227} 1228 1229/* Helper for crossVerifyAnnotationsDirectoryItem(), which checks the 1230 * parameter elements. */ 1231static const u1* crossVerifyParameterAnnotations(const CheckState* state, 1232 u4 count, const u1* addr, u4 definingClass) { 1233 const DexParameterAnnotationsItem* item = 1234 (DexParameterAnnotationsItem*) addr; 1235 1236 while (count--) { 1237 if (!verifyMethodDefiner(state, definingClass, item->methodIdx)) { 1238 return NULL; 1239 } 1240 if (!dexDataMapVerify(state->pDataMap, item->annotationsOff, 1241 kDexTypeAnnotationSetRefList)) { 1242 return NULL; 1243 } 1244 item++; 1245 } 1246 1247 return (const u1*) item; 1248} 1249 1250/* Helper for crossVerifyClassDefItem() and 1251 * crossVerifyAnnotationsDirectoryItem(), which finds the type_idx of 1252 * the definer of the first item in the data. */ 1253static u4 findFirstAnnotationsDirectoryDefiner(const CheckState* state, 1254 const DexAnnotationsDirectoryItem* dir) { 1255 if (dir->fieldsSize != 0) { 1256 const DexFieldAnnotationsItem* fields = 1257 dexGetFieldAnnotations(state->pDexFile, dir); 1258 const DexFieldId* field = 1259 dexGetFieldId(state->pDexFile, fields[0].fieldIdx); 1260 return field->classIdx; 1261 } 1262 1263 if (dir->methodsSize != 0) { 1264 const DexMethodAnnotationsItem* methods = 1265 dexGetMethodAnnotations(state->pDexFile, dir); 1266 const DexMethodId* method = 1267 dexGetMethodId(state->pDexFile, methods[0].methodIdx); 1268 return method->classIdx; 1269 } 1270 1271 if (dir->parametersSize != 0) { 1272 const DexParameterAnnotationsItem* parameters = 1273 dexGetParameterAnnotations(state->pDexFile, dir); 1274 const DexMethodId* method = 1275 dexGetMethodId(state->pDexFile, parameters[0].methodIdx); 1276 return method->classIdx; 1277 } 1278 1279 return kDexNoIndex; 1280} 1281 1282/* Perform cross-item verification of annotations_directory_item. */ 1283static void* crossVerifyAnnotationsDirectoryItem(const CheckState* state, 1284 void* ptr) { 1285 const DexAnnotationsDirectoryItem* item = (const DexAnnotationsDirectoryItem*) ptr; 1286 u4 definingClass = findFirstAnnotationsDirectoryDefiner(state, item); 1287 1288 if (!dexDataMapVerify0Ok(state->pDataMap, 1289 item->classAnnotationsOff, kDexTypeAnnotationSetItem)) { 1290 return NULL; 1291 } 1292 1293 const u1* addr = (const u1*) (item + 1); 1294 1295 if (item->fieldsSize != 0) { 1296 addr = crossVerifyFieldAnnotations(state, item->fieldsSize, addr, 1297 definingClass); 1298 if (addr == NULL) { 1299 return NULL; 1300 } 1301 } 1302 1303 if (item->methodsSize != 0) { 1304 addr = crossVerifyMethodAnnotations(state, item->methodsSize, addr, 1305 definingClass); 1306 if (addr == NULL) { 1307 return NULL; 1308 } 1309 } 1310 1311 if (item->parametersSize != 0) { 1312 addr = crossVerifyParameterAnnotations(state, item->parametersSize, 1313 addr, definingClass); 1314 if (addr == NULL) { 1315 return NULL; 1316 } 1317 } 1318 1319 return (void*) addr; 1320} 1321 1322/* Perform byte-swapping and intra-item verification on type_list. */ 1323static void* swapTypeList(const CheckState* state, void* ptr) 1324{ 1325 DexTypeList* pTypeList = (DexTypeList*) ptr; 1326 DexTypeItem* pType; 1327 u4 count; 1328 1329 CHECK_PTR_RANGE(pTypeList, pTypeList + 1); 1330 SWAP_FIELD4(pTypeList->size); 1331 count = pTypeList->size; 1332 pType = pTypeList->list; 1333 CHECK_LIST_SIZE(pType, count, sizeof(DexTypeItem)); 1334 1335 while (count--) { 1336 SWAP_INDEX2(pType->typeIdx, state->pHeader->typeIdsSize); 1337 pType++; 1338 } 1339 1340 return pType; 1341} 1342 1343/* Perform byte-swapping and intra-item verification on 1344 * annotation_set_ref_list. */ 1345static void* swapAnnotationSetRefList(const CheckState* state, void* ptr) { 1346 DexAnnotationSetRefList* list = (DexAnnotationSetRefList*) ptr; 1347 DexAnnotationSetRefItem* item; 1348 u4 count; 1349 1350 CHECK_PTR_RANGE(list, list + 1); 1351 SWAP_FIELD4(list->size); 1352 count = list->size; 1353 item = list->list; 1354 CHECK_LIST_SIZE(item, count, sizeof(DexAnnotationSetRefItem)); 1355 1356 while (count--) { 1357 SWAP_OFFSET4(item->annotationsOff); 1358 item++; 1359 } 1360 1361 return item; 1362} 1363 1364/* Perform cross-item verification of annotation_set_ref_list. */ 1365static void* crossVerifyAnnotationSetRefList(const CheckState* state, 1366 void* ptr) { 1367 const DexAnnotationSetRefList* list = (const DexAnnotationSetRefList*) ptr; 1368 const DexAnnotationSetRefItem* item = list->list; 1369 int count = list->size; 1370 1371 while (count--) { 1372 if (!dexDataMapVerify0Ok(state->pDataMap, 1373 item->annotationsOff, kDexTypeAnnotationSetItem)) { 1374 return NULL; 1375 } 1376 item++; 1377 } 1378 1379 return (void*) item; 1380} 1381 1382/* Perform byte-swapping and intra-item verification on 1383 * annotation_set_item. */ 1384static void* swapAnnotationSetItem(const CheckState* state, void* ptr) { 1385 DexAnnotationSetItem* set = (DexAnnotationSetItem*) ptr; 1386 u4* item; 1387 u4 count; 1388 1389 CHECK_PTR_RANGE(set, set + 1); 1390 SWAP_FIELD4(set->size); 1391 count = set->size; 1392 item = set->entries; 1393 CHECK_LIST_SIZE(item, count, sizeof(u4)); 1394 1395 while (count--) { 1396 SWAP_OFFSET4(*item); 1397 item++; 1398 } 1399 1400 return item; 1401} 1402 1403/* Helper for crossVerifyAnnotationSetItem(), which extracts the type_idx 1404 * out of an annotation_item. */ 1405static u4 annotationItemTypeIdx(const DexAnnotationItem* item) { 1406 const u1* data = item->annotation; 1407 return readUnsignedLeb128(&data); 1408} 1409 1410/* Perform cross-item verification of annotation_set_item. */ 1411static void* crossVerifyAnnotationSetItem(const CheckState* state, void* ptr) { 1412 const DexAnnotationSetItem* set = (const DexAnnotationSetItem*) ptr; 1413 int count = set->size; 1414 u4 lastIdx = 0; 1415 bool first = true; 1416 int i; 1417 1418 for (i = 0; i < count; i++) { 1419 if (!dexDataMapVerify0Ok(state->pDataMap, 1420 dexGetAnnotationOff(set, i), kDexTypeAnnotationItem)) { 1421 return NULL; 1422 } 1423 1424 const DexAnnotationItem* annotation = 1425 dexGetAnnotationItem(state->pDexFile, set, i); 1426 u4 idx = annotationItemTypeIdx(annotation); 1427 1428 if (first) { 1429 first = false; 1430 } else if (lastIdx >= idx) { 1431 ALOGE("Out-of-order entry types: %#x then %#x", 1432 lastIdx, idx); 1433 return NULL; 1434 } 1435 1436 lastIdx = idx; 1437 } 1438 1439 return (void*) (set->entries + count); 1440} 1441 1442/* Helper for verifyClassDataItem(), which checks a list of fields. */ 1443static bool verifyFields(const CheckState* state, u4 size, 1444 DexField* fields, bool expectStatic) { 1445 u4 i; 1446 1447 for (i = 0; i < size; i++) { 1448 DexField* field = &fields[i]; 1449 u4 accessFlags = field->accessFlags; 1450 bool isStatic = (accessFlags & ACC_STATIC) != 0; 1451 1452 CHECK_INDEX(field->fieldIdx, state->pHeader->fieldIdsSize); 1453 1454 if (isStatic != expectStatic) { 1455 ALOGE("Field in wrong list @ %d", i); 1456 return false; 1457 } 1458 1459 if ((accessFlags & ~ACC_FIELD_MASK) != 0) { 1460 ALOGE("Bogus field access flags %x @ %d", accessFlags, i); 1461 return false; 1462 } 1463 } 1464 1465 return true; 1466} 1467 1468/* Helper for verifyClassDataItem(), which checks a list of methods. */ 1469static bool verifyMethods(const CheckState* state, u4 size, 1470 DexMethod* methods, bool expectDirect) { 1471 u4 i; 1472 1473 for (i = 0; i < size; i++) { 1474 DexMethod* method = &methods[i]; 1475 1476 CHECK_INDEX(method->methodIdx, state->pHeader->methodIdsSize); 1477 1478 u4 accessFlags = method->accessFlags; 1479 bool isDirect = 1480 (accessFlags & (ACC_STATIC | ACC_PRIVATE | ACC_CONSTRUCTOR)) != 0; 1481 bool expectCode = (accessFlags & (ACC_NATIVE | ACC_ABSTRACT)) == 0; 1482 bool isSynchronized = (accessFlags & ACC_SYNCHRONIZED) != 0; 1483 bool allowSynchronized = (accessFlags & ACC_NATIVE) != 0; 1484 1485 if (isDirect != expectDirect) { 1486 ALOGE("Method in wrong list @ %d", i); 1487 return false; 1488 } 1489 1490 if (((accessFlags & ~ACC_METHOD_MASK) != 0) 1491 || (isSynchronized && !allowSynchronized)) { 1492 ALOGE("Bogus method access flags %x @ %d", accessFlags, i); 1493 return false; 1494 } 1495 1496 if (expectCode) { 1497 if (method->codeOff == 0) { 1498 ALOGE("Unexpected zero code_off for access_flags %x", 1499 accessFlags); 1500 return false; 1501 } 1502 } else if (method->codeOff != 0) { 1503 ALOGE("Unexpected non-zero code_off %#x for access_flags %x", 1504 method->codeOff, accessFlags); 1505 return false; 1506 } 1507 } 1508 1509 return true; 1510} 1511 1512/* Helper for verifyClassDataItem(), which does most of the work. */ 1513static bool verifyClassDataItem0(const CheckState* state, 1514 DexClassData* classData) { 1515 bool okay; 1516 1517 okay = verifyFields(state, classData->header.staticFieldsSize, 1518 classData->staticFields, true); 1519 1520 if (!okay) { 1521 ALOGE("Trouble with static fields"); 1522 return false; 1523 } 1524 1525 verifyFields(state, classData->header.instanceFieldsSize, 1526 classData->instanceFields, false); 1527 1528 if (!okay) { 1529 ALOGE("Trouble with instance fields"); 1530 return false; 1531 } 1532 1533 okay = verifyMethods(state, classData->header.directMethodsSize, 1534 classData->directMethods, true); 1535 1536 if (!okay) { 1537 ALOGE("Trouble with direct methods"); 1538 return false; 1539 } 1540 1541 okay = verifyMethods(state, classData->header.virtualMethodsSize, 1542 classData->virtualMethods, false); 1543 1544 if (!okay) { 1545 ALOGE("Trouble with virtual methods"); 1546 return false; 1547 } 1548 1549 return true; 1550} 1551 1552/* Perform intra-item verification on class_data_item. */ 1553static void* intraVerifyClassDataItem(const CheckState* state, void* ptr) { 1554 const u1* data = (const u1*) ptr; 1555 DexClassData* classData = dexReadAndVerifyClassData(&data, state->fileEnd); 1556 1557 if (classData == NULL) { 1558 ALOGE("Unable to parse class_data_item"); 1559 return NULL; 1560 } 1561 1562 bool okay = verifyClassDataItem0(state, classData); 1563 1564 free(classData); 1565 1566 if (!okay) { 1567 return NULL; 1568 } 1569 1570 return (void*) data; 1571} 1572 1573/* Helper for crossVerifyClassDefItem() and 1574 * crossVerifyClassDataItem(), which finds the type_idx of the definer 1575 * of the first item in the data. */ 1576static u4 findFirstClassDataDefiner(const CheckState* state, 1577 DexClassData* classData) { 1578 if (classData->header.staticFieldsSize != 0) { 1579 u4 fieldIdx = classData->staticFields[0].fieldIdx; 1580 const DexFieldId* field = dexGetFieldId(state->pDexFile, fieldIdx); 1581 return field->classIdx; 1582 } 1583 1584 if (classData->header.instanceFieldsSize != 0) { 1585 u4 fieldIdx = classData->instanceFields[0].fieldIdx; 1586 const DexFieldId* field = dexGetFieldId(state->pDexFile, fieldIdx); 1587 return field->classIdx; 1588 } 1589 1590 if (classData->header.directMethodsSize != 0) { 1591 u4 methodIdx = classData->directMethods[0].methodIdx; 1592 const DexMethodId* meth = dexGetMethodId(state->pDexFile, methodIdx); 1593 return meth->classIdx; 1594 } 1595 1596 if (classData->header.virtualMethodsSize != 0) { 1597 u4 methodIdx = classData->virtualMethods[0].methodIdx; 1598 const DexMethodId* meth = dexGetMethodId(state->pDexFile, methodIdx); 1599 return meth->classIdx; 1600 } 1601 1602 return kDexNoIndex; 1603} 1604 1605/* Perform cross-item verification of class_data_item. */ 1606static void* crossVerifyClassDataItem(const CheckState* state, void* ptr) { 1607 const u1* data = (const u1*) ptr; 1608 DexClassData* classData = dexReadAndVerifyClassData(&data, state->fileEnd); 1609 u4 definingClass = findFirstClassDataDefiner(state, classData); 1610 bool okay = true; 1611 u4 i; 1612 1613 for (i = classData->header.staticFieldsSize; okay && (i > 0); /*i*/) { 1614 i--; 1615 const DexField* field = &classData->staticFields[i]; 1616 okay = verifyFieldDefiner(state, definingClass, field->fieldIdx); 1617 } 1618 1619 for (i = classData->header.instanceFieldsSize; okay && (i > 0); /*i*/) { 1620 i--; 1621 const DexField* field = &classData->instanceFields[i]; 1622 okay = verifyFieldDefiner(state, definingClass, field->fieldIdx); 1623 } 1624 1625 for (i = classData->header.directMethodsSize; okay && (i > 0); /*i*/) { 1626 i--; 1627 const DexMethod* meth = &classData->directMethods[i]; 1628 okay = dexDataMapVerify0Ok(state->pDataMap, meth->codeOff, 1629 kDexTypeCodeItem) 1630 && verifyMethodDefiner(state, definingClass, meth->methodIdx); 1631 } 1632 1633 for (i = classData->header.virtualMethodsSize; okay && (i > 0); /*i*/) { 1634 i--; 1635 const DexMethod* meth = &classData->virtualMethods[i]; 1636 okay = dexDataMapVerify0Ok(state->pDataMap, meth->codeOff, 1637 kDexTypeCodeItem) 1638 && verifyMethodDefiner(state, definingClass, meth->methodIdx); 1639 } 1640 1641 free(classData); 1642 1643 if (!okay) { 1644 return NULL; 1645 } 1646 1647 return (void*) data; 1648} 1649 1650/* Helper for swapCodeItem(), which fills an array with all the valid 1651 * handlerOff values for catch handlers and also verifies the handler 1652 * contents. */ 1653static u4 setHandlerOffsAndVerify(const CheckState* state, 1654 DexCode* code, u4 firstOffset, u4 handlersSize, u4* handlerOffs) { 1655 const u1* fileEnd = state->fileEnd; 1656 const u1* handlersBase = dexGetCatchHandlerData(code); 1657 u4 offset = firstOffset; 1658 bool okay = true; 1659 u4 i; 1660 1661 for (i = 0; i < handlersSize; i++) { 1662 const u1* ptr = handlersBase + offset; 1663 int size = readAndVerifySignedLeb128(&ptr, fileEnd, &okay); 1664 bool catchAll; 1665 1666 if (!okay) { 1667 ALOGE("Bogus size"); 1668 return 0; 1669 } 1670 1671 if ((size < -65536) || (size > 65536)) { 1672 ALOGE("Invalid size: %d", size); 1673 return 0; 1674 } 1675 1676 if (size <= 0) { 1677 catchAll = true; 1678 size = -size; 1679 } else { 1680 catchAll = false; 1681 } 1682 1683 handlerOffs[i] = offset; 1684 1685 while (size-- > 0) { 1686 u4 typeIdx = 1687 readAndVerifyUnsignedLeb128(&ptr, fileEnd, &okay); 1688 1689 if (!okay) { 1690 ALOGE("Bogus type_idx"); 1691 return 0; 1692 } 1693 1694 CHECK_INDEX(typeIdx, state->pHeader->typeIdsSize); 1695 1696 u4 addr = readAndVerifyUnsignedLeb128(&ptr, fileEnd, &okay); 1697 1698 if (!okay) { 1699 ALOGE("Bogus addr"); 1700 return 0; 1701 } 1702 1703 if (addr >= code->insnsSize) { 1704 ALOGE("Invalid addr: %#x", addr); 1705 return 0; 1706 } 1707 } 1708 1709 if (catchAll) { 1710 u4 addr = readAndVerifyUnsignedLeb128(&ptr, fileEnd, &okay); 1711 1712 if (!okay) { 1713 ALOGE("Bogus catch_all_addr"); 1714 return 0; 1715 } 1716 1717 if (addr >= code->insnsSize) { 1718 ALOGE("Invalid catch_all_addr: %#x", addr); 1719 return 0; 1720 } 1721 } 1722 1723 offset = ptr - handlersBase; 1724 } 1725 1726 return offset; 1727} 1728 1729/* Helper for swapCodeItem(), which does all the try-catch related 1730 * swapping and verification. */ 1731static void* swapTriesAndCatches(const CheckState* state, DexCode* code) { 1732 const u1* encodedHandlers = dexGetCatchHandlerData(code); 1733 const u1* encodedPtr = encodedHandlers; 1734 bool okay = true; 1735 u4 handlersSize = 1736 readAndVerifyUnsignedLeb128(&encodedPtr, state->fileEnd, &okay); 1737 1738 if (!okay) { 1739 ALOGE("Bogus handlers_size"); 1740 return NULL; 1741 } 1742 1743 if ((handlersSize == 0) || (handlersSize >= 65536)) { 1744 ALOGE("Invalid handlers_size: %d", handlersSize); 1745 return NULL; 1746 } 1747 1748 u4 handlerOffs[handlersSize]; // list of valid handlerOff values 1749 u4 endOffset = setHandlerOffsAndVerify(state, code, 1750 encodedPtr - encodedHandlers, 1751 handlersSize, handlerOffs); 1752 1753 if (endOffset == 0) { 1754 return NULL; 1755 } 1756 1757 DexTry* tries = (DexTry*) dexGetTries(code); 1758 u4 count = code->triesSize; 1759 u4 lastEnd = 0; 1760 1761 CHECK_LIST_SIZE(tries, count, sizeof(DexTry)); 1762 1763 while (count--) { 1764 u4 i; 1765 1766 SWAP_FIELD4(tries->startAddr); 1767 SWAP_FIELD2(tries->insnCount); 1768 SWAP_FIELD2(tries->handlerOff); 1769 1770 if (tries->startAddr < lastEnd) { 1771 ALOGE("Out-of-order try"); 1772 return NULL; 1773 } 1774 1775 if (tries->startAddr >= code->insnsSize) { 1776 ALOGE("Invalid start_addr: %#x", tries->startAddr); 1777 return NULL; 1778 } 1779 1780 for (i = 0; i < handlersSize; i++) { 1781 if (tries->handlerOff == handlerOffs[i]) { 1782 break; 1783 } 1784 } 1785 1786 if (i == handlersSize) { 1787 ALOGE("Bogus handler offset: %#x", tries->handlerOff); 1788 return NULL; 1789 } 1790 1791 lastEnd = tries->startAddr + tries->insnCount; 1792 1793 if (lastEnd > code->insnsSize) { 1794 ALOGE("Invalid insn_count: %#x (end addr %#x)", 1795 tries->insnCount, lastEnd); 1796 return NULL; 1797 } 1798 1799 tries++; 1800 } 1801 1802 return (u1*) encodedHandlers + endOffset; 1803} 1804 1805/* Perform byte-swapping and intra-item verification on code_item. */ 1806static void* swapCodeItem(const CheckState* state, void* ptr) { 1807 DexCode* item = (DexCode*) ptr; 1808 u2* insns; 1809 u4 count; 1810 1811 CHECK_PTR_RANGE(item, item + 1); 1812 SWAP_FIELD2(item->registersSize); 1813 SWAP_FIELD2(item->insSize); 1814 SWAP_FIELD2(item->outsSize); 1815 SWAP_FIELD2(item->triesSize); 1816 SWAP_OFFSET4(item->debugInfoOff); 1817 SWAP_FIELD4(item->insnsSize); 1818 1819 if (item->insSize > item->registersSize) { 1820 ALOGE("insSize (%u) > registersSize (%u)", item->insSize, 1821 item->registersSize); 1822 return NULL; 1823 } 1824 1825 if ((item->outsSize > 5) && (item->outsSize > item->registersSize)) { 1826 /* 1827 * It's okay for outsSize to be up to five, even if registersSize 1828 * is smaller, since the short forms of method invocation allow 1829 * repetition of a register multiple times within a single parameter 1830 * list. Longer parameter lists, though, need to be represented 1831 * in-order in the register file. 1832 */ 1833 ALOGE("outsSize (%u) > registersSize (%u)", item->outsSize, 1834 item->registersSize); 1835 return NULL; 1836 } 1837 1838 count = item->insnsSize; 1839 insns = item->insns; 1840 CHECK_LIST_SIZE(insns, count, sizeof(u2)); 1841 1842 while (count--) { 1843 *insns = SWAP2(*insns); 1844 insns++; 1845 } 1846 1847 if (item->triesSize == 0) { 1848 ptr = insns; 1849 } else { 1850 if ((((uintptr_t) insns) & 3) != 0) { 1851 // Four-byte alignment for the tries. Verify the spacer is a 0. 1852 if (*insns != 0) { 1853 ALOGE("Non-zero padding: %#x", (u4) *insns); 1854 return NULL; 1855 } 1856 } 1857 1858 ptr = swapTriesAndCatches(state, item); 1859 } 1860 1861 return ptr; 1862} 1863 1864/* Perform intra-item verification on string_data_item. */ 1865static void* intraVerifyStringDataItem(const CheckState* state, void* ptr) { 1866 const u1* fileEnd = state->fileEnd; 1867 const u1* data = (const u1*) ptr; 1868 bool okay = true; 1869 u4 utf16Size = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 1870 u4 i; 1871 1872 if (!okay) { 1873 ALOGE("Bogus utf16_size"); 1874 return NULL; 1875 } 1876 1877 for (i = 0; i < utf16Size; i++) { 1878 if (data >= fileEnd) { 1879 ALOGE("String data would go beyond end-of-file"); 1880 return NULL; 1881 } 1882 1883 u1 byte1 = *(data++); 1884 1885 // Switch on the high four bits. 1886 switch (byte1 >> 4) { 1887 case 0x00: { 1888 // Special case of bit pattern 0xxx. 1889 if (byte1 == 0) { 1890 ALOGE("String shorter than indicated utf16_size %#x", 1891 utf16Size); 1892 return NULL; 1893 } 1894 break; 1895 } 1896 case 0x01: 1897 case 0x02: 1898 case 0x03: 1899 case 0x04: 1900 case 0x05: 1901 case 0x06: 1902 case 0x07: { 1903 // Bit pattern 0xxx. No need for any extra bytes or checks. 1904 break; 1905 } 1906 case 0x08: 1907 case 0x09: 1908 case 0x0a: 1909 case 0x0b: 1910 case 0x0f: { 1911 /* 1912 * Bit pattern 10xx or 1111, which are illegal start bytes. 1913 * Note: 1111 is valid for normal UTF-8, but not the 1914 * modified UTF-8 used here. 1915 */ 1916 ALOGE("Illegal start byte %#x", byte1); 1917 return NULL; 1918 } 1919 case 0x0e: { 1920 // Bit pattern 1110, so there are two additional bytes. 1921 u1 byte2 = *(data++); 1922 if ((byte2 & 0xc0) != 0x80) { 1923 ALOGE("Illegal continuation byte %#x", byte2); 1924 return NULL; 1925 } 1926 u1 byte3 = *(data++); 1927 if ((byte3 & 0xc0) != 0x80) { 1928 ALOGE("Illegal continuation byte %#x", byte3); 1929 return NULL; 1930 } 1931 u2 value = ((byte1 & 0x0f) << 12) | ((byte2 & 0x3f) << 6) 1932 | (byte3 & 0x3f); 1933 if (value < 0x800) { 1934 ALOGE("Illegal representation for value %x", value); 1935 return NULL; 1936 } 1937 break; 1938 } 1939 case 0x0c: 1940 case 0x0d: { 1941 // Bit pattern 110x, so there is one additional byte. 1942 u1 byte2 = *(data++); 1943 if ((byte2 & 0xc0) != 0x80) { 1944 ALOGE("Illegal continuation byte %#x", byte2); 1945 return NULL; 1946 } 1947 u2 value = ((byte1 & 0x1f) << 6) | (byte2 & 0x3f); 1948 if ((value != 0) && (value < 0x80)) { 1949 ALOGE("Illegal representation for value %x", value); 1950 return NULL; 1951 } 1952 break; 1953 } 1954 } 1955 } 1956 1957 if (*(data++) != '\0') { 1958 ALOGE("String longer than indicated utf16_size %#x", utf16Size); 1959 return NULL; 1960 } 1961 1962 return (void*) data; 1963} 1964 1965/* Perform intra-item verification on debug_info_item. */ 1966static void* intraVerifyDebugInfoItem(const CheckState* state, void* ptr) { 1967 const u1* fileEnd = state->fileEnd; 1968 const u1* data = (const u1*) ptr; 1969 bool okay = true; 1970 u4 i; 1971 1972 readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 1973 1974 if (!okay) { 1975 ALOGE("Bogus line_start"); 1976 return NULL; 1977 } 1978 1979 u4 parametersSize = 1980 readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 1981 1982 if (!okay) { 1983 ALOGE("Bogus parameters_size"); 1984 return NULL; 1985 } 1986 1987 if (parametersSize > 65536) { 1988 ALOGE("Invalid parameters_size: %#x", parametersSize); 1989 return NULL; 1990 } 1991 1992 for (i = 0; i < parametersSize; i++) { 1993 u4 parameterName = 1994 readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 1995 1996 if (!okay) { 1997 ALOGE("Bogus parameter_name"); 1998 return NULL; 1999 } 2000 2001 if (parameterName != 0) { 2002 parameterName--; 2003 CHECK_INDEX(parameterName, state->pHeader->stringIdsSize); 2004 } 2005 } 2006 2007 bool done = false; 2008 while (!done) { 2009 u1 opcode = *(data++); 2010 2011 switch (opcode) { 2012 case DBG_END_SEQUENCE: { 2013 done = true; 2014 break; 2015 } 2016 case DBG_ADVANCE_PC: { 2017 readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 2018 break; 2019 } 2020 case DBG_ADVANCE_LINE: { 2021 readAndVerifySignedLeb128(&data, fileEnd, &okay); 2022 break; 2023 } 2024 case DBG_START_LOCAL: { 2025 u4 idx; 2026 u4 regNum = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 2027 if (!okay) break; 2028 if (regNum >= 65536) { 2029 okay = false; 2030 break; 2031 } 2032 idx = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 2033 if (!okay) break; 2034 if (idx != 0) { 2035 idx--; 2036 CHECK_INDEX(idx, state->pHeader->stringIdsSize); 2037 } 2038 idx = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 2039 if (!okay) break; 2040 if (idx != 0) { 2041 idx--; 2042 CHECK_INDEX(idx, state->pHeader->stringIdsSize); 2043 } 2044 break; 2045 } 2046 case DBG_END_LOCAL: 2047 case DBG_RESTART_LOCAL: { 2048 u4 regNum = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 2049 if (!okay) break; 2050 if (regNum >= 65536) { 2051 okay = false; 2052 break; 2053 } 2054 break; 2055 } 2056 case DBG_START_LOCAL_EXTENDED: { 2057 u4 idx; 2058 u4 regNum = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 2059 if (!okay) break; 2060 if (regNum >= 65536) { 2061 okay = false; 2062 break; 2063 } 2064 idx = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 2065 if (!okay) break; 2066 if (idx != 0) { 2067 idx--; 2068 CHECK_INDEX(idx, state->pHeader->stringIdsSize); 2069 } 2070 idx = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 2071 if (!okay) break; 2072 if (idx != 0) { 2073 idx--; 2074 CHECK_INDEX(idx, state->pHeader->stringIdsSize); 2075 } 2076 idx = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 2077 if (!okay) break; 2078 if (idx != 0) { 2079 idx--; 2080 CHECK_INDEX(idx, state->pHeader->stringIdsSize); 2081 } 2082 break; 2083 } 2084 case DBG_SET_FILE: { 2085 u4 idx = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 2086 if (!okay) break; 2087 if (idx != 0) { 2088 idx--; 2089 CHECK_INDEX(idx, state->pHeader->stringIdsSize); 2090 } 2091 break; 2092 } 2093 default: { 2094 // No arguments to parse for anything else. 2095 } 2096 } 2097 2098 if (!okay) { 2099 ALOGE("Bogus syntax for opcode %02x", opcode); 2100 return NULL; 2101 } 2102 } 2103 2104 return (void*) data; 2105} 2106 2107/* defined below */ 2108static const u1* verifyEncodedValue(const CheckState* state, const u1* data, 2109 bool crossVerify); 2110static const u1* verifyEncodedAnnotation(const CheckState* state, 2111 const u1* data, bool crossVerify); 2112 2113/* Helper for verifyEncodedValue(), which reads a 1- to 4- byte unsigned 2114 * little endian value. */ 2115static u4 readUnsignedLittleEndian(const CheckState* state, const u1** pData, 2116 u4 size) { 2117 const u1* data = *pData; 2118 u4 result = 0; 2119 u4 i; 2120 2121 CHECK_PTR_RANGE(data, data + size); 2122 2123 for (i = 0; i < size; i++) { 2124 result |= ((u4) *(data++)) << (i * 8); 2125 } 2126 2127 *pData = data; 2128 return result; 2129} 2130 2131/* Helper for *VerifyAnnotationItem() and *VerifyEncodedArrayItem(), which 2132 * verifies an encoded_array. */ 2133static const u1* verifyEncodedArray(const CheckState* state, 2134 const u1* data, bool crossVerify) { 2135 bool okay = true; 2136 u4 size = readAndVerifyUnsignedLeb128(&data, state->fileEnd, &okay); 2137 2138 if (!okay) { 2139 ALOGE("Bogus encoded_array size"); 2140 return NULL; 2141 } 2142 2143 while (size--) { 2144 data = verifyEncodedValue(state, data, crossVerify); 2145 if (data == NULL) { 2146 ALOGE("Bogus encoded_array value"); 2147 return NULL; 2148 } 2149 } 2150 2151 return data; 2152} 2153 2154/* Helper for *VerifyAnnotationItem() and *VerifyEncodedArrayItem(), which 2155 * verifies an encoded_value. */ 2156static const u1* verifyEncodedValue(const CheckState* state, 2157 const u1* data, bool crossVerify) { 2158 CHECK_PTR_RANGE(data, data + 1); 2159 2160 u1 headerByte = *(data++); 2161 u4 valueType = headerByte & kDexAnnotationValueTypeMask; 2162 u4 valueArg = headerByte >> kDexAnnotationValueArgShift; 2163 2164 switch (valueType) { 2165 case kDexAnnotationByte: { 2166 if (valueArg != 0) { 2167 ALOGE("Bogus byte size %#x", valueArg); 2168 return NULL; 2169 } 2170 data++; 2171 break; 2172 } 2173 case kDexAnnotationShort: 2174 case kDexAnnotationChar: { 2175 if (valueArg > 1) { 2176 ALOGE("Bogus char/short size %#x", valueArg); 2177 return NULL; 2178 } 2179 data += valueArg + 1; 2180 break; 2181 } 2182 case kDexAnnotationInt: 2183 case kDexAnnotationFloat: { 2184 if (valueArg > 3) { 2185 ALOGE("Bogus int/float size %#x", valueArg); 2186 return NULL; 2187 } 2188 data += valueArg + 1; 2189 break; 2190 } 2191 case kDexAnnotationLong: 2192 case kDexAnnotationDouble: { 2193 data += valueArg + 1; 2194 break; 2195 } 2196 case kDexAnnotationString: { 2197 if (valueArg > 3) { 2198 ALOGE("Bogus string size %#x", valueArg); 2199 return NULL; 2200 } 2201 u4 idx = readUnsignedLittleEndian(state, &data, valueArg + 1); 2202 CHECK_INDEX(idx, state->pHeader->stringIdsSize); 2203 break; 2204 } 2205 case kDexAnnotationType: { 2206 if (valueArg > 3) { 2207 ALOGE("Bogus type size %#x", valueArg); 2208 return NULL; 2209 } 2210 u4 idx = readUnsignedLittleEndian(state, &data, valueArg + 1); 2211 CHECK_INDEX(idx, state->pHeader->typeIdsSize); 2212 break; 2213 } 2214 case kDexAnnotationField: 2215 case kDexAnnotationEnum: { 2216 if (valueArg > 3) { 2217 ALOGE("Bogus field/enum size %#x", valueArg); 2218 return NULL; 2219 } 2220 u4 idx = readUnsignedLittleEndian(state, &data, valueArg + 1); 2221 CHECK_INDEX(idx, state->pHeader->fieldIdsSize); 2222 break; 2223 } 2224 case kDexAnnotationMethod: { 2225 if (valueArg > 3) { 2226 ALOGE("Bogus method size %#x", valueArg); 2227 return NULL; 2228 } 2229 u4 idx = readUnsignedLittleEndian(state, &data, valueArg + 1); 2230 CHECK_INDEX(idx, state->pHeader->methodIdsSize); 2231 break; 2232 } 2233 case kDexAnnotationArray: { 2234 if (valueArg != 0) { 2235 ALOGE("Bogus array value_arg %#x", valueArg); 2236 return NULL; 2237 } 2238 data = verifyEncodedArray(state, data, crossVerify); 2239 break; 2240 } 2241 case kDexAnnotationAnnotation: { 2242 if (valueArg != 0) { 2243 ALOGE("Bogus annotation value_arg %#x", valueArg); 2244 return NULL; 2245 } 2246 data = verifyEncodedAnnotation(state, data, crossVerify); 2247 break; 2248 } 2249 case kDexAnnotationNull: { 2250 if (valueArg != 0) { 2251 ALOGE("Bogus null value_arg %#x", valueArg); 2252 return NULL; 2253 } 2254 // Nothing else to do for this type. 2255 break; 2256 } 2257 case kDexAnnotationBoolean: { 2258 if (valueArg > 1) { 2259 ALOGE("Bogus boolean value_arg %#x", valueArg); 2260 return NULL; 2261 } 2262 // Nothing else to do for this type. 2263 break; 2264 } 2265 default: { 2266 ALOGE("Bogus value_type %#x", valueType); 2267 return NULL; 2268 } 2269 } 2270 2271 return data; 2272} 2273 2274/* Helper for *VerifyAnnotationItem() and *VerifyEncodedArrayItem(), which 2275 * verifies an encoded_annotation. */ 2276static const u1* verifyEncodedAnnotation(const CheckState* state, 2277 const u1* data, bool crossVerify) { 2278 const u1* fileEnd = state->fileEnd; 2279 bool okay = true; 2280 u4 idx = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 2281 2282 if (!okay) { 2283 ALOGE("Bogus encoded_annotation type_idx"); 2284 return NULL; 2285 } 2286 2287 CHECK_INDEX(idx, state->pHeader->typeIdsSize); 2288 2289 if (crossVerify) { 2290 const char* descriptor = dexStringByTypeIdx(state->pDexFile, idx); 2291 if (!dexIsClassDescriptor(descriptor)) { 2292 ALOGE("Bogus annotation type: '%s'", descriptor); 2293 return NULL; 2294 } 2295 } 2296 2297 u4 size = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 2298 u4 lastIdx = 0; 2299 bool first = true; 2300 2301 if (!okay) { 2302 ALOGE("Bogus encoded_annotation size"); 2303 return NULL; 2304 } 2305 2306 while (size--) { 2307 idx = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay); 2308 2309 if (!okay) { 2310 ALOGE("Bogus encoded_annotation name_idx"); 2311 return NULL; 2312 } 2313 2314 CHECK_INDEX(idx, state->pHeader->stringIdsSize); 2315 2316 if (crossVerify) { 2317 const char* name = dexStringById(state->pDexFile, idx); 2318 if (!dexIsValidMemberName(name)) { 2319 ALOGE("Bogus annotation member name: '%s'", name); 2320 return NULL; 2321 } 2322 } 2323 2324 if (first) { 2325 first = false; 2326 } else if (lastIdx >= idx) { 2327 ALOGE("Out-of-order encoded_annotation name_idx: %#x then %#x", 2328 lastIdx, idx); 2329 return NULL; 2330 } 2331 2332 data = verifyEncodedValue(state, data, crossVerify); 2333 lastIdx = idx; 2334 2335 if (data == NULL) { 2336 return NULL; 2337 } 2338 } 2339 2340 return data; 2341} 2342 2343/* Perform intra-item verification on encoded_array_item. */ 2344static void* intraVerifyEncodedArrayItem(const CheckState* state, void* ptr) { 2345 return (void*) verifyEncodedArray(state, (const u1*) ptr, false); 2346} 2347 2348/* Perform intra-item verification on annotation_item. */ 2349static void* intraVerifyAnnotationItem(const CheckState* state, void* ptr) { 2350 const u1* data = (const u1*) ptr; 2351 2352 CHECK_PTR_RANGE(data, data + 1); 2353 2354 switch (*(data++)) { 2355 case kDexVisibilityBuild: 2356 case kDexVisibilityRuntime: 2357 case kDexVisibilitySystem: { 2358 break; 2359 } 2360 default: { 2361 ALOGE("Bogus annotation visibility: %#x", *data); 2362 return NULL; 2363 } 2364 } 2365 2366 return (void*) verifyEncodedAnnotation(state, data, false); 2367} 2368 2369/* Perform cross-item verification on annotation_item. */ 2370static void* crossVerifyAnnotationItem(const CheckState* state, void* ptr) { 2371 const u1* data = (const u1*) ptr; 2372 2373 // Skip the visibility byte. 2374 data++; 2375 2376 return (void*) verifyEncodedAnnotation(state, data, true); 2377} 2378 2379 2380 2381 2382/* 2383 * Function to visit an individual top-level item type. 2384 */ 2385typedef void* ItemVisitorFunction(const CheckState* state, void* ptr); 2386 2387/* 2388 * Iterate over all the items in a section, optionally updating the 2389 * data map (done if mapType is passed as non-negative). The section 2390 * must consist of concatenated items of the same type. 2391 */ 2392static bool iterateSectionWithOptionalUpdate(CheckState* state, 2393 u4 offset, u4 count, ItemVisitorFunction* func, u4 alignment, 2394 u4* nextOffset, int mapType) { 2395 u4 alignmentMask = alignment - 1; 2396 u4 i; 2397 2398 state->previousItem = NULL; 2399 2400 for (i = 0; i < count; i++) { 2401 u4 newOffset = (offset + alignmentMask) & ~alignmentMask; 2402 u1* ptr = (u1*) filePointer(state, newOffset); 2403 2404 if (offset < newOffset) { 2405 ptr = (u1*) filePointer(state, offset); 2406 if (offset < newOffset) { 2407 CHECK_OFFSET_RANGE(offset, newOffset); 2408 while (offset < newOffset) { 2409 if (*ptr != '\0') { 2410 ALOGE("Non-zero padding 0x%02x @ %x", *ptr, offset); 2411 return false; 2412 } 2413 ptr++; 2414 offset++; 2415 } 2416 } 2417 } 2418 2419 u1* newPtr = (u1*) func(state, ptr); 2420 newOffset = fileOffset(state, newPtr); 2421 2422 if (newPtr == NULL) { 2423 ALOGE("Trouble with item %d @ offset %#x", i, offset); 2424 return false; 2425 } 2426 2427 if (newOffset > state->fileLen) { 2428 ALOGE("Item %d @ offset %#x ends out of bounds", i, offset); 2429 return false; 2430 } 2431 2432 if (mapType >= 0) { 2433 dexDataMapAdd(state->pDataMap, offset, mapType); 2434 } 2435 2436 state->previousItem = ptr; 2437 offset = newOffset; 2438 } 2439 2440 if (nextOffset != NULL) { 2441 *nextOffset = offset; 2442 } 2443 2444 return true; 2445} 2446 2447/* 2448 * Iterate over all the items in a section. The section must consist of 2449 * concatenated items of the same type. This variant will not update the data 2450 * map. 2451 */ 2452static bool iterateSection(CheckState* state, u4 offset, u4 count, 2453 ItemVisitorFunction* func, u4 alignment, u4* nextOffset) { 2454 return iterateSectionWithOptionalUpdate(state, offset, count, func, 2455 alignment, nextOffset, -1); 2456} 2457 2458/* 2459 * Like iterateSection(), but also check that the offset and count match 2460 * a given pair of expected values. 2461 */ 2462static bool checkBoundsAndIterateSection(CheckState* state, 2463 u4 offset, u4 count, u4 expectedOffset, u4 expectedCount, 2464 ItemVisitorFunction* func, u4 alignment, u4* nextOffset) { 2465 if (offset != expectedOffset) { 2466 ALOGE("Bogus offset for section: got %#x; expected %#x", 2467 offset, expectedOffset); 2468 return false; 2469 } 2470 2471 if (count != expectedCount) { 2472 ALOGE("Bogus size for section: got %#x; expected %#x", 2473 count, expectedCount); 2474 return false; 2475 } 2476 2477 return iterateSection(state, offset, count, func, alignment, nextOffset); 2478} 2479 2480/* 2481 * Like iterateSection(), but also update the data section map and 2482 * check that all the items fall within the data section. 2483 */ 2484static bool iterateDataSection(CheckState* state, u4 offset, u4 count, 2485 ItemVisitorFunction* func, u4 alignment, u4* nextOffset, int mapType) { 2486 u4 dataStart = state->pHeader->dataOff; 2487 u4 dataEnd = dataStart + state->pHeader->dataSize; 2488 2489 assert(nextOffset != NULL); 2490 2491 if ((offset < dataStart) || (offset >= dataEnd)) { 2492 ALOGE("Bogus offset for data subsection: %#x", offset); 2493 return false; 2494 } 2495 2496 if (!iterateSectionWithOptionalUpdate(state, offset, count, func, 2497 alignment, nextOffset, mapType)) { 2498 return false; 2499 } 2500 2501 if (*nextOffset > dataEnd) { 2502 ALOGE("Out-of-bounds end of data subsection: %#x", *nextOffset); 2503 return false; 2504 } 2505 2506 return true; 2507} 2508 2509/* 2510 * Byte-swap all items in the given map except the header and the map 2511 * itself, both of which should have already gotten swapped. This also 2512 * does all possible intra-item verification, that is, verification 2513 * that doesn't need to assume the sanctity of the contents of *other* 2514 * items. The intra-item limitation is because at the time an item is 2515 * asked to verify itself, it can't assume that the items it refers to 2516 * have been byte-swapped and verified. 2517 */ 2518static bool swapEverythingButHeaderAndMap(CheckState* state, 2519 DexMapList* pMap) { 2520 const DexMapItem* item = pMap->list; 2521 u4 lastOffset = 0; 2522 u4 count = pMap->size; 2523 bool okay = true; 2524 2525 while (okay && count--) { 2526 u4 sectionOffset = item->offset; 2527 u4 sectionCount = item->size; 2528 u2 type = item->type; 2529 2530 if (lastOffset < sectionOffset) { 2531 CHECK_OFFSET_RANGE(lastOffset, sectionOffset); 2532 const u1* ptr = (const u1*) filePointer(state, lastOffset); 2533 while (lastOffset < sectionOffset) { 2534 if (*ptr != '\0') { 2535 ALOGE("Non-zero padding 0x%02x before section start @ %x", 2536 *ptr, lastOffset); 2537 okay = false; 2538 break; 2539 } 2540 ptr++; 2541 lastOffset++; 2542 } 2543 } else if (lastOffset > sectionOffset) { 2544 ALOGE("Section overlap or out-of-order map: %x, %x", 2545 lastOffset, sectionOffset); 2546 okay = false; 2547 } 2548 2549 if (!okay) { 2550 break; 2551 } 2552 2553 switch (type) { 2554 case kDexTypeHeaderItem: { 2555 /* 2556 * The header got swapped very early on, but do some 2557 * additional sanity checking here. 2558 */ 2559 okay = checkHeaderSection(state, sectionOffset, sectionCount, 2560 &lastOffset); 2561 break; 2562 } 2563 case kDexTypeStringIdItem: { 2564 okay = checkBoundsAndIterateSection(state, sectionOffset, 2565 sectionCount, state->pHeader->stringIdsOff, 2566 state->pHeader->stringIdsSize, swapStringIdItem, 2567 sizeof(u4), &lastOffset); 2568 break; 2569 } 2570 case kDexTypeTypeIdItem: { 2571 okay = checkBoundsAndIterateSection(state, sectionOffset, 2572 sectionCount, state->pHeader->typeIdsOff, 2573 state->pHeader->typeIdsSize, swapTypeIdItem, 2574 sizeof(u4), &lastOffset); 2575 break; 2576 } 2577 case kDexTypeProtoIdItem: { 2578 okay = checkBoundsAndIterateSection(state, sectionOffset, 2579 sectionCount, state->pHeader->protoIdsOff, 2580 state->pHeader->protoIdsSize, swapProtoIdItem, 2581 sizeof(u4), &lastOffset); 2582 break; 2583 } 2584 case kDexTypeFieldIdItem: { 2585 okay = checkBoundsAndIterateSection(state, sectionOffset, 2586 sectionCount, state->pHeader->fieldIdsOff, 2587 state->pHeader->fieldIdsSize, swapFieldIdItem, 2588 sizeof(u4), &lastOffset); 2589 break; 2590 } 2591 case kDexTypeMethodIdItem: { 2592 okay = checkBoundsAndIterateSection(state, sectionOffset, 2593 sectionCount, state->pHeader->methodIdsOff, 2594 state->pHeader->methodIdsSize, swapMethodIdItem, 2595 sizeof(u4), &lastOffset); 2596 break; 2597 } 2598 case kDexTypeClassDefItem: { 2599 okay = checkBoundsAndIterateSection(state, sectionOffset, 2600 sectionCount, state->pHeader->classDefsOff, 2601 state->pHeader->classDefsSize, swapClassDefItem, 2602 sizeof(u4), &lastOffset); 2603 break; 2604 } 2605 case kDexTypeMapList: { 2606 /* 2607 * The map section was swapped early on, but do some 2608 * additional sanity checking here. 2609 */ 2610 okay = checkMapSection(state, sectionOffset, sectionCount, 2611 &lastOffset); 2612 break; 2613 } 2614 case kDexTypeTypeList: { 2615 okay = iterateDataSection(state, sectionOffset, sectionCount, 2616 swapTypeList, sizeof(u4), &lastOffset, type); 2617 break; 2618 } 2619 case kDexTypeAnnotationSetRefList: { 2620 okay = iterateDataSection(state, sectionOffset, sectionCount, 2621 swapAnnotationSetRefList, sizeof(u4), &lastOffset, 2622 type); 2623 break; 2624 } 2625 case kDexTypeAnnotationSetItem: { 2626 okay = iterateDataSection(state, sectionOffset, sectionCount, 2627 swapAnnotationSetItem, sizeof(u4), &lastOffset, type); 2628 break; 2629 } 2630 case kDexTypeClassDataItem: { 2631 okay = iterateDataSection(state, sectionOffset, sectionCount, 2632 intraVerifyClassDataItem, sizeof(u1), &lastOffset, 2633 type); 2634 break; 2635 } 2636 case kDexTypeCodeItem: { 2637 okay = iterateDataSection(state, sectionOffset, sectionCount, 2638 swapCodeItem, sizeof(u4), &lastOffset, type); 2639 break; 2640 } 2641 case kDexTypeStringDataItem: { 2642 okay = iterateDataSection(state, sectionOffset, sectionCount, 2643 intraVerifyStringDataItem, sizeof(u1), &lastOffset, 2644 type); 2645 break; 2646 } 2647 case kDexTypeDebugInfoItem: { 2648 okay = iterateDataSection(state, sectionOffset, sectionCount, 2649 intraVerifyDebugInfoItem, sizeof(u1), &lastOffset, 2650 type); 2651 break; 2652 } 2653 case kDexTypeAnnotationItem: { 2654 okay = iterateDataSection(state, sectionOffset, sectionCount, 2655 intraVerifyAnnotationItem, sizeof(u1), &lastOffset, 2656 type); 2657 break; 2658 } 2659 case kDexTypeEncodedArrayItem: { 2660 okay = iterateDataSection(state, sectionOffset, sectionCount, 2661 intraVerifyEncodedArrayItem, sizeof(u1), &lastOffset, 2662 type); 2663 break; 2664 } 2665 case kDexTypeAnnotationsDirectoryItem: { 2666 okay = iterateDataSection(state, sectionOffset, sectionCount, 2667 swapAnnotationsDirectoryItem, sizeof(u4), &lastOffset, 2668 type); 2669 break; 2670 } 2671 default: { 2672 ALOGE("Unknown map item type %04x", type); 2673 return false; 2674 } 2675 } 2676 2677 if (!okay) { 2678 ALOGE("Swap of section type %04x failed", type); 2679 } 2680 2681 item++; 2682 } 2683 2684 return okay; 2685} 2686 2687/* 2688 * Perform cross-item verification on everything that needs it. This 2689 * pass is only called after all items are byte-swapped and 2690 * intra-verified (checked for internal consistency). 2691 */ 2692static bool crossVerifyEverything(CheckState* state, DexMapList* pMap) 2693{ 2694 const DexMapItem* item = pMap->list; 2695 u4 count = pMap->size; 2696 bool okay = true; 2697 2698 while (okay && count--) { 2699 u4 sectionOffset = item->offset; 2700 u4 sectionCount = item->size; 2701 2702 switch (item->type) { 2703 case kDexTypeHeaderItem: 2704 case kDexTypeMapList: 2705 case kDexTypeTypeList: 2706 case kDexTypeCodeItem: 2707 case kDexTypeStringDataItem: 2708 case kDexTypeDebugInfoItem: 2709 case kDexTypeAnnotationItem: 2710 case kDexTypeEncodedArrayItem: { 2711 // There is no need for cross-item verification for these. 2712 break; 2713 } 2714 case kDexTypeStringIdItem: { 2715 okay = iterateSection(state, sectionOffset, sectionCount, 2716 crossVerifyStringIdItem, sizeof(u4), NULL); 2717 break; 2718 } 2719 case kDexTypeTypeIdItem: { 2720 okay = iterateSection(state, sectionOffset, sectionCount, 2721 crossVerifyTypeIdItem, sizeof(u4), NULL); 2722 break; 2723 } 2724 case kDexTypeProtoIdItem: { 2725 okay = iterateSection(state, sectionOffset, sectionCount, 2726 crossVerifyProtoIdItem, sizeof(u4), NULL); 2727 break; 2728 } 2729 case kDexTypeFieldIdItem: { 2730 okay = iterateSection(state, sectionOffset, sectionCount, 2731 crossVerifyFieldIdItem, sizeof(u4), NULL); 2732 break; 2733 } 2734 case kDexTypeMethodIdItem: { 2735 okay = iterateSection(state, sectionOffset, sectionCount, 2736 crossVerifyMethodIdItem, sizeof(u4), NULL); 2737 break; 2738 } 2739 case kDexTypeClassDefItem: { 2740 // Allocate (on the stack) the "observed class_def" bits. 2741 size_t arraySize = calcDefinedClassBitsSize(state); 2742 u4 definedClassBits[arraySize]; 2743 memset(definedClassBits, 0, arraySize * sizeof(u4)); 2744 state->pDefinedClassBits = definedClassBits; 2745 2746 okay = iterateSection(state, sectionOffset, sectionCount, 2747 crossVerifyClassDefItem, sizeof(u4), NULL); 2748 2749 state->pDefinedClassBits = NULL; 2750 break; 2751 } 2752 case kDexTypeAnnotationSetRefList: { 2753 okay = iterateSection(state, sectionOffset, sectionCount, 2754 crossVerifyAnnotationSetRefList, sizeof(u4), NULL); 2755 break; 2756 } 2757 case kDexTypeAnnotationSetItem: { 2758 okay = iterateSection(state, sectionOffset, sectionCount, 2759 crossVerifyAnnotationSetItem, sizeof(u4), NULL); 2760 break; 2761 } 2762 case kDexTypeClassDataItem: { 2763 okay = iterateSection(state, sectionOffset, sectionCount, 2764 crossVerifyClassDataItem, sizeof(u1), NULL); 2765 break; 2766 } 2767 case kDexTypeAnnotationsDirectoryItem: { 2768 okay = iterateSection(state, sectionOffset, sectionCount, 2769 crossVerifyAnnotationsDirectoryItem, sizeof(u4), NULL); 2770 break; 2771 } 2772 default: { 2773 ALOGE("Unknown map item type %04x", item->type); 2774 return false; 2775 } 2776 } 2777 2778 if (!okay) { 2779 ALOGE("Cross-item verify of section type %04x failed", 2780 item->type); 2781 } 2782 2783 item++; 2784 } 2785 2786 return okay; 2787} 2788 2789/* (documented in header file) */ 2790bool dexHasValidMagic(const DexHeader* pHeader) 2791{ 2792 const u1* magic = pHeader->magic; 2793 const u1* version = &magic[4]; 2794 2795 if (memcmp(magic, DEX_MAGIC, 4) != 0) { 2796 ALOGE("ERROR: unrecognized magic number (%02x %02x %02x %02x)", 2797 magic[0], magic[1], magic[2], magic[3]); 2798 return false; 2799 } 2800 2801 if ((memcmp(version, DEX_MAGIC_VERS, 4) != 0) && 2802 (memcmp(version, DEX_MAGIC_VERS_API_13, 4) != 0)) { 2803 /* 2804 * Magic was correct, but this is an unsupported older or 2805 * newer format variant. 2806 */ 2807 ALOGE("ERROR: unsupported dex version (%02x %02x %02x %02x)", 2808 version[0], version[1], version[2], version[3]); 2809 return false; 2810 } 2811 2812 return true; 2813} 2814 2815/* 2816 * Fix the byte ordering of all fields in the DEX file, and do 2817 * structural verification. This is only required for code that opens 2818 * "raw" DEX files, such as the DEX optimizer. 2819 * 2820 * Returns 0 on success, nonzero on failure. 2821 */ 2822int dexSwapAndVerify(u1* addr, int len) 2823{ 2824 DexHeader* pHeader; 2825 CheckState state; 2826 bool okay = true; 2827 2828 memset(&state, 0, sizeof(state)); 2829 ALOGV("+++ swapping and verifying"); 2830 2831 /* 2832 * Note: The caller must have verified that "len" is at least as 2833 * large as a dex file header. 2834 */ 2835 pHeader = (DexHeader*) addr; 2836 2837 if (!dexHasValidMagic(pHeader)) { 2838 okay = false; 2839 } 2840 2841 if (okay) { 2842 int expectedLen = (int) SWAP4(pHeader->fileSize); 2843 if (len < expectedLen) { 2844 ALOGE("ERROR: Bad length: expected %d, got %d", expectedLen, len); 2845 okay = false; 2846 } else if (len != expectedLen) { 2847 ALOGW("WARNING: Odd length: expected %d, got %d", expectedLen, 2848 len); 2849 // keep going 2850 } 2851 } 2852 2853 if (okay) { 2854 /* 2855 * Compute the adler32 checksum and compare it to what's stored in 2856 * the file. This isn't free, but chances are good that we just 2857 * unpacked this from a jar file and have all of the pages sitting 2858 * in memory, so it's pretty quick. 2859 * 2860 * This might be a big-endian system, so we need to do this before 2861 * we byte-swap the header. 2862 */ 2863 uLong adler = adler32(0L, Z_NULL, 0); 2864 const int nonSum = sizeof(pHeader->magic) + sizeof(pHeader->checksum); 2865 u4 storedFileSize = SWAP4(pHeader->fileSize); 2866 u4 expectedChecksum = SWAP4(pHeader->checksum); 2867 2868 adler = adler32(adler, ((const u1*) pHeader) + nonSum, 2869 storedFileSize - nonSum); 2870 2871 if (adler != expectedChecksum) { 2872 ALOGE("ERROR: bad checksum (%08lx, expected %08x)", 2873 adler, expectedChecksum); 2874 okay = false; 2875 } 2876 } 2877 2878 if (okay) { 2879 state.fileStart = addr; 2880 state.fileEnd = addr + len; 2881 state.fileLen = len; 2882 state.pDexFile = NULL; 2883 state.pDataMap = NULL; 2884 state.pDefinedClassBits = NULL; 2885 state.previousItem = NULL; 2886 2887 /* 2888 * Swap the header and check the contents. 2889 */ 2890 okay = swapDexHeader(&state, pHeader); 2891 } 2892 2893 if (okay) { 2894 state.pHeader = pHeader; 2895 2896 if (pHeader->headerSize < sizeof(DexHeader)) { 2897 ALOGE("ERROR: Small header size %d, struct %d", 2898 pHeader->headerSize, (int) sizeof(DexHeader)); 2899 okay = false; 2900 } else if (pHeader->headerSize > sizeof(DexHeader)) { 2901 ALOGW("WARNING: Large header size %d, struct %d", 2902 pHeader->headerSize, (int) sizeof(DexHeader)); 2903 // keep going? 2904 } 2905 } 2906 2907 if (okay) { 2908 /* 2909 * Look for the map. Swap it and then use it to find and swap 2910 * everything else. 2911 */ 2912 if (pHeader->mapOff != 0) { 2913 DexFile dexFile; 2914 DexMapList* pDexMap = (DexMapList*) (addr + pHeader->mapOff); 2915 2916 okay = okay && swapMap(&state, pDexMap); 2917 okay = okay && swapEverythingButHeaderAndMap(&state, pDexMap); 2918 2919 dexFileSetupBasicPointers(&dexFile, addr); 2920 state.pDexFile = &dexFile; 2921 2922 okay = okay && crossVerifyEverything(&state, pDexMap); 2923 } else { 2924 ALOGE("ERROR: No map found; impossible to byte-swap and verify"); 2925 okay = false; 2926 } 2927 } 2928 2929 if (!okay) { 2930 ALOGE("ERROR: Byte swap + verify failed"); 2931 } 2932 2933 if (state.pDataMap != NULL) { 2934 dexDataMapFree(state.pDataMap); 2935 } 2936 2937 return !okay; // 0 == success 2938} 2939 2940/* 2941 * Detect the file type of the given memory buffer via magic number. 2942 * Call dexSwapAndVerify() on an unoptimized DEX file, do nothing 2943 * but return successfully on an optimized DEX file, and report an 2944 * error for all other cases. 2945 * 2946 * Returns 0 on success, nonzero on failure. 2947 */ 2948int dexSwapAndVerifyIfNecessary(u1* addr, int len) 2949{ 2950 if (memcmp(addr, DEX_OPT_MAGIC, 4) == 0) { 2951 // It is an optimized dex file. 2952 return 0; 2953 } 2954 2955 if (memcmp(addr, DEX_MAGIC, 4) == 0) { 2956 // It is an unoptimized dex file. 2957 return dexSwapAndVerify(addr, len); 2958 } 2959 2960 ALOGE("ERROR: Bad magic number (0x%02x %02x %02x %02x)", 2961 addr[0], addr[1], addr[2], addr[3]); 2962 2963 return 1; 2964} 2965