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