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     if (item->insSize > item->registersSize) {
   1813         LOGE("insSize (%u) > registersSize (%u)\n", item->insSize,
   1814                 item->registersSize);
   1815         return NULL;
   1816     }
   1817 
   1818     if ((item->outsSize > 5) && (item->outsSize > item->registersSize)) {
   1819         /*
   1820          * It's okay for outsSize to be up to five, even if registersSize
   1821          * is smaller, since the short forms of method invocation allow
   1822          * repetition of a register multiple times within a single parameter
   1823          * list. Longer parameter lists, though, need to be represented
   1824          * in-order in the register file.
   1825          */
   1826         LOGE("outsSize (%u) > registersSize (%u)\n", item->outsSize,
   1827                 item->registersSize);
   1828         return NULL;
   1829     }
   1830 
   1831     count = item->insnsSize;
   1832     insns = item->insns;
   1833     CHECK_LIST_SIZE(insns, count, sizeof(u2));
   1834 
   1835     while (count--) {
   1836         *insns = SWAP2(*insns);
   1837         insns++;
   1838     }
   1839 
   1840     if (item->triesSize == 0) {
   1841         ptr = insns;
   1842     } else {
   1843         if ((((u4) insns) & 3) != 0) {
   1844             // Four-byte alignment for the tries. Verify the spacer is a 0.
   1845             if (*insns != 0) {
   1846                 LOGE("Non-zero padding: 0x%x\n", (u4) *insns);
   1847                 return NULL;
   1848             }
   1849         }
   1850 
   1851         ptr = swapTriesAndCatches(state, item);
   1852     }
   1853 
   1854     return ptr;
   1855 }
   1856 
   1857 /* Perform intra-item verification on string_data_item. */
   1858 static void* intraVerifyStringDataItem(const CheckState* state, void* ptr) {
   1859     const u1* fileEnd = state->fileEnd;
   1860     const u1* data = ptr;
   1861     bool okay = true;
   1862     u4 utf16Size = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay);
   1863     u4 i;
   1864 
   1865     if (!okay) {
   1866         LOGE("Bogus utf16_size\n");
   1867         return NULL;
   1868     }
   1869 
   1870     for (i = 0; i < utf16Size; i++) {
   1871         if (data >= fileEnd) {
   1872             LOGE("String data would go beyond end-of-file\n");
   1873             return NULL;
   1874         }
   1875 
   1876         u1 byte1 = *(data++);
   1877 
   1878         // Switch on the high four bits.
   1879         switch (byte1 >> 4) {
   1880             case 0x00: {
   1881                 // Special case of bit pattern 0xxx.
   1882                 if (byte1 == 0) {
   1883                     LOGE("String shorter than indicated utf16_size 0x%x\n",
   1884                             utf16Size);
   1885                     return NULL;
   1886                 }
   1887                 break;
   1888             }
   1889             case 0x01:
   1890             case 0x02:
   1891             case 0x03:
   1892             case 0x04:
   1893             case 0x05:
   1894             case 0x06:
   1895             case 0x07: {
   1896                 // Bit pattern 0xxx. No need for any extra bytes or checks.
   1897                 break;
   1898             }
   1899             case 0x08:
   1900             case 0x09:
   1901             case 0x0a:
   1902             case 0x0b:
   1903             case 0x0f: {
   1904                 /*
   1905                  * Bit pattern 10xx or 1111, which are illegal start bytes.
   1906                  * Note: 1111 is valid for normal UTF-8, but not the
   1907                  * modified UTF-8 used here.
   1908                  */
   1909                 LOGE("Illegal start byte 0x%x\n", byte1);
   1910                 return NULL;
   1911             }
   1912             case 0x0e: {
   1913                 // Bit pattern 1110, so there are two additional bytes.
   1914                 u1 byte2 = *(data++);
   1915                 if ((byte2 & 0xc0) != 0x80) {
   1916                     LOGE("Illegal continuation byte 0x%x\n", byte2);
   1917                     return NULL;
   1918                 }
   1919                 u1 byte3 = *(data++);
   1920                 if ((byte3 & 0xc0) != 0x80) {
   1921                     LOGE("Illegal continuation byte 0x%x\n", byte3);
   1922                     return NULL;
   1923                 }
   1924                 u2 value = ((byte1 & 0x0f) << 12) | ((byte2 & 0x3f) << 6)
   1925                     | (byte3 & 0x3f);
   1926                 if (value < 0x800) {
   1927                     LOGE("Illegal representation for value %x\n", value);
   1928                     return NULL;
   1929                 }
   1930                 break;
   1931             }
   1932             case 0x0c:
   1933             case 0x0d: {
   1934                 // Bit pattern 110x, so there is one additional byte.
   1935                 u1 byte2 = *(data++);
   1936                 if ((byte2 & 0xc0) != 0x80) {
   1937                     LOGE("Illegal continuation byte 0x%x\n", byte2);
   1938                     return NULL;
   1939                 }
   1940                 u2 value = ((byte1 & 0x1f) << 6) | (byte2 & 0x3f);
   1941                 if ((value != 0) && (value < 0x80)) {
   1942                     LOGE("Illegal representation for value %x\n", value);
   1943                     return NULL;
   1944                 }
   1945                 break;
   1946             }
   1947         }
   1948     }
   1949 
   1950     if (*(data++) != '\0') {
   1951         LOGE("String longer than indicated utf16_size 0x%x\n", utf16Size);
   1952         return NULL;
   1953     }
   1954 
   1955     return (void*) data;
   1956 }
   1957 
   1958 /* Perform intra-item verification on debug_info_item. */
   1959 static void* intraVerifyDebugInfoItem(const CheckState* state, void* ptr) {
   1960     const u1* fileEnd = state->fileEnd;
   1961     const u1* data = ptr;
   1962     bool okay = true;
   1963     u4 i;
   1964 
   1965     readAndVerifyUnsignedLeb128(&data, fileEnd, &okay);
   1966 
   1967     if (!okay) {
   1968         LOGE("Bogus line_start\n");
   1969         return NULL;
   1970     }
   1971 
   1972     u4 parametersSize =
   1973         readAndVerifyUnsignedLeb128(&data, fileEnd, &okay);
   1974 
   1975     if (!okay) {
   1976         LOGE("Bogus parameters_size\n");
   1977         return NULL;
   1978     }
   1979 
   1980     if (parametersSize > 65536) {
   1981         LOGE("Invalid parameters_size: 0x%x\n", parametersSize);
   1982         return NULL;
   1983     }
   1984 
   1985     for (i = 0; i < parametersSize; i++) {
   1986         u4 parameterName =
   1987             readAndVerifyUnsignedLeb128(&data, fileEnd, &okay);
   1988 
   1989         if (!okay) {
   1990             LOGE("Bogus parameter_name\n");
   1991             return NULL;
   1992         }
   1993 
   1994         if (parameterName != 0) {
   1995             parameterName--;
   1996             CHECK_INDEX(parameterName, state->pHeader->stringIdsSize);
   1997         }
   1998     }
   1999 
   2000     bool done = false;
   2001     while (!done) {
   2002         u1 opcode = *(data++);
   2003 
   2004         switch (opcode) {
   2005             case DBG_END_SEQUENCE: {
   2006                 done = true;
   2007                 break;
   2008             }
   2009             case DBG_ADVANCE_PC: {
   2010                 readAndVerifyUnsignedLeb128(&data, fileEnd, &okay);
   2011                 break;
   2012             }
   2013             case DBG_ADVANCE_LINE: {
   2014                 readAndVerifySignedLeb128(&data, fileEnd, &okay);
   2015                 break;
   2016             }
   2017             case DBG_START_LOCAL: {
   2018                 u4 idx;
   2019                 u4 regNum = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay);
   2020                 if (!okay) break;
   2021                 if (regNum >= 65536) {
   2022                     okay = false;
   2023                     break;
   2024                 }
   2025                 idx = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay);
   2026                 if (!okay) break;
   2027                 if (idx != 0) {
   2028                     idx--;
   2029                     CHECK_INDEX(idx, state->pHeader->stringIdsSize);
   2030                 }
   2031                 idx = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay);
   2032                 if (!okay) break;
   2033                 if (idx != 0) {
   2034                     idx--;
   2035                     CHECK_INDEX(idx, state->pHeader->stringIdsSize);
   2036                 }
   2037                 break;
   2038             }
   2039             case DBG_END_LOCAL:
   2040             case DBG_RESTART_LOCAL: {
   2041                 u4 regNum = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay);
   2042                 if (!okay) break;
   2043                 if (regNum >= 65536) {
   2044                     okay = false;
   2045                     break;
   2046                 }
   2047                 break;
   2048             }
   2049             case DBG_START_LOCAL_EXTENDED: {
   2050                 u4 idx;
   2051                 u4 regNum = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay);
   2052                 if (!okay) break;
   2053                 if (regNum >= 65536) {
   2054                     okay = false;
   2055                     break;
   2056                 }
   2057                 idx = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay);
   2058                 if (!okay) break;
   2059                 if (idx != 0) {
   2060                     idx--;
   2061                     CHECK_INDEX(idx, state->pHeader->stringIdsSize);
   2062                 }
   2063                 idx = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay);
   2064                 if (!okay) break;
   2065                 if (idx != 0) {
   2066                     idx--;
   2067                     CHECK_INDEX(idx, state->pHeader->stringIdsSize);
   2068                 }
   2069                 idx = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay);
   2070                 if (!okay) break;
   2071                 if (idx != 0) {
   2072                     idx--;
   2073                     CHECK_INDEX(idx, state->pHeader->stringIdsSize);
   2074                 }
   2075                 break;
   2076             }
   2077             case DBG_SET_FILE: {
   2078                 u4 idx = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay);
   2079                 if (!okay) break;
   2080                 if (idx != 0) {
   2081                     idx--;
   2082                     CHECK_INDEX(idx, state->pHeader->stringIdsSize);
   2083                 }
   2084                 break;
   2085             }
   2086             default: {
   2087                 // No arguments to parse for anything else.
   2088             }
   2089         }
   2090 
   2091         if (!okay) {
   2092             LOGE("Bogus syntax for opcode %02x\n", opcode);
   2093             return NULL;
   2094         }
   2095     }
   2096 
   2097     return (void*) data;
   2098 }
   2099 
   2100 /* defined below */
   2101 static const u1* verifyEncodedValue(const CheckState* state, const u1* data,
   2102         bool crossVerify);
   2103 static const u1* verifyEncodedAnnotation(const CheckState* state,
   2104         const u1* data, bool crossVerify);
   2105 
   2106 /* Helper for verifyEncodedValue(), which reads a 1- to 4- byte unsigned
   2107  * little endian value. */
   2108 static u4 readUnsignedLittleEndian(const CheckState* state, const u1** pData,
   2109         u4 size) {
   2110     const u1* data = *pData;
   2111     u4 result = 0;
   2112     u4 i;
   2113 
   2114     CHECK_PTR_RANGE(data, data + size);
   2115 
   2116     for (i = 0; i < size; i++) {
   2117         result |= ((u4) *(data++)) << (i * 8);
   2118     }
   2119 
   2120     *pData = data;
   2121     return result;
   2122 }
   2123 
   2124 /* Helper for *VerifyAnnotationItem() and *VerifyEncodedArrayItem(), which
   2125  * verifies an encoded_array. */
   2126 static const u1* verifyEncodedArray(const CheckState* state,
   2127         const u1* data, bool crossVerify) {
   2128     bool okay = true;
   2129     u4 size = readAndVerifyUnsignedLeb128(&data, state->fileEnd, &okay);
   2130 
   2131     if (!okay) {
   2132         LOGE("Bogus encoded_array size\n");
   2133         return NULL;
   2134     }
   2135 
   2136     while (size--) {
   2137         data = verifyEncodedValue(state, data, crossVerify);
   2138         if (data == NULL) {
   2139             LOGE("Bogus encoded_array value\n");
   2140             return NULL;
   2141         }
   2142     }
   2143 
   2144     return data;
   2145 }
   2146 
   2147 /* Helper for *VerifyAnnotationItem() and *VerifyEncodedArrayItem(), which
   2148  * verifies an encoded_value. */
   2149 static const u1* verifyEncodedValue(const CheckState* state,
   2150         const u1* data, bool crossVerify) {
   2151     CHECK_PTR_RANGE(data, data + 1);
   2152 
   2153     u1 headerByte = *(data++);
   2154     u4 valueType = headerByte & kDexAnnotationValueTypeMask;
   2155     u4 valueArg = headerByte >> kDexAnnotationValueArgShift;
   2156 
   2157     switch (valueType) {
   2158         case kDexAnnotationByte: {
   2159             if (valueArg != 0) {
   2160                 LOGE("Bogus byte size 0x%x\n", valueArg);
   2161                 return NULL;
   2162             }
   2163             data++;
   2164             break;
   2165         }
   2166         case kDexAnnotationShort:
   2167         case kDexAnnotationChar: {
   2168             if (valueArg > 1) {
   2169                 LOGE("Bogus char/short size 0x%x\n", valueArg);
   2170                 return NULL;
   2171             }
   2172             data += valueArg + 1;
   2173             break;
   2174         }
   2175         case kDexAnnotationInt:
   2176         case kDexAnnotationFloat: {
   2177             if (valueArg > 3) {
   2178                 LOGE("Bogus int/float size 0x%x\n", valueArg);
   2179                 return NULL;
   2180             }
   2181             data += valueArg + 1;
   2182             break;
   2183         }
   2184         case kDexAnnotationLong:
   2185         case kDexAnnotationDouble: {
   2186             data += valueArg + 1;
   2187             break;
   2188         }
   2189         case kDexAnnotationString: {
   2190             if (valueArg > 3) {
   2191                 LOGE("Bogus string size 0x%x\n", valueArg);
   2192                 return NULL;
   2193             }
   2194             u4 idx = readUnsignedLittleEndian(state, &data, valueArg + 1);
   2195             CHECK_INDEX(idx, state->pHeader->stringIdsSize);
   2196             break;
   2197         }
   2198         case kDexAnnotationType: {
   2199             if (valueArg > 3) {
   2200                 LOGE("Bogus type size 0x%x\n", valueArg);
   2201                 return NULL;
   2202             }
   2203             u4 idx = readUnsignedLittleEndian(state, &data, valueArg + 1);
   2204             CHECK_INDEX(idx, state->pHeader->typeIdsSize);
   2205             break;
   2206         }
   2207         case kDexAnnotationField:
   2208         case kDexAnnotationEnum: {
   2209             if (valueArg > 3) {
   2210                 LOGE("Bogus field/enum size 0x%x\n", valueArg);
   2211                 return NULL;
   2212             }
   2213             u4 idx = readUnsignedLittleEndian(state, &data, valueArg + 1);
   2214             CHECK_INDEX(idx, state->pHeader->fieldIdsSize);
   2215             break;
   2216         }
   2217         case kDexAnnotationMethod: {
   2218             if (valueArg > 3) {
   2219                 LOGE("Bogus method size 0x%x\n", valueArg);
   2220                 return NULL;
   2221             }
   2222             u4 idx = readUnsignedLittleEndian(state, &data, valueArg + 1);
   2223             CHECK_INDEX(idx, state->pHeader->methodIdsSize);
   2224             break;
   2225         }
   2226         case kDexAnnotationArray: {
   2227             if (valueArg != 0) {
   2228                 LOGE("Bogus array value_arg 0x%x\n", valueArg);
   2229                 return NULL;
   2230             }
   2231             data = verifyEncodedArray(state, data, crossVerify);
   2232             break;
   2233         }
   2234         case kDexAnnotationAnnotation: {
   2235             if (valueArg != 0) {
   2236                 LOGE("Bogus annotation value_arg 0x%x\n", valueArg);
   2237                 return NULL;
   2238             }
   2239             data = verifyEncodedAnnotation(state, data, crossVerify);
   2240             break;
   2241         }
   2242         case kDexAnnotationNull: {
   2243             if (valueArg != 0) {
   2244                 LOGE("Bogus null value_arg 0x%x\n", valueArg);
   2245                 return NULL;
   2246             }
   2247             // Nothing else to do for this type.
   2248             break;
   2249         }
   2250         case kDexAnnotationBoolean: {
   2251             if (valueArg > 1) {
   2252                 LOGE("Bogus boolean value_arg 0x%x\n", valueArg);
   2253                 return NULL;
   2254             }
   2255             // Nothing else to do for this type.
   2256             break;
   2257         }
   2258         default: {
   2259             LOGE("Bogus value_type 0x%x\n", valueType);
   2260             return NULL;
   2261         }
   2262     }
   2263 
   2264     return data;
   2265 }
   2266 
   2267 /* Helper for *VerifyAnnotationItem() and *VerifyEncodedArrayItem(), which
   2268  * verifies an encoded_annotation. */
   2269 static const u1* verifyEncodedAnnotation(const CheckState* state,
   2270         const u1* data, bool crossVerify) {
   2271     const u1* fileEnd = state->fileEnd;
   2272     bool okay = true;
   2273     u4 idx = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay);
   2274 
   2275     if (!okay) {
   2276         LOGE("Bogus encoded_annotation type_idx\n");
   2277         return NULL;
   2278     }
   2279 
   2280     CHECK_INDEX(idx, state->pHeader->typeIdsSize);
   2281 
   2282     if (crossVerify) {
   2283         const char* descriptor = dexStringByTypeIdx(state->pDexFile, idx);
   2284         if (!dexIsClassDescriptor(descriptor)) {
   2285             LOGE("Bogus annotation type: '%s'\n", descriptor);
   2286             return NULL;
   2287         }
   2288     }
   2289 
   2290     u4 size = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay);
   2291     u4 lastIdx = 0;
   2292     bool first = true;
   2293 
   2294     if (!okay) {
   2295         LOGE("Bogus encoded_annotation size\n");
   2296         return NULL;
   2297     }
   2298 
   2299     while (size--) {
   2300         idx = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay);
   2301 
   2302         if (!okay) {
   2303             LOGE("Bogus encoded_annotation name_idx\n");
   2304             return NULL;
   2305         }
   2306 
   2307         CHECK_INDEX(idx, state->pHeader->stringIdsSize);
   2308 
   2309         if (crossVerify) {
   2310             const char* name = dexStringById(state->pDexFile, idx);
   2311             if (!dexIsValidMemberName(name)) {
   2312                 LOGE("Bogus annotation member name: '%s'\n", name);
   2313                 return NULL;
   2314             }
   2315         }
   2316 
   2317         if (first) {
   2318             first = false;
   2319         } else if (lastIdx >= idx) {
   2320             LOGE("Out-of-order encoded_annotation name_idx: 0x%x then 0x%x\n",
   2321                     lastIdx, idx);
   2322             return NULL;
   2323         }
   2324 
   2325         data = verifyEncodedValue(state, data, crossVerify);
   2326         lastIdx = idx;
   2327 
   2328         if (data == NULL) {
   2329             return NULL;
   2330         }
   2331     }
   2332 
   2333     return data;
   2334 }
   2335 
   2336 /* Perform intra-item verification on encoded_array_item. */
   2337 static void* intraVerifyEncodedArrayItem(const CheckState* state, void* ptr) {
   2338     return (void*) verifyEncodedArray(state, (const u1*) ptr, false);
   2339 }
   2340 
   2341 /* Perform intra-item verification on annotation_item. */
   2342 static void* intraVerifyAnnotationItem(const CheckState* state, void* ptr) {
   2343     const u1* data = ptr;
   2344 
   2345     CHECK_PTR_RANGE(data, data + 1);
   2346 
   2347     switch (*(data++)) {
   2348         case kDexVisibilityBuild:
   2349         case kDexVisibilityRuntime:
   2350         case kDexVisibilitySystem: {
   2351             break;
   2352         }
   2353         default: {
   2354             LOGE("Bogus annotation visibility: 0x%x\n", *data);
   2355             return NULL;
   2356         }
   2357     }
   2358 
   2359     return (void*) verifyEncodedAnnotation(state, data, false);
   2360 }
   2361 
   2362 /* Perform cross-item verification on annotation_item. */
   2363 static void* crossVerifyAnnotationItem(const CheckState* state, void* ptr) {
   2364     const u1* data = ptr;
   2365 
   2366     // Skip the visibility byte.
   2367     data++;
   2368 
   2369     return (void*) verifyEncodedAnnotation(state, data, true);
   2370 }
   2371 
   2372 
   2373 
   2374 
   2375 /*
   2376  * Function to visit an individual top-level item type.
   2377  */
   2378 typedef void* ItemVisitorFunction(const CheckState* state, void* ptr);
   2379 
   2380 /*
   2381  * Iterate over all the items in a section, optionally updating the
   2382  * data map (done if mapType is passed as non-negative). The section
   2383  * must consist of concatenated items of the same type.
   2384  */
   2385 static bool iterateSectionWithOptionalUpdate(CheckState* state,
   2386         u4 offset, u4 count, ItemVisitorFunction* func, u4 alignment,
   2387         u4* nextOffset, int mapType) {
   2388     u4 alignmentMask = alignment - 1;
   2389     u4 i;
   2390 
   2391     state->previousItem = NULL;
   2392 
   2393     for (i = 0; i < count; i++) {
   2394         u4 newOffset = (offset + alignmentMask) & ~alignmentMask;
   2395         u1* ptr = filePointer(state, newOffset);
   2396 
   2397         if (offset < newOffset) {
   2398             ptr = filePointer(state, offset);
   2399             if (offset < newOffset) {
   2400                 CHECK_OFFSET_RANGE(offset, newOffset);
   2401                 while (offset < newOffset) {
   2402                     if (*ptr != '\0') {
   2403                         LOGE("Non-zero padding 0x%02x @ %x\n", *ptr, offset);
   2404                         return false;
   2405                     }
   2406                     ptr++;
   2407                     offset++;
   2408                 }
   2409             }
   2410         }
   2411 
   2412         u1* newPtr = (u1*) func(state, ptr);
   2413         newOffset = fileOffset(state, newPtr);
   2414 
   2415         if (newPtr == NULL) {
   2416             LOGE("Trouble with item %d @ offset 0x%x\n", i, offset);
   2417             return false;
   2418         }
   2419 
   2420         if (newOffset > state->fileLen) {
   2421             LOGE("Item %d @ offset 0x%x ends out of bounds\n", i, offset);
   2422             return false;
   2423         }
   2424 
   2425         if (mapType >= 0) {
   2426             dexDataMapAdd(state->pDataMap, offset, mapType);
   2427         }
   2428 
   2429         state->previousItem = ptr;
   2430         offset = newOffset;
   2431     }
   2432 
   2433     if (nextOffset != NULL) {
   2434         *nextOffset = offset;
   2435     }
   2436 
   2437     return true;
   2438 }
   2439 
   2440 /*
   2441  * Iterate over all the items in a section. The section must consist of
   2442  * concatenated items of the same type. This variant will not update the data
   2443  * map.
   2444  */
   2445 static bool iterateSection(CheckState* state, u4 offset, u4 count,
   2446         ItemVisitorFunction* func, u4 alignment, u4* nextOffset) {
   2447     return iterateSectionWithOptionalUpdate(state, offset, count, func,
   2448             alignment, nextOffset, -1);
   2449 }
   2450 
   2451 /*
   2452  * Like iterateSection(), but also check that the offset and count match
   2453  * a given pair of expected values.
   2454  */
   2455 static bool checkBoundsAndIterateSection(CheckState* state,
   2456         u4 offset, u4 count, u4 expectedOffset, u4 expectedCount,
   2457         ItemVisitorFunction* func, u4 alignment, u4* nextOffset) {
   2458     if (offset != expectedOffset) {
   2459         LOGE("Bogus offset for section: got 0x%x; expected 0x%x\n",
   2460                 offset, expectedOffset);
   2461         return false;
   2462     }
   2463 
   2464     if (count != expectedCount) {
   2465         LOGE("Bogus size for section: got 0x%x; expected 0x%x\n",
   2466                 count, expectedCount);
   2467         return false;
   2468     }
   2469 
   2470     return iterateSection(state, offset, count, func, alignment, nextOffset);
   2471 }
   2472 
   2473 /*
   2474  * Like iterateSection(), but also update the data section map and
   2475  * check that all the items fall within the data section.
   2476  */
   2477 static bool iterateDataSection(CheckState* state, u4 offset, u4 count,
   2478         ItemVisitorFunction* func, u4 alignment, u4* nextOffset, int mapType) {
   2479     u4 dataStart = state->pHeader->dataOff;
   2480     u4 dataEnd = dataStart + state->pHeader->dataSize;
   2481 
   2482     assert(nextOffset != NULL);
   2483 
   2484     if ((offset < dataStart) || (offset >= dataEnd)) {
   2485         LOGE("Bogus offset for data subsection: 0x%x\n", offset);
   2486         return false;
   2487     }
   2488 
   2489     if (!iterateSectionWithOptionalUpdate(state, offset, count, func,
   2490                     alignment, nextOffset, mapType)) {
   2491         return false;
   2492     }
   2493 
   2494     if (*nextOffset > dataEnd) {
   2495         LOGE("Out-of-bounds end of data subsection: 0x%x\n", *nextOffset);
   2496         return false;
   2497     }
   2498 
   2499     return true;
   2500 }
   2501 
   2502 /*
   2503  * Byte-swap all items in the given map except the header and the map
   2504  * itself, both of which should have already gotten swapped. This also
   2505  * does all possible intra-item verification, that is, verification
   2506  * that doesn't need to assume the sanctity of the contents of *other*
   2507  * items. The intra-item limitation is because at the time an item is
   2508  * asked to verify itself, it can't assume that the items it refers to
   2509  * have been byte-swapped and verified.
   2510  */
   2511 static bool swapEverythingButHeaderAndMap(CheckState* state,
   2512         DexMapList* pMap) {
   2513     const DexMapItem* item = pMap->list;
   2514     u4 lastOffset = 0;
   2515     u4 count = pMap->size;
   2516     bool okay = true;
   2517 
   2518     while (okay && count--) {
   2519         u4 sectionOffset = item->offset;
   2520         u4 sectionCount = item->size;
   2521         u2 type = item->type;
   2522 
   2523         if (lastOffset < sectionOffset) {
   2524             CHECK_OFFSET_RANGE(lastOffset, sectionOffset);
   2525             const u1* ptr = filePointer(state, lastOffset);
   2526             while (lastOffset < sectionOffset) {
   2527                 if (*ptr != '\0') {
   2528                     LOGE("Non-zero padding 0x%02x before section start @ %x\n",
   2529                             *ptr, lastOffset);
   2530                     okay = false;
   2531                     break;
   2532                 }
   2533                 ptr++;
   2534                 lastOffset++;
   2535             }
   2536         } else if (lastOffset > sectionOffset) {
   2537             LOGE("Section overlap or out-of-order map: %x, %x\n",
   2538                     lastOffset, sectionOffset);
   2539             okay = false;
   2540         }
   2541 
   2542         if (!okay) {
   2543             break;
   2544         }
   2545 
   2546         switch (type) {
   2547             case kDexTypeHeaderItem: {
   2548                 /*
   2549                  * The header got swapped very early on, but do some
   2550                  * additional sanity checking here.
   2551                  */
   2552                 okay = checkHeaderSection(state, sectionOffset, sectionCount,
   2553                         &lastOffset);
   2554                 break;
   2555             }
   2556             case kDexTypeStringIdItem: {
   2557                 okay = checkBoundsAndIterateSection(state, sectionOffset,
   2558                         sectionCount, state->pHeader->stringIdsOff,
   2559                         state->pHeader->stringIdsSize, swapStringIdItem,
   2560                         sizeof(u4), &lastOffset);
   2561                 break;
   2562             }
   2563             case kDexTypeTypeIdItem: {
   2564                 okay = checkBoundsAndIterateSection(state, sectionOffset,
   2565                         sectionCount, state->pHeader->typeIdsOff,
   2566                         state->pHeader->typeIdsSize, swapTypeIdItem,
   2567                         sizeof(u4), &lastOffset);
   2568                 break;
   2569             }
   2570             case kDexTypeProtoIdItem: {
   2571                 okay = checkBoundsAndIterateSection(state, sectionOffset,
   2572                         sectionCount, state->pHeader->protoIdsOff,
   2573                         state->pHeader->protoIdsSize, swapProtoIdItem,
   2574                         sizeof(u4), &lastOffset);
   2575                 break;
   2576             }
   2577             case kDexTypeFieldIdItem: {
   2578                 okay = checkBoundsAndIterateSection(state, sectionOffset,
   2579                         sectionCount, state->pHeader->fieldIdsOff,
   2580                         state->pHeader->fieldIdsSize, swapFieldIdItem,
   2581                         sizeof(u4), &lastOffset);
   2582                 break;
   2583             }
   2584             case kDexTypeMethodIdItem: {
   2585                 okay = checkBoundsAndIterateSection(state, sectionOffset,
   2586                         sectionCount, state->pHeader->methodIdsOff,
   2587                         state->pHeader->methodIdsSize, swapMethodIdItem,
   2588                         sizeof(u4), &lastOffset);
   2589                 break;
   2590             }
   2591             case kDexTypeClassDefItem: {
   2592                 okay = checkBoundsAndIterateSection(state, sectionOffset,
   2593                         sectionCount, state->pHeader->classDefsOff,
   2594                         state->pHeader->classDefsSize, swapClassDefItem,
   2595                         sizeof(u4), &lastOffset);
   2596                 break;
   2597             }
   2598             case kDexTypeMapList: {
   2599                 /*
   2600                  * The map section was swapped early on, but do some
   2601                  * additional sanity checking here.
   2602                  */
   2603                 okay = checkMapSection(state, sectionOffset, sectionCount,
   2604                         &lastOffset);
   2605                 break;
   2606             }
   2607             case kDexTypeTypeList: {
   2608                 okay = iterateDataSection(state, sectionOffset, sectionCount,
   2609                         swapTypeList, sizeof(u4), &lastOffset, type);
   2610                 break;
   2611             }
   2612             case kDexTypeAnnotationSetRefList: {
   2613                 okay = iterateDataSection(state, sectionOffset, sectionCount,
   2614                         swapAnnotationSetRefList, sizeof(u4), &lastOffset,
   2615                         type);
   2616                 break;
   2617             }
   2618             case kDexTypeAnnotationSetItem: {
   2619                 okay = iterateDataSection(state, sectionOffset, sectionCount,
   2620                         swapAnnotationSetItem, sizeof(u4), &lastOffset, type);
   2621                 break;
   2622             }
   2623             case kDexTypeClassDataItem: {
   2624                 okay = iterateDataSection(state, sectionOffset, sectionCount,
   2625                         intraVerifyClassDataItem, sizeof(u1), &lastOffset,
   2626                         type);
   2627                 break;
   2628             }
   2629             case kDexTypeCodeItem: {
   2630                 okay = iterateDataSection(state, sectionOffset, sectionCount,
   2631                         swapCodeItem, sizeof(u4), &lastOffset, type);
   2632                 break;
   2633             }
   2634             case kDexTypeStringDataItem: {
   2635                 okay = iterateDataSection(state, sectionOffset, sectionCount,
   2636                         intraVerifyStringDataItem, sizeof(u1), &lastOffset,
   2637                         type);
   2638                 break;
   2639             }
   2640             case kDexTypeDebugInfoItem: {
   2641                 okay = iterateDataSection(state, sectionOffset, sectionCount,
   2642                         intraVerifyDebugInfoItem, sizeof(u1), &lastOffset,
   2643                         type);
   2644                 break;
   2645             }
   2646             case kDexTypeAnnotationItem: {
   2647                 okay = iterateDataSection(state, sectionOffset, sectionCount,
   2648                         intraVerifyAnnotationItem, sizeof(u1), &lastOffset,
   2649                         type);
   2650                 break;
   2651             }
   2652             case kDexTypeEncodedArrayItem: {
   2653                 okay = iterateDataSection(state, sectionOffset, sectionCount,
   2654                         intraVerifyEncodedArrayItem, sizeof(u1), &lastOffset,
   2655                         type);
   2656                 break;
   2657             }
   2658             case kDexTypeAnnotationsDirectoryItem: {
   2659                 okay = iterateDataSection(state, sectionOffset, sectionCount,
   2660                         swapAnnotationsDirectoryItem, sizeof(u4), &lastOffset,
   2661                         type);
   2662                 break;
   2663             }
   2664             default: {
   2665                 LOGE("Unknown map item type %04x\n", type);
   2666                 return false;
   2667             }
   2668         }
   2669 
   2670         if (!okay) {
   2671             LOGE("Swap of section type %04x failed\n", type);
   2672         }
   2673 
   2674         item++;
   2675     }
   2676 
   2677     return okay;
   2678 }
   2679 
   2680 /*
   2681  * Perform cross-item verification on everything that needs it. This
   2682  * pass is only called after all items are byte-swapped and
   2683  * intra-verified (checked for internal consistency).
   2684  */
   2685 static bool crossVerifyEverything(CheckState* state, DexMapList* pMap)
   2686 {
   2687     const DexMapItem* item = pMap->list;
   2688     u4 count = pMap->size;
   2689     bool okay = true;
   2690 
   2691     while (okay && count--) {
   2692         u4 sectionOffset = item->offset;
   2693         u4 sectionCount = item->size;
   2694 
   2695         switch (item->type) {
   2696             case kDexTypeHeaderItem:
   2697             case kDexTypeMapList:
   2698             case kDexTypeTypeList:
   2699             case kDexTypeCodeItem:
   2700             case kDexTypeStringDataItem:
   2701             case kDexTypeDebugInfoItem:
   2702             case kDexTypeAnnotationItem:
   2703             case kDexTypeEncodedArrayItem: {
   2704                 // There is no need for cross-item verification for these.
   2705                 break;
   2706             }
   2707             case kDexTypeStringIdItem: {
   2708                 okay = iterateSection(state, sectionOffset, sectionCount,
   2709                         crossVerifyStringIdItem, sizeof(u4), NULL);
   2710                 break;
   2711             }
   2712             case kDexTypeTypeIdItem: {
   2713                 okay = iterateSection(state, sectionOffset, sectionCount,
   2714                         crossVerifyTypeIdItem, sizeof(u4), NULL);
   2715                 break;
   2716             }
   2717             case kDexTypeProtoIdItem: {
   2718                 okay = iterateSection(state, sectionOffset, sectionCount,
   2719                         crossVerifyProtoIdItem, sizeof(u4), NULL);
   2720                 break;
   2721             }
   2722             case kDexTypeFieldIdItem: {
   2723                 okay = iterateSection(state, sectionOffset, sectionCount,
   2724                         crossVerifyFieldIdItem, sizeof(u4), NULL);
   2725                 break;
   2726             }
   2727             case kDexTypeMethodIdItem: {
   2728                 okay = iterateSection(state, sectionOffset, sectionCount,
   2729                         crossVerifyMethodIdItem, sizeof(u4), NULL);
   2730                 break;
   2731             }
   2732             case kDexTypeClassDefItem: {
   2733                 // Allocate (on the stack) the "observed class_def" bits.
   2734                 size_t arraySize = calcDefinedClassBitsSize(state);
   2735                 u4 definedClassBits[arraySize];
   2736                 memset(definedClassBits, 0, arraySize * sizeof(u4));
   2737                 state->pDefinedClassBits = definedClassBits;
   2738 
   2739                 okay = iterateSection(state, sectionOffset, sectionCount,
   2740                         crossVerifyClassDefItem, sizeof(u4), NULL);
   2741 
   2742                 state->pDefinedClassBits = NULL;
   2743                 break;
   2744             }
   2745             case kDexTypeAnnotationSetRefList: {
   2746                 okay = iterateSection(state, sectionOffset, sectionCount,
   2747                         crossVerifyAnnotationSetRefList, sizeof(u4), NULL);
   2748                 break;
   2749             }
   2750             case kDexTypeAnnotationSetItem: {
   2751                 okay = iterateSection(state, sectionOffset, sectionCount,
   2752                         crossVerifyAnnotationSetItem, sizeof(u4), NULL);
   2753                 break;
   2754             }
   2755             case kDexTypeClassDataItem: {
   2756                 okay = iterateSection(state, sectionOffset, sectionCount,
   2757                         crossVerifyClassDataItem, sizeof(u1), NULL);
   2758                 break;
   2759             }
   2760             case kDexTypeAnnotationsDirectoryItem: {
   2761                 okay = iterateSection(state, sectionOffset, sectionCount,
   2762                         crossVerifyAnnotationsDirectoryItem, sizeof(u4), NULL);
   2763                 break;
   2764             }
   2765             default: {
   2766                 LOGE("Unknown map item type %04x\n", item->type);
   2767                 return false;
   2768             }
   2769         }
   2770 
   2771         if (!okay) {
   2772             LOGE("Cross-item verify of section type %04x failed\n",
   2773                     item->type);
   2774         }
   2775 
   2776         item++;
   2777     }
   2778 
   2779     return okay;
   2780 }
   2781 
   2782 /*
   2783  * Fix the byte ordering of all fields in the DEX file, and do
   2784  * structural verification. This is only required for code that opens
   2785  * "raw" DEX files, such as the DEX optimizer.
   2786  *
   2787  * Returns 0 on success, nonzero on failure.
   2788  */
   2789 int dexSwapAndVerify(u1* addr, int len)
   2790 {
   2791     DexHeader* pHeader;
   2792     CheckState state;
   2793     bool okay = true;
   2794 
   2795     memset(&state, 0, sizeof(state));
   2796     LOGV("+++ swapping and verifying\n");
   2797 
   2798     /*
   2799      * Start by verifying the magic number.  The caller verified that "len"
   2800      * says we have at least a header's worth of data.
   2801      */
   2802     pHeader = (DexHeader*) addr;
   2803     if (memcmp(pHeader->magic, DEX_MAGIC, 4) != 0) {
   2804         /* really shouldn't be here -- this is weird */
   2805         LOGE("ERROR: Can't byte swap: bad magic number "
   2806                 "(0x%02x %02x %02x %02x)\n",
   2807              pHeader->magic[0], pHeader->magic[1],
   2808              pHeader->magic[2], pHeader->magic[3]);
   2809         okay = false;
   2810     }
   2811 
   2812     if (okay && memcmp(pHeader->magic+4, DEX_MAGIC_VERS, 4) != 0) {
   2813         /* older or newer version we don't know how to read */
   2814         LOGE("ERROR: Can't byte swap: bad dex version "
   2815                 "(0x%02x %02x %02x %02x)\n",
   2816              pHeader->magic[4], pHeader->magic[5],
   2817              pHeader->magic[6], pHeader->magic[7]);
   2818         okay = false;
   2819     }
   2820 
   2821     if (okay) {
   2822         int expectedLen = (int) SWAP4(pHeader->fileSize);
   2823         if (len < expectedLen) {
   2824             LOGE("ERROR: Bad length: expected %d, got %d\n", expectedLen, len);
   2825             okay = false;
   2826         } else if (len != expectedLen) {
   2827             LOGW("WARNING: Odd length: expected %d, got %d\n", expectedLen,
   2828                     len);
   2829             // keep going
   2830         }
   2831     }
   2832 
   2833     if (okay) {
   2834         /*
   2835          * Compute the adler32 checksum and compare it to what's stored in
   2836          * the file.  This isn't free, but chances are good that we just
   2837          * unpacked this from a jar file and have all of the pages sitting
   2838          * in memory, so it's pretty quick.
   2839          *
   2840          * This might be a big-endian system, so we need to do this before
   2841          * we byte-swap the header.
   2842          */
   2843         uLong adler = adler32(0L, Z_NULL, 0);
   2844         const int nonSum = sizeof(pHeader->magic) + sizeof(pHeader->checksum);
   2845         u4 storedFileSize = SWAP4(pHeader->fileSize);
   2846         u4 expectedChecksum = SWAP4(pHeader->checksum);
   2847 
   2848         adler = adler32(adler, ((const u1*) pHeader) + nonSum,
   2849                     storedFileSize - nonSum);
   2850 
   2851         if (adler != expectedChecksum) {
   2852             LOGE("ERROR: bad checksum (%08lx, expected %08x)\n",
   2853                 adler, expectedChecksum);
   2854             okay = false;
   2855         }
   2856     }
   2857 
   2858     if (okay) {
   2859         state.fileStart = addr;
   2860         state.fileEnd = addr + len;
   2861         state.fileLen = len;
   2862         state.pDexFile = NULL;
   2863         state.pDataMap = NULL;
   2864         state.pDefinedClassBits = NULL;
   2865         state.previousItem = NULL;
   2866 
   2867         /*
   2868          * Swap the header and check the contents.
   2869          */
   2870         okay = swapDexHeader(&state, pHeader);
   2871     }
   2872 
   2873     if (okay) {
   2874         state.pHeader = pHeader;
   2875 
   2876         if (pHeader->headerSize < sizeof(DexHeader)) {
   2877             LOGE("ERROR: Small header size %d, struct %d\n",
   2878                     pHeader->headerSize, (int) sizeof(DexHeader));
   2879             okay = false;
   2880         } else if (pHeader->headerSize > sizeof(DexHeader)) {
   2881             LOGW("WARNING: Large header size %d, struct %d\n",
   2882                     pHeader->headerSize, (int) sizeof(DexHeader));
   2883             // keep going?
   2884         }
   2885     }
   2886 
   2887     if (okay) {
   2888         /*
   2889          * Look for the map. Swap it and then use it to find and swap
   2890          * everything else.
   2891          */
   2892         if (pHeader->mapOff != 0) {
   2893             DexFile dexFile;
   2894             DexMapList* pDexMap = (DexMapList*) (addr + pHeader->mapOff);
   2895 
   2896             okay = okay && swapMap(&state, pDexMap);
   2897             okay = okay && swapEverythingButHeaderAndMap(&state, pDexMap);
   2898 
   2899             dexFileSetupBasicPointers(&dexFile, addr);
   2900             state.pDexFile = &dexFile;
   2901 
   2902             okay = okay && crossVerifyEverything(&state, pDexMap);
   2903         } else {
   2904             LOGE("ERROR: No map found; impossible to byte-swap and verify");
   2905             okay = false;
   2906         }
   2907     }
   2908 
   2909     if (!okay) {
   2910         LOGE("ERROR: Byte swap + verify failed\n");
   2911     }
   2912 
   2913     if (state.pDataMap != NULL) {
   2914         dexDataMapFree(state.pDataMap);
   2915     }
   2916 
   2917     return !okay;       // 0 == success
   2918 }
   2919 
   2920 /*
   2921  * Detect the file type of the given memory buffer via magic number.
   2922  * Call dexSwapAndVerify() on an unoptimized DEX file, do nothing
   2923  * but return successfully on an optimized DEX file, and report an
   2924  * error for all other cases.
   2925  *
   2926  * Returns 0 on success, nonzero on failure.
   2927  */
   2928 int dexSwapAndVerifyIfNecessary(u1* addr, int len)
   2929 {
   2930     if (memcmp(addr, DEX_OPT_MAGIC, 4) == 0) {
   2931         // It is an optimized dex file.
   2932         return 0;
   2933     }
   2934 
   2935     if (memcmp(addr, DEX_MAGIC, 4) == 0) {
   2936         // It is an unoptimized dex file.
   2937         return dexSwapAndVerify(addr, len);
   2938     }
   2939 
   2940     LOGE("ERROR: Bad magic number (0x%02x %02x %02x %02x)\n",
   2941              addr[0], addr[1], addr[2], addr[3]);
   2942 
   2943     return 1;
   2944 }
   2945