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