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