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