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