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