OSDN Git Service

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