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