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     if ((item->accessFlags & ~ACC_CLASS_MASK) != 0) {
    915         // The VM specification says that unknown flags should be ignored.
    916         ALOGV("Bogus class access flags %x", item->accessFlags);
    917         item->accessFlags &= ACC_CLASS_MASK;
    918     }
    919 
    920     return item + 1;
    921 }
    922 
    923 /* defined below */
    924 static u4 findFirstClassDataDefiner(const CheckState* state,
    925         DexClassData* classData);
    926 static u4 findFirstAnnotationsDirectoryDefiner(const CheckState* state,
    927         const DexAnnotationsDirectoryItem* dir);
    928 
    929 /* Helper for crossVerifyClassDefItem(), which checks a class_data_item to
    930  * make sure all its references are to a given class. */
    931 static bool verifyClassDataIsForDef(const CheckState* state, u4 offset,
    932         u4 definerIdx) {
    933     if (offset == 0) {
    934         return true;
    935     }
    936 
    937     const u1* data = (const u1*) filePointer(state, offset);
    938     DexClassData* classData = dexReadAndVerifyClassData(&data, NULL);
    939 
    940     if (classData == NULL) {
    941         // Shouldn't happen, but bail here just in case.
    942         return false;
    943     }
    944 
    945     /*
    946      * The class_data_item verification ensures that
    947      * it consistently refers to the same definer, so all we need to
    948      * do is check the first one.
    949      */
    950     u4 dataDefiner = findFirstClassDataDefiner(state, classData);
    951     bool result = (dataDefiner == definerIdx) || (dataDefiner == kDexNoIndex);
    952 
    953     free(classData);
    954     return result;
    955 }
    956 
    957 /* Helper for crossVerifyClassDefItem(), which checks an
    958  * annotations_directory_item to make sure all its references are to a
    959  * given class. */
    960 static bool verifyAnnotationsDirectoryIsForDef(const CheckState* state,
    961         u4 offset, u4 definerIdx) {
    962     if (offset == 0) {
    963         return true;
    964     }
    965 
    966     const DexAnnotationsDirectoryItem* dir =
    967         (const DexAnnotationsDirectoryItem*) filePointer(state, offset);
    968     u4 annoDefiner = findFirstAnnotationsDirectoryDefiner(state, dir);
    969 
    970     return (annoDefiner == definerIdx) || (annoDefiner == kDexNoIndex);
    971 }
    972 
    973 /* Perform cross-item verification of class_def_item. */
    974 static void* crossVerifyClassDefItem(const CheckState* state, void* ptr) {
    975     const DexClassDef* item = (const DexClassDef*) ptr;
    976     u4 classIdx = item->classIdx;
    977     const char* descriptor = dexStringByTypeIdx(state->pDexFile, classIdx);
    978 
    979     if (!dexIsClassDescriptor(descriptor)) {
    980         ALOGE("Invalid class: '%s'", descriptor);
    981         return NULL;
    982     }
    983 
    984     if (setDefinedClassBit(state, classIdx)) {
    985         ALOGE("Duplicate class definition: '%s'", descriptor);
    986         return NULL;
    987     }
    988 
    989     bool okay =
    990         dexDataMapVerify0Ok(state->pDataMap,
    991                 item->interfacesOff, kDexTypeTypeList)
    992         && dexDataMapVerify0Ok(state->pDataMap,
    993                 item->annotationsOff, kDexTypeAnnotationsDirectoryItem)
    994         && dexDataMapVerify0Ok(state->pDataMap,
    995                 item->classDataOff, kDexTypeClassDataItem)
    996         && dexDataMapVerify0Ok(state->pDataMap,
    997                 item->staticValuesOff, kDexTypeEncodedArrayItem);
    998 
    999     if (!okay) {
   1000         return NULL;
   1001     }
   1002 
   1003     if (item->superclassIdx != kDexNoIndex) {
   1004         descriptor = dexStringByTypeIdx(state->pDexFile, item->superclassIdx);
   1005         if (!dexIsClassDescriptor(descriptor)) {
   1006             ALOGE("Invalid superclass: '%s'", descriptor);
   1007             return NULL;
   1008         }
   1009     }
   1010 
   1011     const DexTypeList* interfaces =
   1012         dexGetInterfacesList(state->pDexFile, item);
   1013     if (interfaces != NULL) {
   1014         u4 size = interfaces->size;
   1015         u4 i;
   1016 
   1017         /*
   1018          * Ensure that all interfaces refer to classes (not arrays or
   1019          * primitives).
   1020          */
   1021         for (i = 0; i < size; i++) {
   1022             descriptor = dexStringByTypeIdx(state->pDexFile,
   1023                     dexTypeListGetIdx(interfaces, i));
   1024             if (!dexIsClassDescriptor(descriptor)) {
   1025                 ALOGE("Invalid interface: '%s'", descriptor);
   1026                 return NULL;
   1027             }
   1028         }
   1029 
   1030         /*
   1031          * Ensure that there are no duplicates. This is an O(N^2) test,
   1032          * but in practice the number of interfaces implemented by any
   1033          * given class is low. I will buy a milkshake for the
   1034          * first person to show me a realistic case for which this test
   1035          * would be unacceptably slow.
   1036          */
   1037         for (i = 1; i < size; i++) {
   1038             u4 idx1 = dexTypeListGetIdx(interfaces, i);
   1039             u4 j;
   1040             for (j = 0; j < i; j++) {
   1041                 u4 idx2 = dexTypeListGetIdx(interfaces, j);
   1042                 if (idx1 == idx2) {
   1043                     ALOGE("Duplicate interface: '%s'",
   1044                             dexStringByTypeIdx(state->pDexFile, idx1));
   1045                     return NULL;
   1046                 }
   1047             }
   1048         }
   1049     }
   1050 
   1051     if (!verifyClassDataIsForDef(state, item->classDataOff, item->classIdx)) {
   1052         ALOGE("Invalid class_data_item");
   1053         return NULL;
   1054     }
   1055 
   1056     if (!verifyAnnotationsDirectoryIsForDef(state, item->annotationsOff,
   1057                     item->classIdx)) {
   1058         ALOGE("Invalid annotations_directory_item");
   1059         return NULL;
   1060     }
   1061 
   1062     return (void*) (item + 1);
   1063 }
   1064 
   1065 /* Helper for swapAnnotationsDirectoryItem(), which performs
   1066  * byte-swapping and intra-item verification on an
   1067  * annotation_directory_item's field elements. */
   1068 static u1* swapFieldAnnotations(const CheckState* state, u4 count, u1* addr) {
   1069     DexFieldAnnotationsItem* item = (DexFieldAnnotationsItem*) addr;
   1070     bool first = true;
   1071     u4 lastIdx = 0;
   1072 
   1073     CHECK_LIST_SIZE(item, count, sizeof(DexFieldAnnotationsItem));
   1074 
   1075     while (count--) {
   1076         SWAP_INDEX4(item->fieldIdx, state->pHeader->fieldIdsSize);
   1077         SWAP_OFFSET4(item->annotationsOff);
   1078 
   1079         if (first) {
   1080             first = false;
   1081         } else if (lastIdx >= item->fieldIdx) {
   1082             ALOGE("Out-of-order field_idx: %#x then %#x", lastIdx,
   1083                  item->fieldIdx);
   1084             return NULL;
   1085         }
   1086 
   1087         lastIdx = item->fieldIdx;
   1088         item++;
   1089     }
   1090 
   1091     return (u1*) item;
   1092 }
   1093 
   1094 /* Helper for swapAnnotationsDirectoryItem(), which performs
   1095  * byte-swapping and intra-item verification on an
   1096  * annotation_directory_item's method elements. */
   1097 static u1* swapMethodAnnotations(const CheckState* state, u4 count, u1* addr) {
   1098     DexMethodAnnotationsItem* item = (DexMethodAnnotationsItem*) addr;
   1099     bool first = true;
   1100     u4 lastIdx = 0;
   1101 
   1102     CHECK_LIST_SIZE(item, count, sizeof(DexMethodAnnotationsItem));
   1103 
   1104     while (count--) {
   1105         SWAP_INDEX4(item->methodIdx, state->pHeader->methodIdsSize);
   1106         SWAP_OFFSET4(item->annotationsOff);
   1107 
   1108         if (first) {
   1109             first = false;
   1110         } else if (lastIdx >= item->methodIdx) {
   1111             ALOGE("Out-of-order method_idx: %#x then %#x", lastIdx,
   1112                  item->methodIdx);
   1113             return NULL;
   1114         }
   1115 
   1116         lastIdx = item->methodIdx;
   1117         item++;
   1118     }
   1119 
   1120     return (u1*) item;
   1121 }
   1122 
   1123 /* Helper for swapAnnotationsDirectoryItem(), which performs
   1124  * byte-swapping and intra-item verification on an
   1125  * annotation_directory_item's parameter elements. */
   1126 static u1* swapParameterAnnotations(const CheckState* state, u4 count,
   1127         u1* addr) {
   1128     DexParameterAnnotationsItem* item = (DexParameterAnnotationsItem*) addr;
   1129     bool first = true;
   1130     u4 lastIdx = 0;
   1131 
   1132     CHECK_LIST_SIZE(item, count, sizeof(DexParameterAnnotationsItem));
   1133 
   1134     while (count--) {
   1135         SWAP_INDEX4(item->methodIdx, state->pHeader->methodIdsSize);
   1136         SWAP_OFFSET4(item->annotationsOff);
   1137 
   1138         if (first) {
   1139             first = false;
   1140         } else if (lastIdx >= item->methodIdx) {
   1141             ALOGE("Out-of-order method_idx: %#x then %#x", lastIdx,
   1142                  item->methodIdx);
   1143             return NULL;
   1144         }
   1145 
   1146         lastIdx = item->methodIdx;
   1147         item++;
   1148     }
   1149 
   1150     return (u1*) item;
   1151 }
   1152 
   1153 /* Perform byte-swapping and intra-item verification on
   1154  * annotations_directory_item. */
   1155 static void* swapAnnotationsDirectoryItem(const CheckState* state, void* ptr) {
   1156     DexAnnotationsDirectoryItem* item = (DexAnnotationsDirectoryItem*) ptr;
   1157 
   1158     CHECK_PTR_RANGE(item, item + 1);
   1159     SWAP_OFFSET4(item->classAnnotationsOff);
   1160     SWAP_FIELD4(item->fieldsSize);
   1161     SWAP_FIELD4(item->methodsSize);
   1162     SWAP_FIELD4(item->parametersSize);
   1163 
   1164     u1* addr = (u1*) (item + 1);
   1165 
   1166     if (item->fieldsSize != 0) {
   1167         addr = swapFieldAnnotations(state, item->fieldsSize, addr);
   1168         if (addr == NULL) {
   1169             return NULL;
   1170         }
   1171     }
   1172 
   1173     if (item->methodsSize != 0) {
   1174         addr = swapMethodAnnotations(state, item->methodsSize, addr);
   1175         if (addr == NULL) {
   1176             return NULL;
   1177         }
   1178     }
   1179 
   1180     if (item->parametersSize != 0) {
   1181         addr = swapParameterAnnotations(state, item->parametersSize, addr);
   1182         if (addr == NULL) {
   1183             return NULL;
   1184         }
   1185     }
   1186 
   1187     return addr;
   1188 }
   1189 
   1190 /* Helper for crossVerifyAnnotationsDirectoryItem(), which checks the
   1191  * field elements. */
   1192 static const u1* crossVerifyFieldAnnotations(const CheckState* state, u4 count,
   1193         const u1* addr, u4 definingClass) {
   1194     const DexFieldAnnotationsItem* item = (DexFieldAnnotationsItem*) addr;
   1195 
   1196     while (count--) {
   1197         if (!verifyFieldDefiner(state, definingClass, item->fieldIdx)) {
   1198             return NULL;
   1199         }
   1200         if (!dexDataMapVerify(state->pDataMap, item->annotationsOff,
   1201                         kDexTypeAnnotationSetItem)) {
   1202             return NULL;
   1203         }
   1204         item++;
   1205     }
   1206 
   1207     return (const u1*) item;
   1208 }
   1209 
   1210 /* Helper for crossVerifyAnnotationsDirectoryItem(), which checks the
   1211  * method elements. */
   1212 static const u1* crossVerifyMethodAnnotations(const CheckState* state,
   1213         u4 count, const u1* addr, u4 definingClass) {
   1214     const DexMethodAnnotationsItem* item = (DexMethodAnnotationsItem*) addr;
   1215 
   1216     while (count--) {
   1217         if (!verifyMethodDefiner(state, definingClass, item->methodIdx)) {
   1218             return NULL;
   1219         }
   1220         if (!dexDataMapVerify(state->pDataMap, item->annotationsOff,
   1221                         kDexTypeAnnotationSetItem)) {
   1222             return NULL;
   1223         }
   1224         item++;
   1225     }
   1226 
   1227     return (const u1*) item;
   1228 }
   1229 
   1230 /* Helper for crossVerifyAnnotationsDirectoryItem(), which checks the
   1231  * parameter elements. */
   1232 static const u1* crossVerifyParameterAnnotations(const CheckState* state,
   1233         u4 count, const u1* addr, u4 definingClass) {
   1234     const DexParameterAnnotationsItem* item =
   1235         (DexParameterAnnotationsItem*) addr;
   1236 
   1237     while (count--) {
   1238         if (!verifyMethodDefiner(state, definingClass, item->methodIdx)) {
   1239             return NULL;
   1240         }
   1241         if (!dexDataMapVerify(state->pDataMap, item->annotationsOff,
   1242                         kDexTypeAnnotationSetRefList)) {
   1243             return NULL;
   1244         }
   1245         item++;
   1246     }
   1247 
   1248     return (const u1*) item;
   1249 }
   1250 
   1251 /* Helper for crossVerifyClassDefItem() and
   1252  * crossVerifyAnnotationsDirectoryItem(), which finds the type_idx of
   1253  * the definer of the first item in the data. */
   1254 static u4 findFirstAnnotationsDirectoryDefiner(const CheckState* state,
   1255         const DexAnnotationsDirectoryItem* dir) {
   1256     if (dir->fieldsSize != 0) {
   1257         const DexFieldAnnotationsItem* fields =
   1258             dexGetFieldAnnotations(state->pDexFile, dir);
   1259         const DexFieldId* field =
   1260             dexGetFieldId(state->pDexFile, fields[0].fieldIdx);
   1261         return field->classIdx;
   1262     }
   1263 
   1264     if (dir->methodsSize != 0) {
   1265         const DexMethodAnnotationsItem* methods =
   1266             dexGetMethodAnnotations(state->pDexFile, dir);
   1267         const DexMethodId* method =
   1268             dexGetMethodId(state->pDexFile, methods[0].methodIdx);
   1269         return method->classIdx;
   1270     }
   1271 
   1272     if (dir->parametersSize != 0) {
   1273         const DexParameterAnnotationsItem* parameters =
   1274             dexGetParameterAnnotations(state->pDexFile, dir);
   1275         const DexMethodId* method =
   1276             dexGetMethodId(state->pDexFile, parameters[0].methodIdx);
   1277         return method->classIdx;
   1278     }
   1279 
   1280     return kDexNoIndex;
   1281 }
   1282 
   1283 /* Perform cross-item verification of annotations_directory_item. */
   1284 static void* crossVerifyAnnotationsDirectoryItem(const CheckState* state,
   1285         void* ptr) {
   1286     const DexAnnotationsDirectoryItem* item = (const DexAnnotationsDirectoryItem*) ptr;
   1287     u4 definingClass = findFirstAnnotationsDirectoryDefiner(state, item);
   1288 
   1289     if (!dexDataMapVerify0Ok(state->pDataMap,
   1290                     item->classAnnotationsOff, kDexTypeAnnotationSetItem)) {
   1291         return NULL;
   1292     }
   1293 
   1294     const u1* addr = (const u1*) (item + 1);
   1295 
   1296     if (item->fieldsSize != 0) {
   1297         addr = crossVerifyFieldAnnotations(state, item->fieldsSize, addr,
   1298                 definingClass);
   1299         if (addr == NULL) {
   1300             return NULL;
   1301         }
   1302     }
   1303 
   1304     if (item->methodsSize != 0) {
   1305         addr = crossVerifyMethodAnnotations(state, item->methodsSize, addr,
   1306                 definingClass);
   1307         if (addr == NULL) {
   1308             return NULL;
   1309         }
   1310     }
   1311 
   1312     if (item->parametersSize != 0) {
   1313         addr = crossVerifyParameterAnnotations(state, item->parametersSize,
   1314                 addr, definingClass);
   1315         if (addr == NULL) {
   1316             return NULL;
   1317         }
   1318     }
   1319 
   1320     return (void*) addr;
   1321 }
   1322 
   1323 /* Perform byte-swapping and intra-item verification on type_list. */
   1324 static void* swapTypeList(const CheckState* state, void* ptr)
   1325 {
   1326     DexTypeList* pTypeList = (DexTypeList*) ptr;
   1327     DexTypeItem* pType;
   1328     u4 count;
   1329 
   1330     CHECK_PTR_RANGE(pTypeList, pTypeList + 1);
   1331     SWAP_FIELD4(pTypeList->size);
   1332     count = pTypeList->size;
   1333     pType = pTypeList->list;
   1334     CHECK_LIST_SIZE(pType, count, sizeof(DexTypeItem));
   1335 
   1336     while (count--) {
   1337         SWAP_INDEX2(pType->typeIdx, state->pHeader->typeIdsSize);
   1338         pType++;
   1339     }
   1340 
   1341     return pType;
   1342 }
   1343 
   1344 /* Perform byte-swapping and intra-item verification on
   1345  * annotation_set_ref_list. */
   1346 static void* swapAnnotationSetRefList(const CheckState* state, void* ptr) {
   1347     DexAnnotationSetRefList* list = (DexAnnotationSetRefList*) ptr;
   1348     DexAnnotationSetRefItem* item;
   1349     u4 count;
   1350 
   1351     CHECK_PTR_RANGE(list, list + 1);
   1352     SWAP_FIELD4(list->size);
   1353     count = list->size;
   1354     item = list->list;
   1355     CHECK_LIST_SIZE(item, count, sizeof(DexAnnotationSetRefItem));
   1356 
   1357     while (count--) {
   1358         SWAP_OFFSET4(item->annotationsOff);
   1359         item++;
   1360     }
   1361 
   1362     return item;
   1363 }
   1364 
   1365 /* Perform cross-item verification of annotation_set_ref_list. */
   1366 static void* crossVerifyAnnotationSetRefList(const CheckState* state,
   1367         void* ptr) {
   1368     const DexAnnotationSetRefList* list = (const DexAnnotationSetRefList*) ptr;
   1369     const DexAnnotationSetRefItem* item = list->list;
   1370     int count = list->size;
   1371 
   1372     while (count--) {
   1373         if (!dexDataMapVerify0Ok(state->pDataMap,
   1374                         item->annotationsOff, kDexTypeAnnotationSetItem)) {
   1375             return NULL;
   1376         }
   1377         item++;
   1378     }
   1379 
   1380     return (void*) item;
   1381 }
   1382 
   1383 /* Perform byte-swapping and intra-item verification on
   1384  * annotation_set_item. */
   1385 static void* swapAnnotationSetItem(const CheckState* state, void* ptr) {
   1386     DexAnnotationSetItem* set = (DexAnnotationSetItem*) ptr;
   1387     u4* item;
   1388     u4 count;
   1389 
   1390     CHECK_PTR_RANGE(set, set + 1);
   1391     SWAP_FIELD4(set->size);
   1392     count = set->size;
   1393     item = set->entries;
   1394     CHECK_LIST_SIZE(item, count, sizeof(u4));
   1395 
   1396     while (count--) {
   1397         SWAP_OFFSET4(*item);
   1398         item++;
   1399     }
   1400 
   1401     return item;
   1402 }
   1403 
   1404 /* Helper for crossVerifyAnnotationSetItem(), which extracts the type_idx
   1405  * out of an annotation_item. */
   1406 static u4 annotationItemTypeIdx(const DexAnnotationItem* item) {
   1407     const u1* data = item->annotation;
   1408     return readUnsignedLeb128(&data);
   1409 }
   1410 
   1411 /* Perform cross-item verification of annotation_set_item. */
   1412 static void* crossVerifyAnnotationSetItem(const CheckState* state, void* ptr) {
   1413     const DexAnnotationSetItem* set = (const DexAnnotationSetItem*) ptr;
   1414     int count = set->size;
   1415     u4 lastIdx = 0;
   1416     bool first = true;
   1417     int i;
   1418 
   1419     for (i = 0; i < count; i++) {
   1420         if (!dexDataMapVerify0Ok(state->pDataMap,
   1421                         dexGetAnnotationOff(set, i), kDexTypeAnnotationItem)) {
   1422             return NULL;
   1423         }
   1424 
   1425         const DexAnnotationItem* annotation =
   1426             dexGetAnnotationItem(state->pDexFile, set, i);
   1427         u4 idx = annotationItemTypeIdx(annotation);
   1428 
   1429         if (first) {
   1430             first = false;
   1431         } else if (lastIdx >= idx) {
   1432             ALOGE("Out-of-order entry types: %#x then %#x",
   1433                     lastIdx, idx);
   1434             return NULL;
   1435         }
   1436 
   1437         lastIdx = idx;
   1438     }
   1439 
   1440     return (void*) (set->entries + count);
   1441 }
   1442 
   1443 /* Helper for verifyClassDataItem(), which checks a list of fields. */
   1444 static bool verifyFields(const CheckState* state, u4 size,
   1445         DexField* fields, bool expectStatic) {
   1446     u4 i;
   1447 
   1448     for (i = 0; i < size; i++) {
   1449         DexField* field = &fields[i];
   1450         u4 accessFlags = field->accessFlags;
   1451         bool isStatic = (accessFlags & ACC_STATIC) != 0;
   1452 
   1453         CHECK_INDEX(field->fieldIdx, state->pHeader->fieldIdsSize);
   1454 
   1455         if (isStatic != expectStatic) {
   1456             ALOGE("Field in wrong list @ %d", i);
   1457             return false;
   1458         }
   1459 
   1460         if ((accessFlags & ~ACC_FIELD_MASK) != 0) {
   1461             // The VM specification says that unknown flags should be ignored.
   1462             ALOGV("Bogus field access flags %x @ %d", accessFlags, i);
   1463             field->accessFlags &= ACC_FIELD_MASK;
   1464         }
   1465     }
   1466 
   1467     return true;
   1468 }
   1469 
   1470 /* Helper for verifyClassDataItem(), which checks a list of methods. */
   1471 static bool verifyMethods(const CheckState* state, u4 size,
   1472         DexMethod* methods, bool expectDirect) {
   1473     u4 i;
   1474 
   1475     for (i = 0; i < size; i++) {
   1476         DexMethod* method = &methods[i];
   1477 
   1478         CHECK_INDEX(method->methodIdx, state->pHeader->methodIdsSize);
   1479 
   1480         u4 accessFlags = method->accessFlags;
   1481         bool isDirect =
   1482             (accessFlags & (ACC_STATIC | ACC_PRIVATE | ACC_CONSTRUCTOR)) != 0;
   1483         bool expectCode = (accessFlags & (ACC_NATIVE | ACC_ABSTRACT)) == 0;
   1484         bool isSynchronized = (accessFlags & ACC_SYNCHRONIZED) != 0;
   1485         bool allowSynchronized = (accessFlags & ACC_NATIVE) != 0;
   1486 
   1487         if (isDirect != expectDirect) {
   1488             ALOGE("Method in wrong list @ %d", i);
   1489             return false;
   1490         }
   1491 
   1492         if (isSynchronized && !allowSynchronized) {
   1493             ALOGE("Bogus method access flags (synchronization) %x @ %d", accessFlags, i);
   1494             return false;
   1495         }
   1496 
   1497         if ((accessFlags & ~ACC_METHOD_MASK) != 0) {
   1498             // The VM specification says that unknown flags should be ignored.
   1499             ALOGV("Bogus method access flags %x @ %d", accessFlags, i);
   1500             method->accessFlags &= ACC_METHOD_MASK;
   1501         }
   1502 
   1503         if (expectCode) {
   1504             if (method->codeOff == 0) {
   1505                 ALOGE("Unexpected zero code_off for access_flags %x",
   1506                         accessFlags);
   1507                 return false;
   1508             }
   1509         } else if (method->codeOff != 0) {
   1510             ALOGE("Unexpected non-zero code_off %#x for access_flags %x",
   1511                     method->codeOff, accessFlags);
   1512             return false;
   1513         }
   1514     }
   1515 
   1516     return true;
   1517 }
   1518 
   1519 /* Helper for verifyClassDataItem(), which does most of the work. */
   1520 static bool verifyClassDataItem0(const CheckState* state,
   1521         DexClassData* classData) {
   1522     bool okay;
   1523 
   1524     okay = verifyFields(state, classData->header.staticFieldsSize,
   1525             classData->staticFields, true);
   1526 
   1527     if (!okay) {
   1528         ALOGE("Trouble with static fields");
   1529         return false;
   1530     }
   1531 
   1532     verifyFields(state, classData->header.instanceFieldsSize,
   1533             classData->instanceFields, false);
   1534 
   1535     if (!okay) {
   1536         ALOGE("Trouble with instance fields");
   1537         return false;
   1538     }
   1539 
   1540     okay = verifyMethods(state, classData->header.directMethodsSize,
   1541             classData->directMethods, true);
   1542 
   1543     if (!okay) {
   1544         ALOGE("Trouble with direct methods");
   1545         return false;
   1546     }
   1547 
   1548     okay = verifyMethods(state, classData->header.virtualMethodsSize,
   1549             classData->virtualMethods, false);
   1550 
   1551     if (!okay) {
   1552         ALOGE("Trouble with virtual methods");
   1553         return false;
   1554     }
   1555 
   1556     return true;
   1557 }
   1558 
   1559 /* Perform intra-item verification on class_data_item. */
   1560 static void* intraVerifyClassDataItem(const CheckState* state, void* ptr) {
   1561     const u1* data = (const u1*) ptr;
   1562     DexClassData* classData = dexReadAndVerifyClassData(&data, state->fileEnd);
   1563 
   1564     if (classData == NULL) {
   1565         ALOGE("Unable to parse class_data_item");
   1566         return NULL;
   1567     }
   1568 
   1569     bool okay = verifyClassDataItem0(state, classData);
   1570 
   1571     free(classData);
   1572 
   1573     if (!okay) {
   1574         return NULL;
   1575     }
   1576 
   1577     return (void*) data;
   1578 }
   1579 
   1580 /* Helper for crossVerifyClassDefItem() and
   1581  * crossVerifyClassDataItem(), which finds the type_idx of the definer
   1582  * of the first item in the data. */
   1583 static u4 findFirstClassDataDefiner(const CheckState* state,
   1584         DexClassData* classData) {
   1585     if (classData->header.staticFieldsSize != 0) {
   1586         u4 fieldIdx = classData->staticFields[0].fieldIdx;
   1587         const DexFieldId* field = dexGetFieldId(state->pDexFile, fieldIdx);
   1588         return field->classIdx;
   1589     }
   1590 
   1591     if (classData->header.instanceFieldsSize != 0) {
   1592         u4 fieldIdx = classData->instanceFields[0].fieldIdx;
   1593         const DexFieldId* field = dexGetFieldId(state->pDexFile, fieldIdx);
   1594         return field->classIdx;
   1595     }
   1596 
   1597     if (classData->header.directMethodsSize != 0) {
   1598         u4 methodIdx = classData->directMethods[0].methodIdx;
   1599         const DexMethodId* meth = dexGetMethodId(state->pDexFile, methodIdx);
   1600         return meth->classIdx;
   1601     }
   1602 
   1603     if (classData->header.virtualMethodsSize != 0) {
   1604         u4 methodIdx = classData->virtualMethods[0].methodIdx;
   1605         const DexMethodId* meth = dexGetMethodId(state->pDexFile, methodIdx);
   1606         return meth->classIdx;
   1607     }
   1608 
   1609     return kDexNoIndex;
   1610 }
   1611 
   1612 /* Perform cross-item verification of class_data_item. */
   1613 static void* crossVerifyClassDataItem(const CheckState* state, void* ptr) {
   1614     const u1* data = (const u1*) ptr;
   1615     DexClassData* classData = dexReadAndVerifyClassData(&data, state->fileEnd);
   1616     u4 definingClass = findFirstClassDataDefiner(state, classData);
   1617     bool okay = true;
   1618     u4 i;
   1619 
   1620     for (i = classData->header.staticFieldsSize; okay && (i > 0); /*i*/) {
   1621         i--;
   1622         const DexField* field = &classData->staticFields[i];
   1623         okay = verifyFieldDefiner(state, definingClass, field->fieldIdx);
   1624     }
   1625 
   1626     for (i = classData->header.instanceFieldsSize; okay && (i > 0); /*i*/) {
   1627         i--;
   1628         const DexField* field = &classData->instanceFields[i];
   1629         okay = verifyFieldDefiner(state, definingClass, field->fieldIdx);
   1630     }
   1631 
   1632     for (i = classData->header.directMethodsSize; okay && (i > 0); /*i*/) {
   1633         i--;
   1634         const DexMethod* meth = &classData->directMethods[i];
   1635         okay = dexDataMapVerify0Ok(state->pDataMap, meth->codeOff,
   1636                 kDexTypeCodeItem)
   1637             && verifyMethodDefiner(state, definingClass, meth->methodIdx);
   1638     }
   1639 
   1640     for (i = classData->header.virtualMethodsSize; okay && (i > 0); /*i*/) {
   1641         i--;
   1642         const DexMethod* meth = &classData->virtualMethods[i];
   1643         okay = dexDataMapVerify0Ok(state->pDataMap, meth->codeOff,
   1644                 kDexTypeCodeItem)
   1645             && verifyMethodDefiner(state, definingClass, meth->methodIdx);
   1646     }
   1647 
   1648     free(classData);
   1649 
   1650     if (!okay) {
   1651         return NULL;
   1652     }
   1653 
   1654     return (void*) data;
   1655 }
   1656 
   1657 /* Helper for swapCodeItem(), which fills an array with all the valid
   1658  * handlerOff values for catch handlers and also verifies the handler
   1659  * contents. */
   1660 static u4 setHandlerOffsAndVerify(const CheckState* state,
   1661         DexCode* code, u4 firstOffset, u4 handlersSize, u4* handlerOffs) {
   1662     const u1* fileEnd = state->fileEnd;
   1663     const u1* handlersBase = dexGetCatchHandlerData(code);
   1664     u4 offset = firstOffset;
   1665     bool okay = true;
   1666     u4 i;
   1667 
   1668     for (i = 0; i < handlersSize; i++) {
   1669         const u1* ptr = handlersBase + offset;
   1670         int size = readAndVerifySignedLeb128(&ptr, fileEnd, &okay);
   1671         bool catchAll;
   1672 
   1673         if (!okay) {
   1674             ALOGE("Bogus size");
   1675             return 0;
   1676         }
   1677 
   1678         if ((size < -65536) || (size > 65536)) {
   1679             ALOGE("Invalid size: %d", size);
   1680             return 0;
   1681         }
   1682 
   1683         if (size <= 0) {
   1684             catchAll = true;
   1685             size = -size;
   1686         } else {
   1687             catchAll = false;
   1688         }
   1689 
   1690         handlerOffs[i] = offset;
   1691 
   1692         while (size-- > 0) {
   1693             u4 typeIdx =
   1694                 readAndVerifyUnsignedLeb128(&ptr, fileEnd, &okay);
   1695 
   1696             if (!okay) {
   1697                 ALOGE("Bogus type_idx");
   1698                 return 0;
   1699             }
   1700 
   1701             CHECK_INDEX(typeIdx, state->pHeader->typeIdsSize);
   1702 
   1703             u4 addr = readAndVerifyUnsignedLeb128(&ptr, fileEnd, &okay);
   1704 
   1705             if (!okay) {
   1706                 ALOGE("Bogus addr");
   1707                 return 0;
   1708             }
   1709 
   1710             if (addr >= code->insnsSize) {
   1711                 ALOGE("Invalid addr: %#x", addr);
   1712                 return 0;
   1713             }
   1714         }
   1715 
   1716         if (catchAll) {
   1717             u4 addr = readAndVerifyUnsignedLeb128(&ptr, fileEnd, &okay);
   1718 
   1719             if (!okay) {
   1720                 ALOGE("Bogus catch_all_addr");
   1721                 return 0;
   1722             }
   1723 
   1724             if (addr >= code->insnsSize) {
   1725                 ALOGE("Invalid catch_all_addr: %#x", addr);
   1726                 return 0;
   1727             }
   1728         }
   1729 
   1730         offset = ptr - handlersBase;
   1731     }
   1732 
   1733     return offset;
   1734 }
   1735 
   1736 /* Helper for swapCodeItem(), which does all the try-catch related
   1737  * swapping and verification. */
   1738 static void* swapTriesAndCatches(const CheckState* state, DexCode* code) {
   1739     const u1* encodedHandlers = dexGetCatchHandlerData(code);
   1740     const u1* encodedPtr = encodedHandlers;
   1741     bool okay = true;
   1742     u4 handlersSize =
   1743         readAndVerifyUnsignedLeb128(&encodedPtr, state->fileEnd, &okay);
   1744 
   1745     if (!okay) {
   1746         ALOGE("Bogus handlers_size");
   1747         return NULL;
   1748     }
   1749 
   1750     if ((handlersSize == 0) || (handlersSize >= 65536)) {
   1751         ALOGE("Invalid handlers_size: %d", handlersSize);
   1752         return NULL;
   1753     }
   1754 
   1755     u4 handlerOffs[handlersSize]; // list of valid handlerOff values
   1756     u4 endOffset = setHandlerOffsAndVerify(state, code,
   1757             encodedPtr - encodedHandlers,
   1758             handlersSize, handlerOffs);
   1759 
   1760     if (endOffset == 0) {
   1761         return NULL;
   1762     }
   1763 
   1764     DexTry* tries = (DexTry*) dexGetTries(code);
   1765     u4 count = code->triesSize;
   1766     u4 lastEnd = 0;
   1767 
   1768     CHECK_LIST_SIZE(tries, count, sizeof(DexTry));
   1769 
   1770     while (count--) {
   1771         u4 i;
   1772 
   1773         SWAP_FIELD4(tries->startAddr);
   1774         SWAP_FIELD2(tries->insnCount);
   1775         SWAP_FIELD2(tries->handlerOff);
   1776 
   1777         if (tries->startAddr < lastEnd) {
   1778             ALOGE("Out-of-order try");
   1779             return NULL;
   1780         }
   1781 
   1782         if (tries->startAddr >= code->insnsSize) {
   1783             ALOGE("Invalid start_addr: %#x", tries->startAddr);
   1784             return NULL;
   1785         }
   1786 
   1787         for (i = 0; i < handlersSize; i++) {
   1788             if (tries->handlerOff == handlerOffs[i]) {
   1789                 break;
   1790             }
   1791         }
   1792 
   1793         if (i == handlersSize) {
   1794             ALOGE("Bogus handler offset: %#x", tries->handlerOff);
   1795             return NULL;
   1796         }
   1797 
   1798         lastEnd = tries->startAddr + tries->insnCount;
   1799 
   1800         if (lastEnd > code->insnsSize) {
   1801             ALOGE("Invalid insn_count: %#x (end addr %#x)",
   1802                     tries->insnCount, lastEnd);
   1803             return NULL;
   1804         }
   1805 
   1806         tries++;
   1807     }
   1808 
   1809     return (u1*) encodedHandlers + endOffset;
   1810 }
   1811 
   1812 /* Perform byte-swapping and intra-item verification on code_item. */
   1813 static void* swapCodeItem(const CheckState* state, void* ptr) {
   1814     DexCode* item = (DexCode*) ptr;
   1815     u2* insns;
   1816     u4 count;
   1817 
   1818     CHECK_PTR_RANGE(item, item + 1);
   1819     SWAP_FIELD2(item->registersSize);
   1820     SWAP_FIELD2(item->insSize);
   1821     SWAP_FIELD2(item->outsSize);
   1822     SWAP_FIELD2(item->triesSize);
   1823     SWAP_OFFSET4(item->debugInfoOff);
   1824     SWAP_FIELD4(item->insnsSize);
   1825 
   1826     if (item->insSize > item->registersSize) {
   1827         ALOGE("insSize (%u) > registersSize (%u)", item->insSize,
   1828                 item->registersSize);
   1829         return NULL;
   1830     }
   1831 
   1832     if ((item->outsSize > 5) && (item->outsSize > item->registersSize)) {
   1833         /*
   1834          * It's okay for outsSize to be up to five, even if registersSize
   1835          * is smaller, since the short forms of method invocation allow
   1836          * repetition of a register multiple times within a single parameter
   1837          * list. Longer parameter lists, though, need to be represented
   1838          * in-order in the register file.
   1839          */
   1840         ALOGE("outsSize (%u) > registersSize (%u)", item->outsSize,
   1841                 item->registersSize);
   1842         return NULL;
   1843     }
   1844 
   1845     count = item->insnsSize;
   1846     insns = item->insns;
   1847     CHECK_LIST_SIZE(insns, count, sizeof(u2));
   1848 
   1849     while (count--) {
   1850         *insns = SWAP2(*insns);
   1851         insns++;
   1852     }
   1853 
   1854     if (item->triesSize == 0) {
   1855         ptr = insns;
   1856     } else {
   1857         if ((((uintptr_t) insns) & 3) != 0) {
   1858             // Four-byte alignment for the tries. Verify the spacer is a 0.
   1859             if (*insns != 0) {
   1860                 ALOGE("Non-zero padding: %#x", (u4) *insns);
   1861                 return NULL;
   1862             }
   1863         }
   1864 
   1865         ptr = swapTriesAndCatches(state, item);
   1866     }
   1867 
   1868     return ptr;
   1869 }
   1870 
   1871 /* Perform intra-item verification on string_data_item. */
   1872 static void* intraVerifyStringDataItem(const CheckState* state, void* ptr) {
   1873     const u1* fileEnd = state->fileEnd;
   1874     const u1* data = (const u1*) ptr;
   1875     bool okay = true;
   1876     u4 utf16Size = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay);
   1877     u4 i;
   1878 
   1879     if (!okay) {
   1880         ALOGE("Bogus utf16_size");
   1881         return NULL;
   1882     }
   1883 
   1884     for (i = 0; i < utf16Size; i++) {
   1885         if (data >= fileEnd) {
   1886             ALOGE("String data would go beyond end-of-file");
   1887             return NULL;
   1888         }
   1889 
   1890         u1 byte1 = *(data++);
   1891 
   1892         // Switch on the high four bits.
   1893         switch (byte1 >> 4) {
   1894             case 0x00: {
   1895                 // Special case of bit pattern 0xxx.
   1896                 if (byte1 == 0) {
   1897                     ALOGE("String shorter than indicated utf16_size %#x",
   1898                             utf16Size);
   1899                     return NULL;
   1900                 }
   1901                 break;
   1902             }
   1903             case 0x01:
   1904             case 0x02:
   1905             case 0x03:
   1906             case 0x04:
   1907             case 0x05:
   1908             case 0x06:
   1909             case 0x07: {
   1910                 // Bit pattern 0xxx. No need for any extra bytes or checks.
   1911                 break;
   1912             }
   1913             case 0x08:
   1914             case 0x09:
   1915             case 0x0a:
   1916             case 0x0b:
   1917             case 0x0f: {
   1918                 /*
   1919                  * Bit pattern 10xx or 1111, which are illegal start bytes.
   1920                  * Note: 1111 is valid for normal UTF-8, but not the
   1921                  * modified UTF-8 used here.
   1922                  */
   1923                 ALOGE("Illegal start byte %#x", byte1);
   1924                 return NULL;
   1925             }
   1926             case 0x0e: {
   1927                 // Bit pattern 1110, so there are two additional bytes.
   1928                 u1 byte2 = *(data++);
   1929                 if ((byte2 & 0xc0) != 0x80) {
   1930                     ALOGE("Illegal continuation byte %#x", byte2);
   1931                     return NULL;
   1932                 }
   1933                 u1 byte3 = *(data++);
   1934                 if ((byte3 & 0xc0) != 0x80) {
   1935                     ALOGE("Illegal continuation byte %#x", byte3);
   1936                     return NULL;
   1937                 }
   1938                 u2 value = ((byte1 & 0x0f) << 12) | ((byte2 & 0x3f) << 6)
   1939                     | (byte3 & 0x3f);
   1940                 if (value < 0x800) {
   1941                     ALOGE("Illegal representation for value %x", value);
   1942                     return NULL;
   1943                 }
   1944                 break;
   1945             }
   1946             case 0x0c:
   1947             case 0x0d: {
   1948                 // Bit pattern 110x, so there is one additional byte.
   1949                 u1 byte2 = *(data++);
   1950                 if ((byte2 & 0xc0) != 0x80) {
   1951                     ALOGE("Illegal continuation byte %#x", byte2);
   1952                     return NULL;
   1953                 }
   1954                 u2 value = ((byte1 & 0x1f) << 6) | (byte2 & 0x3f);
   1955                 if ((value != 0) && (value < 0x80)) {
   1956                     ALOGE("Illegal representation for value %x", value);
   1957                     return NULL;
   1958                 }
   1959                 break;
   1960             }
   1961         }
   1962     }
   1963 
   1964     if (*(data++) != '\0') {
   1965         ALOGE("String longer than indicated utf16_size %#x", utf16Size);
   1966         return NULL;
   1967     }
   1968 
   1969     return (void*) data;
   1970 }
   1971 
   1972 /* Perform intra-item verification on debug_info_item. */
   1973 static void* intraVerifyDebugInfoItem(const CheckState* state, void* ptr) {
   1974     const u1* fileEnd = state->fileEnd;
   1975     const u1* data = (const u1*) ptr;
   1976     bool okay = true;
   1977     u4 i;
   1978 
   1979     readAndVerifyUnsignedLeb128(&data, fileEnd, &okay);
   1980 
   1981     if (!okay) {
   1982         ALOGE("Bogus line_start");
   1983         return NULL;
   1984     }
   1985 
   1986     u4 parametersSize =
   1987         readAndVerifyUnsignedLeb128(&data, fileEnd, &okay);
   1988 
   1989     if (!okay) {
   1990         ALOGE("Bogus parameters_size");
   1991         return NULL;
   1992     }
   1993 
   1994     if (parametersSize > 65536) {
   1995         ALOGE("Invalid parameters_size: %#x", parametersSize);
   1996         return NULL;
   1997     }
   1998 
   1999     for (i = 0; i < parametersSize; i++) {
   2000         u4 parameterName =
   2001             readAndVerifyUnsignedLeb128(&data, fileEnd, &okay);
   2002 
   2003         if (!okay) {
   2004             ALOGE("Bogus parameter_name");
   2005             return NULL;
   2006         }
   2007 
   2008         if (parameterName != 0) {
   2009             parameterName--;
   2010             CHECK_INDEX(parameterName, state->pHeader->stringIdsSize);
   2011         }
   2012     }
   2013 
   2014     bool done = false;
   2015     while (!done) {
   2016         u1 opcode = *(data++);
   2017 
   2018         switch (opcode) {
   2019             case DBG_END_SEQUENCE: {
   2020                 done = true;
   2021                 break;
   2022             }
   2023             case DBG_ADVANCE_PC: {
   2024                 readAndVerifyUnsignedLeb128(&data, fileEnd, &okay);
   2025                 break;
   2026             }
   2027             case DBG_ADVANCE_LINE: {
   2028                 readAndVerifySignedLeb128(&data, fileEnd, &okay);
   2029                 break;
   2030             }
   2031             case DBG_START_LOCAL: {
   2032                 u4 idx;
   2033                 u4 regNum = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay);
   2034                 if (!okay) break;
   2035                 if (regNum >= 65536) {
   2036                     okay = false;
   2037                     break;
   2038                 }
   2039                 idx = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay);
   2040                 if (!okay) break;
   2041                 if (idx != 0) {
   2042                     idx--;
   2043                     CHECK_INDEX(idx, state->pHeader->stringIdsSize);
   2044                 }
   2045                 idx = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay);
   2046                 if (!okay) break;
   2047                 if (idx != 0) {
   2048                     idx--;
   2049                     CHECK_INDEX(idx, state->pHeader->stringIdsSize);
   2050                 }
   2051                 break;
   2052             }
   2053             case DBG_END_LOCAL:
   2054             case DBG_RESTART_LOCAL: {
   2055                 u4 regNum = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay);
   2056                 if (!okay) break;
   2057                 if (regNum >= 65536) {
   2058                     okay = false;
   2059                     break;
   2060                 }
   2061                 break;
   2062             }
   2063             case DBG_START_LOCAL_EXTENDED: {
   2064                 u4 idx;
   2065                 u4 regNum = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay);
   2066                 if (!okay) break;
   2067                 if (regNum >= 65536) {
   2068                     okay = false;
   2069                     break;
   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                 idx = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay);
   2078                 if (!okay) break;
   2079                 if (idx != 0) {
   2080                     idx--;
   2081                     CHECK_INDEX(idx, state->pHeader->stringIdsSize);
   2082                 }
   2083                 idx = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay);
   2084                 if (!okay) break;
   2085                 if (idx != 0) {
   2086                     idx--;
   2087                     CHECK_INDEX(idx, state->pHeader->stringIdsSize);
   2088                 }
   2089                 break;
   2090             }
   2091             case DBG_SET_FILE: {
   2092                 u4 idx = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay);
   2093                 if (!okay) break;
   2094                 if (idx != 0) {
   2095                     idx--;
   2096                     CHECK_INDEX(idx, state->pHeader->stringIdsSize);
   2097                 }
   2098                 break;
   2099             }
   2100             default: {
   2101                 // No arguments to parse for anything else.
   2102             }
   2103         }
   2104 
   2105         if (!okay) {
   2106             ALOGE("Bogus syntax for opcode %02x", opcode);
   2107             return NULL;
   2108         }
   2109     }
   2110 
   2111     return (void*) data;
   2112 }
   2113 
   2114 /* defined below */
   2115 static const u1* verifyEncodedValue(const CheckState* state, const u1* data,
   2116         bool crossVerify);
   2117 static const u1* verifyEncodedAnnotation(const CheckState* state,
   2118         const u1* data, bool crossVerify);
   2119 
   2120 /* Helper for verifyEncodedValue(), which reads a 1- to 4- byte unsigned
   2121  * little endian value. */
   2122 static u4 readUnsignedLittleEndian(const CheckState* state, const u1** pData,
   2123         u4 size) {
   2124     const u1* data = *pData;
   2125     u4 result = 0;
   2126     u4 i;
   2127 
   2128     CHECK_PTR_RANGE(data, data + size);
   2129 
   2130     for (i = 0; i < size; i++) {
   2131         result |= ((u4) *(data++)) << (i * 8);
   2132     }
   2133 
   2134     *pData = data;
   2135     return result;
   2136 }
   2137 
   2138 /* Helper for *VerifyAnnotationItem() and *VerifyEncodedArrayItem(), which
   2139  * verifies an encoded_array. */
   2140 static const u1* verifyEncodedArray(const CheckState* state,
   2141         const u1* data, bool crossVerify) {
   2142     bool okay = true;
   2143     u4 size = readAndVerifyUnsignedLeb128(&data, state->fileEnd, &okay);
   2144 
   2145     if (!okay) {
   2146         ALOGE("Bogus encoded_array size");
   2147         return NULL;
   2148     }
   2149 
   2150     while (size--) {
   2151         data = verifyEncodedValue(state, data, crossVerify);
   2152         if (data == NULL) {
   2153             ALOGE("Bogus encoded_array value");
   2154             return NULL;
   2155         }
   2156     }
   2157 
   2158     return data;
   2159 }
   2160 
   2161 /* Helper for *VerifyAnnotationItem() and *VerifyEncodedArrayItem(), which
   2162  * verifies an encoded_value. */
   2163 static const u1* verifyEncodedValue(const CheckState* state,
   2164         const u1* data, bool crossVerify) {
   2165     CHECK_PTR_RANGE(data, data + 1);
   2166 
   2167     u1 headerByte = *(data++);
   2168     u4 valueType = headerByte & kDexAnnotationValueTypeMask;
   2169     u4 valueArg = headerByte >> kDexAnnotationValueArgShift;
   2170 
   2171     switch (valueType) {
   2172         case kDexAnnotationByte: {
   2173             if (valueArg != 0) {
   2174                 ALOGE("Bogus byte size %#x", valueArg);
   2175                 return NULL;
   2176             }
   2177             data++;
   2178             break;
   2179         }
   2180         case kDexAnnotationShort:
   2181         case kDexAnnotationChar: {
   2182             if (valueArg > 1) {
   2183                 ALOGE("Bogus char/short size %#x", valueArg);
   2184                 return NULL;
   2185             }
   2186             data += valueArg + 1;
   2187             break;
   2188         }
   2189         case kDexAnnotationInt:
   2190         case kDexAnnotationFloat: {
   2191             if (valueArg > 3) {
   2192                 ALOGE("Bogus int/float size %#x", valueArg);
   2193                 return NULL;
   2194             }
   2195             data += valueArg + 1;
   2196             break;
   2197         }
   2198         case kDexAnnotationLong:
   2199         case kDexAnnotationDouble: {
   2200             data += valueArg + 1;
   2201             break;
   2202         }
   2203         case kDexAnnotationString: {
   2204             if (valueArg > 3) {
   2205                 ALOGE("Bogus string size %#x", valueArg);
   2206                 return NULL;
   2207             }
   2208             u4 idx = readUnsignedLittleEndian(state, &data, valueArg + 1);
   2209             CHECK_INDEX(idx, state->pHeader->stringIdsSize);
   2210             break;
   2211         }
   2212         case kDexAnnotationType: {
   2213             if (valueArg > 3) {
   2214                 ALOGE("Bogus type size %#x", valueArg);
   2215                 return NULL;
   2216             }
   2217             u4 idx = readUnsignedLittleEndian(state, &data, valueArg + 1);
   2218             CHECK_INDEX(idx, state->pHeader->typeIdsSize);
   2219             break;
   2220         }
   2221         case kDexAnnotationField:
   2222         case kDexAnnotationEnum: {
   2223             if (valueArg > 3) {
   2224                 ALOGE("Bogus field/enum size %#x", valueArg);
   2225                 return NULL;
   2226             }
   2227             u4 idx = readUnsignedLittleEndian(state, &data, valueArg + 1);
   2228             CHECK_INDEX(idx, state->pHeader->fieldIdsSize);
   2229             break;
   2230         }
   2231         case kDexAnnotationMethod: {
   2232             if (valueArg > 3) {
   2233                 ALOGE("Bogus method size %#x", valueArg);
   2234                 return NULL;
   2235             }
   2236             u4 idx = readUnsignedLittleEndian(state, &data, valueArg + 1);
   2237             CHECK_INDEX(idx, state->pHeader->methodIdsSize);
   2238             break;
   2239         }
   2240         case kDexAnnotationArray: {
   2241             if (valueArg != 0) {
   2242                 ALOGE("Bogus array value_arg %#x", valueArg);
   2243                 return NULL;
   2244             }
   2245             data = verifyEncodedArray(state, data, crossVerify);
   2246             break;
   2247         }
   2248         case kDexAnnotationAnnotation: {
   2249             if (valueArg != 0) {
   2250                 ALOGE("Bogus annotation value_arg %#x", valueArg);
   2251                 return NULL;
   2252             }
   2253             data = verifyEncodedAnnotation(state, data, crossVerify);
   2254             break;
   2255         }
   2256         case kDexAnnotationNull: {
   2257             if (valueArg != 0) {
   2258                 ALOGE("Bogus null value_arg %#x", valueArg);
   2259                 return NULL;
   2260             }
   2261             // Nothing else to do for this type.
   2262             break;
   2263         }
   2264         case kDexAnnotationBoolean: {
   2265             if (valueArg > 1) {
   2266                 ALOGE("Bogus boolean value_arg %#x", valueArg);
   2267                 return NULL;
   2268             }
   2269             // Nothing else to do for this type.
   2270             break;
   2271         }
   2272         default: {
   2273             ALOGE("Bogus value_type %#x", valueType);
   2274             return NULL;
   2275         }
   2276     }
   2277 
   2278     return data;
   2279 }
   2280 
   2281 /* Helper for *VerifyAnnotationItem() and *VerifyEncodedArrayItem(), which
   2282  * verifies an encoded_annotation. */
   2283 static const u1* verifyEncodedAnnotation(const CheckState* state,
   2284         const u1* data, bool crossVerify) {
   2285     const u1* fileEnd = state->fileEnd;
   2286     bool okay = true;
   2287     u4 idx = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay);
   2288 
   2289     if (!okay) {
   2290         ALOGE("Bogus encoded_annotation type_idx");
   2291         return NULL;
   2292     }
   2293 
   2294     CHECK_INDEX(idx, state->pHeader->typeIdsSize);
   2295 
   2296     if (crossVerify) {
   2297         const char* descriptor = dexStringByTypeIdx(state->pDexFile, idx);
   2298         if (!dexIsClassDescriptor(descriptor)) {
   2299             ALOGE("Bogus annotation type: '%s'", descriptor);
   2300             return NULL;
   2301         }
   2302     }
   2303 
   2304     u4 size = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay);
   2305     u4 lastIdx = 0;
   2306     bool first = true;
   2307 
   2308     if (!okay) {
   2309         ALOGE("Bogus encoded_annotation size");
   2310         return NULL;
   2311     }
   2312 
   2313     while (size--) {
   2314         idx = readAndVerifyUnsignedLeb128(&data, fileEnd, &okay);
   2315 
   2316         if (!okay) {
   2317             ALOGE("Bogus encoded_annotation name_idx");
   2318             return NULL;
   2319         }
   2320 
   2321         CHECK_INDEX(idx, state->pHeader->stringIdsSize);
   2322 
   2323         if (crossVerify) {
   2324             const char* name = dexStringById(state->pDexFile, idx);
   2325             if (!dexIsValidMemberName(name)) {
   2326                 ALOGE("Bogus annotation member name: '%s'", name);
   2327                 return NULL;
   2328             }
   2329         }
   2330 
   2331         if (first) {
   2332             first = false;
   2333         } else if (lastIdx >= idx) {
   2334             ALOGE("Out-of-order encoded_annotation name_idx: %#x then %#x",
   2335                     lastIdx, idx);
   2336             return NULL;
   2337         }
   2338 
   2339         data = verifyEncodedValue(state, data, crossVerify);
   2340         lastIdx = idx;
   2341 
   2342         if (data == NULL) {
   2343             return NULL;
   2344         }
   2345     }
   2346 
   2347     return data;
   2348 }
   2349 
   2350 /* Perform intra-item verification on encoded_array_item. */
   2351 static void* intraVerifyEncodedArrayItem(const CheckState* state, void* ptr) {
   2352     return (void*) verifyEncodedArray(state, (const u1*) ptr, false);
   2353 }
   2354 
   2355 /* Perform intra-item verification on annotation_item. */
   2356 static void* intraVerifyAnnotationItem(const CheckState* state, void* ptr) {
   2357     const u1* data = (const u1*) ptr;
   2358 
   2359     CHECK_PTR_RANGE(data, data + 1);
   2360 
   2361     switch (*(data++)) {
   2362         case kDexVisibilityBuild:
   2363         case kDexVisibilityRuntime:
   2364         case kDexVisibilitySystem: {
   2365             break;
   2366         }
   2367         default: {
   2368             ALOGE("Bogus annotation visibility: %#x", *data);
   2369             return NULL;
   2370         }
   2371     }
   2372 
   2373     return (void*) verifyEncodedAnnotation(state, data, false);
   2374 }
   2375 
   2376 /* Perform cross-item verification on annotation_item. */
   2377 static void* crossVerifyAnnotationItem(const CheckState* state, void* ptr) {
   2378     const u1* data = (const u1*) ptr;
   2379 
   2380     // Skip the visibility byte.
   2381     data++;
   2382 
   2383     return (void*) verifyEncodedAnnotation(state, data, true);
   2384 }
   2385 
   2386 
   2387 
   2388 
   2389 /*
   2390  * Function to visit an individual top-level item type.
   2391  */
   2392 typedef void* ItemVisitorFunction(const CheckState* state, void* ptr);
   2393 
   2394 /*
   2395  * Iterate over all the items in a section, optionally updating the
   2396  * data map (done if mapType is passed as non-negative). The section
   2397  * must consist of concatenated items of the same type.
   2398  */
   2399 static bool iterateSectionWithOptionalUpdate(CheckState* state,
   2400         u4 offset, u4 count, ItemVisitorFunction* func, u4 alignment,
   2401         u4* nextOffset, int mapType) {
   2402     u4 alignmentMask = alignment - 1;
   2403     u4 i;
   2404 
   2405     state->previousItem = NULL;
   2406 
   2407     for (i = 0; i < count; i++) {
   2408         u4 newOffset = (offset + alignmentMask) & ~alignmentMask;
   2409         u1* ptr = (u1*) filePointer(state, newOffset);
   2410 
   2411         if (offset < newOffset) {
   2412             ptr = (u1*) filePointer(state, offset);
   2413             if (offset < newOffset) {
   2414                 CHECK_OFFSET_RANGE(offset, newOffset);
   2415                 while (offset < newOffset) {
   2416                     if (*ptr != '\0') {
   2417                         ALOGE("Non-zero padding 0x%02x @ %x", *ptr, offset);
   2418                         return false;
   2419                     }
   2420                     ptr++;
   2421                     offset++;
   2422                 }
   2423             }
   2424         }
   2425 
   2426         u1* newPtr = (u1*) func(state, ptr);
   2427         newOffset = fileOffset(state, newPtr);
   2428 
   2429         if (newPtr == NULL) {
   2430             ALOGE("Trouble with item %d @ offset %#x", i, offset);
   2431             return false;
   2432         }
   2433 
   2434         if (newOffset > state->fileLen) {
   2435             ALOGE("Item %d @ offset %#x ends out of bounds", i, offset);
   2436             return false;
   2437         }
   2438 
   2439         if (mapType >= 0) {
   2440             dexDataMapAdd(state->pDataMap, offset, mapType);
   2441         }
   2442 
   2443         state->previousItem = ptr;
   2444         offset = newOffset;
   2445     }
   2446 
   2447     if (nextOffset != NULL) {
   2448         *nextOffset = offset;
   2449     }
   2450 
   2451     return true;
   2452 }
   2453 
   2454 /*
   2455  * Iterate over all the items in a section. The section must consist of
   2456  * concatenated items of the same type. This variant will not update the data
   2457  * map.
   2458  */
   2459 static bool iterateSection(CheckState* state, u4 offset, u4 count,
   2460         ItemVisitorFunction* func, u4 alignment, u4* nextOffset) {
   2461     return iterateSectionWithOptionalUpdate(state, offset, count, func,
   2462             alignment, nextOffset, -1);
   2463 }
   2464 
   2465 /*
   2466  * Like iterateSection(), but also check that the offset and count match
   2467  * a given pair of expected values.
   2468  */
   2469 static bool checkBoundsAndIterateSection(CheckState* state,
   2470         u4 offset, u4 count, u4 expectedOffset, u4 expectedCount,
   2471         ItemVisitorFunction* func, u4 alignment, u4* nextOffset) {
   2472     if (offset != expectedOffset) {
   2473         ALOGE("Bogus offset for section: got %#x; expected %#x",
   2474                 offset, expectedOffset);
   2475         return false;
   2476     }
   2477 
   2478     if (count != expectedCount) {
   2479         ALOGE("Bogus size for section: got %#x; expected %#x",
   2480                 count, expectedCount);
   2481         return false;
   2482     }
   2483 
   2484     return iterateSection(state, offset, count, func, alignment, nextOffset);
   2485 }
   2486 
   2487 /*
   2488  * Like iterateSection(), but also update the data section map and
   2489  * check that all the items fall within the data section.
   2490  */
   2491 static bool iterateDataSection(CheckState* state, u4 offset, u4 count,
   2492         ItemVisitorFunction* func, u4 alignment, u4* nextOffset, int mapType) {
   2493     u4 dataStart = state->pHeader->dataOff;
   2494     u4 dataEnd = dataStart + state->pHeader->dataSize;
   2495 
   2496     assert(nextOffset != NULL);
   2497 
   2498     if ((offset < dataStart) || (offset >= dataEnd)) {
   2499         ALOGE("Bogus offset for data subsection: %#x", offset);
   2500         return false;
   2501     }
   2502 
   2503     if (!iterateSectionWithOptionalUpdate(state, offset, count, func,
   2504                     alignment, nextOffset, mapType)) {
   2505         return false;
   2506     }
   2507 
   2508     if (*nextOffset > dataEnd) {
   2509         ALOGE("Out-of-bounds end of data subsection: %#x", *nextOffset);
   2510         return false;
   2511     }
   2512 
   2513     return true;
   2514 }
   2515 
   2516 /*
   2517  * Byte-swap all items in the given map except the header and the map
   2518  * itself, both of which should have already gotten swapped. This also
   2519  * does all possible intra-item verification, that is, verification
   2520  * that doesn't need to assume the sanctity of the contents of *other*
   2521  * items. The intra-item limitation is because at the time an item is
   2522  * asked to verify itself, it can't assume that the items it refers to
   2523  * have been byte-swapped and verified.
   2524  */
   2525 static bool swapEverythingButHeaderAndMap(CheckState* state,
   2526         DexMapList* pMap) {
   2527     const DexMapItem* item = pMap->list;
   2528     u4 lastOffset = 0;
   2529     u4 count = pMap->size;
   2530     bool okay = true;
   2531 
   2532     while (okay && count--) {
   2533         u4 sectionOffset = item->offset;
   2534         u4 sectionCount = item->size;
   2535         u2 type = item->type;
   2536 
   2537         if (lastOffset < sectionOffset) {
   2538             CHECK_OFFSET_RANGE(lastOffset, sectionOffset);
   2539             const u1* ptr = (const u1*) filePointer(state, lastOffset);
   2540             while (lastOffset < sectionOffset) {
   2541                 if (*ptr != '\0') {
   2542                     ALOGE("Non-zero padding 0x%02x before section start @ %x",
   2543                             *ptr, lastOffset);
   2544                     okay = false;
   2545                     break;
   2546                 }
   2547                 ptr++;
   2548                 lastOffset++;
   2549             }
   2550         } else if (lastOffset > sectionOffset) {
   2551             ALOGE("Section overlap or out-of-order map: %x, %x",
   2552                     lastOffset, sectionOffset);
   2553             okay = false;
   2554         }
   2555 
   2556         if (!okay) {
   2557             break;
   2558         }
   2559 
   2560         switch (type) {
   2561             case kDexTypeHeaderItem: {
   2562                 /*
   2563                  * The header got swapped very early on, but do some
   2564                  * additional sanity checking here.
   2565                  */
   2566                 okay = checkHeaderSection(state, sectionOffset, sectionCount,
   2567                         &lastOffset);
   2568                 break;
   2569             }
   2570             case kDexTypeStringIdItem: {
   2571                 okay = checkBoundsAndIterateSection(state, sectionOffset,
   2572                         sectionCount, state->pHeader->stringIdsOff,
   2573                         state->pHeader->stringIdsSize, swapStringIdItem,
   2574                         sizeof(u4), &lastOffset);
   2575                 break;
   2576             }
   2577             case kDexTypeTypeIdItem: {
   2578                 okay = checkBoundsAndIterateSection(state, sectionOffset,
   2579                         sectionCount, state->pHeader->typeIdsOff,
   2580                         state->pHeader->typeIdsSize, swapTypeIdItem,
   2581                         sizeof(u4), &lastOffset);
   2582                 break;
   2583             }
   2584             case kDexTypeProtoIdItem: {
   2585                 okay = checkBoundsAndIterateSection(state, sectionOffset,
   2586                         sectionCount, state->pHeader->protoIdsOff,
   2587                         state->pHeader->protoIdsSize, swapProtoIdItem,
   2588                         sizeof(u4), &lastOffset);
   2589                 break;
   2590             }
   2591             case kDexTypeFieldIdItem: {
   2592                 okay = checkBoundsAndIterateSection(state, sectionOffset,
   2593                         sectionCount, state->pHeader->fieldIdsOff,
   2594                         state->pHeader->fieldIdsSize, swapFieldIdItem,
   2595                         sizeof(u4), &lastOffset);
   2596                 break;
   2597             }
   2598             case kDexTypeMethodIdItem: {
   2599                 okay = checkBoundsAndIterateSection(state, sectionOffset,
   2600                         sectionCount, state->pHeader->methodIdsOff,
   2601                         state->pHeader->methodIdsSize, swapMethodIdItem,
   2602                         sizeof(u4), &lastOffset);
   2603                 break;
   2604             }
   2605             case kDexTypeClassDefItem: {
   2606                 okay = checkBoundsAndIterateSection(state, sectionOffset,
   2607                         sectionCount, state->pHeader->classDefsOff,
   2608                         state->pHeader->classDefsSize, swapClassDefItem,
   2609                         sizeof(u4), &lastOffset);
   2610                 break;
   2611             }
   2612             case kDexTypeMapList: {
   2613                 /*
   2614                  * The map section was swapped early on, but do some
   2615                  * additional sanity checking here.
   2616                  */
   2617                 okay = checkMapSection(state, sectionOffset, sectionCount,
   2618                         &lastOffset);
   2619                 break;
   2620             }
   2621             case kDexTypeTypeList: {
   2622                 okay = iterateDataSection(state, sectionOffset, sectionCount,
   2623                         swapTypeList, sizeof(u4), &lastOffset, type);
   2624                 break;
   2625             }
   2626             case kDexTypeAnnotationSetRefList: {
   2627                 okay = iterateDataSection(state, sectionOffset, sectionCount,
   2628                         swapAnnotationSetRefList, sizeof(u4), &lastOffset,
   2629                         type);
   2630                 break;
   2631             }
   2632             case kDexTypeAnnotationSetItem: {
   2633                 okay = iterateDataSection(state, sectionOffset, sectionCount,
   2634                         swapAnnotationSetItem, sizeof(u4), &lastOffset, type);
   2635                 break;
   2636             }
   2637             case kDexTypeClassDataItem: {
   2638                 okay = iterateDataSection(state, sectionOffset, sectionCount,
   2639                         intraVerifyClassDataItem, sizeof(u1), &lastOffset,
   2640                         type);
   2641                 break;
   2642             }
   2643             case kDexTypeCodeItem: {
   2644                 okay = iterateDataSection(state, sectionOffset, sectionCount,
   2645                         swapCodeItem, sizeof(u4), &lastOffset, type);
   2646                 break;
   2647             }
   2648             case kDexTypeStringDataItem: {
   2649                 okay = iterateDataSection(state, sectionOffset, sectionCount,
   2650                         intraVerifyStringDataItem, sizeof(u1), &lastOffset,
   2651                         type);
   2652                 break;
   2653             }
   2654             case kDexTypeDebugInfoItem: {
   2655                 okay = iterateDataSection(state, sectionOffset, sectionCount,
   2656                         intraVerifyDebugInfoItem, sizeof(u1), &lastOffset,
   2657                         type);
   2658                 break;
   2659             }
   2660             case kDexTypeAnnotationItem: {
   2661                 okay = iterateDataSection(state, sectionOffset, sectionCount,
   2662                         intraVerifyAnnotationItem, sizeof(u1), &lastOffset,
   2663                         type);
   2664                 break;
   2665             }
   2666             case kDexTypeEncodedArrayItem: {
   2667                 okay = iterateDataSection(state, sectionOffset, sectionCount,
   2668                         intraVerifyEncodedArrayItem, sizeof(u1), &lastOffset,
   2669                         type);
   2670                 break;
   2671             }
   2672             case kDexTypeAnnotationsDirectoryItem: {
   2673                 okay = iterateDataSection(state, sectionOffset, sectionCount,
   2674                         swapAnnotationsDirectoryItem, sizeof(u4), &lastOffset,
   2675                         type);
   2676                 break;
   2677             }
   2678             default: {
   2679                 ALOGE("Unknown map item type %04x", type);
   2680                 return false;
   2681             }
   2682         }
   2683 
   2684         if (!okay) {
   2685             ALOGE("Swap of section type %04x failed", type);
   2686         }
   2687 
   2688         item++;
   2689     }
   2690 
   2691     return okay;
   2692 }
   2693 
   2694 /*
   2695  * Perform cross-item verification on everything that needs it. This
   2696  * pass is only called after all items are byte-swapped and
   2697  * intra-verified (checked for internal consistency).
   2698  */
   2699 static bool crossVerifyEverything(CheckState* state, DexMapList* pMap)
   2700 {
   2701     const DexMapItem* item = pMap->list;
   2702     u4 count = pMap->size;
   2703     bool okay = true;
   2704 
   2705     while (okay && count--) {
   2706         u4 sectionOffset = item->offset;
   2707         u4 sectionCount = item->size;
   2708 
   2709         switch (item->type) {
   2710             case kDexTypeHeaderItem:
   2711             case kDexTypeMapList:
   2712             case kDexTypeTypeList:
   2713             case kDexTypeCodeItem:
   2714             case kDexTypeStringDataItem:
   2715             case kDexTypeDebugInfoItem:
   2716             case kDexTypeAnnotationItem:
   2717             case kDexTypeEncodedArrayItem: {
   2718                 // There is no need for cross-item verification for these.
   2719                 break;
   2720             }
   2721             case kDexTypeStringIdItem: {
   2722                 okay = iterateSection(state, sectionOffset, sectionCount,
   2723                         crossVerifyStringIdItem, sizeof(u4), NULL);
   2724                 break;
   2725             }
   2726             case kDexTypeTypeIdItem: {
   2727                 okay = iterateSection(state, sectionOffset, sectionCount,
   2728                         crossVerifyTypeIdItem, sizeof(u4), NULL);
   2729                 break;
   2730             }
   2731             case kDexTypeProtoIdItem: {
   2732                 okay = iterateSection(state, sectionOffset, sectionCount,
   2733                         crossVerifyProtoIdItem, sizeof(u4), NULL);
   2734                 break;
   2735             }
   2736             case kDexTypeFieldIdItem: {
   2737                 okay = iterateSection(state, sectionOffset, sectionCount,
   2738                         crossVerifyFieldIdItem, sizeof(u4), NULL);
   2739                 break;
   2740             }
   2741             case kDexTypeMethodIdItem: {
   2742                 okay = iterateSection(state, sectionOffset, sectionCount,
   2743                         crossVerifyMethodIdItem, sizeof(u4), NULL);
   2744                 break;
   2745             }
   2746             case kDexTypeClassDefItem: {
   2747                 // Allocate (on the stack) the "observed class_def" bits.
   2748                 size_t arraySize = calcDefinedClassBitsSize(state);
   2749                 u4 definedClassBits[arraySize];
   2750                 memset(definedClassBits, 0, arraySize * sizeof(u4));
   2751                 state->pDefinedClassBits = definedClassBits;
   2752 
   2753                 okay = iterateSection(state, sectionOffset, sectionCount,
   2754                         crossVerifyClassDefItem, sizeof(u4), NULL);
   2755 
   2756                 state->pDefinedClassBits = NULL;
   2757                 break;
   2758             }
   2759             case kDexTypeAnnotationSetRefList: {
   2760                 okay = iterateSection(state, sectionOffset, sectionCount,
   2761                         crossVerifyAnnotationSetRefList, sizeof(u4), NULL);
   2762                 break;
   2763             }
   2764             case kDexTypeAnnotationSetItem: {
   2765                 okay = iterateSection(state, sectionOffset, sectionCount,
   2766                         crossVerifyAnnotationSetItem, sizeof(u4), NULL);
   2767                 break;
   2768             }
   2769             case kDexTypeClassDataItem: {
   2770                 okay = iterateSection(state, sectionOffset, sectionCount,
   2771                         crossVerifyClassDataItem, sizeof(u1), NULL);
   2772                 break;
   2773             }
   2774             case kDexTypeAnnotationsDirectoryItem: {
   2775                 okay = iterateSection(state, sectionOffset, sectionCount,
   2776                         crossVerifyAnnotationsDirectoryItem, sizeof(u4), NULL);
   2777                 break;
   2778             }
   2779             default: {
   2780                 ALOGE("Unknown map item type %04x", item->type);
   2781                 return false;
   2782             }
   2783         }
   2784 
   2785         if (!okay) {
   2786             ALOGE("Cross-item verify of section type %04x failed",
   2787                     item->type);
   2788         }
   2789 
   2790         item++;
   2791     }
   2792 
   2793     return okay;
   2794 }
   2795 
   2796 /* (documented in header file) */
   2797 bool dexHasValidMagic(const DexHeader* pHeader)
   2798 {
   2799     const u1* magic = pHeader->magic;
   2800     const u1* version = &magic[4];
   2801 
   2802     if (memcmp(magic, DEX_MAGIC, 4) != 0) {
   2803         ALOGE("ERROR: unrecognized magic number (%02x %02x %02x %02x)",
   2804             magic[0], magic[1], magic[2], magic[3]);
   2805         return false;
   2806     }
   2807 
   2808     if ((memcmp(version, DEX_MAGIC_VERS, 4) != 0) &&
   2809             (memcmp(version, DEX_MAGIC_VERS_API_13, 4) != 0)) {
   2810         /*
   2811          * Magic was correct, but this is an unsupported older or
   2812          * newer format variant.
   2813          */
   2814         ALOGE("ERROR: unsupported dex version (%02x %02x %02x %02x)",
   2815             version[0], version[1], version[2], version[3]);
   2816         return false;
   2817     }
   2818 
   2819     return true;
   2820 }
   2821 
   2822 /*
   2823  * Fix the byte ordering of all fields in the DEX file, and do
   2824  * structural verification. This is only required for code that opens
   2825  * "raw" DEX files, such as the DEX optimizer.
   2826  *
   2827  * Returns 0 on success, nonzero on failure.
   2828  */
   2829 int dexSwapAndVerify(u1* addr, int len)
   2830 {
   2831     DexHeader* pHeader;
   2832     CheckState state;
   2833     bool okay = true;
   2834 
   2835     memset(&state, 0, sizeof(state));
   2836     ALOGV("+++ swapping and verifying");
   2837 
   2838     /*
   2839      * Note: The caller must have verified that "len" is at least as
   2840      * large as a dex file header.
   2841      */
   2842     pHeader = (DexHeader*) addr;
   2843 
   2844     if (!dexHasValidMagic(pHeader)) {
   2845         okay = false;
   2846     }
   2847 
   2848     if (okay) {
   2849         int expectedLen = (int) SWAP4(pHeader->fileSize);
   2850         if (len < expectedLen) {
   2851             ALOGE("ERROR: Bad length: expected %d, got %d", expectedLen, len);
   2852             okay = false;
   2853         } else if (len != expectedLen) {
   2854             ALOGW("WARNING: Odd length: expected %d, got %d", expectedLen,
   2855                     len);
   2856             // keep going
   2857         }
   2858     }
   2859 
   2860     if (okay) {
   2861         /*
   2862          * Compute the adler32 checksum and compare it to what's stored in
   2863          * the file.  This isn't free, but chances are good that we just
   2864          * unpacked this from a jar file and have all of the pages sitting
   2865          * in memory, so it's pretty quick.
   2866          *
   2867          * This might be a big-endian system, so we need to do this before
   2868          * we byte-swap the header.
   2869          */
   2870         uLong adler = adler32(0L, Z_NULL, 0);
   2871         const int nonSum = sizeof(pHeader->magic) + sizeof(pHeader->checksum);
   2872         u4 storedFileSize = SWAP4(pHeader->fileSize);
   2873         u4 expectedChecksum = SWAP4(pHeader->checksum);
   2874 
   2875         adler = adler32(adler, ((const u1*) pHeader) + nonSum,
   2876                     storedFileSize - nonSum);
   2877 
   2878         if (adler != expectedChecksum) {
   2879             ALOGE("ERROR: bad checksum (%08lx, expected %08x)",
   2880                 adler, expectedChecksum);
   2881             okay = false;
   2882         }
   2883     }
   2884 
   2885     if (okay) {
   2886         state.fileStart = addr;
   2887         state.fileEnd = addr + len;
   2888         state.fileLen = len;
   2889         state.pDexFile = NULL;
   2890         state.pDataMap = NULL;
   2891         state.pDefinedClassBits = NULL;
   2892         state.previousItem = NULL;
   2893 
   2894         /*
   2895          * Swap the header and check the contents.
   2896          */
   2897         okay = swapDexHeader(&state, pHeader);
   2898     }
   2899 
   2900     if (okay) {
   2901         state.pHeader = pHeader;
   2902 
   2903         if (pHeader->headerSize < sizeof(DexHeader)) {
   2904             ALOGE("ERROR: Small header size %d, struct %d",
   2905                     pHeader->headerSize, (int) sizeof(DexHeader));
   2906             okay = false;
   2907         } else if (pHeader->headerSize > sizeof(DexHeader)) {
   2908             ALOGW("WARNING: Large header size %d, struct %d",
   2909                     pHeader->headerSize, (int) sizeof(DexHeader));
   2910             // keep going?
   2911         }
   2912     }
   2913 
   2914     if (okay) {
   2915         /*
   2916          * Look for the map. Swap it and then use it to find and swap
   2917          * everything else.
   2918          */
   2919         if (pHeader->mapOff != 0) {
   2920             DexFile dexFile;
   2921             DexMapList* pDexMap = (DexMapList*) (addr + pHeader->mapOff);
   2922 
   2923             okay = okay && swapMap(&state, pDexMap);
   2924             okay = okay && swapEverythingButHeaderAndMap(&state, pDexMap);
   2925 
   2926             dexFileSetupBasicPointers(&dexFile, addr);
   2927             state.pDexFile = &dexFile;
   2928 
   2929             okay = okay && crossVerifyEverything(&state, pDexMap);
   2930         } else {
   2931             ALOGE("ERROR: No map found; impossible to byte-swap and verify");
   2932             okay = false;
   2933         }
   2934     }
   2935 
   2936     if (!okay) {
   2937         ALOGE("ERROR: Byte swap + verify failed");
   2938     }
   2939 
   2940     if (state.pDataMap != NULL) {
   2941         dexDataMapFree(state.pDataMap);
   2942     }
   2943 
   2944     return !okay;       // 0 == success
   2945 }
   2946 
   2947 /*
   2948  * Detect the file type of the given memory buffer via magic number.
   2949  * Call dexSwapAndVerify() on an unoptimized DEX file, do nothing
   2950  * but return successfully on an optimized DEX file, and report an
   2951  * error for all other cases.
   2952  *
   2953  * Returns 0 on success, nonzero on failure.
   2954  */
   2955 int dexSwapAndVerifyIfNecessary(u1* addr, int len)
   2956 {
   2957     if (memcmp(addr, DEX_OPT_MAGIC, 4) == 0) {
   2958         // It is an optimized dex file.
   2959         return 0;
   2960     }
   2961 
   2962     if (memcmp(addr, DEX_MAGIC, 4) == 0) {
   2963         // It is an unoptimized dex file.
   2964         return dexSwapAndVerify(addr, len);
   2965     }
   2966 
   2967     ALOGE("ERROR: Bad magic number (0x%02x %02x %02x %02x)",
   2968              addr[0], addr[1], addr[2], addr[3]);
   2969 
   2970     return 1;
   2971 }
   2972