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