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