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