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