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