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