• 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  * Dalvik bytecode structural verifier.  The only public entry point
19  * (except for a few shared utility functions) is dvmVerifyCodeFlow().
20  *
21  * TODO: might benefit from a signature-->class lookup cache.  Could avoid
22  * some string-peeling and wouldn't need to compute hashes.
23  *
24  * TODO: we do too much stuff in here that could be done in the static
25  * verification pass.  It's convenient, because we have all of the
26  * necessary information, but it's more efficient to do it over in
27  * DexVerify.c because in here we may have to process instructions
28  * multiple times.
29  */
30 #include "Dalvik.h"
31 #include "analysis/CodeVerify.h"
32 #include "analysis/RegisterMap.h"
33 #include "libdex/DexCatch.h"
34 #include "libdex/InstrUtils.h"
35 
36 #include <stddef.h>
37 
38 
39 /*
40  * We don't need to store the register data for many instructions, because
41  * we either only need it at branch points (for verification) or GC points
42  * and branches (for verification + type-precise register analysis).
43  */
44 typedef enum RegisterTrackingMode {
45     kTrackRegsBranches,
46     kTrackRegsGcPoints,
47     kTrackRegsAll
48 } RegisterTrackingMode;
49 
50 /*
51  * Set this to enable dead code scanning.  This is not required, but it's
52  * very useful when testing changes to the verifier (to make sure we're not
53  * skipping over stuff) and for checking the optimized output from "dx".
54  * The only reason not to do it is that it slightly increases the time
55  * required to perform verification.
56  */
57 #define DEAD_CODE_SCAN  true
58 
59 static bool gDebugVerbose = false;      // TODO: remove this
60 
61 #if 0
62 int gDvm__totalInstr = 0;
63 int gDvm__gcInstr = 0;
64 int gDvm__gcData = 0;
65 int gDvm__gcSimpleData = 0;
66 #endif
67 
68 /*
69  * Selectively enable verbose debug logging -- use this to activate
70  * dumpRegTypes() calls for all instructions in the specified method.
71  */
doVerboseLogging(const Method * meth)72 static inline bool doVerboseLogging(const Method* meth) {
73     return false;       /* COMMENT OUT to enable verbose debugging */
74 
75     const char* cd = "Landroid/net/http/Request;";
76     const char* mn = "readResponse";
77     const char* sg = "(Landroid/net/http/AndroidHttpClientConnection;)V";
78     return (strcmp(meth->clazz->descriptor, cd) == 0 &&
79             dvmCompareNameDescriptorAndMethod(mn, sg, meth) == 0);
80 }
81 
82 #define SHOW_REG_DETAILS    (0 /*| DRT_SHOW_REF_TYPES | DRT_SHOW_LOCALS*/)
83 
84 /*
85  * We need an extra "pseudo register" to hold the return type briefly.  It
86  * can be category 1 or 2, so we need two slots.
87  */
88 #define kExtraRegs  2
89 #define RESULT_REGISTER(_insnRegCount)  (_insnRegCount)
90 
91 /*
92  * Big fat collection of registers.
93  */
94 typedef struct RegisterTable {
95     /*
96      * Array of RegType arrays, one per address in the method.  We only
97      * set the pointers for certain addresses, based on what we're trying
98      * to accomplish.
99      */
100     RegType**   addrRegs;
101 
102     /*
103      * Number of registers we track for each instruction.  This is equal
104      * to the method's declared "registersSize" plus kExtraRegs.
105      */
106     int         insnRegCountPlus;
107 
108     /*
109      * A single large alloc, with all of the storage needed for addrRegs.
110      */
111     RegType*    regAlloc;
112 } RegisterTable;
113 
114 
115 /* fwd */
116 static void checkMergeTab(void);
117 static bool isInitMethod(const Method* meth);
118 static RegType getInvocationThis(const RegType* insnRegs,\
119     const int insnRegCount, const DecodedInstruction* pDecInsn,
120     VerifyError* pFailure);
121 static void verifyRegisterType(const RegType* insnRegs, const int insnRegCount,\
122     u4 vsrc, RegType checkType, VerifyError* pFailure);
123 static bool doCodeVerification(Method* meth, InsnFlags* insnFlags,\
124     RegisterTable* regTable, UninitInstanceMap* uninitMap);
125 static bool verifyInstruction(Method* meth, InsnFlags* insnFlags,\
126     RegisterTable* regTable, RegType* workRegs, int insnIdx,
127     UninitInstanceMap* uninitMap, int* pStartGuess);
128 static ClassObject* findCommonSuperclass(ClassObject* c1, ClassObject* c2);
129 static void dumpRegTypes(const Method* meth, const InsnFlags* insnFlags,\
130     const RegType* addrRegs, int addr, const char* addrName,
131     const UninitInstanceMap* uninitMap, int displayFlags);
132 
133 /* bit values for dumpRegTypes() "displayFlags" */
134 enum {
135     DRT_SIMPLE          = 0,
136     DRT_SHOW_REF_TYPES  = 0x01,
137     DRT_SHOW_LOCALS     = 0x02,
138 };
139 
140 
141 /*
142  * ===========================================================================
143  *      RegType and UninitInstanceMap utility functions
144  * ===========================================================================
145  */
146 
147 #define __  kRegTypeUnknown
148 #define _U  kRegTypeUninit
149 #define _X  kRegTypeConflict
150 #define _F  kRegTypeFloat
151 #define _0  kRegTypeZero
152 #define _1  kRegTypeOne
153 #define _Z  kRegTypeBoolean
154 #define _b  kRegTypePosByte
155 #define _B  kRegTypeByte
156 #define _s  kRegTypePosShort
157 #define _S  kRegTypeShort
158 #define _C  kRegTypeChar
159 #define _I  kRegTypeInteger
160 #define _J  kRegTypeLongLo
161 #define _j  kRegTypeLongHi
162 #define _D  kRegTypeDoubleLo
163 #define _d  kRegTypeDoubleHi
164 
165 /*
166  * Merge result table for primitive values.  The table is symmetric along
167  * the diagonal.
168  *
169  * Note that 32-bit int/float do not merge into 64-bit long/double.  This
170  * is a register merge, not a widening conversion.  Only the "implicit"
171  * widening within a category, e.g. byte to short, is allowed.
172  *
173  * Because Dalvik does not draw a distinction between int and float, we
174  * have to allow free exchange between 32-bit int/float and 64-bit
175  * long/double.
176  *
177  * Note that Uninit+Uninit=Uninit.  This holds true because we only
178  * use this when the RegType value is exactly equal to kRegTypeUninit, which
179  * can only happen for the zeroeth entry in the table.
180  *
181  * "Unknown" never merges with anything known.  The only time a register
182  * transitions from "unknown" to "known" is when we're executing code
183  * for the first time, and we handle that with a simple copy.
184  */
185 const char gDvmMergeTab[kRegTypeMAX][kRegTypeMAX] =
186 {
187     /* chk:  _  U  X  F  0  1  Z  b  B  s  S  C  I  J  j  D  d */
188     { /*_*/ __,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X },
189     { /*U*/ _X,_U,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X },
190     { /*X*/ _X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X },
191     { /*F*/ _X,_X,_X,_F,_F,_F,_F,_F,_F,_F,_F,_F,_F,_X,_X,_X,_X },
192     { /*0*/ _X,_X,_X,_F,_0,_Z,_Z,_b,_B,_s,_S,_C,_I,_X,_X,_X,_X },
193     { /*1*/ _X,_X,_X,_F,_Z,_1,_Z,_b,_B,_s,_S,_C,_I,_X,_X,_X,_X },
194     { /*Z*/ _X,_X,_X,_F,_Z,_Z,_Z,_b,_B,_s,_S,_C,_I,_X,_X,_X,_X },
195     { /*b*/ _X,_X,_X,_F,_b,_b,_b,_b,_B,_s,_S,_C,_I,_X,_X,_X,_X },
196     { /*B*/ _X,_X,_X,_F,_B,_B,_B,_B,_B,_S,_S,_I,_I,_X,_X,_X,_X },
197     { /*s*/ _X,_X,_X,_F,_s,_s,_s,_s,_S,_s,_S,_C,_I,_X,_X,_X,_X },
198     { /*S*/ _X,_X,_X,_F,_S,_S,_S,_S,_S,_S,_S,_I,_I,_X,_X,_X,_X },
199     { /*C*/ _X,_X,_X,_F,_C,_C,_C,_C,_I,_C,_I,_C,_I,_X,_X,_X,_X },
200     { /*I*/ _X,_X,_X,_F,_I,_I,_I,_I,_I,_I,_I,_I,_I,_X,_X,_X,_X },
201     { /*J*/ _X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_J,_X,_J,_X },
202     { /*j*/ _X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_j,_X,_j },
203     { /*D*/ _X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_J,_X,_D,_X },
204     { /*d*/ _X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_j,_X,_d },
205 };
206 
207 #undef __
208 #undef _U
209 #undef _X
210 #undef _F
211 #undef _0
212 #undef _1
213 #undef _Z
214 #undef _b
215 #undef _B
216 #undef _s
217 #undef _S
218 #undef _C
219 #undef _I
220 #undef _J
221 #undef _j
222 #undef _D
223 #undef _d
224 
225 #ifndef NDEBUG
226 /*
227  * Verify symmetry in the conversion table.
228  */
checkMergeTab(void)229 static void checkMergeTab(void)
230 {
231     int i, j;
232 
233     for (i = 0; i < kRegTypeMAX; i++) {
234         for (j = i; j < kRegTypeMAX; j++) {
235             if (gDvmMergeTab[i][j] != gDvmMergeTab[j][i]) {
236                 LOGE("Symmetry violation: %d,%d vs %d,%d\n", i, j, j, i);
237                 dvmAbort();
238             }
239         }
240     }
241 }
242 #endif
243 
244 /*
245  * Determine whether we can convert "srcType" to "checkType", where
246  * "checkType" is one of the category-1 non-reference types.
247  *
248  * 32-bit int and float are interchangeable.
249  */
canConvertTo1nr(RegType srcType,RegType checkType)250 static bool canConvertTo1nr(RegType srcType, RegType checkType)
251 {
252     static const char convTab
253         [kRegType1nrEND-kRegType1nrSTART+1][kRegType1nrEND-kRegType1nrSTART+1] =
254     {
255         /* chk: F  0  1  Z  b  B  s  S  C  I */
256         { /*F*/ 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
257         { /*0*/ 1, 1, 0, 1, 1, 1, 1, 1, 1, 1 },
258         { /*1*/ 1, 0, 1, 1, 1, 1, 1, 1, 1, 1 },
259         { /*Z*/ 1, 0, 0, 1, 1, 1, 1, 1, 1, 1 },
260         { /*b*/ 1, 0, 0, 0, 1, 1, 1, 1, 1, 1 },
261         { /*B*/ 1, 0, 0, 0, 0, 1, 0, 1, 0, 1 },
262         { /*s*/ 1, 0, 0, 0, 0, 0, 1, 1, 1, 1 },
263         { /*S*/ 1, 0, 0, 0, 0, 0, 0, 1, 0, 1 },
264         { /*C*/ 1, 0, 0, 0, 0, 0, 0, 0, 1, 1 },
265         { /*I*/ 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
266     };
267 
268     assert(checkType >= kRegType1nrSTART && checkType <= kRegType1nrEND);
269 #if 0
270     if (checkType < kRegType1nrSTART || checkType > kRegType1nrEND) {
271         LOG_VFY("Unexpected checkType %d (srcType=%d)\n", checkType, srcType);
272         assert(false);
273         return false;
274     }
275 #endif
276 
277     //printf("convTab[%d][%d] = %d\n", srcType, checkType,
278     //    convTab[srcType-kRegType1nrSTART][checkType-kRegType1nrSTART]);
279     if (srcType >= kRegType1nrSTART && srcType <= kRegType1nrEND)
280         return (bool) convTab[srcType-kRegType1nrSTART][checkType-kRegType1nrSTART];
281 
282     return false;
283 }
284 
285 /*
286  * Determine whether the types are compatible.  In Dalvik, 64-bit doubles
287  * and longs are interchangeable.
288  */
canConvertTo2(RegType srcType,RegType checkType)289 static bool canConvertTo2(RegType srcType, RegType checkType)
290 {
291     return ((srcType == kRegTypeLongLo || srcType == kRegTypeDoubleLo) &&
292             (checkType == kRegTypeLongLo || checkType == kRegTypeDoubleLo));
293 }
294 
295 /*
296  * Determine whether or not "instrType" and "targetType" are compatible,
297  * for purposes of getting or setting a value in a field or array.  The
298  * idea is that an instruction with a category 1nr type (say, aget-short
299  * or iput-boolean) is accessing a static field, instance field, or array
300  * entry, and we want to make sure sure that the operation is legal.
301  *
302  * At a minimum, source and destination must have the same width.  We
303  * further refine this to assert that "short" and "char" are not
304  * compatible, because the sign-extension is different on the "get"
305  * operations.  As usual, "float" and "int" are interoperable.
306  *
307  * We're not considering the actual contents of the register, so we'll
308  * never get "pseudo-types" like kRegTypeZero or kRegTypePosShort.  We
309  * could get kRegTypeUnknown in "targetType" if a field or array class
310  * lookup failed.  Category 2 types and references are checked elsewhere.
311  */
checkFieldArrayStore1nr(RegType instrType,RegType targetType)312 static bool checkFieldArrayStore1nr(RegType instrType, RegType targetType)
313 {
314     if (instrType == targetType)
315         return true;            /* quick positive; most common case */
316 
317     if ((instrType == kRegTypeInteger && targetType == kRegTypeFloat) ||
318         (instrType == kRegTypeFloat && targetType == kRegTypeInteger))
319     {
320         return true;
321     }
322 
323     return false;
324 }
325 
326 /*
327  * Convert a VM PrimitiveType enum value to the equivalent RegType value.
328  */
primitiveTypeToRegType(PrimitiveType primType)329 static RegType primitiveTypeToRegType(PrimitiveType primType)
330 {
331     static const struct {
332         RegType         regType;        /* type equivalent */
333         PrimitiveType   primType;       /* verification */
334     } convTab[] = {
335         /* must match order of enum in Object.h */
336         { kRegTypeBoolean,      PRIM_BOOLEAN },
337         { kRegTypeChar,         PRIM_CHAR },
338         { kRegTypeFloat,        PRIM_FLOAT },
339         { kRegTypeDoubleLo,     PRIM_DOUBLE },
340         { kRegTypeByte,         PRIM_BYTE },
341         { kRegTypeShort,        PRIM_SHORT },
342         { kRegTypeInteger,      PRIM_INT },
343         { kRegTypeLongLo,       PRIM_LONG },
344         // PRIM_VOID
345     };
346 
347     if (primType < 0 || primType > (int) (sizeof(convTab) / sizeof(convTab[0])))
348     {
349         assert(false);
350         return kRegTypeUnknown;
351     }
352 
353     assert(convTab[primType].primType == primType);
354     return convTab[primType].regType;
355 }
356 
357 /*
358  * Create a new uninitialized instance map.
359  *
360  * The map is allocated and populated with address entries.  The addresses
361  * appear in ascending order to allow binary searching.
362  *
363  * Very few methods have 10 or more new-instance instructions; the
364  * majority have 0 or 1.  Occasionally a static initializer will have 200+.
365  */
dvmCreateUninitInstanceMap(const Method * meth,const InsnFlags * insnFlags,int newInstanceCount)366 UninitInstanceMap* dvmCreateUninitInstanceMap(const Method* meth,
367     const InsnFlags* insnFlags, int newInstanceCount)
368 {
369     const int insnsSize = dvmGetMethodInsnsSize(meth);
370     const u2* insns = meth->insns;
371     UninitInstanceMap* uninitMap;
372     bool isInit = false;
373     int idx, addr;
374 
375     if (isInitMethod(meth)) {
376         newInstanceCount++;
377         isInit = true;
378     }
379 
380     /*
381      * Allocate the header and map as a single unit.
382      *
383      * TODO: consider having a static instance so we can avoid allocations.
384      * I don't think the verifier is guaranteed to be single-threaded when
385      * running in the VM (rather than dexopt), so that must be taken into
386      * account.
387      */
388     int size = offsetof(UninitInstanceMap, map) +
389                 newInstanceCount * sizeof(uninitMap->map[0]);
390     uninitMap = calloc(1, size);
391     if (uninitMap == NULL)
392         return NULL;
393     uninitMap->numEntries = newInstanceCount;
394 
395     idx = 0;
396     if (isInit) {
397         uninitMap->map[idx++].addr = kUninitThisArgAddr;
398     }
399 
400     /*
401      * Run through and find the new-instance instructions.
402      */
403     for (addr = 0; addr < insnsSize; /**/) {
404         int width = dvmInsnGetWidth(insnFlags, addr);
405 
406         if ((*insns & 0xff) == OP_NEW_INSTANCE)
407             uninitMap->map[idx++].addr = addr;
408 
409         addr += width;
410         insns += width;
411     }
412 
413     assert(idx == newInstanceCount);
414     return uninitMap;
415 }
416 
417 /*
418  * Free the map.
419  */
dvmFreeUninitInstanceMap(UninitInstanceMap * uninitMap)420 void dvmFreeUninitInstanceMap(UninitInstanceMap* uninitMap)
421 {
422     free(uninitMap);
423 }
424 
425 /*
426  * Set the class object associated with the instruction at "addr".
427  *
428  * Returns the map slot index, or -1 if the address isn't listed in the map
429  * (shouldn't happen) or if a class is already associated with the address
430  * (bad bytecode).
431  *
432  * Entries, once set, do not change -- a given address can only allocate
433  * one type of object.
434  */
dvmSetUninitInstance(UninitInstanceMap * uninitMap,int addr,ClassObject * clazz)435 int dvmSetUninitInstance(UninitInstanceMap* uninitMap, int addr,
436     ClassObject* clazz)
437 {
438     int idx;
439 
440     assert(clazz != NULL);
441 
442     /* TODO: binary search when numEntries > 8 */
443     for (idx = uninitMap->numEntries - 1; idx >= 0; idx--) {
444         if (uninitMap->map[idx].addr == addr) {
445             if (uninitMap->map[idx].clazz != NULL &&
446                 uninitMap->map[idx].clazz != clazz)
447             {
448                 LOG_VFY("VFY: addr %d already set to %p, not setting to %p\n",
449                     addr, uninitMap->map[idx].clazz, clazz);
450                 return -1;          // already set to something else??
451             }
452             uninitMap->map[idx].clazz = clazz;
453             return idx;
454         }
455     }
456 
457     LOG_VFY("VFY: addr %d not found in uninit map\n", addr);
458     assert(false);      // shouldn't happen
459     return -1;
460 }
461 
462 /*
463  * Get the class object at the specified index.
464  */
dvmGetUninitInstance(const UninitInstanceMap * uninitMap,int idx)465 ClassObject* dvmGetUninitInstance(const UninitInstanceMap* uninitMap, int idx)
466 {
467     assert(idx >= 0 && idx < uninitMap->numEntries);
468     return uninitMap->map[idx].clazz;
469 }
470 
471 /* determine if "type" is actually an object reference (init/uninit/zero) */
regTypeIsReference(RegType type)472 static inline bool regTypeIsReference(RegType type) {
473     return (type > kRegTypeMAX || type == kRegTypeUninit ||
474             type == kRegTypeZero);
475 }
476 
477 /* determine if "type" is an uninitialized object reference */
regTypeIsUninitReference(RegType type)478 static inline bool regTypeIsUninitReference(RegType type) {
479     return ((type & kRegTypeUninitMask) == kRegTypeUninit);
480 }
481 
482 /* convert the initialized reference "type" to a ClassObject pointer */
483 /* (does not expect uninit ref types or "zero") */
regTypeInitializedReferenceToClass(RegType type)484 static ClassObject* regTypeInitializedReferenceToClass(RegType type)
485 {
486     assert(regTypeIsReference(type) && type != kRegTypeZero);
487     if ((type & 0x01) == 0) {
488         return (ClassObject*) type;
489     } else {
490         //LOG_VFY("VFY: attempted to use uninitialized reference\n");
491         return NULL;
492     }
493 }
494 
495 /* extract the index into the uninitialized instance map table */
regTypeToUninitIndex(RegType type)496 static inline int regTypeToUninitIndex(RegType type) {
497     assert(regTypeIsUninitReference(type));
498     return (type & ~kRegTypeUninitMask) >> kRegTypeUninitShift;
499 }
500 
501 /* convert the reference "type" to a ClassObject pointer */
regTypeReferenceToClass(RegType type,const UninitInstanceMap * uninitMap)502 static ClassObject* regTypeReferenceToClass(RegType type,
503     const UninitInstanceMap* uninitMap)
504 {
505     assert(regTypeIsReference(type) && type != kRegTypeZero);
506     if (regTypeIsUninitReference(type)) {
507         assert(uninitMap != NULL);
508         return dvmGetUninitInstance(uninitMap, regTypeToUninitIndex(type));
509     } else {
510         return (ClassObject*) type;
511     }
512 }
513 
514 /* convert the ClassObject pointer to an (initialized) register type */
regTypeFromClass(ClassObject * clazz)515 static inline RegType regTypeFromClass(ClassObject* clazz) {
516     return (u4) clazz;
517 }
518 
519 /* return the RegType for the uninitialized reference in slot "uidx" */
regTypeFromUninitIndex(int uidx)520 static RegType regTypeFromUninitIndex(int uidx) {
521     return (u4) (kRegTypeUninit | (uidx << kRegTypeUninitShift));
522 }
523 
524 
525 /*
526  * ===========================================================================
527  *      Signature operations
528  * ===========================================================================
529  */
530 
531 /*
532  * Is this method a constructor?
533  */
isInitMethod(const Method * meth)534 static bool isInitMethod(const Method* meth)
535 {
536     return (*meth->name == '<' && strcmp(meth->name+1, "init>") == 0);
537 }
538 
539 /*
540  * Is this method a class initializer?
541  */
isClassInitMethod(const Method * meth)542 static bool isClassInitMethod(const Method* meth)
543 {
544     return (*meth->name == '<' && strcmp(meth->name+1, "clinit>") == 0);
545 }
546 
547 /*
548  * Look up a class reference given as a simple string descriptor.
549  *
550  * If we can't find it, return a generic substitute when possible.
551  */
lookupClassByDescriptor(const Method * meth,const char * pDescriptor,VerifyError * pFailure)552 static ClassObject* lookupClassByDescriptor(const Method* meth,
553     const char* pDescriptor, VerifyError* pFailure)
554 {
555     /*
556      * The javac compiler occasionally puts references to nonexistent
557      * classes in signatures.  For example, if you have a non-static
558      * inner class with no constructor, the compiler provides
559      * a private <init> for you.  Constructing the class
560      * requires <init>(parent), but the outer class can't call
561      * that because the method is private.  So the compiler
562      * generates a package-scope <init>(parent,bogus) method that
563      * just calls the regular <init> (the "bogus" part being necessary
564      * to distinguish the signature of the synthetic method).
565      * Treating the bogus class as an instance of java.lang.Object
566      * allows the verifier to process the class successfully.
567      */
568 
569     //LOGI("Looking up '%s'\n", typeStr);
570     ClassObject* clazz;
571     clazz = dvmFindClassNoInit(pDescriptor, meth->clazz->classLoader);
572     if (clazz == NULL) {
573         dvmClearOptException(dvmThreadSelf());
574         if (strchr(pDescriptor, '$') != NULL) {
575             LOGV("VFY: unable to find class referenced in signature (%s)\n",
576                 pDescriptor);
577         } else {
578             LOG_VFY("VFY: unable to find class referenced in signature (%s)\n",
579                 pDescriptor);
580         }
581 
582         if (pDescriptor[0] == '[') {
583             /* We are looking at an array descriptor. */
584 
585             /*
586              * There should never be a problem loading primitive arrays.
587              */
588             if (pDescriptor[1] != 'L' && pDescriptor[1] != '[') {
589                 LOG_VFY("VFY: invalid char in signature in '%s'\n",
590                     pDescriptor);
591                 *pFailure = VERIFY_ERROR_GENERIC;
592             }
593 
594             /*
595              * Try to continue with base array type.  This will let
596              * us pass basic stuff (e.g. get array len) that wouldn't
597              * fly with an Object.  This is NOT correct if the
598              * missing type is a primitive array, but we should never
599              * have a problem loading those.  (I'm not convinced this
600              * is correct or even useful.  Just use Object here?)
601              */
602             clazz = dvmFindClassNoInit("[Ljava/lang/Object;",
603                 meth->clazz->classLoader);
604         } else if (pDescriptor[0] == 'L') {
605             /*
606              * We are looking at a non-array reference descriptor;
607              * try to continue with base reference type.
608              */
609             clazz = gDvm.classJavaLangObject;
610         } else {
611             /* We are looking at a primitive type. */
612             LOG_VFY("VFY: invalid char in signature in '%s'\n", pDescriptor);
613             *pFailure = VERIFY_ERROR_GENERIC;
614         }
615 
616         if (clazz == NULL) {
617             *pFailure = VERIFY_ERROR_GENERIC;
618         }
619     }
620 
621     if (dvmIsPrimitiveClass(clazz)) {
622         LOG_VFY("VFY: invalid use of primitive type '%s'\n", pDescriptor);
623         *pFailure = VERIFY_ERROR_GENERIC;
624         clazz = NULL;
625     }
626 
627     return clazz;
628 }
629 
630 /*
631  * Look up a class reference in a signature.  Could be an arg or the
632  * return value.
633  *
634  * Advances "*pSig" to the last character in the signature (that is, to
635  * the ';').
636  *
637  * NOTE: this is also expected to verify the signature.
638  */
lookupSignatureClass(const Method * meth,const char ** pSig,VerifyError * pFailure)639 static ClassObject* lookupSignatureClass(const Method* meth, const char** pSig,
640     VerifyError* pFailure)
641 {
642     const char* sig = *pSig;
643     const char* endp = sig;
644 
645     assert(sig != NULL && *sig == 'L');
646 
647     while (*++endp != ';' && *endp != '\0')
648         ;
649     if (*endp != ';') {
650         LOG_VFY("VFY: bad signature component '%s' (missing ';')\n", sig);
651         *pFailure = VERIFY_ERROR_GENERIC;
652         return NULL;
653     }
654 
655     endp++;    /* Advance past the ';'. */
656     int typeLen = endp - sig;
657     char typeStr[typeLen+1]; /* +1 for the '\0' */
658     memcpy(typeStr, sig, typeLen);
659     typeStr[typeLen] = '\0';
660 
661     *pSig = endp - 1; /* - 1 so that *pSig points at, not past, the ';' */
662 
663     return lookupClassByDescriptor(meth, typeStr, pFailure);
664 }
665 
666 /*
667  * Look up an array class reference in a signature.  Could be an arg or the
668  * return value.
669  *
670  * Advances "*pSig" to the last character in the signature.
671  *
672  * NOTE: this is also expected to verify the signature.
673  */
lookupSignatureArrayClass(const Method * meth,const char ** pSig,VerifyError * pFailure)674 static ClassObject* lookupSignatureArrayClass(const Method* meth,
675     const char** pSig, VerifyError* pFailure)
676 {
677     const char* sig = *pSig;
678     const char* endp = sig;
679 
680     assert(sig != NULL && *sig == '[');
681 
682     /* find the end */
683     while (*++endp == '[' && *endp != '\0')
684         ;
685 
686     if (*endp == 'L') {
687         while (*++endp != ';' && *endp != '\0')
688             ;
689         if (*endp != ';') {
690             LOG_VFY("VFY: bad signature component '%s' (missing ';')\n", sig);
691             *pFailure = VERIFY_ERROR_GENERIC;
692             return NULL;
693         }
694     }
695 
696     int typeLen = endp - sig +1;
697     char typeStr[typeLen+1];
698     memcpy(typeStr, sig, typeLen);
699     typeStr[typeLen] = '\0';
700 
701     *pSig = endp;
702 
703     return lookupClassByDescriptor(meth, typeStr, pFailure);
704 }
705 
706 /*
707  * Set the register types for the first instruction in the method based on
708  * the method signature.
709  *
710  * This has the side-effect of validating the signature.
711  *
712  * Returns "true" on success.
713  */
setTypesFromSignature(const Method * meth,RegType * regTypes,UninitInstanceMap * uninitMap)714 static bool setTypesFromSignature(const Method* meth, RegType* regTypes,
715     UninitInstanceMap* uninitMap)
716 {
717     DexParameterIterator iterator;
718     int actualArgs, expectedArgs, argStart;
719     VerifyError failure = VERIFY_ERROR_NONE;
720 
721     dexParameterIteratorInit(&iterator, &meth->prototype);
722     argStart = meth->registersSize - meth->insSize;
723     expectedArgs = meth->insSize;     /* long/double count as two */
724     actualArgs = 0;
725 
726     assert(argStart >= 0);      /* should have been verified earlier */
727 
728     /*
729      * Include the "this" pointer.
730      */
731     if (!dvmIsStaticMethod(meth)) {
732         /*
733          * If this is a constructor for a class other than java.lang.Object,
734          * mark the first ("this") argument as uninitialized.  This restricts
735          * field access until the superclass constructor is called.
736          */
737         if (isInitMethod(meth) && meth->clazz != gDvm.classJavaLangObject) {
738             int uidx = dvmSetUninitInstance(uninitMap, kUninitThisArgAddr,
739                             meth->clazz);
740             assert(uidx == 0);
741             regTypes[argStart + actualArgs] = regTypeFromUninitIndex(uidx);
742         } else {
743             regTypes[argStart + actualArgs] = regTypeFromClass(meth->clazz);
744         }
745         actualArgs++;
746     }
747 
748     for (;;) {
749         const char* descriptor = dexParameterIteratorNextDescriptor(&iterator);
750 
751         if (descriptor == NULL) {
752             break;
753         }
754 
755         if (actualArgs >= expectedArgs) {
756             LOG_VFY("VFY: expected %d args, found more (%s)\n",
757                 expectedArgs, descriptor);
758             goto bad_sig;
759         }
760 
761         switch (*descriptor) {
762         case 'L':
763         case '[':
764             /*
765              * We assume that reference arguments are initialized.  The
766              * only way it could be otherwise (assuming the caller was
767              * verified) is if the current method is <init>, but in that
768              * case it's effectively considered initialized the instant
769              * we reach here (in the sense that we can return without
770              * doing anything or call virtual methods).
771              */
772             {
773                 ClassObject* clazz =
774                     lookupClassByDescriptor(meth, descriptor, &failure);
775                 if (!VERIFY_OK(failure))
776                     goto bad_sig;
777                 regTypes[argStart + actualArgs] = regTypeFromClass(clazz);
778             }
779             actualArgs++;
780             break;
781         case 'Z':
782             regTypes[argStart + actualArgs] = kRegTypeBoolean;
783             actualArgs++;
784             break;
785         case 'C':
786             regTypes[argStart + actualArgs] = kRegTypeChar;
787             actualArgs++;
788             break;
789         case 'B':
790             regTypes[argStart + actualArgs] = kRegTypeByte;
791             actualArgs++;
792             break;
793         case 'I':
794             regTypes[argStart + actualArgs] = kRegTypeInteger;
795             actualArgs++;
796             break;
797         case 'S':
798             regTypes[argStart + actualArgs] = kRegTypeShort;
799             actualArgs++;
800             break;
801         case 'F':
802             regTypes[argStart + actualArgs] = kRegTypeFloat;
803             actualArgs++;
804             break;
805         case 'D':
806             regTypes[argStart + actualArgs] = kRegTypeDoubleLo;
807             regTypes[argStart + actualArgs +1] = kRegTypeDoubleHi;
808             actualArgs += 2;
809             break;
810         case 'J':
811             regTypes[argStart + actualArgs] = kRegTypeLongLo;
812             regTypes[argStart + actualArgs +1] = kRegTypeLongHi;
813             actualArgs += 2;
814             break;
815         default:
816             LOG_VFY("VFY: unexpected signature type char '%c'\n", *descriptor);
817             goto bad_sig;
818         }
819     }
820 
821     if (actualArgs != expectedArgs) {
822         LOG_VFY("VFY: expected %d args, found %d\n", expectedArgs, actualArgs);
823         goto bad_sig;
824     }
825 
826     const char* descriptor = dexProtoGetReturnType(&meth->prototype);
827 
828     /*
829      * Validate return type.  We don't do the type lookup; just want to make
830      * sure that it has the right format.  Only major difference from the
831      * method argument format is that 'V' is supported.
832      */
833     switch (*descriptor) {
834     case 'I':
835     case 'C':
836     case 'S':
837     case 'B':
838     case 'Z':
839     case 'V':
840     case 'F':
841     case 'D':
842     case 'J':
843         if (*(descriptor+1) != '\0')
844             goto bad_sig;
845         break;
846     case '[':
847         /* single/multi, object/primitive */
848         while (*++descriptor == '[')
849             ;
850         if (*descriptor == 'L') {
851             while (*++descriptor != ';' && *descriptor != '\0')
852                 ;
853             if (*descriptor != ';')
854                 goto bad_sig;
855         } else {
856             if (*(descriptor+1) != '\0')
857                 goto bad_sig;
858         }
859         break;
860     case 'L':
861         /* could be more thorough here, but shouldn't be required */
862         while (*++descriptor != ';' && *descriptor != '\0')
863             ;
864         if (*descriptor != ';')
865             goto bad_sig;
866         break;
867     default:
868         goto bad_sig;
869     }
870 
871     return true;
872 
873 //fail:
874 //    LOG_VFY_METH(meth, "VFY:  bad sig\n");
875 //    return false;
876 
877 bad_sig:
878     {
879         char* desc = dexProtoCopyMethodDescriptor(&meth->prototype);
880         LOG_VFY("VFY: bad signature '%s' for %s.%s\n",
881             desc, meth->clazz->descriptor, meth->name);
882         free(desc);
883     }
884     return false;
885 }
886 
887 /*
888  * Return the register type for the method.  We can't just use the
889  * already-computed DalvikJniReturnType, because if it's a reference type
890  * we need to do the class lookup.
891  *
892  * Returned references are assumed to be initialized.
893  *
894  * Returns kRegTypeUnknown for "void".
895  */
getMethodReturnType(const Method * meth)896 static RegType getMethodReturnType(const Method* meth)
897 {
898     RegType type;
899     const char* descriptor = dexProtoGetReturnType(&meth->prototype);
900 
901     switch (*descriptor) {
902     case 'I':
903         type = kRegTypeInteger;
904         break;
905     case 'C':
906         type = kRegTypeChar;
907         break;
908     case 'S':
909         type = kRegTypeShort;
910         break;
911     case 'B':
912         type = kRegTypeByte;
913         break;
914     case 'Z':
915         type = kRegTypeBoolean;
916         break;
917     case 'V':
918         type = kRegTypeUnknown;
919         break;
920     case 'F':
921         type = kRegTypeFloat;
922         break;
923     case 'D':
924         type = kRegTypeDoubleLo;
925         break;
926     case 'J':
927         type = kRegTypeLongLo;
928         break;
929     case 'L':
930     case '[':
931         {
932             VerifyError failure = VERIFY_ERROR_NONE;
933             ClassObject* clazz =
934                 lookupClassByDescriptor(meth, descriptor, &failure);
935             assert(VERIFY_OK(failure));
936             type = regTypeFromClass(clazz);
937         }
938         break;
939     default:
940         /* we verified signature return type earlier, so this is impossible */
941         assert(false);
942         type = kRegTypeConflict;
943         break;
944     }
945 
946     return type;
947 }
948 
949 /*
950  * Convert a single-character signature value (i.e. a primitive type) to
951  * the corresponding RegType.  This is intended for access to object fields
952  * holding primitive types.
953  *
954  * Returns kRegTypeUnknown for objects, arrays, and void.
955  */
primSigCharToRegType(char sigChar)956 static RegType primSigCharToRegType(char sigChar)
957 {
958     RegType type;
959 
960     switch (sigChar) {
961     case 'I':
962         type = kRegTypeInteger;
963         break;
964     case 'C':
965         type = kRegTypeChar;
966         break;
967     case 'S':
968         type = kRegTypeShort;
969         break;
970     case 'B':
971         type = kRegTypeByte;
972         break;
973     case 'Z':
974         type = kRegTypeBoolean;
975         break;
976     case 'F':
977         type = kRegTypeFloat;
978         break;
979     case 'D':
980         type = kRegTypeDoubleLo;
981         break;
982     case 'J':
983         type = kRegTypeLongLo;
984         break;
985     case 'V':
986     case 'L':
987     case '[':
988         type = kRegTypeUnknown;
989         break;
990     default:
991         assert(false);
992         type = kRegTypeUnknown;
993         break;
994     }
995 
996     return type;
997 }
998 
999 /*
1000  * Verify the arguments to a method.  We're executing in "method", making
1001  * a call to the method reference in vB.
1002  *
1003  * If this is a "direct" invoke, we allow calls to <init>.  For calls to
1004  * <init>, the first argument may be an uninitialized reference.  Otherwise,
1005  * calls to anything starting with '<' will be rejected, as will any
1006  * uninitialized reference arguments.
1007  *
1008  * For non-static method calls, this will verify that the method call is
1009  * appropriate for the "this" argument.
1010  *
1011  * The method reference is in vBBBB.  The "isRange" parameter determines
1012  * whether we use 0-4 "args" values or a range of registers defined by
1013  * vAA and vCCCC.
1014  *
1015  * Widening conversions on integers and references are allowed, but
1016  * narrowing conversions are not.
1017  *
1018  * Returns the resolved method on success, NULL on failure (with *pFailure
1019  * set appropriately).
1020  */
verifyInvocationArgs(const Method * meth,const RegType * insnRegs,const int insnRegCount,const DecodedInstruction * pDecInsn,UninitInstanceMap * uninitMap,MethodType methodType,bool isRange,bool isSuper,VerifyError * pFailure)1021 static Method* verifyInvocationArgs(const Method* meth, const RegType* insnRegs,
1022     const int insnRegCount, const DecodedInstruction* pDecInsn,
1023     UninitInstanceMap* uninitMap, MethodType methodType, bool isRange,
1024     bool isSuper, VerifyError* pFailure)
1025 {
1026     Method* resMethod;
1027     char* sigOriginal = NULL;
1028 
1029     /*
1030      * Resolve the method.  This could be an abstract or concrete method
1031      * depending on what sort of call we're making.
1032      */
1033     if (methodType == METHOD_INTERFACE) {
1034         resMethod = dvmOptResolveInterfaceMethod(meth->clazz, pDecInsn->vB);
1035     } else {
1036         resMethod = dvmOptResolveMethod(meth->clazz, pDecInsn->vB, methodType,
1037             pFailure);
1038     }
1039     if (resMethod == NULL) {
1040         /* failed; print a meaningful failure message */
1041         DexFile* pDexFile = meth->clazz->pDvmDex->pDexFile;
1042         const DexMethodId* pMethodId;
1043         const char* methodName;
1044         char* methodDesc;
1045         const char* classDescriptor;
1046 
1047         pMethodId = dexGetMethodId(pDexFile, pDecInsn->vB);
1048         methodName = dexStringById(pDexFile, pMethodId->nameIdx);
1049         methodDesc = dexCopyDescriptorFromMethodId(pDexFile, pMethodId);
1050         classDescriptor = dexStringByTypeIdx(pDexFile, pMethodId->classIdx);
1051 
1052         if (!gDvm.optimizing) {
1053             char* dotMissingClass = dvmDescriptorToDot(classDescriptor);
1054             char* dotMethClass = dvmDescriptorToDot(meth->clazz->descriptor);
1055             //char* curMethodDesc =
1056             //    dexProtoCopyMethodDescriptor(&meth->prototype);
1057 
1058             LOGI("Could not find method %s.%s, referenced from "
1059                  "method %s.%s\n",
1060                  dotMissingClass, methodName/*, methodDesc*/,
1061                  dotMethClass, meth->name/*, curMethodDesc*/);
1062 
1063             free(dotMissingClass);
1064             free(dotMethClass);
1065             //free(curMethodDesc);
1066         }
1067 
1068         LOG_VFY("VFY: unable to resolve %s method %u: %s.%s %s\n",
1069             dvmMethodTypeStr(methodType), pDecInsn->vB,
1070             classDescriptor, methodName, methodDesc);
1071         free(methodDesc);
1072         if (VERIFY_OK(*pFailure))       /* not set for interface resolve */
1073             *pFailure = VERIFY_ERROR_NO_METHOD;
1074         goto fail;
1075     }
1076 
1077     /*
1078      * Only time you can explicitly call a method starting with '<' is when
1079      * making a "direct" invocation on "<init>".  There are additional
1080      * restrictions but we don't enforce them here.
1081      */
1082     if (resMethod->name[0] == '<') {
1083         if (methodType != METHOD_DIRECT || !isInitMethod(resMethod)) {
1084             LOG_VFY("VFY: invalid call to %s.%s\n",
1085                     resMethod->clazz->descriptor, resMethod->name);
1086             goto bad_sig;
1087         }
1088     }
1089 
1090     /*
1091      * If we're using invoke-super(method), make sure that the executing
1092      * method's class' superclass has a vtable entry for the target method.
1093      */
1094     if (isSuper) {
1095         assert(methodType == METHOD_VIRTUAL);
1096         ClassObject* super = meth->clazz->super;
1097         if (super == NULL || resMethod->methodIndex > super->vtableCount) {
1098             char* desc = dexProtoCopyMethodDescriptor(&resMethod->prototype);
1099             LOG_VFY("VFY: invalid invoke-super from %s.%s to super %s.%s %s\n",
1100                     meth->clazz->descriptor, meth->name,
1101                     (super == NULL) ? "-" : super->descriptor,
1102                     resMethod->name, desc);
1103             free(desc);
1104             *pFailure = VERIFY_ERROR_NO_METHOD;
1105             goto fail;
1106         }
1107     }
1108 
1109     /*
1110      * We use vAA as our expected arg count, rather than resMethod->insSize,
1111      * because we need to match the call to the signature.  Also, we might
1112      * might be calling through an abstract method definition (which doesn't
1113      * have register count values).
1114      */
1115     sigOriginal = dexProtoCopyMethodDescriptor(&resMethod->prototype);
1116     const char* sig = sigOriginal;
1117     int expectedArgs = pDecInsn->vA;
1118     int actualArgs = 0;
1119 
1120     if (!isRange && expectedArgs > 5) {
1121         LOG_VFY("VFY: invalid arg count in non-range invoke (%d)\n",
1122             pDecInsn->vA);
1123         goto fail;
1124     }
1125     if (expectedArgs > meth->outsSize) {
1126         LOG_VFY("VFY: invalid arg count (%d) exceeds outsSize (%d)\n",
1127             expectedArgs, meth->outsSize);
1128         goto fail;
1129     }
1130 
1131     if (*sig++ != '(')
1132         goto bad_sig;
1133 
1134     /*
1135      * Check the "this" argument, which must be an instance of the class
1136      * that declared the method.  For an interface class, we don't do the
1137      * full interface merge, so we can't do a rigorous check here (which
1138      * is okay since we have to do it at runtime).
1139      */
1140     if (!dvmIsStaticMethod(resMethod)) {
1141         ClassObject* actualThisRef;
1142         RegType actualArgType;
1143 
1144         actualArgType = getInvocationThis(insnRegs, insnRegCount, pDecInsn,
1145                             pFailure);
1146         if (!VERIFY_OK(*pFailure))
1147             goto fail;
1148 
1149         if (regTypeIsUninitReference(actualArgType) && resMethod->name[0] != '<')
1150         {
1151             LOG_VFY("VFY: 'this' arg must be initialized\n");
1152             goto fail;
1153         }
1154         if (methodType != METHOD_INTERFACE && actualArgType != kRegTypeZero) {
1155             actualThisRef = regTypeReferenceToClass(actualArgType, uninitMap);
1156             if (!dvmInstanceof(actualThisRef, resMethod->clazz)) {
1157                 LOG_VFY("VFY: 'this' arg '%s' not instance of '%s'\n",
1158                         actualThisRef->descriptor,
1159                         resMethod->clazz->descriptor);
1160                 goto fail;
1161             }
1162         }
1163         actualArgs++;
1164     }
1165 
1166     /*
1167      * Process the target method's signature.  This signature may or may not
1168      * have been verified, so we can't assume it's properly formed.
1169      */
1170     while (*sig != '\0' && *sig != ')') {
1171         if (actualArgs >= expectedArgs) {
1172             LOG_VFY("VFY: expected %d args, found more (%c)\n",
1173                 expectedArgs, *sig);
1174             goto bad_sig;
1175         }
1176 
1177         u4 getReg;
1178         if (isRange)
1179             getReg = pDecInsn->vC + actualArgs;
1180         else
1181             getReg = pDecInsn->arg[actualArgs];
1182 
1183         switch (*sig) {
1184         case 'L':
1185             {
1186                 ClassObject* clazz = lookupSignatureClass(meth, &sig, pFailure);
1187                 if (!VERIFY_OK(*pFailure))
1188                     goto bad_sig;
1189                 verifyRegisterType(insnRegs, insnRegCount, getReg,
1190                     regTypeFromClass(clazz), pFailure);
1191                 if (!VERIFY_OK(*pFailure)) {
1192                     LOG_VFY("VFY: bad arg %d (into %s)\n",
1193                             actualArgs, clazz->descriptor);
1194                     goto bad_sig;
1195                 }
1196             }
1197             actualArgs++;
1198             break;
1199         case '[':
1200             {
1201                 ClassObject* clazz =
1202                     lookupSignatureArrayClass(meth, &sig, pFailure);
1203                 if (!VERIFY_OK(*pFailure))
1204                     goto bad_sig;
1205                 verifyRegisterType(insnRegs, insnRegCount, getReg,
1206                     regTypeFromClass(clazz), pFailure);
1207                 if (!VERIFY_OK(*pFailure)) {
1208                     LOG_VFY("VFY: bad arg %d (into %s)\n",
1209                             actualArgs, clazz->descriptor);
1210                     goto bad_sig;
1211                 }
1212             }
1213             actualArgs++;
1214             break;
1215         case 'Z':
1216             verifyRegisterType(insnRegs, insnRegCount, getReg,
1217                 kRegTypeBoolean, pFailure);
1218             actualArgs++;
1219             break;
1220         case 'C':
1221             verifyRegisterType(insnRegs, insnRegCount, getReg,
1222                 kRegTypeChar, pFailure);
1223             actualArgs++;
1224             break;
1225         case 'B':
1226             verifyRegisterType(insnRegs, insnRegCount, getReg,
1227                 kRegTypeByte, pFailure);
1228             actualArgs++;
1229             break;
1230         case 'I':
1231             verifyRegisterType(insnRegs, insnRegCount, getReg,
1232                 kRegTypeInteger, pFailure);
1233             actualArgs++;
1234             break;
1235         case 'S':
1236             verifyRegisterType(insnRegs, insnRegCount, getReg,
1237                 kRegTypeShort, pFailure);
1238             actualArgs++;
1239             break;
1240         case 'F':
1241             verifyRegisterType(insnRegs, insnRegCount, getReg,
1242                 kRegTypeFloat, pFailure);
1243             actualArgs++;
1244             break;
1245         case 'D':
1246             verifyRegisterType(insnRegs, insnRegCount, getReg,
1247                 kRegTypeDoubleLo, pFailure);
1248             actualArgs += 2;
1249             break;
1250         case 'J':
1251             verifyRegisterType(insnRegs, insnRegCount, getReg,
1252                 kRegTypeLongLo, pFailure);
1253             actualArgs += 2;
1254             break;
1255         default:
1256             LOG_VFY("VFY: invocation target: bad signature type char '%c'\n",
1257                 *sig);
1258             goto bad_sig;
1259         }
1260 
1261         sig++;
1262     }
1263     if (*sig != ')') {
1264         char* desc = dexProtoCopyMethodDescriptor(&resMethod->prototype);
1265         LOG_VFY("VFY: invocation target: bad signature '%s'\n", desc);
1266         free(desc);
1267         goto bad_sig;
1268     }
1269 
1270     if (actualArgs != expectedArgs) {
1271         LOG_VFY("VFY: expected %d args, found %d\n", expectedArgs, actualArgs);
1272         goto bad_sig;
1273     }
1274 
1275     free(sigOriginal);
1276     return resMethod;
1277 
1278 bad_sig:
1279     if (resMethod != NULL) {
1280         char* desc = dexProtoCopyMethodDescriptor(&resMethod->prototype);
1281         LOG_VFY("VFY:  rejecting call to %s.%s %s\n",
1282             resMethod->clazz->descriptor, resMethod->name, desc);
1283         free(desc);
1284     }
1285 
1286 fail:
1287     free(sigOriginal);
1288     if (*pFailure == VERIFY_ERROR_NONE)
1289         *pFailure = VERIFY_ERROR_GENERIC;
1290     return NULL;
1291 }
1292 
1293 /*
1294  * Get the class object for the type of data stored in a field.  This isn't
1295  * stored in the Field struct, so we have to recover it from the signature.
1296  *
1297  * This only works for reference types.  Don't call this for primitive types.
1298  *
1299  * If we can't find the class, we return java.lang.Object, so that
1300  * verification can continue if a field is only accessed in trivial ways.
1301  */
getFieldClass(const Method * meth,const Field * field)1302 static ClassObject* getFieldClass(const Method* meth, const Field* field)
1303 {
1304     ClassObject* fieldClass;
1305     const char* signature = field->signature;
1306 
1307     if ((*signature == 'L') || (*signature == '[')) {
1308         fieldClass = dvmFindClassNoInit(signature,
1309                 meth->clazz->classLoader);
1310     } else {
1311         return NULL;
1312     }
1313 
1314     if (fieldClass == NULL) {
1315         dvmClearOptException(dvmThreadSelf());
1316         LOGV("VFY: unable to find class '%s' for field %s.%s, trying Object\n",
1317             field->signature, meth->clazz->descriptor, field->name);
1318         fieldClass = gDvm.classJavaLangObject;
1319     } else {
1320         assert(!dvmIsPrimitiveClass(fieldClass));
1321     }
1322     return fieldClass;
1323 }
1324 
1325 
1326 /*
1327  * ===========================================================================
1328  *      Register operations
1329  * ===========================================================================
1330  */
1331 
1332 /*
1333  * Get the type of register N, verifying that the register is valid.
1334  *
1335  * Sets "*pFailure" appropriately if the register number is out of range.
1336  */
getRegisterType(const RegType * insnRegs,const int insnRegCount,u4 vsrc,VerifyError * pFailure)1337 static inline RegType getRegisterType(const RegType* insnRegs,
1338     const int insnRegCount, u4 vsrc, VerifyError* pFailure)
1339 {
1340     RegType type;
1341 
1342     if (vsrc >= (u4) insnRegCount) {
1343         *pFailure = VERIFY_ERROR_GENERIC;
1344         return kRegTypeUnknown;
1345     } else {
1346         return insnRegs[vsrc];
1347     }
1348 }
1349 
1350 /*
1351  * Get the value from a register, and cast it to a ClassObject.  Sets
1352  * "*pFailure" if something fails.
1353  *
1354  * This fails if the register holds an uninitialized class.
1355  *
1356  * If the register holds kRegTypeZero, this returns a NULL pointer.
1357  */
getClassFromRegister(const RegType * insnRegs,const int insnRegCount,u4 vsrc,VerifyError * pFailure)1358 static ClassObject* getClassFromRegister(const RegType* insnRegs,
1359     const int insnRegCount, u4 vsrc, VerifyError* pFailure)
1360 {
1361     ClassObject* clazz = NULL;
1362     RegType type;
1363 
1364     /* get the element type of the array held in vsrc */
1365     type = getRegisterType(insnRegs, insnRegCount, vsrc, pFailure);
1366     if (!VERIFY_OK(*pFailure))
1367         goto bail;
1368 
1369     /* if "always zero", we allow it to fail at runtime */
1370     if (type == kRegTypeZero)
1371         goto bail;
1372 
1373     if (!regTypeIsReference(type)) {
1374         LOG_VFY("VFY: tried to get class from non-ref register v%d (type=%d)\n",
1375             vsrc, type);
1376         *pFailure = VERIFY_ERROR_GENERIC;
1377         goto bail;
1378     }
1379     if (regTypeIsUninitReference(type)) {
1380         LOG_VFY("VFY: register %u holds uninitialized reference\n", vsrc);
1381         *pFailure = VERIFY_ERROR_GENERIC;
1382         goto bail;
1383     }
1384 
1385     clazz = regTypeInitializedReferenceToClass(type);
1386 
1387 bail:
1388     return clazz;
1389 }
1390 
1391 /*
1392  * Get the "this" pointer from a non-static method invocation.  This
1393  * returns the RegType so the caller can decide whether it needs the
1394  * reference to be initialized or not.  (Can also return kRegTypeZero
1395  * if the reference can only be zero at this point.)
1396  *
1397  * The argument count is in vA, and the first argument is in vC, for both
1398  * "simple" and "range" versions.  We just need to make sure vA is >= 1
1399  * and then return vC.
1400  */
getInvocationThis(const RegType * insnRegs,const int insnRegCount,const DecodedInstruction * pDecInsn,VerifyError * pFailure)1401 static RegType getInvocationThis(const RegType* insnRegs,
1402     const int insnRegCount, const DecodedInstruction* pDecInsn,
1403     VerifyError* pFailure)
1404 {
1405     RegType thisType = kRegTypeUnknown;
1406 
1407     if (pDecInsn->vA < 1) {
1408         LOG_VFY("VFY: invoke lacks 'this'\n");
1409         *pFailure = VERIFY_ERROR_GENERIC;
1410         goto bail;
1411     }
1412 
1413     /* get the element type of the array held in vsrc */
1414     thisType = getRegisterType(insnRegs, insnRegCount, pDecInsn->vC, pFailure);
1415     if (!VERIFY_OK(*pFailure)) {
1416         LOG_VFY("VFY: failed to get 'this' from register %u\n", pDecInsn->vC);
1417         goto bail;
1418     }
1419 
1420     if (!regTypeIsReference(thisType)) {
1421         LOG_VFY("VFY: tried to get class from non-ref register v%d (type=%d)\n",
1422             pDecInsn->vC, thisType);
1423         *pFailure = VERIFY_ERROR_GENERIC;
1424         goto bail;
1425     }
1426 
1427 bail:
1428     return thisType;
1429 }
1430 
1431 /*
1432  * Set the type of register N, verifying that the register is valid.  If
1433  * "newType" is the "Lo" part of a 64-bit value, register N+1 will be
1434  * set to "newType+1".
1435  *
1436  * Sets "*pFailure" if the register number is out of range.
1437  */
setRegisterType(RegType * insnRegs,const int insnRegCount,u4 vdst,RegType newType,VerifyError * pFailure)1438 static void setRegisterType(RegType* insnRegs, const int insnRegCount,
1439     u4 vdst, RegType newType, VerifyError* pFailure)
1440 {
1441     //LOGD("set-reg v%u = %d\n", vdst, newType);
1442     switch (newType) {
1443     case kRegTypeUnknown:
1444     case kRegTypeBoolean:
1445     case kRegTypeOne:
1446     case kRegTypeByte:
1447     case kRegTypePosByte:
1448     case kRegTypeShort:
1449     case kRegTypePosShort:
1450     case kRegTypeChar:
1451     case kRegTypeInteger:
1452     case kRegTypeFloat:
1453     case kRegTypeZero:
1454         if (vdst >= (u4) insnRegCount) {
1455             *pFailure = VERIFY_ERROR_GENERIC;
1456         } else {
1457             insnRegs[vdst] = newType;
1458         }
1459         break;
1460     case kRegTypeLongLo:
1461     case kRegTypeDoubleLo:
1462         if (vdst+1 >= (u4) insnRegCount) {
1463             *pFailure = VERIFY_ERROR_GENERIC;
1464         } else {
1465             insnRegs[vdst] = newType;
1466             insnRegs[vdst+1] = newType+1;
1467         }
1468         break;
1469     case kRegTypeLongHi:
1470     case kRegTypeDoubleHi:
1471         /* should never set these explicitly */
1472         *pFailure = VERIFY_ERROR_GENERIC;
1473         break;
1474 
1475     case kRegTypeUninit:
1476     default:
1477         if (regTypeIsReference(newType)) {
1478             if (vdst >= (u4) insnRegCount) {
1479                 *pFailure = VERIFY_ERROR_GENERIC;
1480                 break;
1481             }
1482             insnRegs[vdst] = newType;
1483 
1484             /*
1485              * In most circumstances we won't see a reference to a primitive
1486              * class here (e.g. "D"), since that would mean the object in the
1487              * register is actually a primitive type.  It can happen as the
1488              * result of an assumed-successful check-cast instruction in
1489              * which the second argument refers to a primitive class.  (In
1490              * practice, such an instruction will always throw an exception.)
1491              *
1492              * This is not an issue for instructions like const-class, where
1493              * the object in the register is a java.lang.Class instance.
1494              */
1495             break;
1496         }
1497         /* bad - fall through */
1498 
1499     case kRegTypeConflict:      // should only be set during a merge
1500         LOG_VFY("Unexpected set type %d\n", newType);
1501         assert(false);
1502         *pFailure = VERIFY_ERROR_GENERIC;
1503         break;
1504     }
1505 }
1506 
1507 /*
1508  * Verify that the contents of the specified register have the specified
1509  * type (or can be converted to it through an implicit widening conversion).
1510  *
1511  * In theory we could use this to modify the type of the source register,
1512  * e.g. a generic 32-bit constant, once used as a float, would thereafter
1513  * remain a float.  There is no compelling reason to require this though.
1514  *
1515  * If "vsrc" is a reference, both it and the "vsrc" register must be
1516  * initialized ("vsrc" may be Zero).  This will verify that the value in
1517  * the register is an instance of checkType, or if checkType is an
1518  * interface, verify that the register implements checkType.
1519  */
verifyRegisterType(const RegType * insnRegs,const int insnRegCount,u4 vsrc,RegType checkType,VerifyError * pFailure)1520 static void verifyRegisterType(const RegType* insnRegs, const int insnRegCount,
1521     u4 vsrc, RegType checkType, VerifyError* pFailure)
1522 {
1523     if (vsrc >= (u4) insnRegCount) {
1524         *pFailure = VERIFY_ERROR_GENERIC;
1525         return;
1526     }
1527 
1528     RegType srcType = insnRegs[vsrc];
1529 
1530     //LOGD("check-reg v%u = %d\n", vsrc, checkType);
1531     switch (checkType) {
1532     case kRegTypeFloat:
1533     case kRegTypeBoolean:
1534     case kRegTypePosByte:
1535     case kRegTypeByte:
1536     case kRegTypePosShort:
1537     case kRegTypeShort:
1538     case kRegTypeChar:
1539     case kRegTypeInteger:
1540         if (!canConvertTo1nr(srcType, checkType)) {
1541             LOG_VFY("VFY: register1 v%u type %d, wanted %d\n",
1542                 vsrc, srcType, checkType);
1543             *pFailure = VERIFY_ERROR_GENERIC;
1544         }
1545         break;
1546     case kRegTypeLongLo:
1547     case kRegTypeDoubleLo:
1548         if (vsrc+1 >= (u4) insnRegCount) {
1549             LOG_VFY("VFY: register2 v%u out of range (%d)\n",
1550                 vsrc, insnRegCount);
1551             *pFailure = VERIFY_ERROR_GENERIC;
1552         } else if (insnRegs[vsrc+1] != srcType+1) {
1553             LOG_VFY("VFY: register2 v%u-%u values %d,%d\n",
1554                 vsrc, vsrc+1, insnRegs[vsrc], insnRegs[vsrc+1]);
1555             *pFailure = VERIFY_ERROR_GENERIC;
1556         } else if (!canConvertTo2(srcType, checkType)) {
1557             LOG_VFY("VFY: register2 v%u type %d, wanted %d\n",
1558                 vsrc, srcType, checkType);
1559             *pFailure = VERIFY_ERROR_GENERIC;
1560         }
1561         break;
1562 
1563     case kRegTypeLongHi:
1564     case kRegTypeDoubleHi:
1565     case kRegTypeZero:
1566     case kRegTypeOne:
1567     case kRegTypeUnknown:
1568     case kRegTypeConflict:
1569         /* should never be checking for these explicitly */
1570         assert(false);
1571         *pFailure = VERIFY_ERROR_GENERIC;
1572         return;
1573     case kRegTypeUninit:
1574     default:
1575         /* make sure checkType is initialized reference */
1576         if (!regTypeIsReference(checkType)) {
1577             LOG_VFY("VFY: unexpected check type %d\n", checkType);
1578             assert(false);
1579             *pFailure = VERIFY_ERROR_GENERIC;
1580             break;
1581         }
1582         if (regTypeIsUninitReference(checkType)) {
1583             LOG_VFY("VFY: uninitialized ref not expected as reg check\n");
1584             *pFailure = VERIFY_ERROR_GENERIC;
1585             break;
1586         }
1587         /* make sure srcType is initialized reference or always-NULL */
1588         if (!regTypeIsReference(srcType)) {
1589             LOG_VFY("VFY: register1 v%u type %d, wanted ref\n", vsrc, srcType);
1590             *pFailure = VERIFY_ERROR_GENERIC;
1591             break;
1592         }
1593         if (regTypeIsUninitReference(srcType)) {
1594             LOG_VFY("VFY: register1 v%u holds uninitialized ref\n", vsrc);
1595             *pFailure = VERIFY_ERROR_GENERIC;
1596             break;
1597         }
1598         /* if the register isn't Zero, make sure it's an instance of check */
1599         if (srcType != kRegTypeZero) {
1600             ClassObject* srcClass = regTypeInitializedReferenceToClass(srcType);
1601             ClassObject* checkClass = regTypeInitializedReferenceToClass(checkType);
1602             assert(srcClass != NULL);
1603             assert(checkClass != NULL);
1604 
1605             if (dvmIsInterfaceClass(checkClass)) {
1606                 /*
1607                  * All objects implement all interfaces as far as the
1608                  * verifier is concerned.  The runtime has to sort it out.
1609                  * See comments above findCommonSuperclass.
1610                  */
1611                 /*
1612                 if (srcClass != checkClass &&
1613                     !dvmImplements(srcClass, checkClass))
1614                 {
1615                     LOG_VFY("VFY: %s does not implement %s\n",
1616                             srcClass->descriptor, checkClass->descriptor);
1617                     *pFailure = VERIFY_ERROR_GENERIC;
1618                 }
1619                 */
1620             } else {
1621                 if (!dvmInstanceof(srcClass, checkClass)) {
1622                     LOG_VFY("VFY: %s is not instance of %s\n",
1623                             srcClass->descriptor, checkClass->descriptor);
1624                     *pFailure = VERIFY_ERROR_GENERIC;
1625                 }
1626             }
1627         }
1628         break;
1629     }
1630 }
1631 
1632 /*
1633  * Set the type of the "result" register.  Mostly this exists to expand
1634  * "insnRegCount" to encompass the result register.
1635  */
setResultRegisterType(RegType * insnRegs,const int insnRegCount,RegType newType,VerifyError * pFailure)1636 static void setResultRegisterType(RegType* insnRegs, const int insnRegCount,
1637     RegType newType, VerifyError* pFailure)
1638 {
1639     setRegisterType(insnRegs, insnRegCount + kExtraRegs,
1640         RESULT_REGISTER(insnRegCount), newType, pFailure);
1641 }
1642 
1643 
1644 /*
1645  * Update all registers holding "uninitType" to instead hold the
1646  * corresponding initialized reference type.  This is called when an
1647  * appropriate <init> method is invoked -- all copies of the reference
1648  * must be marked as initialized.
1649  */
markRefsAsInitialized(RegType * insnRegs,int insnRegCount,UninitInstanceMap * uninitMap,RegType uninitType,VerifyError * pFailure)1650 static void markRefsAsInitialized(RegType* insnRegs, int insnRegCount,
1651     UninitInstanceMap* uninitMap, RegType uninitType, VerifyError* pFailure)
1652 {
1653     ClassObject* clazz;
1654     RegType initType;
1655     int i, changed;
1656 
1657     clazz = dvmGetUninitInstance(uninitMap, regTypeToUninitIndex(uninitType));
1658     if (clazz == NULL) {
1659         LOGE("VFY: unable to find type=0x%x (idx=%d)\n",
1660             uninitType, regTypeToUninitIndex(uninitType));
1661         *pFailure = VERIFY_ERROR_GENERIC;
1662         return;
1663     }
1664     initType = regTypeFromClass(clazz);
1665 
1666     changed = 0;
1667     for (i = 0; i < insnRegCount; i++) {
1668         if (insnRegs[i] == uninitType) {
1669             insnRegs[i] = initType;
1670             changed++;
1671         }
1672     }
1673     //LOGD("VFY: marked %d registers as initialized\n", changed);
1674     assert(changed > 0);
1675 
1676     return;
1677 }
1678 
1679 /*
1680  * We're creating a new instance of class C at address A.  Any registers
1681  * holding instances previously created at address A must be initialized
1682  * by now.  If not, we mark them as "conflict" to prevent them from being
1683  * used (otherwise, markRefsAsInitialized would mark the old ones and the
1684  * new ones at the same time).
1685  */
markUninitRefsAsInvalid(RegType * insnRegs,int insnRegCount,UninitInstanceMap * uninitMap,RegType uninitType)1686 static void markUninitRefsAsInvalid(RegType* insnRegs, int insnRegCount,
1687     UninitInstanceMap* uninitMap, RegType uninitType)
1688 {
1689     int i, changed;
1690 
1691     changed = 0;
1692     for (i = 0; i < insnRegCount; i++) {
1693         if (insnRegs[i] == uninitType) {
1694             insnRegs[i] = kRegTypeConflict;
1695             changed++;
1696         }
1697     }
1698 
1699     //if (changed)
1700     //    LOGD("VFY: marked %d uninitialized registers as invalid\n", changed);
1701 }
1702 
1703 /*
1704  * Find the start of the register set for the specified instruction in
1705  * the current method.
1706  */
getRegisterLine(const RegisterTable * regTable,int insnIdx)1707 static inline RegType* getRegisterLine(const RegisterTable* regTable,
1708     int insnIdx)
1709 {
1710     return regTable->addrRegs[insnIdx];
1711 }
1712 
1713 /*
1714  * Copy a bunch of registers.
1715  */
copyRegisters(RegType * dst,const RegType * src,int numRegs)1716 static inline void copyRegisters(RegType* dst, const RegType* src,
1717     int numRegs)
1718 {
1719     memcpy(dst, src, numRegs * sizeof(RegType));
1720 }
1721 
1722 /*
1723  * Compare a bunch of registers.
1724  *
1725  * Returns 0 if they match.  Using this for a sort is unwise, since the
1726  * value can change based on machine endianness.
1727  */
compareRegisters(const RegType * src1,const RegType * src2,int numRegs)1728 static inline int compareRegisters(const RegType* src1, const RegType* src2,
1729     int numRegs)
1730 {
1731     return memcmp(src1, src2, numRegs * sizeof(RegType));
1732 }
1733 
1734 /*
1735  * Register type categories, for type checking.
1736  *
1737  * The spec says category 1 includes boolean, byte, char, short, int, float,
1738  * reference, and returnAddress.  Category 2 includes long and double.
1739  *
1740  * We treat object references separately, so we have "category1nr".  We
1741  * don't support jsr/ret, so there is no "returnAddress" type.
1742  */
1743 typedef enum TypeCategory {
1744     kTypeCategoryUnknown = 0,
1745     kTypeCategory1nr,           // byte, char, int, float, boolean
1746     kTypeCategory2,             // long, double
1747     kTypeCategoryRef,           // object reference
1748 } TypeCategory;
1749 
1750 /*
1751  * See if "type" matches "cat".  All we're really looking for here is that
1752  * we're not mixing and matching 32-bit and 64-bit quantities, and we're
1753  * not mixing references with numerics.  (For example, the arguments to
1754  * "a < b" could be integers of different sizes, but they must both be
1755  * integers.  Dalvik is less specific about int vs. float, so we treat them
1756  * as equivalent here.)
1757  *
1758  * For category 2 values, "type" must be the "low" half of the value.
1759  *
1760  * Sets "*pFailure" if something looks wrong.
1761  */
checkTypeCategory(RegType type,TypeCategory cat,VerifyError * pFailure)1762 static void checkTypeCategory(RegType type, TypeCategory cat,
1763     VerifyError* pFailure)
1764 {
1765     switch (cat) {
1766     case kTypeCategory1nr:
1767         switch (type) {
1768         case kRegTypeFloat:
1769         case kRegTypeZero:
1770         case kRegTypeOne:
1771         case kRegTypeBoolean:
1772         case kRegTypePosByte:
1773         case kRegTypeByte:
1774         case kRegTypePosShort:
1775         case kRegTypeShort:
1776         case kRegTypeChar:
1777         case kRegTypeInteger:
1778             break;
1779         default:
1780             *pFailure = VERIFY_ERROR_GENERIC;
1781             break;
1782         }
1783         break;
1784 
1785     case kTypeCategory2:
1786         switch (type) {
1787         case kRegTypeLongLo:
1788         case kRegTypeDoubleLo:
1789             break;
1790         default:
1791             *pFailure = VERIFY_ERROR_GENERIC;
1792             break;
1793         }
1794         break;
1795 
1796     case kTypeCategoryRef:
1797         if (type != kRegTypeZero && !regTypeIsReference(type))
1798             *pFailure = VERIFY_ERROR_GENERIC;
1799         break;
1800 
1801     default:
1802         assert(false);
1803         *pFailure = VERIFY_ERROR_GENERIC;
1804         break;
1805     }
1806 }
1807 
1808 /*
1809  * For a category 2 register pair, verify that "typeh" is the appropriate
1810  * high part for "typel".
1811  *
1812  * Does not verify that "typel" is in fact the low part of a 64-bit
1813  * register pair.
1814  */
checkWidePair(RegType typel,RegType typeh,VerifyError * pFailure)1815 static void checkWidePair(RegType typel, RegType typeh, VerifyError* pFailure)
1816 {
1817     if ((typeh != typel+1))
1818         *pFailure = VERIFY_ERROR_GENERIC;
1819 }
1820 
1821 /*
1822  * Implement category-1 "move" instructions.  Copy a 32-bit value from
1823  * "vsrc" to "vdst".
1824  *
1825  * "insnRegCount" is the number of registers available.  The "vdst" and
1826  * "vsrc" values are checked against this.
1827  */
copyRegister1(RegType * insnRegs,int insnRegCount,u4 vdst,u4 vsrc,TypeCategory cat,VerifyError * pFailure)1828 static void copyRegister1(RegType* insnRegs, int insnRegCount, u4 vdst,
1829     u4 vsrc, TypeCategory cat, VerifyError* pFailure)
1830 {
1831     RegType type = getRegisterType(insnRegs, insnRegCount, vsrc, pFailure);
1832     if (VERIFY_OK(*pFailure))
1833         checkTypeCategory(type, cat, pFailure);
1834     if (VERIFY_OK(*pFailure))
1835         setRegisterType(insnRegs, insnRegCount, vdst, type, pFailure);
1836 
1837     if (!VERIFY_OK(*pFailure)) {
1838         LOG_VFY("VFY: copy1 v%u<-v%u type=%d cat=%d\n", vdst, vsrc, type, cat);
1839     }
1840 }
1841 
1842 /*
1843  * Implement category-2 "move" instructions.  Copy a 64-bit value from
1844  * "vsrc" to "vdst".  This copies both halves of the register.
1845  */
copyRegister2(RegType * insnRegs,int insnRegCount,u4 vdst,u4 vsrc,VerifyError * pFailure)1846 static void copyRegister2(RegType* insnRegs, int insnRegCount, u4 vdst,
1847     u4 vsrc, VerifyError* pFailure)
1848 {
1849     RegType typel = getRegisterType(insnRegs, insnRegCount, vsrc, pFailure);
1850     RegType typeh = getRegisterType(insnRegs, insnRegCount, vsrc+1, pFailure);
1851     if (VERIFY_OK(*pFailure)) {
1852         checkTypeCategory(typel, kTypeCategory2, pFailure);
1853         checkWidePair(typel, typeh, pFailure);
1854     }
1855     if (VERIFY_OK(*pFailure))
1856         setRegisterType(insnRegs, insnRegCount, vdst, typel, pFailure);
1857 
1858     if (!VERIFY_OK(*pFailure)) {
1859         LOG_VFY("VFY: copy2 v%u<-v%u type=%d/%d\n", vdst, vsrc, typel, typeh);
1860     }
1861 }
1862 
1863 /*
1864  * Implement "move-result".  Copy the category-1 value from the result
1865  * register to another register, and reset the result register.
1866  *
1867  * We can't just call copyRegister1 with an altered insnRegCount,
1868  * because that would affect the test on "vdst" as well.
1869  */
copyResultRegister1(RegType * insnRegs,const int insnRegCount,u4 vdst,TypeCategory cat,VerifyError * pFailure)1870 static void copyResultRegister1(RegType* insnRegs, const int insnRegCount,
1871     u4 vdst, TypeCategory cat, VerifyError* pFailure)
1872 {
1873     RegType type;
1874     u4 vsrc;
1875 
1876     vsrc = RESULT_REGISTER(insnRegCount);
1877     type = getRegisterType(insnRegs, insnRegCount + kExtraRegs, vsrc, pFailure);
1878     if (VERIFY_OK(*pFailure))
1879         checkTypeCategory(type, cat, pFailure);
1880     if (VERIFY_OK(*pFailure)) {
1881         setRegisterType(insnRegs, insnRegCount, vdst, type, pFailure);
1882         insnRegs[vsrc] = kRegTypeUnknown;
1883     }
1884 
1885     if (!VERIFY_OK(*pFailure)) {
1886         LOG_VFY("VFY: copyRes1 v%u<-v%u cat=%d type=%d\n",
1887             vdst, vsrc, cat, type);
1888     }
1889 }
1890 
1891 /*
1892  * Implement "move-result-wide".  Copy the category-2 value from the result
1893  * register to another register, and reset the result register.
1894  *
1895  * We can't just call copyRegister2 with an altered insnRegCount,
1896  * because that would affect the test on "vdst" as well.
1897  */
copyResultRegister2(RegType * insnRegs,const int insnRegCount,u4 vdst,VerifyError * pFailure)1898 static void copyResultRegister2(RegType* insnRegs, const int insnRegCount,
1899     u4 vdst, VerifyError* pFailure)
1900 {
1901     RegType typel, typeh;
1902     u4 vsrc;
1903 
1904     vsrc = RESULT_REGISTER(insnRegCount);
1905     typel = getRegisterType(insnRegs, insnRegCount + kExtraRegs, vsrc,
1906                 pFailure);
1907     typeh = getRegisterType(insnRegs, insnRegCount + kExtraRegs, vsrc+1,
1908                 pFailure);
1909     if (VERIFY_OK(*pFailure)) {
1910         checkTypeCategory(typel, kTypeCategory2, pFailure);
1911         checkWidePair(typel, typeh, pFailure);
1912     }
1913     if (VERIFY_OK(*pFailure)) {
1914         setRegisterType(insnRegs, insnRegCount, vdst, typel, pFailure);
1915         insnRegs[vsrc] = kRegTypeUnknown;
1916         insnRegs[vsrc+1] = kRegTypeUnknown;
1917     }
1918 
1919     if (!VERIFY_OK(*pFailure)) {
1920         LOG_VFY("VFY: copyRes2 v%u<-v%u type=%d/%d\n",
1921             vdst, vsrc, typel, typeh);
1922     }
1923 }
1924 
1925 /*
1926  * Verify types for a simple two-register instruction (e.g. "neg-int").
1927  * "dstType" is stored into vA, and "srcType" is verified against vB.
1928  */
checkUnop(RegType * insnRegs,const int insnRegCount,DecodedInstruction * pDecInsn,RegType dstType,RegType srcType,VerifyError * pFailure)1929 static void checkUnop(RegType* insnRegs, const int insnRegCount,
1930     DecodedInstruction* pDecInsn, RegType dstType, RegType srcType,
1931     VerifyError* pFailure)
1932 {
1933     verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vB, srcType, pFailure);
1934     setRegisterType(insnRegs, insnRegCount, pDecInsn->vA, dstType, pFailure);
1935 }
1936 
1937 /*
1938  * We're performing an operation like "and-int/2addr" that can be
1939  * performed on booleans as well as integers.  We get no indication of
1940  * boolean-ness, but we can infer it from the types of the arguments.
1941  *
1942  * Assumes we've already validated reg1/reg2.
1943  *
1944  * TODO: consider generalizing this.  The key principle is that the
1945  * result of a bitwise operation can only be as wide as the widest of
1946  * the operands.  You can safely AND/OR/XOR two chars together and know
1947  * you still have a char, so it's reasonable for the compiler or "dx"
1948  * to skip the int-to-char instruction.  (We need to do this for boolean
1949  * because there is no int-to-boolean operation.)
1950  *
1951  * Returns true if both args are Boolean, Zero, or One.
1952  */
upcastBooleanOp(RegType * insnRegs,const int insnRegCount,u4 reg1,u4 reg2)1953 static bool upcastBooleanOp(RegType* insnRegs, const int insnRegCount,
1954     u4 reg1, u4 reg2)
1955 {
1956     RegType type1, type2;
1957 
1958     type1 = insnRegs[reg1];
1959     type2 = insnRegs[reg2];
1960 
1961     if ((type1 == kRegTypeBoolean || type1 == kRegTypeZero ||
1962             type1 == kRegTypeOne) &&
1963         (type2 == kRegTypeBoolean || type2 == kRegTypeZero ||
1964             type2 == kRegTypeOne))
1965     {
1966         return true;
1967     }
1968     return false;
1969 }
1970 
1971 /*
1972  * Verify types for A two-register instruction with a literal constant
1973  * (e.g. "add-int/lit8").  "dstType" is stored into vA, and "srcType" is
1974  * verified against vB.
1975  *
1976  * If "checkBooleanOp" is set, we use the constant value in vC.
1977  */
checkLitop(RegType * insnRegs,const int insnRegCount,DecodedInstruction * pDecInsn,RegType dstType,RegType srcType,bool checkBooleanOp,VerifyError * pFailure)1978 static void checkLitop(RegType* insnRegs, const int insnRegCount,
1979     DecodedInstruction* pDecInsn, RegType dstType, RegType srcType,
1980     bool checkBooleanOp, VerifyError* pFailure)
1981 {
1982     verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vB, srcType, pFailure);
1983     if (VERIFY_OK(*pFailure) && checkBooleanOp) {
1984         assert(dstType == kRegTypeInteger);
1985         /* check vB with the call, then check the constant manually */
1986         if (upcastBooleanOp(insnRegs, insnRegCount, pDecInsn->vB, pDecInsn->vB)
1987             && (pDecInsn->vC == 0 || pDecInsn->vC == 1))
1988         {
1989             dstType = kRegTypeBoolean;
1990         }
1991     }
1992     setRegisterType(insnRegs, insnRegCount, pDecInsn->vA, dstType, pFailure);
1993 }
1994 
1995 /*
1996  * Verify types for a simple three-register instruction (e.g. "add-int").
1997  * "dstType" is stored into vA, and "srcType1"/"srcType2" are verified
1998  * against vB/vC.
1999  */
checkBinop(RegType * insnRegs,const int insnRegCount,DecodedInstruction * pDecInsn,RegType dstType,RegType srcType1,RegType srcType2,bool checkBooleanOp,VerifyError * pFailure)2000 static void checkBinop(RegType* insnRegs, const int insnRegCount,
2001     DecodedInstruction* pDecInsn, RegType dstType, RegType srcType1,
2002     RegType srcType2, bool checkBooleanOp, VerifyError* pFailure)
2003 {
2004     verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vB, srcType1,
2005         pFailure);
2006     verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vC, srcType2,
2007         pFailure);
2008     if (VERIFY_OK(*pFailure) && checkBooleanOp) {
2009         assert(dstType == kRegTypeInteger);
2010         if (upcastBooleanOp(insnRegs, insnRegCount, pDecInsn->vB, pDecInsn->vC))
2011             dstType = kRegTypeBoolean;
2012     }
2013     setRegisterType(insnRegs, insnRegCount, pDecInsn->vA, dstType, pFailure);
2014 }
2015 
2016 /*
2017  * Verify types for a binary "2addr" operation.  "srcType1"/"srcType2"
2018  * are verified against vA/vB, then "dstType" is stored into vA.
2019  */
checkBinop2addr(RegType * insnRegs,const int insnRegCount,DecodedInstruction * pDecInsn,RegType dstType,RegType srcType1,RegType srcType2,bool checkBooleanOp,VerifyError * pFailure)2020 static void checkBinop2addr(RegType* insnRegs, const int insnRegCount,
2021     DecodedInstruction* pDecInsn, RegType dstType, RegType srcType1,
2022     RegType srcType2, bool checkBooleanOp, VerifyError* pFailure)
2023 {
2024     verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vA, srcType1,
2025         pFailure);
2026     verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vB, srcType2,
2027         pFailure);
2028     if (VERIFY_OK(*pFailure) && checkBooleanOp) {
2029         assert(dstType == kRegTypeInteger);
2030         if (upcastBooleanOp(insnRegs, insnRegCount, pDecInsn->vA, pDecInsn->vB))
2031             dstType = kRegTypeBoolean;
2032     }
2033     setRegisterType(insnRegs, insnRegCount, pDecInsn->vA, dstType, pFailure);
2034 }
2035 
2036 /*
2037  * Treat right-shifting as a narrowing conversion when possible.
2038  *
2039  * For example, right-shifting an int 24 times results in a value that can
2040  * be treated as a byte.
2041  *
2042  * Things get interesting when contemplating sign extension.  Right-
2043  * shifting an integer by 16 yields a value that can be represented in a
2044  * "short" but not a "char", but an unsigned right shift by 16 yields a
2045  * value that belongs in a char rather than a short.  (Consider what would
2046  * happen if the result of the shift were cast to a char or short and then
2047  * cast back to an int.  If sign extension, or the lack thereof, causes
2048  * a change in the 32-bit representation, then the conversion was lossy.)
2049  *
2050  * A signed right shift by 17 on an integer results in a short.  An unsigned
2051  * right shfit by 17 on an integer results in a posshort, which can be
2052  * assigned to a short or a char.
2053  *
2054  * An unsigned right shift on a short can actually expand the result into
2055  * a 32-bit integer.  For example, 0xfffff123 >>> 8 becomes 0x00fffff1,
2056  * which can't be represented in anything smaller than an int.
2057  *
2058  * javac does not generate code that takes advantage of this, but some
2059  * of the code optimizers do.  It's generally a peephole optimization
2060  * that replaces a particular sequence, e.g. (bipush 24, ishr, i2b) is
2061  * replaced by (bipush 24, ishr).  Knowing that shifting a short 8 times
2062  * to the right yields a byte is really more than we need to handle the
2063  * code that's out there, but support is not much more complex than just
2064  * handling integer.
2065  *
2066  * Right-shifting never yields a boolean value.
2067  *
2068  * Returns the new register type.
2069  */
adjustForRightShift(RegType * workRegs,const int insnRegCount,int reg,unsigned int shiftCount,bool isUnsignedShift,VerifyError * pFailure)2070 static RegType adjustForRightShift(RegType* workRegs, const int insnRegCount,
2071     int reg, unsigned int shiftCount, bool isUnsignedShift,
2072     VerifyError* pFailure)
2073 {
2074     RegType srcType = getRegisterType(workRegs, insnRegCount, reg, pFailure);
2075     RegType newType;
2076 
2077     /* no-op */
2078     if (shiftCount == 0)
2079         return srcType;
2080 
2081     /* safe defaults */
2082     if (isUnsignedShift)
2083         newType = kRegTypeInteger;
2084     else
2085         newType = srcType;
2086 
2087     if (shiftCount >= 32) {
2088         LOG_VFY("Got unexpectedly large shift count %u\n", shiftCount);
2089         /* fail? */
2090         return newType;
2091     }
2092 
2093     switch (srcType) {
2094     case kRegTypeInteger:               /* 32-bit signed value */
2095     case kRegTypeFloat:                 /* (allowed; treat same as int) */
2096         if (isUnsignedShift) {
2097             if (shiftCount > 24)
2098                 newType = kRegTypePosByte;
2099             else if (shiftCount >= 16)
2100                 newType = kRegTypeChar;
2101         } else {
2102             if (shiftCount >= 24)
2103                 newType = kRegTypeByte;
2104             else if (shiftCount >= 16)
2105                 newType = kRegTypeShort;
2106         }
2107         break;
2108     case kRegTypeShort:                 /* 16-bit signed value */
2109         if (isUnsignedShift) {
2110             /* default (kRegTypeInteger) is correct */
2111         } else {
2112             if (shiftCount >= 8)
2113                 newType = kRegTypeByte;
2114         }
2115         break;
2116     case kRegTypePosShort:              /* 15-bit unsigned value */
2117         if (shiftCount >= 8)
2118             newType = kRegTypePosByte;
2119         break;
2120     case kRegTypeChar:                  /* 16-bit unsigned value */
2121         if (shiftCount > 8)
2122             newType = kRegTypePosByte;
2123         break;
2124     case kRegTypeByte:                  /* 8-bit signed value */
2125         /* defaults (u=kRegTypeInteger / s=srcType) are correct */
2126         break;
2127     case kRegTypePosByte:               /* 7-bit unsigned value */
2128         /* always use newType=srcType */
2129         newType = srcType;
2130         break;
2131     case kRegTypeZero:                  /* 1-bit unsigned value */
2132     case kRegTypeOne:
2133     case kRegTypeBoolean:
2134         /* unnecessary? */
2135         newType = kRegTypeZero;
2136         break;
2137     default:
2138         /* long, double, references; shouldn't be here! */
2139         assert(false);
2140         break;
2141     }
2142 
2143     if (newType != srcType) {
2144         LOGVV("narrowing: %d(%d) --> %d to %d\n",
2145             shiftCount, isUnsignedShift, srcType, newType);
2146     } else {
2147         LOGVV("not narrowed: %d(%d) --> %d\n",
2148             shiftCount, isUnsignedShift, srcType);
2149     }
2150     return newType;
2151 }
2152 
2153 
2154 /*
2155  * ===========================================================================
2156  *      Register merge
2157  * ===========================================================================
2158  */
2159 
2160 /*
2161  * Compute the "class depth" of a class.  This is the distance from the
2162  * class to the top of the tree, chasing superclass links.  java.lang.Object
2163  * has a class depth of 0.
2164  */
getClassDepth(ClassObject * clazz)2165 static int getClassDepth(ClassObject* clazz)
2166 {
2167     int depth = 0;
2168 
2169     while (clazz->super != NULL) {
2170         clazz = clazz->super;
2171         depth++;
2172     }
2173     return depth;
2174 }
2175 
2176 /*
2177  * Given two classes, walk up the superclass tree to find a common
2178  * ancestor.  (Called from findCommonSuperclass().)
2179  *
2180  * TODO: consider caching the class depth in the class object so we don't
2181  * have to search for it here.
2182  */
digForSuperclass(ClassObject * c1,ClassObject * c2)2183 static ClassObject* digForSuperclass(ClassObject* c1, ClassObject* c2)
2184 {
2185     int depth1, depth2;
2186 
2187     depth1 = getClassDepth(c1);
2188     depth2 = getClassDepth(c2);
2189 
2190     if (gDebugVerbose) {
2191         LOGVV("COMMON: %s(%d) + %s(%d)\n",
2192             c1->descriptor, depth1, c2->descriptor, depth2);
2193     }
2194 
2195     /* pull the deepest one up */
2196     if (depth1 > depth2) {
2197         while (depth1 > depth2) {
2198             c1 = c1->super;
2199             depth1--;
2200         }
2201     } else {
2202         while (depth2 > depth1) {
2203             c2 = c2->super;
2204             depth2--;
2205         }
2206     }
2207 
2208     /* walk up in lock-step */
2209     while (c1 != c2) {
2210         c1 = c1->super;
2211         c2 = c2->super;
2212 
2213         assert(c1 != NULL && c2 != NULL);
2214     }
2215 
2216     if (gDebugVerbose) {
2217         LOGVV("      : --> %s\n", c1->descriptor);
2218     }
2219     return c1;
2220 }
2221 
2222 /*
2223  * Merge two array classes.  We can't use the general "walk up to the
2224  * superclass" merge because the superclass of an array is always Object.
2225  * We want String[] + Integer[] = Object[].  This works for higher dimensions
2226  * as well, e.g. String[][] + Integer[][] = Object[][].
2227  *
2228  * If Foo1 and Foo2 are subclasses of Foo, Foo1[] + Foo2[] = Foo[].
2229  *
2230  * If Class implements Type, Class[] + Type[] = Type[].
2231  *
2232  * If the dimensions don't match, we want to convert to an array of Object
2233  * with the least dimension, e.g. String[][] + String[][][][] = Object[][].
2234  *
2235  * This gets a little awkward because we may have to ask the VM to create
2236  * a new array type with the appropriate element and dimensions.  However, we
2237  * shouldn't be doing this often.
2238  */
findCommonArraySuperclass(ClassObject * c1,ClassObject * c2)2239 static ClassObject* findCommonArraySuperclass(ClassObject* c1, ClassObject* c2)
2240 {
2241     ClassObject* arrayClass = NULL;
2242     ClassObject* commonElem;
2243     int i, numDims;
2244 
2245     assert(c1->arrayDim > 0);
2246     assert(c2->arrayDim > 0);
2247 
2248     if (c1->arrayDim == c2->arrayDim) {
2249         //commonElem = digForSuperclass(c1->elementClass, c2->elementClass);
2250         commonElem = findCommonSuperclass(c1->elementClass, c2->elementClass);
2251         numDims = c1->arrayDim;
2252     } else {
2253         if (c1->arrayDim < c2->arrayDim)
2254             numDims = c1->arrayDim;
2255         else
2256             numDims = c2->arrayDim;
2257         commonElem = c1->super;     // == java.lang.Object
2258     }
2259 
2260     /* walk from the element to the (multi-)dimensioned array type */
2261     for (i = 0; i < numDims; i++) {
2262         arrayClass = dvmFindArrayClassForElement(commonElem);
2263         commonElem = arrayClass;
2264     }
2265 
2266     LOGVV("ArrayMerge '%s' + '%s' --> '%s'\n",
2267         c1->descriptor, c2->descriptor, arrayClass->descriptor);
2268     return arrayClass;
2269 }
2270 
2271 /*
2272  * Find the first common superclass of the two classes.  We're not
2273  * interested in common interfaces.
2274  *
2275  * The easiest way to do this for concrete classes is to compute the "class
2276  * depth" of each, move up toward the root of the deepest one until they're
2277  * at the same depth, then walk both up to the root until they match.
2278  *
2279  * If both classes are arrays of non-primitive types, we need to merge
2280  * based on array depth and element type.
2281  *
2282  * If one class is an interface, we check to see if the other class/interface
2283  * (or one of its predecessors) implements the interface.  If so, we return
2284  * the interface; otherwise, we return Object.
2285  *
2286  * NOTE: we continue the tradition of "lazy interface handling".  To wit,
2287  * suppose we have three classes:
2288  *   One implements Fancy, Free
2289  *   Two implements Fancy, Free
2290  *   Three implements Free
2291  * where Fancy and Free are unrelated interfaces.  The code requires us
2292  * to merge One into Two.  Ideally we'd use a common interface, which
2293  * gives us a choice between Fancy and Free, and no guidance on which to
2294  * use.  If we use Free, we'll be okay when Three gets merged in, but if
2295  * we choose Fancy, we're hosed.  The "ideal" solution is to create a
2296  * set of common interfaces and carry that around, merging further references
2297  * into it.  This is a pain.  The easy solution is to simply boil them
2298  * down to Objects and let the runtime invokeinterface call fail, which
2299  * is what we do.
2300  */
findCommonSuperclass(ClassObject * c1,ClassObject * c2)2301 static ClassObject* findCommonSuperclass(ClassObject* c1, ClassObject* c2)
2302 {
2303     assert(!dvmIsPrimitiveClass(c1) && !dvmIsPrimitiveClass(c2));
2304 
2305     if (c1 == c2)
2306         return c1;
2307 
2308     if (dvmIsInterfaceClass(c1) && dvmImplements(c2, c1)) {
2309         if (gDebugVerbose)
2310             LOGVV("COMMON/I1: %s + %s --> %s\n",
2311                 c1->descriptor, c2->descriptor, c1->descriptor);
2312         return c1;
2313     }
2314     if (dvmIsInterfaceClass(c2) && dvmImplements(c1, c2)) {
2315         if (gDebugVerbose)
2316             LOGVV("COMMON/I2: %s + %s --> %s\n",
2317                 c1->descriptor, c2->descriptor, c2->descriptor);
2318         return c2;
2319     }
2320 
2321     if (dvmIsArrayClass(c1) && dvmIsArrayClass(c2) &&
2322         !dvmIsPrimitiveClass(c1->elementClass) &&
2323         !dvmIsPrimitiveClass(c2->elementClass))
2324     {
2325         return findCommonArraySuperclass(c1, c2);
2326     }
2327 
2328     return digForSuperclass(c1, c2);
2329 }
2330 
2331 /*
2332  * Merge two RegType values.
2333  *
2334  * Sets "*pChanged" to "true" if the result doesn't match "type1".
2335  */
mergeTypes(RegType type1,RegType type2,bool * pChanged)2336 static RegType mergeTypes(RegType type1, RegType type2, bool* pChanged)
2337 {
2338     RegType result;
2339 
2340     /*
2341      * Check for trivial case so we don't have to hit memory.
2342      */
2343     if (type1 == type2)
2344         return type1;
2345 
2346     /*
2347      * Use the table if we can, and reject any attempts to merge something
2348      * from the table with a reference type.
2349      *
2350      * The uninitialized table entry at index zero *will* show up as a
2351      * simple kRegTypeUninit value.  Since this cannot be merged with
2352      * anything but itself, the rules do the right thing.
2353      */
2354     if (type1 < kRegTypeMAX) {
2355         if (type2 < kRegTypeMAX) {
2356             result = gDvmMergeTab[type1][type2];
2357         } else {
2358             /* simple + reference == conflict, usually */
2359             if (type1 == kRegTypeZero)
2360                 result = type2;
2361             else
2362                 result = kRegTypeConflict;
2363         }
2364     } else {
2365         if (type2 < kRegTypeMAX) {
2366             /* reference + simple == conflict, usually */
2367             if (type2 == kRegTypeZero)
2368                 result = type1;
2369             else
2370                 result = kRegTypeConflict;
2371         } else {
2372             /* merging two references */
2373             if (regTypeIsUninitReference(type1) ||
2374                 regTypeIsUninitReference(type2))
2375             {
2376                 /* can't merge uninit with anything but self */
2377                 result = kRegTypeConflict;
2378             } else {
2379                 ClassObject* clazz1 = regTypeInitializedReferenceToClass(type1);
2380                 ClassObject* clazz2 = regTypeInitializedReferenceToClass(type2);
2381                 ClassObject* mergedClass;
2382 
2383                 mergedClass = findCommonSuperclass(clazz1, clazz2);
2384                 assert(mergedClass != NULL);
2385                 result = regTypeFromClass(mergedClass);
2386             }
2387         }
2388     }
2389 
2390     if (result != type1)
2391         *pChanged = true;
2392     return result;
2393 }
2394 
2395 /*
2396  * Control can transfer to "nextInsn".
2397  *
2398  * Merge the registers from "workRegs" into "regTypes" at "nextInsn", and
2399  * set the "changed" flag on the target address if the registers have changed.
2400  */
updateRegisters(const Method * meth,InsnFlags * insnFlags,RegisterTable * regTable,int nextInsn,const RegType * workRegs)2401 static void updateRegisters(const Method* meth, InsnFlags* insnFlags,
2402     RegisterTable* regTable, int nextInsn, const RegType* workRegs)
2403 {
2404     RegType* targetRegs = getRegisterLine(regTable, nextInsn);
2405     const int insnRegCount = meth->registersSize;
2406 
2407 #if 0
2408     if (!dvmInsnIsBranchTarget(insnFlags, nextInsn)) {
2409         LOGE("insnFlags[0x%x]=0x%08x\n", nextInsn, insnFlags[nextInsn]);
2410         LOGE(" In %s.%s %s\n",
2411             meth->clazz->descriptor, meth->name, meth->descriptor);
2412         assert(false);
2413     }
2414 #endif
2415 
2416     if (!dvmInsnIsVisitedOrChanged(insnFlags, nextInsn)) {
2417         /*
2418          * We haven't processed this instruction before, and we haven't
2419          * touched the registers here, so there's nothing to "merge".  Copy
2420          * the registers over and mark it as changed.  (This is the only
2421          * way a register can transition out of "unknown", so this is not
2422          * just an optimization.)
2423          */
2424         LOGVV("COPY into 0x%04x\n", nextInsn);
2425         copyRegisters(targetRegs, workRegs, insnRegCount + kExtraRegs);
2426         dvmInsnSetChanged(insnFlags, nextInsn, true);
2427     } else {
2428         if (gDebugVerbose) {
2429             LOGVV("MERGE into 0x%04x\n", nextInsn);
2430             //dumpRegTypes(meth, insnFlags, targetRegs, 0, "targ", NULL, 0);
2431             //dumpRegTypes(meth, insnFlags, workRegs, 0, "work", NULL, 0);
2432         }
2433         /* merge registers, set Changed only if different */
2434         bool changed = false;
2435         int i;
2436 
2437         for (i = 0; i < insnRegCount + kExtraRegs; i++) {
2438             targetRegs[i] = mergeTypes(targetRegs[i], workRegs[i], &changed);
2439         }
2440 
2441         if (gDebugVerbose) {
2442             //LOGI(" RESULT (changed=%d)\n", changed);
2443             //dumpRegTypes(meth, insnFlags, targetRegs, 0, "rslt", NULL, 0);
2444         }
2445 
2446         if (changed)
2447             dvmInsnSetChanged(insnFlags, nextInsn, true);
2448     }
2449 }
2450 
2451 
2452 /*
2453  * ===========================================================================
2454  *      Utility functions
2455  * ===========================================================================
2456  */
2457 
2458 /*
2459  * Look up an instance field, specified by "fieldIdx", that is going to be
2460  * accessed in object "objType".  This resolves the field and then verifies
2461  * that the class containing the field is an instance of the reference in
2462  * "objType".
2463  *
2464  * It is possible for "objType" to be kRegTypeZero, meaning that we might
2465  * have a null reference.  This is a runtime problem, so we allow it,
2466  * skipping some of the type checks.
2467  *
2468  * In general, "objType" must be an initialized reference.  However, we
2469  * allow it to be uninitialized if this is an "<init>" method and the field
2470  * is declared within the "objType" class.
2471  *
2472  * Returns an InstField on success, returns NULL and sets "*pFailure"
2473  * on failure.
2474  */
getInstField(const Method * meth,const UninitInstanceMap * uninitMap,RegType objType,int fieldIdx,VerifyError * pFailure)2475 static InstField* getInstField(const Method* meth,
2476     const UninitInstanceMap* uninitMap, RegType objType, int fieldIdx,
2477     VerifyError* pFailure)
2478 {
2479     InstField* instField = NULL;
2480     ClassObject* objClass;
2481     bool mustBeLocal = false;
2482 
2483     if (!regTypeIsReference(objType)) {
2484         LOG_VFY("VFY: attempt to access field in non-reference type %d\n",
2485             objType);
2486         *pFailure = VERIFY_ERROR_GENERIC;
2487         goto bail;
2488     }
2489 
2490     instField = dvmOptResolveInstField(meth->clazz, fieldIdx, pFailure);
2491     if (instField == NULL) {
2492         LOG_VFY("VFY: unable to resolve instance field %u\n", fieldIdx);
2493         assert(!VERIFY_OK(*pFailure));
2494         goto bail;
2495     }
2496 
2497     if (objType == kRegTypeZero)
2498         goto bail;
2499 
2500     /*
2501      * Access to fields in uninitialized objects is allowed if this is
2502      * the <init> method for the object and the field in question is
2503      * declared by this class.
2504      */
2505     objClass = regTypeReferenceToClass(objType, uninitMap);
2506     assert(objClass != NULL);
2507     if (regTypeIsUninitReference(objType)) {
2508         if (!isInitMethod(meth) || meth->clazz != objClass) {
2509             LOG_VFY("VFY: attempt to access field via uninitialized ref\n");
2510             *pFailure = VERIFY_ERROR_GENERIC;
2511             goto bail;
2512         }
2513         mustBeLocal = true;
2514     }
2515 
2516     if (!dvmInstanceof(objClass, instField->field.clazz)) {
2517         LOG_VFY("VFY: invalid field access (field %s.%s, through %s ref)\n",
2518                 instField->field.clazz->descriptor, instField->field.name,
2519                 objClass->descriptor);
2520         *pFailure = VERIFY_ERROR_NO_FIELD;
2521         goto bail;
2522     }
2523 
2524     if (mustBeLocal) {
2525         /* for uninit ref, make sure it's defined by this class, not super */
2526         if (instField < objClass->ifields ||
2527             instField >= objClass->ifields + objClass->ifieldCount)
2528         {
2529             LOG_VFY("VFY: invalid constructor field access (field %s in %s)\n",
2530                     instField->field.name, objClass->descriptor);
2531             *pFailure = VERIFY_ERROR_GENERIC;
2532             goto bail;
2533         }
2534     }
2535 
2536 bail:
2537     return instField;
2538 }
2539 
2540 /*
2541  * Look up a static field.
2542  *
2543  * Returns a StaticField on success, returns NULL and sets "*pFailure"
2544  * on failure.
2545  */
getStaticField(const Method * meth,int fieldIdx,VerifyError * pFailure)2546 static StaticField* getStaticField(const Method* meth, int fieldIdx,
2547     VerifyError* pFailure)
2548 {
2549     StaticField* staticField;
2550 
2551     staticField = dvmOptResolveStaticField(meth->clazz, fieldIdx, pFailure);
2552     if (staticField == NULL) {
2553         DexFile* pDexFile = meth->clazz->pDvmDex->pDexFile;
2554         const DexFieldId* pFieldId;
2555 
2556         pFieldId = dexGetFieldId(pDexFile, fieldIdx);
2557 
2558         LOG_VFY("VFY: unable to resolve static field %u (%s) in %s\n", fieldIdx,
2559             dexStringById(pDexFile, pFieldId->nameIdx),
2560             dexStringByTypeIdx(pDexFile, pFieldId->classIdx));
2561         assert(!VERIFY_OK(*pFailure));
2562         goto bail;
2563     }
2564 
2565 bail:
2566     return staticField;
2567 }
2568 
2569 /*
2570  * If "field" is marked "final", make sure this is the either <clinit>
2571  * or <init> as appropriate.
2572  *
2573  * Sets "*pFailure" on failure.
2574  */
checkFinalFieldAccess(const Method * meth,const Field * field,VerifyError * pFailure)2575 static void checkFinalFieldAccess(const Method* meth, const Field* field,
2576     VerifyError* pFailure)
2577 {
2578     if (!dvmIsFinalField(field))
2579         return;
2580 
2581     /* make sure we're in the same class */
2582     if (meth->clazz != field->clazz) {
2583         LOG_VFY_METH(meth, "VFY: can't modify final field %s.%s\n",
2584             field->clazz->descriptor, field->name);
2585         *pFailure = VERIFY_ERROR_ACCESS_FIELD;
2586         return;
2587     }
2588 
2589     /*
2590      * The VM spec descriptions of putfield and putstatic say that
2591      * IllegalAccessError is only thrown when the instructions appear
2592      * outside the declaring class.  Our earlier attempts to restrict
2593      * final field modification to constructors are, therefore, wrong.
2594      */
2595 #if 0
2596     /* make sure we're in the right kind of constructor */
2597     if (dvmIsStaticField(field)) {
2598         if (!isClassInitMethod(meth)) {
2599             LOG_VFY_METH(meth,
2600                 "VFY: can't modify final static field outside <clinit>\n");
2601             *pFailure = VERIFY_ERROR_GENERIC;
2602         }
2603     } else {
2604         if (!isInitMethod(meth)) {
2605             LOG_VFY_METH(meth,
2606                 "VFY: can't modify final field outside <init>\n");
2607             *pFailure = VERIFY_ERROR_GENERIC;
2608         }
2609     }
2610 #endif
2611 }
2612 
2613 /*
2614  * Make sure that the register type is suitable for use as an array index.
2615  *
2616  * Sets "*pFailure" if not.
2617  */
checkArrayIndexType(const Method * meth,RegType regType,VerifyError * pFailure)2618 static void checkArrayIndexType(const Method* meth, RegType regType,
2619     VerifyError* pFailure)
2620 {
2621     if (VERIFY_OK(*pFailure)) {
2622         /*
2623          * The 1nr types are interchangeable at this level.  We could
2624          * do something special if we can definitively identify it as a
2625          * float, but there's no real value in doing so.
2626          */
2627         checkTypeCategory(regType, kTypeCategory1nr, pFailure);
2628         if (!VERIFY_OK(*pFailure)) {
2629             LOG_VFY_METH(meth, "Invalid reg type for array index (%d)\n",
2630                 regType);
2631         }
2632     }
2633 }
2634 
2635 /*
2636  * Check constraints on constructor return.  Specifically, make sure that
2637  * the "this" argument got initialized.
2638  *
2639  * The "this" argument to <init> uses code offset kUninitThisArgAddr, which
2640  * puts it at the start of the list in slot 0.  If we see a register with
2641  * an uninitialized slot 0 reference, we know it somehow didn't get
2642  * initialized.
2643  *
2644  * Returns "true" if all is well.
2645  */
checkConstructorReturn(const Method * meth,const RegType * insnRegs,const int insnRegCount)2646 static bool checkConstructorReturn(const Method* meth, const RegType* insnRegs,
2647     const int insnRegCount)
2648 {
2649     int i;
2650 
2651     if (!isInitMethod(meth))
2652         return true;
2653 
2654     RegType uninitThis = regTypeFromUninitIndex(kUninitThisArgSlot);
2655 
2656     for (i = 0; i < insnRegCount; i++) {
2657         if (insnRegs[i] == uninitThis) {
2658             LOG_VFY("VFY: <init> returning without calling superclass init\n");
2659             return false;
2660         }
2661     }
2662     return true;
2663 }
2664 
2665 /*
2666  * Verify that the target instruction is not "move-exception".  It's important
2667  * that the only way to execute a move-exception is as the first instruction
2668  * of an exception handler.
2669  *
2670  * Returns "true" if all is well, "false" if the target instruction is
2671  * move-exception.
2672  */
checkMoveException(const Method * meth,int insnIdx,const char * logNote)2673 static bool checkMoveException(const Method* meth, int insnIdx,
2674     const char* logNote)
2675 {
2676     assert(insnIdx >= 0 && insnIdx < (int)dvmGetMethodInsnsSize(meth));
2677 
2678     if ((meth->insns[insnIdx] & 0xff) == OP_MOVE_EXCEPTION) {
2679         LOG_VFY("VFY: invalid use of move-exception\n");
2680         return false;
2681     }
2682     return true;
2683 }
2684 
2685 /*
2686  * For the "move-exception" instruction at "insnIdx", which must be at an
2687  * exception handler address, determine the first common superclass of
2688  * all exceptions that can land here.  (For javac output, we're probably
2689  * looking at multiple spans of bytecode covered by one "try" that lands
2690  * at an exception-specific "catch", but in general the handler could be
2691  * shared for multiple exceptions.)
2692  *
2693  * Returns NULL if no matching exception handler can be found, or if the
2694  * exception is not a subclass of Throwable.
2695  */
getCaughtExceptionType(const Method * meth,int insnIdx,VerifyError * pFailure)2696 static ClassObject* getCaughtExceptionType(const Method* meth, int insnIdx,
2697     VerifyError* pFailure)
2698 {
2699     VerifyError localFailure;
2700     const DexCode* pCode;
2701     DexFile* pDexFile;
2702     ClassObject* commonSuper = NULL;
2703     bool foundPossibleHandler = false;
2704     u4 handlersSize;
2705     u4 offset;
2706     u4 i;
2707 
2708     pDexFile = meth->clazz->pDvmDex->pDexFile;
2709     pCode = dvmGetMethodCode(meth);
2710 
2711     if (pCode->triesSize != 0) {
2712         handlersSize = dexGetHandlersSize(pCode);
2713         offset = dexGetFirstHandlerOffset(pCode);
2714     } else {
2715         handlersSize = 0;
2716         offset = 0;
2717     }
2718 
2719     for (i = 0; i < handlersSize; i++) {
2720         DexCatchIterator iterator;
2721         dexCatchIteratorInit(&iterator, pCode, offset);
2722 
2723         for (;;) {
2724             const DexCatchHandler* handler = dexCatchIteratorNext(&iterator);
2725 
2726             if (handler == NULL) {
2727                 break;
2728             }
2729 
2730             if (handler->address == (u4) insnIdx) {
2731                 ClassObject* clazz;
2732                 foundPossibleHandler = true;
2733 
2734                 if (handler->typeIdx == kDexNoIndex)
2735                     clazz = gDvm.classJavaLangThrowable;
2736                 else
2737                     clazz = dvmOptResolveClass(meth->clazz, handler->typeIdx,
2738                                 &localFailure);
2739 
2740                 if (clazz == NULL) {
2741                     LOG_VFY("VFY: unable to resolve exception class %u (%s)\n",
2742                         handler->typeIdx,
2743                         dexStringByTypeIdx(pDexFile, handler->typeIdx));
2744                     /* TODO: do we want to keep going?  If we don't fail
2745                      * this we run the risk of having a non-Throwable
2746                      * introduced at runtime.  However, that won't pass
2747                      * an instanceof test, so is essentially harmless. */
2748                 } else {
2749                     if (commonSuper == NULL)
2750                         commonSuper = clazz;
2751                     else
2752                         commonSuper = findCommonSuperclass(clazz, commonSuper);
2753                 }
2754             }
2755         }
2756 
2757         offset = dexCatchIteratorGetEndOffset(&iterator, pCode);
2758     }
2759 
2760     if (commonSuper == NULL) {
2761         /* no catch blocks, or no catches with classes we can find */
2762         LOG_VFY_METH(meth,
2763             "VFY: unable to find exception handler at addr 0x%x\n", insnIdx);
2764         *pFailure = VERIFY_ERROR_GENERIC;
2765     } else {
2766         // TODO: verify the class is an instance of Throwable?
2767     }
2768 
2769     return commonSuper;
2770 }
2771 
2772 /*
2773  * Initialize the RegisterTable.
2774  *
2775  * Every instruction address can have a different set of information about
2776  * what's in which register, but for verification purposes we only need to
2777  * store it at branch target addresses (because we merge into that).
2778  *
2779  * By zeroing out the storage we are effectively initializing the register
2780  * information to kRegTypeUnknown.
2781  */
initRegisterTable(const Method * meth,const InsnFlags * insnFlags,RegisterTable * regTable,RegisterTrackingMode trackRegsFor)2782 static bool initRegisterTable(const Method* meth, const InsnFlags* insnFlags,
2783     RegisterTable* regTable, RegisterTrackingMode trackRegsFor)
2784 {
2785     const int insnsSize = dvmGetMethodInsnsSize(meth);
2786     int i;
2787 
2788     regTable->insnRegCountPlus = meth->registersSize + kExtraRegs;
2789     regTable->addrRegs = (RegType**) calloc(insnsSize, sizeof(RegType*));
2790     if (regTable->addrRegs == NULL)
2791         return false;
2792 
2793     assert(insnsSize > 0);
2794 
2795     /*
2796      * "All" means "every address that holds the start of an instruction".
2797      * "Branches" and "GcPoints" mean just those addresses.
2798      *
2799      * "GcPoints" fills about half the addresses, "Branches" about 15%.
2800      */
2801     int interestingCount = 0;
2802     //int insnCount = 0;
2803 
2804     for (i = 0; i < insnsSize; i++) {
2805         bool interesting;
2806 
2807         switch (trackRegsFor) {
2808         case kTrackRegsAll:
2809             interesting = dvmInsnIsOpcode(insnFlags, i);
2810             break;
2811         case kTrackRegsGcPoints:
2812             interesting = dvmInsnIsGcPoint(insnFlags, i) ||
2813                           dvmInsnIsBranchTarget(insnFlags, i);
2814             break;
2815         case kTrackRegsBranches:
2816             interesting = dvmInsnIsBranchTarget(insnFlags, i);
2817             break;
2818         default:
2819             dvmAbort();
2820             return false;
2821         }
2822 
2823         if (interesting)
2824             interestingCount++;
2825 
2826         /* count instructions, for display only */
2827         //if (dvmInsnIsOpcode(insnFlags, i))
2828         //    insnCount++;
2829     }
2830 
2831     regTable->regAlloc = (RegType*)
2832         calloc(regTable->insnRegCountPlus * interestingCount, sizeof(RegType));
2833     if (regTable->regAlloc == NULL)
2834         return false;
2835 
2836     RegType* regPtr = regTable->regAlloc;
2837     for (i = 0; i < insnsSize; i++) {
2838         bool interesting;
2839 
2840         switch (trackRegsFor) {
2841         case kTrackRegsAll:
2842             interesting = dvmInsnIsOpcode(insnFlags, i);
2843             break;
2844         case kTrackRegsGcPoints:
2845             interesting = dvmInsnIsGcPoint(insnFlags, i) ||
2846                           dvmInsnIsBranchTarget(insnFlags, i);
2847             break;
2848         case kTrackRegsBranches:
2849             interesting = dvmInsnIsBranchTarget(insnFlags, i);
2850             break;
2851         default:
2852             dvmAbort();
2853             return false;
2854         }
2855 
2856         if (interesting) {
2857             regTable->addrRegs[i] = regPtr;
2858             regPtr += regTable->insnRegCountPlus;
2859         }
2860     }
2861 
2862     //LOGD("Tracking registers for %d, total %d of %d(%d) (%d%%)\n",
2863     //    TRACK_REGS_FOR, interestingCount, insnCount, insnsSize,
2864     //    (interestingCount*100) / insnCount);
2865 
2866     assert(regPtr - regTable->regAlloc ==
2867         regTable->insnRegCountPlus * interestingCount);
2868     assert(regTable->addrRegs[0] != NULL);
2869     return true;
2870 }
2871 
2872 
2873 /*
2874  * Verify that the arguments in a filled-new-array instruction are valid.
2875  *
2876  * "resClass" is the class refered to by pDecInsn->vB.
2877  */
verifyFilledNewArrayRegs(const Method * meth,const RegType * insnRegs,const int insnRegCount,const DecodedInstruction * pDecInsn,ClassObject * resClass,bool isRange,VerifyError * pFailure)2878 static void verifyFilledNewArrayRegs(const Method* meth,
2879     const RegType* insnRegs, const int insnRegCount,
2880     const DecodedInstruction* pDecInsn, ClassObject* resClass, bool isRange,
2881     VerifyError* pFailure)
2882 {
2883     u4 argCount = pDecInsn->vA;
2884     RegType expectedType;
2885     PrimitiveType elemType;
2886     unsigned int ui;
2887 
2888     assert(dvmIsArrayClass(resClass));
2889     elemType = resClass->elementClass->primitiveType;
2890     if (elemType == PRIM_NOT) {
2891         expectedType = regTypeFromClass(resClass->elementClass);
2892     } else {
2893         expectedType = primitiveTypeToRegType(elemType);
2894     }
2895     //LOGI("filled-new-array: %s -> %d\n", resClass->descriptor, expectedType);
2896 
2897     /*
2898      * Verify each register.  If "argCount" is bad, verifyRegisterType()
2899      * will run off the end of the list and fail.  It's legal, if silly,
2900      * for argCount to be zero.
2901      */
2902     for (ui = 0; ui < argCount; ui++) {
2903         u4 getReg;
2904 
2905         if (isRange)
2906             getReg = pDecInsn->vC + ui;
2907         else
2908             getReg = pDecInsn->arg[ui];
2909 
2910         verifyRegisterType(insnRegs, insnRegCount, getReg, expectedType,
2911             pFailure);
2912         if (!VERIFY_OK(*pFailure)) {
2913             LOG_VFY("VFY: filled-new-array arg %u(%u) not valid\n", ui, getReg);
2914             return;
2915         }
2916     }
2917 }
2918 
2919 
2920 /*
2921  * Replace an instruction with "throw-verification-error".  This allows us to
2922  * defer error reporting until the code path is first used.
2923  *
2924  * The throw-verification-error instruction requires two code units.  Some
2925  * of the replaced instructions require three; the third code unit will
2926  * receive a "nop".  The instruction's length will be left unchanged
2927  * in "insnFlags".
2928  *
2929  * IMPORTANT: this may replace meth->insns with a pointer to a new copy of
2930  * the instructions.
2931  *
2932  * Returns "true" on success.
2933  */
replaceFailingInstruction(Method * meth,InsnFlags * insnFlags,int insnIdx,VerifyError failure)2934 static bool replaceFailingInstruction(Method* meth, InsnFlags* insnFlags,
2935     int insnIdx, VerifyError failure)
2936 {
2937     VerifyErrorRefType refType;
2938     const u2* oldInsns = meth->insns + insnIdx;
2939     u2 oldInsn = *oldInsns;
2940     bool result = false;
2941 
2942     dvmMakeCodeReadWrite(meth);
2943 
2944     //LOGD("  was 0x%04x\n", oldInsn);
2945     u2* newInsns = (u2*) meth->insns + insnIdx;
2946 
2947     /*
2948      * Generate the new instruction out of the old.
2949      *
2950      * First, make sure this is an instruction we're expecting to stomp on.
2951      */
2952     switch (oldInsn & 0xff) {
2953     case OP_CONST_CLASS:                // insn[1] == class ref, 2 bytes
2954     case OP_CHECK_CAST:
2955     case OP_INSTANCE_OF:
2956     case OP_NEW_INSTANCE:
2957     case OP_NEW_ARRAY:
2958     case OP_FILLED_NEW_ARRAY:           // insn[1] == class ref, 3 bytes
2959     case OP_FILLED_NEW_ARRAY_RANGE:
2960         refType = VERIFY_ERROR_REF_CLASS;
2961         break;
2962 
2963     case OP_IGET:                       // insn[1] == field ref, 2 bytes
2964     case OP_IGET_BOOLEAN:
2965     case OP_IGET_BYTE:
2966     case OP_IGET_CHAR:
2967     case OP_IGET_SHORT:
2968     case OP_IGET_WIDE:
2969     case OP_IGET_OBJECT:
2970     case OP_IPUT:
2971     case OP_IPUT_BOOLEAN:
2972     case OP_IPUT_BYTE:
2973     case OP_IPUT_CHAR:
2974     case OP_IPUT_SHORT:
2975     case OP_IPUT_WIDE:
2976     case OP_IPUT_OBJECT:
2977     case OP_SGET:
2978     case OP_SGET_BOOLEAN:
2979     case OP_SGET_BYTE:
2980     case OP_SGET_CHAR:
2981     case OP_SGET_SHORT:
2982     case OP_SGET_WIDE:
2983     case OP_SGET_OBJECT:
2984     case OP_SPUT:
2985     case OP_SPUT_BOOLEAN:
2986     case OP_SPUT_BYTE:
2987     case OP_SPUT_CHAR:
2988     case OP_SPUT_SHORT:
2989     case OP_SPUT_WIDE:
2990     case OP_SPUT_OBJECT:
2991         refType = VERIFY_ERROR_REF_FIELD;
2992         break;
2993 
2994     case OP_INVOKE_VIRTUAL:             // insn[1] == method ref, 3 bytes
2995     case OP_INVOKE_VIRTUAL_RANGE:
2996     case OP_INVOKE_SUPER:
2997     case OP_INVOKE_SUPER_RANGE:
2998     case OP_INVOKE_DIRECT:
2999     case OP_INVOKE_DIRECT_RANGE:
3000     case OP_INVOKE_STATIC:
3001     case OP_INVOKE_STATIC_RANGE:
3002     case OP_INVOKE_INTERFACE:
3003     case OP_INVOKE_INTERFACE_RANGE:
3004         refType = VERIFY_ERROR_REF_METHOD;
3005         break;
3006 
3007     default:
3008         /* could handle this in a generic way, but this is probably safer */
3009         LOG_VFY("GLITCH: verifier asked to replace opcode 0x%02x\n",
3010             oldInsn & 0xff);
3011         goto bail;
3012     }
3013 
3014     /* write a NOP over the third code unit, if necessary */
3015     int width = dvmInsnGetWidth(insnFlags, insnIdx);
3016     switch (width) {
3017     case 2:
3018         /* nothing to do */
3019         break;
3020     case 3:
3021         newInsns[2] = OP_NOP;
3022         break;
3023     default:
3024         /* whoops */
3025         LOGE("ERROR: stomped a %d-unit instruction with a verifier error\n",
3026             width);
3027         dvmAbort();
3028     }
3029 
3030     /* encode the opcode, with the failure code in the high byte */
3031     newInsns[0] = OP_THROW_VERIFICATION_ERROR |
3032         (failure << 8) | (refType << (8 + kVerifyErrorRefTypeShift));
3033 
3034     result = true;
3035 
3036 bail:
3037     dvmMakeCodeReadOnly(meth);
3038     return result;
3039 }
3040 
3041 
3042 /*
3043  * ===========================================================================
3044  *      Entry point and driver loop
3045  * ===========================================================================
3046  */
3047 
3048 /*
3049  * Entry point for the detailed code-flow analysis.
3050  */
dvmVerifyCodeFlow(Method * meth,InsnFlags * insnFlags,UninitInstanceMap * uninitMap)3051 bool dvmVerifyCodeFlow(Method* meth, InsnFlags* insnFlags,
3052     UninitInstanceMap* uninitMap)
3053 {
3054     bool result = false;
3055     const int insnsSize = dvmGetMethodInsnsSize(meth);
3056     const u2* insns = meth->insns;
3057     const bool generateRegisterMap = gDvm.generateRegisterMaps;
3058     int i, offset;
3059     bool isConditional;
3060     RegisterTable regTable;
3061 
3062     memset(&regTable, 0, sizeof(regTable));
3063 
3064 #ifndef NDEBUG
3065     checkMergeTab();     // only need to do this if table gets updated
3066 #endif
3067 
3068     /*
3069      * We rely on these for verification of const-class, const-string,
3070      * and throw instructions.  Make sure we have them.
3071      */
3072     if (gDvm.classJavaLangClass == NULL)
3073         gDvm.classJavaLangClass =
3074             dvmFindSystemClassNoInit("Ljava/lang/Class;");
3075     if (gDvm.classJavaLangString == NULL)
3076         gDvm.classJavaLangString =
3077             dvmFindSystemClassNoInit("Ljava/lang/String;");
3078     if (gDvm.classJavaLangThrowable == NULL) {
3079         gDvm.classJavaLangThrowable =
3080             dvmFindSystemClassNoInit("Ljava/lang/Throwable;");
3081         gDvm.offJavaLangThrowable_cause =
3082             dvmFindFieldOffset(gDvm.classJavaLangThrowable,
3083                 "cause", "Ljava/lang/Throwable;");
3084     }
3085     if (gDvm.classJavaLangObject == NULL)
3086         gDvm.classJavaLangObject =
3087             dvmFindSystemClassNoInit("Ljava/lang/Object;");
3088 
3089     if (meth->registersSize * insnsSize > 2*1024*1024) {
3090         /* should probably base this on actual memory requirements */
3091         LOG_VFY_METH(meth,
3092             "VFY: arbitrarily rejecting large method (regs=%d count=%d)\n",
3093             meth->registersSize, insnsSize);
3094         goto bail;
3095     }
3096 
3097     /*
3098      * Create register lists, and initialize them to "Unknown".  If we're
3099      * also going to create the register map, we need to retain the
3100      * register lists for a larger set of addresses.
3101      */
3102     if (!initRegisterTable(meth, insnFlags, &regTable,
3103             generateRegisterMap ? kTrackRegsGcPoints : kTrackRegsBranches))
3104         goto bail;
3105 
3106     /*
3107      * Initialize the types of the registers that correspond to the
3108      * method arguments.  We can determine this from the method signature.
3109      */
3110     if (!setTypesFromSignature(meth, regTable.addrRegs[0], uninitMap))
3111         goto bail;
3112 
3113     /*
3114      * Run the verifier.
3115      */
3116     if (!doCodeVerification(meth, insnFlags, &regTable, uninitMap))
3117         goto bail;
3118 
3119     /*
3120      * Generate a register map.
3121      */
3122     if (generateRegisterMap) {
3123         RegisterMap* pMap;
3124         VerifierData vd;
3125 
3126         vd.method = meth;
3127         vd.insnsSize = insnsSize;
3128         vd.insnRegCount = meth->registersSize;
3129         vd.insnFlags = insnFlags;
3130         vd.addrRegs = regTable.addrRegs;
3131 
3132         pMap = dvmGenerateRegisterMapV(&vd);
3133         if (pMap != NULL) {
3134             /*
3135              * Tuck it into the Method struct.  It will either get used
3136              * directly or, if we're in dexopt, will be packed up and
3137              * appended to the DEX file.
3138              */
3139             dvmSetRegisterMap((Method*)meth, pMap);
3140         }
3141     }
3142 
3143     /*
3144      * Success.
3145      */
3146     result = true;
3147 
3148 bail:
3149     free(regTable.addrRegs);
3150     free(regTable.regAlloc);
3151     return result;
3152 }
3153 
3154 /*
3155  * Grind through the instructions.
3156  *
3157  * The basic strategy is as outlined in v3 4.11.1.2: set the "changed" bit
3158  * on the first instruction, process it (setting additional "changed" bits),
3159  * and repeat until there are no more.
3160  *
3161  * v3 4.11.1.1
3162  * - (N/A) operand stack is always the same size
3163  * - operand stack [registers] contain the correct types of values
3164  * - local variables [registers] contain the correct types of values
3165  * - methods are invoked with the appropriate arguments
3166  * - fields are assigned using values of appropriate types
3167  * - opcodes have the correct type values in operand registers
3168  * - there is never an uninitialized class instance in a local variable in
3169  *   code protected by an exception handler (operand stack is okay, because
3170  *   the operand stack is discarded when an exception is thrown) [can't
3171  *   know what's a local var w/o the debug info -- should fall out of
3172  *   register typing]
3173  *
3174  * v3 4.11.1.2
3175  * - execution cannot fall off the end of the code
3176  *
3177  * (We also do many of the items described in the "static checks" sections,
3178  * because it's easier to do them here.)
3179  *
3180  * We need an array of RegType values, one per register, for every
3181  * instruction.  In theory this could become quite large -- up to several
3182  * megabytes for a monster function.  For self-preservation we reject
3183  * anything that requires more than a certain amount of memory.  (Typical
3184  * "large" should be on the order of 4K code units * 8 registers.)  This
3185  * will likely have to be adjusted.
3186  *
3187  *
3188  * The spec forbids backward branches when there's an uninitialized reference
3189  * in a register.  The idea is to prevent something like this:
3190  *   loop:
3191  *     move r1, r0
3192  *     new-instance r0, MyClass
3193  *     ...
3194  *     if-eq rN, loop  // once
3195  *   initialize r0
3196  *
3197  * This leaves us with two different instances, both allocated by the
3198  * same instruction, but only one is initialized.  The scheme outlined in
3199  * v3 4.11.1.4 wouldn't catch this, so they work around it by preventing
3200  * backward branches.  We achieve identical results without restricting
3201  * code reordering by specifying that you can't execute the new-instance
3202  * instruction if a register contains an uninitialized instance created
3203  * by that same instrutcion.
3204  */
doCodeVerification(Method * meth,InsnFlags * insnFlags,RegisterTable * regTable,UninitInstanceMap * uninitMap)3205 static bool doCodeVerification(Method* meth, InsnFlags* insnFlags,
3206     RegisterTable* regTable, UninitInstanceMap* uninitMap)
3207 {
3208     const int insnsSize = dvmGetMethodInsnsSize(meth);
3209     const u2* insns = meth->insns;
3210     RegType workRegs[meth->registersSize + kExtraRegs];
3211     bool result = false;
3212     bool debugVerbose = false;
3213     int insnIdx, startGuess, prevAddr;
3214 
3215     /*
3216      * Begin by marking the first instruction as "changed".
3217      */
3218     dvmInsnSetChanged(insnFlags, 0, true);
3219 
3220     if (doVerboseLogging(meth)) {
3221         IF_LOGI() {
3222             char* desc = dexProtoCopyMethodDescriptor(&meth->prototype);
3223             LOGI("Now verifying: %s.%s %s (ins=%d regs=%d)\n",
3224                 meth->clazz->descriptor, meth->name, desc,
3225                 meth->insSize, meth->registersSize);
3226             LOGI(" ------ [0    4    8    12   16   20   24   28   32   36\n");
3227             free(desc);
3228         }
3229         debugVerbose = true;
3230         gDebugVerbose = true;
3231     } else {
3232         gDebugVerbose = false;
3233     }
3234 
3235     startGuess = 0;
3236 
3237     /*
3238      * Continue until no instructions are marked "changed".
3239      */
3240     while (true) {
3241         /*
3242          * Find the first marked one.  Use "startGuess" as a way to find
3243          * one quickly.
3244          */
3245         for (insnIdx = startGuess; insnIdx < insnsSize; insnIdx++) {
3246             if (dvmInsnIsChanged(insnFlags, insnIdx))
3247                 break;
3248         }
3249 
3250         if (insnIdx == insnsSize) {
3251             if (startGuess != 0) {
3252                 /* try again, starting from the top */
3253                 startGuess = 0;
3254                 continue;
3255             } else {
3256                 /* all flags are clear */
3257                 break;
3258             }
3259         }
3260 
3261         /*
3262          * We carry the working set of registers from instruction to
3263          * instruction.  If this address can be the target of a branch
3264          * (or throw) instruction, or if we're skipping around chasing
3265          * "changed" flags, we need to load the set of registers from
3266          * the table.
3267          *
3268          * Because we always prefer to continue on to the next instruction,
3269          * we should never have a situation where we have a stray
3270          * "changed" flag set on an instruction that isn't a branch target.
3271          */
3272         if (dvmInsnIsBranchTarget(insnFlags, insnIdx)) {
3273             RegType* insnRegs = getRegisterLine(regTable, insnIdx);
3274             assert(insnRegs != NULL);
3275             copyRegisters(workRegs, insnRegs, meth->registersSize + kExtraRegs);
3276 
3277             if (debugVerbose) {
3278                 dumpRegTypes(meth, insnFlags, workRegs, insnIdx, NULL,uninitMap,
3279                     SHOW_REG_DETAILS);
3280             }
3281 
3282         } else {
3283             if (debugVerbose) {
3284                 dumpRegTypes(meth, insnFlags, workRegs, insnIdx, NULL,uninitMap,
3285                     SHOW_REG_DETAILS);
3286             }
3287 
3288 #ifndef NDEBUG
3289             /*
3290              * Sanity check: retrieve the stored register line (assuming
3291              * a full table) and make sure it actually matches.
3292              */
3293             RegType* insnRegs = getRegisterLine(regTable, insnIdx);
3294             if (insnRegs != NULL &&
3295                 compareRegisters(workRegs, insnRegs,
3296                     meth->registersSize + kExtraRegs) != 0)
3297             {
3298                 char* desc = dexProtoCopyMethodDescriptor(&meth->prototype);
3299                 LOG_VFY("HUH? workRegs diverged in %s.%s %s\n",
3300                         meth->clazz->descriptor, meth->name, desc);
3301                 free(desc);
3302                 dumpRegTypes(meth, insnFlags, workRegs, 0, "work",
3303                     uninitMap, DRT_SHOW_REF_TYPES | DRT_SHOW_LOCALS);
3304                 dumpRegTypes(meth, insnFlags, insnRegs, 0, "insn",
3305                     uninitMap, DRT_SHOW_REF_TYPES | DRT_SHOW_LOCALS);
3306             }
3307 #endif
3308         }
3309 
3310         //LOGI("process %s.%s %s %d\n",
3311         //    meth->clazz->descriptor, meth->name, meth->descriptor, insnIdx);
3312         if (!verifyInstruction(meth, insnFlags, regTable, workRegs, insnIdx,
3313                 uninitMap, &startGuess))
3314         {
3315             //LOGD("+++ %s bailing at %d\n", meth->name, insnIdx);
3316             goto bail;
3317         }
3318 
3319 #if 0
3320         {
3321             static const int gcMask = kInstrCanBranch | kInstrCanSwitch |
3322                                       kInstrCanThrow | kInstrCanReturn;
3323             OpCode opCode = *(meth->insns + insnIdx) & 0xff;
3324             int flags = dexGetInstrFlags(gDvm.instrFlags, opCode);
3325 
3326             /* 8, 16, 32, or 32*n -bit regs */
3327             int regWidth = (meth->registersSize + 7) / 8;
3328             if (regWidth == 3)
3329                 regWidth = 4;
3330             if (regWidth > 4) {
3331                 regWidth = ((regWidth + 3) / 4) * 4;
3332                 if (false) {
3333                     LOGW("WOW: %d regs -> %d  %s.%s\n",
3334                         meth->registersSize, regWidth,
3335                         meth->clazz->descriptor, meth->name);
3336                     //x = true;
3337                 }
3338             }
3339 
3340             if ((flags & gcMask) != 0) {
3341                 /* this is a potential GC point */
3342                 gDvm__gcInstr++;
3343 
3344                 if (insnsSize < 256)
3345                     gDvm__gcData += 1;
3346                 else
3347                     gDvm__gcData += 2;
3348                 gDvm__gcData += regWidth;
3349             }
3350             gDvm__gcSimpleData += regWidth;
3351 
3352             gDvm__totalInstr++;
3353         }
3354 #endif
3355 
3356         /*
3357          * Clear "changed" and mark as visited.
3358          */
3359         dvmInsnSetVisited(insnFlags, insnIdx, true);
3360         dvmInsnSetChanged(insnFlags, insnIdx, false);
3361     }
3362 
3363     if (DEAD_CODE_SCAN && !IS_METHOD_FLAG_SET(meth, METHOD_ISWRITABLE)) {
3364         /*
3365          * Scan for dead code.  There's nothing "evil" about dead code
3366          * (besides the wasted space), but it indicates a flaw somewhere
3367          * down the line, possibly in the verifier.
3368          *
3369          * If we've rewritten "always throw" instructions into the stream,
3370          * we are almost certainly going to have some dead code.
3371          */
3372         int deadStart = -1;
3373         for (insnIdx = 0; insnIdx < insnsSize;
3374             insnIdx += dvmInsnGetWidth(insnFlags, insnIdx))
3375         {
3376             /*
3377              * Switch-statement data doesn't get "visited" by scanner.  It
3378              * may or may not be preceded by a padding NOP.
3379              */
3380             int instr = meth->insns[insnIdx];
3381             if (instr == kPackedSwitchSignature ||
3382                 instr == kSparseSwitchSignature ||
3383                 instr == kArrayDataSignature ||
3384                 (instr == OP_NOP &&
3385                  (meth->insns[insnIdx+1] == kPackedSwitchSignature ||
3386                   meth->insns[insnIdx+1] == kSparseSwitchSignature ||
3387                   meth->insns[insnIdx+1] == kArrayDataSignature)))
3388             {
3389                 dvmInsnSetVisited(insnFlags, insnIdx, true);
3390             }
3391 
3392             if (!dvmInsnIsVisited(insnFlags, insnIdx)) {
3393                 if (deadStart < 0)
3394                     deadStart = insnIdx;
3395             } else if (deadStart >= 0) {
3396                 IF_LOGD() {
3397                     char* desc =
3398                         dexProtoCopyMethodDescriptor(&meth->prototype);
3399                     LOGD("VFY: dead code 0x%04x-%04x in %s.%s %s\n",
3400                         deadStart, insnIdx-1,
3401                         meth->clazz->descriptor, meth->name, desc);
3402                     free(desc);
3403                 }
3404 
3405                 deadStart = -1;
3406             }
3407         }
3408         if (deadStart >= 0) {
3409             IF_LOGD() {
3410                 char* desc = dexProtoCopyMethodDescriptor(&meth->prototype);
3411                 LOGD("VFY: dead code 0x%04x-%04x in %s.%s %s\n",
3412                     deadStart, insnIdx-1,
3413                     meth->clazz->descriptor, meth->name, desc);
3414                 free(desc);
3415             }
3416         }
3417     }
3418 
3419     result = true;
3420 
3421 bail:
3422     return result;
3423 }
3424 
3425 
3426 /*
3427  * Perform verification for a single instruction.
3428  *
3429  * This requires fully decoding the instruction to determine the effect
3430  * it has on registers.
3431  *
3432  * Finds zero or more following instructions and sets the "changed" flag
3433  * if execution at that point needs to be (re-)evaluated.  Register changes
3434  * are merged into "regTypes" at the target addresses.  Does not set or
3435  * clear any other flags in "insnFlags".
3436  *
3437  * This may alter meth->insns if we need to replace an instruction with
3438  * throw-verification-error.
3439  */
verifyInstruction(Method * meth,InsnFlags * insnFlags,RegisterTable * regTable,RegType * workRegs,int insnIdx,UninitInstanceMap * uninitMap,int * pStartGuess)3440 static bool verifyInstruction(Method* meth, InsnFlags* insnFlags,
3441     RegisterTable* regTable, RegType* workRegs, int insnIdx,
3442     UninitInstanceMap* uninitMap, int* pStartGuess)
3443 {
3444     const int insnsSize = dvmGetMethodInsnsSize(meth);
3445     const u2* insns = meth->insns + insnIdx;
3446     bool result = false;
3447 
3448     /*
3449      * Once we finish decoding the instruction, we need to figure out where
3450      * we can go from here.  There are three possible ways to transfer
3451      * control to another statement:
3452      *
3453      * (1) Continue to the next instruction.  Applies to all but
3454      *     unconditional branches, method returns, and exception throws.
3455      * (2) Branch to one or more possible locations.  Applies to branches
3456      *     and switch statements.
3457      * (3) Exception handlers.  Applies to any instruction that can
3458      *     throw an exception that is handled by an encompassing "try"
3459      *     block.  (We simplify this to be any instruction that can
3460      *     throw any exception.)
3461      *
3462      * We can also return, in which case there is no successor instruction
3463      * from this point.
3464      *
3465      * The behavior can be determined from the InstrFlags.
3466      */
3467 
3468     const DexFile* pDexFile = meth->clazz->pDvmDex->pDexFile;
3469     RegType entryRegs[meth->registersSize + kExtraRegs];
3470     ClassObject* resClass;
3471     const char* className;
3472     int branchTarget = 0;
3473     const int insnRegCount = meth->registersSize;
3474     RegType tmpType;
3475     DecodedInstruction decInsn;
3476     bool justSetResult = false;
3477     VerifyError failure = VERIFY_ERROR_NONE;
3478 
3479 #ifndef NDEBUG
3480     memset(&decInsn, 0x81, sizeof(decInsn));
3481 #endif
3482     dexDecodeInstruction(gDvm.instrFormat, insns, &decInsn);
3483 
3484     int nextFlags = dexGetInstrFlags(gDvm.instrFlags, decInsn.opCode);
3485 
3486     /*
3487      * Make a copy of the previous register state.  If the instruction
3488      * throws an exception, we merge *this* into the destination rather
3489      * than workRegs, because we don't want the result from the "successful"
3490      * code path (e.g. a check-cast that "improves" a type) to be visible
3491      * to the exception handler.
3492      */
3493     if ((nextFlags & kInstrCanThrow) != 0 && dvmInsnIsInTry(insnFlags, insnIdx))
3494     {
3495         copyRegisters(entryRegs, workRegs, meth->registersSize + kExtraRegs);
3496     } else {
3497 #ifndef NDEBUG
3498         memset(entryRegs, 0xdd,
3499             (meth->registersSize + kExtraRegs) * sizeof(RegType));
3500 #endif
3501     }
3502 
3503     switch (decInsn.opCode) {
3504     case OP_NOP:
3505         /*
3506          * A "pure" NOP has no effect on anything.  Data tables start with
3507          * a signature that looks like a NOP; if we see one of these in
3508          * the course of executing code then we have a problem.
3509          */
3510         if (decInsn.vA != 0) {
3511             LOG_VFY("VFY: encountered data table in instruction stream\n");
3512             failure = VERIFY_ERROR_GENERIC;
3513         }
3514         break;
3515 
3516     case OP_MOVE:
3517     case OP_MOVE_FROM16:
3518     case OP_MOVE_16:
3519         copyRegister1(workRegs, insnRegCount, decInsn.vA, decInsn.vB,
3520             kTypeCategory1nr, &failure);
3521         break;
3522     case OP_MOVE_WIDE:
3523     case OP_MOVE_WIDE_FROM16:
3524     case OP_MOVE_WIDE_16:
3525         copyRegister2(workRegs, insnRegCount, decInsn.vA, decInsn.vB, &failure);
3526         break;
3527     case OP_MOVE_OBJECT:
3528     case OP_MOVE_OBJECT_FROM16:
3529     case OP_MOVE_OBJECT_16:
3530         copyRegister1(workRegs, insnRegCount, decInsn.vA, decInsn.vB,
3531             kTypeCategoryRef, &failure);
3532         break;
3533 
3534     /*
3535      * The move-result instructions copy data out of a "pseudo-register"
3536      * with the results from the last method invocation.  In practice we
3537      * might want to hold the result in an actual CPU register, so the
3538      * Dalvik spec requires that these only appear immediately after an
3539      * invoke or filled-new-array.
3540      *
3541      * These calls invalidate the "result" register.  (This is now
3542      * redundant with the reset done below, but it can make the debug info
3543      * easier to read in some cases.)
3544      */
3545     case OP_MOVE_RESULT:
3546         copyResultRegister1(workRegs, insnRegCount, decInsn.vA,
3547             kTypeCategory1nr, &failure);
3548         break;
3549     case OP_MOVE_RESULT_WIDE:
3550         copyResultRegister2(workRegs, insnRegCount, decInsn.vA, &failure);
3551         break;
3552     case OP_MOVE_RESULT_OBJECT:
3553         copyResultRegister1(workRegs, insnRegCount, decInsn.vA,
3554             kTypeCategoryRef, &failure);
3555         break;
3556 
3557     case OP_MOVE_EXCEPTION:
3558         /*
3559          * This statement can only appear as the first instruction in an
3560          * exception handler (though not all exception handlers need to
3561          * have one of these).  We verify that as part of extracting the
3562          * exception type from the catch block list.
3563          *
3564          * "resClass" will hold the closest common superclass of all
3565          * exceptions that can be handled here.
3566          */
3567         resClass = getCaughtExceptionType(meth, insnIdx, &failure);
3568         if (resClass == NULL) {
3569             assert(!VERIFY_OK(failure));
3570         } else {
3571             setRegisterType(workRegs, insnRegCount, decInsn.vA,
3572                 regTypeFromClass(resClass), &failure);
3573         }
3574         break;
3575 
3576     case OP_RETURN_VOID:
3577         if (!checkConstructorReturn(meth, workRegs, insnRegCount)) {
3578             failure = VERIFY_ERROR_GENERIC;
3579         } else if (getMethodReturnType(meth) != kRegTypeUnknown) {
3580             LOG_VFY("VFY: return-void not expected\n");
3581             failure = VERIFY_ERROR_GENERIC;
3582         }
3583         break;
3584     case OP_RETURN:
3585         if (!checkConstructorReturn(meth, workRegs, insnRegCount)) {
3586             failure = VERIFY_ERROR_GENERIC;
3587         } else {
3588             /* check the method signature */
3589             RegType returnType = getMethodReturnType(meth);
3590             checkTypeCategory(returnType, kTypeCategory1nr, &failure);
3591             if (!VERIFY_OK(failure))
3592                 LOG_VFY("VFY: return-32 not expected\n");
3593 
3594             /* check the register contents */
3595             returnType = getRegisterType(workRegs, insnRegCount, decInsn.vA,
3596                 &failure);
3597             checkTypeCategory(returnType, kTypeCategory1nr, &failure);
3598             if (!VERIFY_OK(failure))
3599                 LOG_VFY("VFY: return-32 on invalid register v%d\n", decInsn.vA);
3600         }
3601         break;
3602     case OP_RETURN_WIDE:
3603         if (!checkConstructorReturn(meth, workRegs, insnRegCount)) {
3604             failure = VERIFY_ERROR_GENERIC;
3605         } else {
3606             RegType returnType, returnTypeHi;
3607 
3608             /* check the method signature */
3609             returnType = getMethodReturnType(meth);
3610             checkTypeCategory(returnType, kTypeCategory2, &failure);
3611             if (!VERIFY_OK(failure))
3612                 LOG_VFY("VFY: return-wide not expected\n");
3613 
3614             /* check the register contents */
3615             returnType = getRegisterType(workRegs, insnRegCount, decInsn.vA,
3616                 &failure);
3617             returnTypeHi = getRegisterType(workRegs, insnRegCount,
3618                 decInsn.vA +1, &failure);
3619             if (VERIFY_OK(failure)) {
3620                 checkTypeCategory(returnType, kTypeCategory2, &failure);
3621                 checkWidePair(returnType, returnTypeHi, &failure);
3622             }
3623             if (!VERIFY_OK(failure)) {
3624                 LOG_VFY("VFY: return-wide on invalid register pair v%d\n",
3625                     decInsn.vA);
3626             }
3627         }
3628         break;
3629     case OP_RETURN_OBJECT:
3630         if (!checkConstructorReturn(meth, workRegs, insnRegCount)) {
3631             failure = VERIFY_ERROR_GENERIC;
3632         } else {
3633             RegType returnType = getMethodReturnType(meth);
3634             checkTypeCategory(returnType, kTypeCategoryRef, &failure);
3635             if (!VERIFY_OK(failure)) {
3636                 LOG_VFY("VFY: return-object not expected\n");
3637                 break;
3638             }
3639 
3640             /* returnType is the *expected* return type, not register value */
3641             assert(returnType != kRegTypeZero);
3642             assert(!regTypeIsUninitReference(returnType));
3643 
3644             /*
3645              * Verify that the reference in vAA is an instance of the type
3646              * in "returnType".  The Zero type is allowed here.  If the
3647              * method is declared to return an interface, then any
3648              * initialized reference is acceptable.
3649              *
3650              * Note getClassFromRegister fails if the register holds an
3651              * uninitialized reference, so we do not allow them to be
3652              * returned.
3653              */
3654             ClassObject* declClass;
3655 
3656             declClass = regTypeInitializedReferenceToClass(returnType);
3657             resClass = getClassFromRegister(workRegs, insnRegCount,
3658                             decInsn.vA, &failure);
3659             if (!VERIFY_OK(failure))
3660                 break;
3661             if (resClass != NULL) {
3662                 if (!dvmIsInterfaceClass(declClass) &&
3663                     !dvmInstanceof(resClass, declClass))
3664                 {
3665                     LOG_VFY("VFY: returning %s (cl=%p), declared %s (cl=%p)\n",
3666                             resClass->descriptor, resClass->classLoader,
3667                             declClass->descriptor, declClass->classLoader);
3668                     failure = VERIFY_ERROR_GENERIC;
3669                     break;
3670                 }
3671             }
3672         }
3673         break;
3674 
3675     case OP_CONST_4:
3676     case OP_CONST_16:
3677     case OP_CONST:
3678         /* could be boolean, int, float, or a null reference */
3679         setRegisterType(workRegs, insnRegCount, decInsn.vA,
3680             dvmDetermineCat1Const((s4)decInsn.vB), &failure);
3681         break;
3682     case OP_CONST_HIGH16:
3683         /* could be boolean, int, float, or a null reference */
3684         setRegisterType(workRegs, insnRegCount, decInsn.vA,
3685             dvmDetermineCat1Const((s4) decInsn.vB << 16), &failure);
3686         break;
3687     case OP_CONST_WIDE_16:
3688     case OP_CONST_WIDE_32:
3689     case OP_CONST_WIDE:
3690     case OP_CONST_WIDE_HIGH16:
3691         /* could be long or double; default to long and allow conversion */
3692         setRegisterType(workRegs, insnRegCount, decInsn.vA,
3693             kRegTypeLongLo, &failure);
3694         break;
3695     case OP_CONST_STRING:
3696     case OP_CONST_STRING_JUMBO:
3697         assert(gDvm.classJavaLangString != NULL);
3698         setRegisterType(workRegs, insnRegCount, decInsn.vA,
3699             regTypeFromClass(gDvm.classJavaLangString), &failure);
3700         break;
3701     case OP_CONST_CLASS:
3702         assert(gDvm.classJavaLangClass != NULL);
3703         /* make sure we can resolve the class; access check is important */
3704         resClass = dvmOptResolveClass(meth->clazz, decInsn.vB, &failure);
3705         if (resClass == NULL) {
3706             const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vB);
3707             dvmLogUnableToResolveClass(badClassDesc, meth);
3708             LOG_VFY("VFY: unable to resolve const-class %d (%s) in %s\n",
3709                 decInsn.vB, badClassDesc, meth->clazz->descriptor);
3710             assert(failure != VERIFY_ERROR_GENERIC);
3711         } else {
3712             setRegisterType(workRegs, insnRegCount, decInsn.vA,
3713                 regTypeFromClass(gDvm.classJavaLangClass), &failure);
3714         }
3715         break;
3716 
3717     case OP_MONITOR_ENTER:
3718     case OP_MONITOR_EXIT:
3719         tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &failure);
3720         if (VERIFY_OK(failure)) {
3721             if (!regTypeIsReference(tmpType)) {
3722                 LOG_VFY("VFY: monitor op on non-object\n");
3723                 failure = VERIFY_ERROR_GENERIC;
3724             }
3725         }
3726         break;
3727 
3728     case OP_CHECK_CAST:
3729         /*
3730          * If this instruction succeeds, we will promote register vA to
3731          * the type in vB.  (This could be a demotion -- not expected, so
3732          * we don't try to address it.)
3733          *
3734          * If it fails, an exception is thrown, which we deal with later
3735          * by ignoring the update to decInsn.vA when branching to a handler.
3736          */
3737         resClass = dvmOptResolveClass(meth->clazz, decInsn.vB, &failure);
3738         if (resClass == NULL) {
3739             const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vB);
3740             dvmLogUnableToResolveClass(badClassDesc, meth);
3741             LOG_VFY("VFY: unable to resolve check-cast %d (%s) in %s\n",
3742                 decInsn.vB, badClassDesc, meth->clazz->descriptor);
3743             assert(failure != VERIFY_ERROR_GENERIC);
3744         } else {
3745             RegType origType;
3746 
3747             origType = getRegisterType(workRegs, insnRegCount, decInsn.vA,
3748                         &failure);
3749             if (!VERIFY_OK(failure))
3750                 break;
3751             if (!regTypeIsReference(origType)) {
3752                 LOG_VFY("VFY: check-cast on non-reference in v%u\n",decInsn.vA);
3753                 failure = VERIFY_ERROR_GENERIC;
3754                 break;
3755             }
3756             setRegisterType(workRegs, insnRegCount, decInsn.vA,
3757                 regTypeFromClass(resClass), &failure);
3758         }
3759         break;
3760     case OP_INSTANCE_OF:
3761         /* make sure we're checking a reference type */
3762         tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vB, &failure);
3763         if (!VERIFY_OK(failure))
3764             break;
3765         if (!regTypeIsReference(tmpType)) {
3766             LOG_VFY("VFY: vB not a reference (%d)\n", tmpType);
3767             failure = VERIFY_ERROR_GENERIC;
3768             break;
3769         }
3770 
3771         /* make sure we can resolve the class; access check is important */
3772         resClass = dvmOptResolveClass(meth->clazz, decInsn.vC, &failure);
3773         if (resClass == NULL) {
3774             const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vC);
3775             dvmLogUnableToResolveClass(badClassDesc, meth);
3776             LOG_VFY("VFY: unable to resolve instanceof %d (%s) in %s\n",
3777                 decInsn.vC, badClassDesc, meth->clazz->descriptor);
3778             assert(failure != VERIFY_ERROR_GENERIC);
3779         } else {
3780             /* result is boolean */
3781             setRegisterType(workRegs, insnRegCount, decInsn.vA,
3782                 kRegTypeBoolean, &failure);
3783         }
3784         break;
3785 
3786     case OP_ARRAY_LENGTH:
3787         resClass = getClassFromRegister(workRegs, insnRegCount,
3788                         decInsn.vB, &failure);
3789         if (!VERIFY_OK(failure))
3790             break;
3791         if (resClass != NULL && !dvmIsArrayClass(resClass)) {
3792             LOG_VFY("VFY: array-length on non-array\n");
3793             failure = VERIFY_ERROR_GENERIC;
3794             break;
3795         }
3796         setRegisterType(workRegs, insnRegCount, decInsn.vA, kRegTypeInteger,
3797             &failure);
3798         break;
3799 
3800     case OP_NEW_INSTANCE:
3801         resClass = dvmOptResolveClass(meth->clazz, decInsn.vB, &failure);
3802         if (resClass == NULL) {
3803             const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vB);
3804             dvmLogUnableToResolveClass(badClassDesc, meth);
3805             LOG_VFY("VFY: unable to resolve new-instance %d (%s) in %s\n",
3806                 decInsn.vB, badClassDesc, meth->clazz->descriptor);
3807             assert(failure != VERIFY_ERROR_GENERIC);
3808         } else {
3809             RegType uninitType;
3810 
3811             /* can't create an instance of an interface or abstract class */
3812             if (dvmIsAbstractClass(resClass) || dvmIsInterfaceClass(resClass)) {
3813                 LOG_VFY("VFY: new-instance on interface or abstract class %s\n",
3814                     resClass->descriptor);
3815                 failure = VERIFY_ERROR_INSTANTIATION;
3816                 break;
3817             }
3818 
3819             /* add resolved class to uninit map if not already there */
3820             int uidx = dvmSetUninitInstance(uninitMap, insnIdx, resClass);
3821             assert(uidx >= 0);
3822             uninitType = regTypeFromUninitIndex(uidx);
3823 
3824             /*
3825              * Any registers holding previous allocations from this address
3826              * that have not yet been initialized must be marked invalid.
3827              */
3828             markUninitRefsAsInvalid(workRegs, insnRegCount, uninitMap,
3829                 uninitType);
3830 
3831             /* add the new uninitialized reference to the register ste */
3832             setRegisterType(workRegs, insnRegCount, decInsn.vA,
3833                 uninitType, &failure);
3834         }
3835         break;
3836     case OP_NEW_ARRAY:
3837         resClass = dvmOptResolveClass(meth->clazz, decInsn.vC, &failure);
3838         if (resClass == NULL) {
3839             const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vC);
3840             dvmLogUnableToResolveClass(badClassDesc, meth);
3841             LOG_VFY("VFY: unable to resolve new-array %d (%s) in %s\n",
3842                 decInsn.vC, badClassDesc, meth->clazz->descriptor);
3843             assert(failure != VERIFY_ERROR_GENERIC);
3844         } else if (!dvmIsArrayClass(resClass)) {
3845             LOG_VFY("VFY: new-array on non-array class\n");
3846             failure = VERIFY_ERROR_GENERIC;
3847         } else {
3848             /* make sure "size" register is valid type */
3849             verifyRegisterType(workRegs, insnRegCount, decInsn.vB,
3850                 kRegTypeInteger, &failure);
3851             /* set register type to array class */
3852             setRegisterType(workRegs, insnRegCount, decInsn.vA,
3853                 regTypeFromClass(resClass), &failure);
3854         }
3855         break;
3856     case OP_FILLED_NEW_ARRAY:
3857     case OP_FILLED_NEW_ARRAY_RANGE:
3858         resClass = dvmOptResolveClass(meth->clazz, decInsn.vB, &failure);
3859         if (resClass == NULL) {
3860             const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vB);
3861             dvmLogUnableToResolveClass(badClassDesc, meth);
3862             LOG_VFY("VFY: unable to resolve filled-array %d (%s) in %s\n",
3863                 decInsn.vB, badClassDesc, meth->clazz->descriptor);
3864             assert(failure != VERIFY_ERROR_GENERIC);
3865         } else if (!dvmIsArrayClass(resClass)) {
3866             LOG_VFY("VFY: filled-new-array on non-array class\n");
3867             failure = VERIFY_ERROR_GENERIC;
3868         } else {
3869             bool isRange = (decInsn.opCode == OP_FILLED_NEW_ARRAY_RANGE);
3870 
3871             /* check the arguments to the instruction */
3872             verifyFilledNewArrayRegs(meth, workRegs, insnRegCount, &decInsn,
3873                 resClass, isRange, &failure);
3874             /* filled-array result goes into "result" register */
3875             setResultRegisterType(workRegs, insnRegCount,
3876                 regTypeFromClass(resClass), &failure);
3877             justSetResult = true;
3878         }
3879         break;
3880 
3881     case OP_CMPL_FLOAT:
3882     case OP_CMPG_FLOAT:
3883         verifyRegisterType(workRegs, insnRegCount, decInsn.vB, kRegTypeFloat,
3884             &failure);
3885         verifyRegisterType(workRegs, insnRegCount, decInsn.vC, kRegTypeFloat,
3886             &failure);
3887         setRegisterType(workRegs, insnRegCount, decInsn.vA, kRegTypeBoolean,
3888             &failure);
3889         break;
3890     case OP_CMPL_DOUBLE:
3891     case OP_CMPG_DOUBLE:
3892         verifyRegisterType(workRegs, insnRegCount, decInsn.vB, kRegTypeDoubleLo,
3893             &failure);
3894         verifyRegisterType(workRegs, insnRegCount, decInsn.vC, kRegTypeDoubleLo,
3895             &failure);
3896         setRegisterType(workRegs, insnRegCount, decInsn.vA, kRegTypeBoolean,
3897             &failure);
3898         break;
3899     case OP_CMP_LONG:
3900         verifyRegisterType(workRegs, insnRegCount, decInsn.vB, kRegTypeLongLo,
3901             &failure);
3902         verifyRegisterType(workRegs, insnRegCount, decInsn.vC, kRegTypeLongLo,
3903             &failure);
3904         setRegisterType(workRegs, insnRegCount, decInsn.vA, kRegTypeBoolean,
3905             &failure);
3906         break;
3907 
3908     case OP_THROW:
3909         resClass = getClassFromRegister(workRegs, insnRegCount,
3910                         decInsn.vA, &failure);
3911         if (VERIFY_OK(failure) && resClass != NULL) {
3912             if (!dvmInstanceof(resClass, gDvm.classJavaLangThrowable)) {
3913                 LOG_VFY("VFY: thrown class %s not instanceof Throwable\n",
3914                         resClass->descriptor);
3915                 failure = VERIFY_ERROR_GENERIC;
3916             }
3917         }
3918         break;
3919 
3920     case OP_GOTO:
3921     case OP_GOTO_16:
3922     case OP_GOTO_32:
3923         /* no effect on or use of registers */
3924         break;
3925 
3926     case OP_PACKED_SWITCH:
3927     case OP_SPARSE_SWITCH:
3928         /* verify that vAA is an integer, or can be converted to one */
3929         verifyRegisterType(workRegs, insnRegCount, decInsn.vA,
3930             kRegTypeInteger, &failure);
3931         break;
3932 
3933     case OP_FILL_ARRAY_DATA:
3934         {
3935             RegType valueType;
3936             const u2 *arrayData;
3937             u2 elemWidth;
3938 
3939             /* Similar to the verification done for APUT */
3940             resClass = getClassFromRegister(workRegs, insnRegCount,
3941                             decInsn.vA, &failure);
3942             if (!VERIFY_OK(failure))
3943                 break;
3944 
3945             /* resClass can be null if the reg type is Zero */
3946             if (resClass == NULL)
3947                 break;
3948 
3949             if (!dvmIsArrayClass(resClass) || resClass->arrayDim != 1 ||
3950                 resClass->elementClass->primitiveType == PRIM_NOT ||
3951                 resClass->elementClass->primitiveType == PRIM_VOID)
3952             {
3953                 LOG_VFY("VFY: invalid fill-array-data on %s\n",
3954                         resClass->descriptor);
3955                 failure = VERIFY_ERROR_GENERIC;
3956                 break;
3957             }
3958 
3959             valueType = primitiveTypeToRegType(
3960                                     resClass->elementClass->primitiveType);
3961             assert(valueType != kRegTypeUnknown);
3962 
3963             /*
3964              * Now verify if the element width in the table matches the element
3965              * width declared in the array
3966              */
3967             arrayData = insns + (insns[1] | (((s4)insns[2]) << 16));
3968             if (arrayData[0] != kArrayDataSignature) {
3969                 LOG_VFY("VFY: invalid magic for array-data\n");
3970                 failure = VERIFY_ERROR_GENERIC;
3971                 break;
3972             }
3973 
3974             switch (resClass->elementClass->primitiveType) {
3975                 case PRIM_BOOLEAN:
3976                 case PRIM_BYTE:
3977                      elemWidth = 1;
3978                      break;
3979                 case PRIM_CHAR:
3980                 case PRIM_SHORT:
3981                      elemWidth = 2;
3982                      break;
3983                 case PRIM_FLOAT:
3984                 case PRIM_INT:
3985                      elemWidth = 4;
3986                      break;
3987                 case PRIM_DOUBLE:
3988                 case PRIM_LONG:
3989                      elemWidth = 8;
3990                      break;
3991                 default:
3992                      elemWidth = 0;
3993                      break;
3994             }
3995 
3996             /*
3997              * Since we don't compress the data in Dex, expect to see equal
3998              * width of data stored in the table and expected from the array
3999              * class.
4000              */
4001             if (arrayData[1] != elemWidth) {
4002                 LOG_VFY("VFY: array-data size mismatch (%d vs %d)\n",
4003                         arrayData[1], elemWidth);
4004                 failure = VERIFY_ERROR_GENERIC;
4005             }
4006         }
4007         break;
4008 
4009     case OP_IF_EQ:
4010     case OP_IF_NE:
4011         {
4012             RegType type1, type2;
4013             bool tmpResult;
4014 
4015             type1 = getRegisterType(workRegs, insnRegCount, decInsn.vA,
4016                         &failure);
4017             type2 = getRegisterType(workRegs, insnRegCount, decInsn.vB,
4018                         &failure);
4019             if (!VERIFY_OK(failure))
4020                 break;
4021 
4022             /* both references? */
4023             if (regTypeIsReference(type1) && regTypeIsReference(type2))
4024                 break;
4025 
4026             /* both category-1nr? */
4027             checkTypeCategory(type1, kTypeCategory1nr, &failure);
4028             checkTypeCategory(type2, kTypeCategory1nr, &failure);
4029             if (!VERIFY_OK(failure)) {
4030                 LOG_VFY("VFY: args to if-eq/if-ne must both be refs or cat1\n");
4031                 break;
4032             }
4033         }
4034         break;
4035     case OP_IF_LT:
4036     case OP_IF_GE:
4037     case OP_IF_GT:
4038     case OP_IF_LE:
4039         tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &failure);
4040         if (!VERIFY_OK(failure))
4041             break;
4042         checkTypeCategory(tmpType, kTypeCategory1nr, &failure);
4043         if (!VERIFY_OK(failure)) {
4044             LOG_VFY("VFY: args to 'if' must be cat-1nr\n");
4045             break;
4046         }
4047         tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vB, &failure);
4048         if (!VERIFY_OK(failure))
4049             break;
4050         checkTypeCategory(tmpType, kTypeCategory1nr, &failure);
4051         if (!VERIFY_OK(failure)) {
4052             LOG_VFY("VFY: args to 'if' must be cat-1nr\n");
4053             break;
4054         }
4055         break;
4056     case OP_IF_EQZ:
4057     case OP_IF_NEZ:
4058         tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &failure);
4059         if (!VERIFY_OK(failure))
4060             break;
4061         if (regTypeIsReference(tmpType))
4062             break;
4063         checkTypeCategory(tmpType, kTypeCategory1nr, &failure);
4064         if (!VERIFY_OK(failure))
4065             LOG_VFY("VFY: expected cat-1 arg to if\n");
4066         break;
4067     case OP_IF_LTZ:
4068     case OP_IF_GEZ:
4069     case OP_IF_GTZ:
4070     case OP_IF_LEZ:
4071         tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &failure);
4072         if (!VERIFY_OK(failure))
4073             break;
4074         checkTypeCategory(tmpType, kTypeCategory1nr, &failure);
4075         if (!VERIFY_OK(failure))
4076             LOG_VFY("VFY: expected cat-1 arg to if\n");
4077         break;
4078 
4079     case OP_AGET:
4080         tmpType = kRegTypeInteger;
4081         goto aget_1nr_common;
4082     case OP_AGET_BOOLEAN:
4083         tmpType = kRegTypeBoolean;
4084         goto aget_1nr_common;
4085     case OP_AGET_BYTE:
4086         tmpType = kRegTypeByte;
4087         goto aget_1nr_common;
4088     case OP_AGET_CHAR:
4089         tmpType = kRegTypeChar;
4090         goto aget_1nr_common;
4091     case OP_AGET_SHORT:
4092         tmpType = kRegTypeShort;
4093         goto aget_1nr_common;
4094 aget_1nr_common:
4095         {
4096             RegType srcType, indexType;
4097 
4098             indexType = getRegisterType(workRegs, insnRegCount, decInsn.vC,
4099                             &failure);
4100             checkArrayIndexType(meth, indexType, &failure);
4101             if (!VERIFY_OK(failure))
4102                 break;
4103 
4104             resClass = getClassFromRegister(workRegs, insnRegCount,
4105                             decInsn.vB, &failure);
4106             if (!VERIFY_OK(failure))
4107                 break;
4108             if (resClass != NULL) {
4109                 /* verify the class */
4110                 if (!dvmIsArrayClass(resClass) || resClass->arrayDim != 1 ||
4111                     resClass->elementClass->primitiveType == PRIM_NOT)
4112                 {
4113                     LOG_VFY("VFY: invalid aget-1nr target %s\n",
4114                         resClass->descriptor);
4115                     failure = VERIFY_ERROR_GENERIC;
4116                     break;
4117                 }
4118 
4119                 /* make sure array type matches instruction */
4120                 srcType = primitiveTypeToRegType(
4121                                         resClass->elementClass->primitiveType);
4122 
4123                 if (!checkFieldArrayStore1nr(tmpType, srcType)) {
4124                     LOG_VFY("VFY: invalid aget-1nr, array type=%d with"
4125                             " inst type=%d (on %s)\n",
4126                         srcType, tmpType, resClass->descriptor);
4127                     failure = VERIFY_ERROR_GENERIC;
4128                     break;
4129                 }
4130 
4131             }
4132             setRegisterType(workRegs, insnRegCount, decInsn.vA,
4133                 tmpType, &failure);
4134         }
4135         break;
4136 
4137     case OP_AGET_WIDE:
4138         {
4139             RegType dstType, indexType;
4140 
4141             indexType = getRegisterType(workRegs, insnRegCount, decInsn.vC,
4142                             &failure);
4143             checkArrayIndexType(meth, indexType, &failure);
4144             if (!VERIFY_OK(failure))
4145                 break;
4146 
4147             resClass = getClassFromRegister(workRegs, insnRegCount,
4148                             decInsn.vB, &failure);
4149             if (!VERIFY_OK(failure))
4150                 break;
4151             if (resClass != NULL) {
4152                 /* verify the class */
4153                 if (!dvmIsArrayClass(resClass) || resClass->arrayDim != 1 ||
4154                     resClass->elementClass->primitiveType == PRIM_NOT)
4155                 {
4156                     LOG_VFY("VFY: invalid aget-wide target %s\n",
4157                         resClass->descriptor);
4158                     failure = VERIFY_ERROR_GENERIC;
4159                     break;
4160                 }
4161 
4162                 /* try to refine "dstType" */
4163                 switch (resClass->elementClass->primitiveType) {
4164                 case PRIM_LONG:
4165                     dstType = kRegTypeLongLo;
4166                     break;
4167                 case PRIM_DOUBLE:
4168                     dstType = kRegTypeDoubleLo;
4169                     break;
4170                 default:
4171                     LOG_VFY("VFY: invalid aget-wide on %s\n",
4172                         resClass->descriptor);
4173                     dstType = kRegTypeUnknown;
4174                     failure = VERIFY_ERROR_GENERIC;
4175                     break;
4176                 }
4177             } else {
4178                 /*
4179                  * Null array ref; this code path will fail at runtime.  We
4180                  * know this is either long or double, and we don't really
4181                  * discriminate between those during verification, so we
4182                  * call it a long.
4183                  */
4184                 dstType = kRegTypeLongLo;
4185             }
4186             setRegisterType(workRegs, insnRegCount, decInsn.vA,
4187                 dstType, &failure);
4188         }
4189         break;
4190 
4191     case OP_AGET_OBJECT:
4192         {
4193             RegType dstType, indexType;
4194 
4195             indexType = getRegisterType(workRegs, insnRegCount, decInsn.vC,
4196                             &failure);
4197             checkArrayIndexType(meth, indexType, &failure);
4198             if (!VERIFY_OK(failure))
4199                 break;
4200 
4201             /* get the class of the array we're pulling an object from */
4202             resClass = getClassFromRegister(workRegs, insnRegCount,
4203                             decInsn.vB, &failure);
4204             if (!VERIFY_OK(failure))
4205                 break;
4206             if (resClass != NULL) {
4207                 ClassObject* elementClass;
4208 
4209                 assert(resClass != NULL);
4210                 if (!dvmIsArrayClass(resClass)) {
4211                     LOG_VFY("VFY: aget-object on non-array class\n");
4212                     failure = VERIFY_ERROR_GENERIC;
4213                     break;
4214                 }
4215                 assert(resClass->elementClass != NULL);
4216 
4217                 /*
4218                  * Find the element class.  resClass->elementClass indicates
4219                  * the basic type, which won't be what we want for a
4220                  * multi-dimensional array.
4221                  */
4222                 if (resClass->descriptor[1] == '[') {
4223                     assert(resClass->arrayDim > 1);
4224                     elementClass = dvmFindArrayClass(&resClass->descriptor[1],
4225                                         resClass->classLoader);
4226                 } else if (resClass->descriptor[1] == 'L') {
4227                     assert(resClass->arrayDim == 1);
4228                     elementClass = resClass->elementClass;
4229                 } else {
4230                     LOG_VFY("VFY: aget-object on non-ref array class (%s)\n",
4231                         resClass->descriptor);
4232                     failure = VERIFY_ERROR_GENERIC;
4233                     break;
4234                 }
4235 
4236                 dstType = regTypeFromClass(elementClass);
4237             } else {
4238                 /*
4239                  * The array reference is NULL, so the current code path will
4240                  * throw an exception.  For proper merging with later code
4241                  * paths, and correct handling of "if-eqz" tests on the
4242                  * result of the array get, we want to treat this as a null
4243                  * reference.
4244                  */
4245                 dstType = kRegTypeZero;
4246             }
4247             setRegisterType(workRegs, insnRegCount, decInsn.vA,
4248                 dstType, &failure);
4249         }
4250         break;
4251     case OP_APUT:
4252         tmpType = kRegTypeInteger;
4253         goto aput_1nr_common;
4254     case OP_APUT_BOOLEAN:
4255         tmpType = kRegTypeBoolean;
4256         goto aput_1nr_common;
4257     case OP_APUT_BYTE:
4258         tmpType = kRegTypeByte;
4259         goto aput_1nr_common;
4260     case OP_APUT_CHAR:
4261         tmpType = kRegTypeChar;
4262         goto aput_1nr_common;
4263     case OP_APUT_SHORT:
4264         tmpType = kRegTypeShort;
4265         goto aput_1nr_common;
4266 aput_1nr_common:
4267         {
4268             RegType srcType, dstType, indexType;
4269 
4270             indexType = getRegisterType(workRegs, insnRegCount, decInsn.vC,
4271                             &failure);
4272             checkArrayIndexType(meth, indexType, &failure);
4273             if (!VERIFY_OK(failure))
4274                 break;
4275 
4276             /* make sure the source register has the correct type */
4277             srcType = getRegisterType(workRegs, insnRegCount, decInsn.vA,
4278                             &failure);
4279             if (!canConvertTo1nr(srcType, tmpType)) {
4280                 LOG_VFY("VFY: invalid reg type %d on aput instr (need %d)\n",
4281                     srcType, tmpType);
4282                 failure = VERIFY_ERROR_GENERIC;
4283                 break;
4284             }
4285 
4286             resClass = getClassFromRegister(workRegs, insnRegCount,
4287                             decInsn.vB, &failure);
4288             if (!VERIFY_OK(failure))
4289                 break;
4290 
4291             /* resClass can be null if the reg type is Zero */
4292             if (resClass == NULL)
4293                 break;
4294 
4295             if (!dvmIsArrayClass(resClass) || resClass->arrayDim != 1 ||
4296                 resClass->elementClass->primitiveType == PRIM_NOT)
4297             {
4298                 LOG_VFY("VFY: invalid aput-1nr on %s\n", resClass->descriptor);
4299                 failure = VERIFY_ERROR_GENERIC;
4300                 break;
4301             }
4302 
4303             /* verify that instruction matches array */
4304             dstType = primitiveTypeToRegType(
4305                                     resClass->elementClass->primitiveType);
4306             assert(dstType != kRegTypeUnknown);
4307 
4308             if (!checkFieldArrayStore1nr(tmpType, dstType)) {
4309                 LOG_VFY("VFY: invalid aput-1nr on %s (inst=%d dst=%d)\n",
4310                         resClass->descriptor, tmpType, dstType);
4311                 failure = VERIFY_ERROR_GENERIC;
4312                 break;
4313             }
4314         }
4315         break;
4316     case OP_APUT_WIDE:
4317         tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vC,
4318                         &failure);
4319         checkArrayIndexType(meth, tmpType, &failure);
4320         if (!VERIFY_OK(failure))
4321             break;
4322 
4323         tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &failure);
4324         if (VERIFY_OK(failure)) {
4325             RegType typeHi =
4326                 getRegisterType(workRegs, insnRegCount, decInsn.vA+1, &failure);
4327             checkTypeCategory(tmpType, kTypeCategory2, &failure);
4328             checkWidePair(tmpType, typeHi, &failure);
4329         }
4330         if (!VERIFY_OK(failure))
4331             break;
4332 
4333         resClass = getClassFromRegister(workRegs, insnRegCount,
4334                         decInsn.vB, &failure);
4335         if (!VERIFY_OK(failure))
4336             break;
4337         if (resClass != NULL) {
4338             /* verify the class and try to refine "dstType" */
4339             if (!dvmIsArrayClass(resClass) || resClass->arrayDim != 1 ||
4340                 resClass->elementClass->primitiveType == PRIM_NOT)
4341             {
4342                 LOG_VFY("VFY: invalid aput-wide on %s\n",
4343                         resClass->descriptor);
4344                 failure = VERIFY_ERROR_GENERIC;
4345                 break;
4346             }
4347 
4348             switch (resClass->elementClass->primitiveType) {
4349             case PRIM_LONG:
4350             case PRIM_DOUBLE:
4351                 /* these are okay */
4352                 break;
4353             default:
4354                 LOG_VFY("VFY: invalid aput-wide on %s\n",
4355                         resClass->descriptor);
4356                 failure = VERIFY_ERROR_GENERIC;
4357                 break;
4358             }
4359         }
4360         break;
4361     case OP_APUT_OBJECT:
4362         tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vC,
4363                         &failure);
4364         checkArrayIndexType(meth, tmpType, &failure);
4365         if (!VERIFY_OK(failure))
4366             break;
4367 
4368         /* get the ref we're storing; Zero is okay, Uninit is not */
4369         resClass = getClassFromRegister(workRegs, insnRegCount,
4370                         decInsn.vA, &failure);
4371         if (!VERIFY_OK(failure))
4372             break;
4373         if (resClass != NULL) {
4374             ClassObject* arrayClass;
4375             ClassObject* elementClass;
4376 
4377             /*
4378              * Get the array class.  If the array ref is null, we won't
4379              * have type information (and we'll crash at runtime with a
4380              * null pointer exception).
4381              */
4382             arrayClass = getClassFromRegister(workRegs, insnRegCount,
4383                             decInsn.vB, &failure);
4384 
4385             if (arrayClass != NULL) {
4386                 /* see if the array holds a compatible type */
4387                 if (!dvmIsArrayClass(arrayClass)) {
4388                     LOG_VFY("VFY: invalid aput-object on %s\n",
4389                             arrayClass->descriptor);
4390                     failure = VERIFY_ERROR_GENERIC;
4391                     break;
4392                 }
4393 
4394                 /*
4395                  * Find the element class.  resClass->elementClass indicates
4396                  * the basic type, which won't be what we want for a
4397                  * multi-dimensional array.
4398                  *
4399                  * All we want to check here is that the element type is a
4400                  * reference class.  We *don't* check instanceof here, because
4401                  * you can still put a String into a String[] after the latter
4402                  * has been cast to an Object[].
4403                  */
4404                 if (arrayClass->descriptor[1] == '[') {
4405                     assert(arrayClass->arrayDim > 1);
4406                     elementClass = dvmFindArrayClass(&arrayClass->descriptor[1],
4407                                         arrayClass->classLoader);
4408                 } else {
4409                     assert(arrayClass->arrayDim == 1);
4410                     elementClass = arrayClass->elementClass;
4411                 }
4412                 if (elementClass->primitiveType != PRIM_NOT) {
4413                     LOG_VFY("VFY: invalid aput-object of %s into %s\n",
4414                             resClass->descriptor, arrayClass->descriptor);
4415                     failure = VERIFY_ERROR_GENERIC;
4416                     break;
4417                 }
4418             }
4419         }
4420         break;
4421 
4422     case OP_IGET:
4423         tmpType = kRegTypeInteger;
4424         goto iget_1nr_common;
4425     case OP_IGET_BOOLEAN:
4426         tmpType = kRegTypeBoolean;
4427         goto iget_1nr_common;
4428     case OP_IGET_BYTE:
4429         tmpType = kRegTypeByte;
4430         goto iget_1nr_common;
4431     case OP_IGET_CHAR:
4432         tmpType = kRegTypeChar;
4433         goto iget_1nr_common;
4434     case OP_IGET_SHORT:
4435         tmpType = kRegTypeShort;
4436         goto iget_1nr_common;
4437 iget_1nr_common:
4438         {
4439             ClassObject* fieldClass;
4440             InstField* instField;
4441             RegType objType, fieldType;
4442 
4443             objType = getRegisterType(workRegs, insnRegCount, decInsn.vB,
4444                         &failure);
4445             if (!VERIFY_OK(failure))
4446                 break;
4447             instField = getInstField(meth, uninitMap, objType, decInsn.vC,
4448                             &failure);
4449             if (!VERIFY_OK(failure))
4450                 break;
4451 
4452             /* make sure the field's type is compatible with expectation */
4453             fieldType = primSigCharToRegType(instField->field.signature[0]);
4454             if (fieldType == kRegTypeUnknown ||
4455                 !checkFieldArrayStore1nr(tmpType, fieldType))
4456             {
4457                 LOG_VFY("VFY: invalid iget-1nr of %s.%s (inst=%d field=%d)\n",
4458                         instField->field.clazz->descriptor,
4459                         instField->field.name, tmpType, fieldType);
4460                 failure = VERIFY_ERROR_GENERIC;
4461                 break;
4462             }
4463 
4464             setRegisterType(workRegs, insnRegCount, decInsn.vA, tmpType,
4465                 &failure);
4466         }
4467         break;
4468     case OP_IGET_WIDE:
4469         {
4470             RegType dstType;
4471             ClassObject* fieldClass;
4472             InstField* instField;
4473             RegType objType;
4474 
4475             objType = getRegisterType(workRegs, insnRegCount, decInsn.vB,
4476                         &failure);
4477             if (!VERIFY_OK(failure))
4478                 break;
4479             instField = getInstField(meth, uninitMap, objType, decInsn.vC,
4480                             &failure);
4481             if (!VERIFY_OK(failure))
4482                 break;
4483             /* check the type, which should be prim */
4484             switch (instField->field.signature[0]) {
4485             case 'D':
4486                 dstType = kRegTypeDoubleLo;
4487                 break;
4488             case 'J':
4489                 dstType = kRegTypeLongLo;
4490                 break;
4491             default:
4492                 LOG_VFY("VFY: invalid iget-wide of %s.%s\n",
4493                         instField->field.clazz->descriptor,
4494                         instField->field.name);
4495                 dstType = kRegTypeUnknown;
4496                 failure = VERIFY_ERROR_GENERIC;
4497                 break;
4498             }
4499             if (VERIFY_OK(failure)) {
4500                 setRegisterType(workRegs, insnRegCount, decInsn.vA,
4501                     dstType, &failure);
4502             }
4503         }
4504         break;
4505     case OP_IGET_OBJECT:
4506         {
4507             ClassObject* fieldClass;
4508             InstField* instField;
4509             RegType objType;
4510 
4511             objType = getRegisterType(workRegs, insnRegCount, decInsn.vB,
4512                         &failure);
4513             if (!VERIFY_OK(failure))
4514                 break;
4515             instField = getInstField(meth, uninitMap, objType, decInsn.vC,
4516                             &failure);
4517             if (!VERIFY_OK(failure))
4518                 break;
4519             fieldClass = getFieldClass(meth, &instField->field);
4520             if (fieldClass == NULL) {
4521                 /* class not found or primitive type */
4522                 LOG_VFY("VFY: unable to recover field class from '%s'\n",
4523                     instField->field.signature);
4524                 failure = VERIFY_ERROR_GENERIC;
4525                 break;
4526             }
4527             if (VERIFY_OK(failure)) {
4528                 assert(!dvmIsPrimitiveClass(fieldClass));
4529                 setRegisterType(workRegs, insnRegCount, decInsn.vA,
4530                     regTypeFromClass(fieldClass), &failure);
4531             }
4532         }
4533         break;
4534     case OP_IPUT:
4535         tmpType = kRegTypeInteger;
4536         goto iput_1nr_common;
4537     case OP_IPUT_BOOLEAN:
4538         tmpType = kRegTypeBoolean;
4539         goto iput_1nr_common;
4540     case OP_IPUT_BYTE:
4541         tmpType = kRegTypeByte;
4542         goto iput_1nr_common;
4543     case OP_IPUT_CHAR:
4544         tmpType = kRegTypeChar;
4545         goto iput_1nr_common;
4546     case OP_IPUT_SHORT:
4547         tmpType = kRegTypeShort;
4548         goto iput_1nr_common;
4549 iput_1nr_common:
4550         {
4551             RegType srcType, fieldType, objType;
4552             ClassObject* fieldClass;
4553             InstField* instField;
4554 
4555             srcType = getRegisterType(workRegs, insnRegCount, decInsn.vA,
4556                         &failure);
4557 
4558             /*
4559              * javac generates synthetic functions that write byte values
4560              * into boolean fields.
4561              */
4562             if (tmpType == kRegTypeBoolean && srcType == kRegTypeByte)
4563                 srcType = kRegTypeBoolean;
4564 
4565             /* make sure the source register has the correct type */
4566             if (!canConvertTo1nr(srcType, tmpType)) {
4567                 LOG_VFY("VFY: invalid reg type %d on iput instr (need %d)\n",
4568                     srcType, tmpType);
4569                 failure = VERIFY_ERROR_GENERIC;
4570                 break;
4571             }
4572 
4573             objType = getRegisterType(workRegs, insnRegCount, decInsn.vB,
4574                         &failure);
4575             if (!VERIFY_OK(failure))
4576                 break;
4577             instField = getInstField(meth, uninitMap, objType, decInsn.vC,
4578                             &failure);
4579             if (!VERIFY_OK(failure))
4580                 break;
4581             checkFinalFieldAccess(meth, &instField->field, &failure);
4582             if (!VERIFY_OK(failure))
4583                 break;
4584 
4585             /* get type of field we're storing into */
4586             fieldType = primSigCharToRegType(instField->field.signature[0]);
4587             if (fieldType == kRegTypeUnknown ||
4588                 !checkFieldArrayStore1nr(tmpType, fieldType))
4589             {
4590                 LOG_VFY("VFY: invalid iput-1nr of %s.%s (inst=%d field=%d)\n",
4591                         instField->field.clazz->descriptor,
4592                         instField->field.name, tmpType, fieldType);
4593                 failure = VERIFY_ERROR_GENERIC;
4594                 break;
4595             }
4596         }
4597         break;
4598     case OP_IPUT_WIDE:
4599         tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &failure);
4600         if (VERIFY_OK(failure)) {
4601             RegType typeHi =
4602                 getRegisterType(workRegs, insnRegCount, decInsn.vA+1, &failure);
4603             checkTypeCategory(tmpType, kTypeCategory2, &failure);
4604             checkWidePair(tmpType, typeHi, &failure);
4605         }
4606         if (VERIFY_OK(failure)) {
4607             ClassObject* fieldClass;
4608             InstField* instField;
4609             RegType objType;
4610 
4611             objType = getRegisterType(workRegs, insnRegCount, decInsn.vB,
4612                         &failure);
4613             if (!VERIFY_OK(failure))
4614                 break;
4615             instField = getInstField(meth, uninitMap, objType, decInsn.vC,
4616                             &failure);
4617             if (!VERIFY_OK(failure))
4618                 break;
4619             checkFinalFieldAccess(meth, &instField->field, &failure);
4620             if (!VERIFY_OK(failure))
4621                 break;
4622 
4623             /* check the type, which should be prim */
4624             switch (instField->field.signature[0]) {
4625             case 'D':
4626             case 'J':
4627                 /* these are okay (and interchangeable) */
4628                 break;
4629             default:
4630                 LOG_VFY("VFY: invalid iput-wide of %s.%s\n",
4631                         instField->field.clazz->descriptor,
4632                         instField->field.name);
4633                 failure = VERIFY_ERROR_GENERIC;
4634                 break;
4635             }
4636         }
4637         break;
4638     case OP_IPUT_OBJECT:
4639         {
4640             ClassObject* fieldClass;
4641             ClassObject* valueClass;
4642             InstField* instField;
4643             RegType objType, valueType;
4644 
4645             objType = getRegisterType(workRegs, insnRegCount, decInsn.vB,
4646                         &failure);
4647             if (!VERIFY_OK(failure))
4648                 break;
4649             instField = getInstField(meth, uninitMap, objType, decInsn.vC,
4650                             &failure);
4651             if (!VERIFY_OK(failure))
4652                 break;
4653             checkFinalFieldAccess(meth, &instField->field, &failure);
4654             if (!VERIFY_OK(failure))
4655                 break;
4656 
4657             fieldClass = getFieldClass(meth, &instField->field);
4658             if (fieldClass == NULL) {
4659                 LOG_VFY("VFY: unable to recover field class from '%s'\n",
4660                     instField->field.signature);
4661                 failure = VERIFY_ERROR_GENERIC;
4662                 break;
4663             }
4664 
4665             valueType = getRegisterType(workRegs, insnRegCount, decInsn.vA,
4666                         &failure);
4667             if (!VERIFY_OK(failure))
4668                 break;
4669             if (!regTypeIsReference(valueType)) {
4670                 LOG_VFY("VFY: storing non-ref v%d into ref field '%s' (%s)\n",
4671                         decInsn.vA, instField->field.name,
4672                         fieldClass->descriptor);
4673                 failure = VERIFY_ERROR_GENERIC;
4674                 break;
4675             }
4676             if (valueType != kRegTypeZero) {
4677                 valueClass = regTypeInitializedReferenceToClass(valueType);
4678                 if (valueClass == NULL) {
4679                     LOG_VFY("VFY: storing uninit ref v%d into ref field\n",
4680                         decInsn.vA);
4681                     failure = VERIFY_ERROR_GENERIC;
4682                     break;
4683                 }
4684                 /* allow if field is any interface or field is base class */
4685                 if (!dvmIsInterfaceClass(fieldClass) &&
4686                     !dvmInstanceof(valueClass, fieldClass))
4687                 {
4688                     LOG_VFY("VFY: storing type '%s' into field type '%s' (%s.%s)\n",
4689                             valueClass->descriptor, fieldClass->descriptor,
4690                             instField->field.clazz->descriptor,
4691                             instField->field.name);
4692                     failure = VERIFY_ERROR_GENERIC;
4693                     break;
4694                 }
4695             }
4696         }
4697         break;
4698 
4699     case OP_SGET:
4700         tmpType = kRegTypeInteger;
4701         goto sget_1nr_common;
4702     case OP_SGET_BOOLEAN:
4703         tmpType = kRegTypeBoolean;
4704         goto sget_1nr_common;
4705     case OP_SGET_BYTE:
4706         tmpType = kRegTypeByte;
4707         goto sget_1nr_common;
4708     case OP_SGET_CHAR:
4709         tmpType = kRegTypeChar;
4710         goto sget_1nr_common;
4711     case OP_SGET_SHORT:
4712         tmpType = kRegTypeShort;
4713         goto sget_1nr_common;
4714 sget_1nr_common:
4715         {
4716             StaticField* staticField;
4717             RegType fieldType;
4718 
4719             staticField = getStaticField(meth, decInsn.vB, &failure);
4720             if (!VERIFY_OK(failure))
4721                 break;
4722 
4723             /*
4724              * Make sure the field's type is compatible with expectation.
4725              * We can get ourselves into trouble if we mix & match loads
4726              * and stores with different widths, so rather than just checking
4727              * "canConvertTo1nr" we require that the field types have equal
4728              * widths.  (We can't generally require an exact type match,
4729              * because e.g. "int" and "float" are interchangeable.)
4730              */
4731             fieldType = primSigCharToRegType(staticField->field.signature[0]);
4732             if (!checkFieldArrayStore1nr(tmpType, fieldType)) {
4733                 LOG_VFY("VFY: invalid sget-1nr of %s.%s (inst=%d actual=%d)\n",
4734                     staticField->field.clazz->descriptor,
4735                     staticField->field.name, tmpType, fieldType);
4736                 failure = VERIFY_ERROR_GENERIC;
4737                 break;
4738             }
4739 
4740             setRegisterType(workRegs, insnRegCount, decInsn.vA, tmpType,
4741                 &failure);
4742         }
4743         break;
4744     case OP_SGET_WIDE:
4745         {
4746             StaticField* staticField;
4747             RegType dstType;
4748 
4749             staticField = getStaticField(meth, decInsn.vB, &failure);
4750             if (!VERIFY_OK(failure))
4751                 break;
4752             /* check the type, which should be prim */
4753             switch (staticField->field.signature[0]) {
4754             case 'D':
4755                 dstType = kRegTypeDoubleLo;
4756                 break;
4757             case 'J':
4758                 dstType = kRegTypeLongLo;
4759                 break;
4760             default:
4761                 LOG_VFY("VFY: invalid sget-wide of %s.%s\n",
4762                         staticField->field.clazz->descriptor,
4763                         staticField->field.name);
4764                 dstType = kRegTypeUnknown;
4765                 failure = VERIFY_ERROR_GENERIC;
4766                 break;
4767             }
4768             if (VERIFY_OK(failure)) {
4769                 setRegisterType(workRegs, insnRegCount, decInsn.vA,
4770                     dstType, &failure);
4771             }
4772         }
4773         break;
4774     case OP_SGET_OBJECT:
4775         {
4776             StaticField* staticField;
4777             ClassObject* fieldClass;
4778 
4779             staticField = getStaticField(meth, decInsn.vB, &failure);
4780             if (!VERIFY_OK(failure))
4781                 break;
4782             fieldClass = getFieldClass(meth, &staticField->field);
4783             if (fieldClass == NULL) {
4784                 LOG_VFY("VFY: unable to recover field class from '%s'\n",
4785                     staticField->field.signature);
4786                 failure = VERIFY_ERROR_GENERIC;
4787                 break;
4788             }
4789             if (dvmIsPrimitiveClass(fieldClass)) {
4790                 LOG_VFY("VFY: attempt to get prim field with sget-object\n");
4791                 failure = VERIFY_ERROR_GENERIC;
4792                 break;
4793             }
4794             setRegisterType(workRegs, insnRegCount, decInsn.vA,
4795                 regTypeFromClass(fieldClass), &failure);
4796         }
4797         break;
4798     case OP_SPUT:
4799         tmpType = kRegTypeInteger;
4800         goto sput_1nr_common;
4801     case OP_SPUT_BOOLEAN:
4802         tmpType = kRegTypeBoolean;
4803         goto sput_1nr_common;
4804     case OP_SPUT_BYTE:
4805         tmpType = kRegTypeByte;
4806         goto sput_1nr_common;
4807     case OP_SPUT_CHAR:
4808         tmpType = kRegTypeChar;
4809         goto sput_1nr_common;
4810     case OP_SPUT_SHORT:
4811         tmpType = kRegTypeShort;
4812         goto sput_1nr_common;
4813 sput_1nr_common:
4814         {
4815             RegType srcType, fieldType;
4816             StaticField* staticField;
4817 
4818             srcType = getRegisterType(workRegs, insnRegCount, decInsn.vA,
4819                         &failure);
4820 
4821             /*
4822              * javac generates synthetic functions that write byte values
4823              * into boolean fields.
4824              */
4825             if (tmpType == kRegTypeBoolean && srcType == kRegTypeByte)
4826                 srcType = kRegTypeBoolean;
4827 
4828             /* make sure the source register has the correct type */
4829             if (!canConvertTo1nr(srcType, tmpType)) {
4830                 LOG_VFY("VFY: invalid reg type %d on sput instr (need %d)\n",
4831                     srcType, tmpType);
4832                 failure = VERIFY_ERROR_GENERIC;
4833                 break;
4834             }
4835 
4836             staticField = getStaticField(meth, decInsn.vB, &failure);
4837             if (!VERIFY_OK(failure))
4838                 break;
4839             checkFinalFieldAccess(meth, &staticField->field, &failure);
4840             if (!VERIFY_OK(failure))
4841                 break;
4842 
4843             /*
4844              * Get type of field we're storing into.  We know that the
4845              * contents of the register match the instruction, but we also
4846              * need to ensure that the instruction matches the field type.
4847              * Using e.g. sput-short to write into a 32-bit integer field
4848              * can lead to trouble if we do 16-bit writes.
4849              */
4850             fieldType = primSigCharToRegType(staticField->field.signature[0]);
4851             if (!checkFieldArrayStore1nr(tmpType, fieldType)) {
4852                 LOG_VFY("VFY: invalid sput-1nr of %s.%s (inst=%d actual=%d)\n",
4853                     staticField->field.clazz->descriptor,
4854                     staticField->field.name, tmpType, fieldType);
4855                 failure = VERIFY_ERROR_GENERIC;
4856                 break;
4857             }
4858         }
4859         break;
4860     case OP_SPUT_WIDE:
4861         tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &failure);
4862         if (VERIFY_OK(failure)) {
4863             RegType typeHi =
4864                 getRegisterType(workRegs, insnRegCount, decInsn.vA+1, &failure);
4865             checkTypeCategory(tmpType, kTypeCategory2, &failure);
4866             checkWidePair(tmpType, typeHi, &failure);
4867         }
4868         if (VERIFY_OK(failure)) {
4869             StaticField* staticField;
4870 
4871             staticField = getStaticField(meth, decInsn.vB, &failure);
4872             if (!VERIFY_OK(failure))
4873                 break;
4874             checkFinalFieldAccess(meth, &staticField->field, &failure);
4875             if (!VERIFY_OK(failure))
4876                 break;
4877 
4878             /* check the type, which should be prim */
4879             switch (staticField->field.signature[0]) {
4880             case 'D':
4881             case 'J':
4882                 /* these are okay */
4883                 break;
4884             default:
4885                 LOG_VFY("VFY: invalid sput-wide of %s.%s\n",
4886                         staticField->field.clazz->descriptor,
4887                         staticField->field.name);
4888                 failure = VERIFY_ERROR_GENERIC;
4889                 break;
4890             }
4891         }
4892         break;
4893     case OP_SPUT_OBJECT:
4894         {
4895             ClassObject* fieldClass;
4896             ClassObject* valueClass;
4897             StaticField* staticField;
4898             RegType valueType;
4899 
4900             staticField = getStaticField(meth, decInsn.vB, &failure);
4901             if (!VERIFY_OK(failure))
4902                 break;
4903             checkFinalFieldAccess(meth, &staticField->field, &failure);
4904             if (!VERIFY_OK(failure))
4905                 break;
4906 
4907             fieldClass = getFieldClass(meth, &staticField->field);
4908             if (fieldClass == NULL) {
4909                 LOG_VFY("VFY: unable to recover field class from '%s'\n",
4910                     staticField->field.signature);
4911                 failure = VERIFY_ERROR_GENERIC;
4912                 break;
4913             }
4914 
4915             valueType = getRegisterType(workRegs, insnRegCount, decInsn.vA,
4916                         &failure);
4917             if (!VERIFY_OK(failure))
4918                 break;
4919             if (!regTypeIsReference(valueType)) {
4920                 LOG_VFY("VFY: storing non-ref v%d into ref field '%s' (%s)\n",
4921                         decInsn.vA, staticField->field.name,
4922                         fieldClass->descriptor);
4923                 failure = VERIFY_ERROR_GENERIC;
4924                 break;
4925             }
4926             if (valueType != kRegTypeZero) {
4927                 valueClass = regTypeInitializedReferenceToClass(valueType);
4928                 if (valueClass == NULL) {
4929                     LOG_VFY("VFY: storing uninit ref v%d into ref field\n",
4930                         decInsn.vA);
4931                     failure = VERIFY_ERROR_GENERIC;
4932                     break;
4933                 }
4934                 /* allow if field is any interface or field is base class */
4935                 if (!dvmIsInterfaceClass(fieldClass) &&
4936                     !dvmInstanceof(valueClass, fieldClass))
4937                 {
4938                     LOG_VFY("VFY: storing type '%s' into field type '%s' (%s.%s)\n",
4939                             valueClass->descriptor, fieldClass->descriptor,
4940                             staticField->field.clazz->descriptor,
4941                             staticField->field.name);
4942                     failure = VERIFY_ERROR_GENERIC;
4943                     break;
4944                 }
4945             }
4946         }
4947         break;
4948 
4949     case OP_INVOKE_VIRTUAL:
4950     case OP_INVOKE_VIRTUAL_RANGE:
4951     case OP_INVOKE_SUPER:
4952     case OP_INVOKE_SUPER_RANGE:
4953         {
4954             Method* calledMethod;
4955             RegType returnType;
4956             bool isRange;
4957             bool isSuper;
4958 
4959             isRange =  (decInsn.opCode == OP_INVOKE_VIRTUAL_RANGE ||
4960                         decInsn.opCode == OP_INVOKE_SUPER_RANGE);
4961             isSuper =  (decInsn.opCode == OP_INVOKE_SUPER ||
4962                         decInsn.opCode == OP_INVOKE_SUPER_RANGE);
4963 
4964             calledMethod = verifyInvocationArgs(meth, workRegs, insnRegCount,
4965                             &decInsn, uninitMap, METHOD_VIRTUAL, isRange,
4966                             isSuper, &failure);
4967             if (!VERIFY_OK(failure))
4968                 break;
4969             returnType = getMethodReturnType(calledMethod);
4970             setResultRegisterType(workRegs, insnRegCount, returnType, &failure);
4971             justSetResult = true;
4972         }
4973         break;
4974     case OP_INVOKE_DIRECT:
4975     case OP_INVOKE_DIRECT_RANGE:
4976         {
4977             RegType returnType;
4978             Method* calledMethod;
4979             bool isRange;
4980 
4981             isRange =  (decInsn.opCode == OP_INVOKE_DIRECT_RANGE);
4982             calledMethod = verifyInvocationArgs(meth, workRegs, insnRegCount,
4983                             &decInsn, uninitMap, METHOD_DIRECT, isRange,
4984                             false, &failure);
4985             if (!VERIFY_OK(failure))
4986                 break;
4987 
4988             /*
4989              * Some additional checks when calling <init>.  We know from
4990              * the invocation arg check that the "this" argument is an
4991              * instance of calledMethod->clazz.  Now we further restrict
4992              * that to require that calledMethod->clazz is the same as
4993              * this->clazz or this->super, allowing the latter only if
4994              * the "this" argument is the same as the "this" argument to
4995              * this method (which implies that we're in <init> ourselves).
4996              */
4997             if (isInitMethod(calledMethod)) {
4998                 RegType thisType;
4999                 thisType = getInvocationThis(workRegs, insnRegCount,
5000                             &decInsn, &failure);
5001                 if (!VERIFY_OK(failure))
5002                     break;
5003 
5004                 /* no null refs allowed (?) */
5005                 if (thisType == kRegTypeZero) {
5006                     LOG_VFY("VFY: unable to initialize null ref\n");
5007                     failure = VERIFY_ERROR_GENERIC;
5008                     break;
5009                 }
5010 
5011                 ClassObject* thisClass;
5012 
5013                 thisClass = regTypeReferenceToClass(thisType, uninitMap);
5014                 assert(thisClass != NULL);
5015 
5016                 /* must be in same class or in superclass */
5017                 if (calledMethod->clazz == thisClass->super) {
5018                     if (thisClass != meth->clazz) {
5019                         LOG_VFY("VFY: invoke-direct <init> on super only "
5020                             "allowed for 'this' in <init>");
5021                         failure = VERIFY_ERROR_GENERIC;
5022                         break;
5023                     }
5024                 }  else if (calledMethod->clazz != thisClass) {
5025                     LOG_VFY("VFY: invoke-direct <init> must be on current "
5026                             "class or super\n");
5027                     failure = VERIFY_ERROR_GENERIC;
5028                     break;
5029                 }
5030 
5031                 /* arg must be an uninitialized reference */
5032                 if (!regTypeIsUninitReference(thisType)) {
5033                     LOG_VFY("VFY: can only initialize the uninitialized\n");
5034                     failure = VERIFY_ERROR_GENERIC;
5035                     break;
5036                 }
5037 
5038                 /*
5039                  * Replace the uninitialized reference with an initialized
5040                  * one, and clear the entry in the uninit map.  We need to
5041                  * do this for all registers that have the same object
5042                  * instance in them, not just the "this" register.
5043                  */
5044                 int uidx = regTypeToUninitIndex(thisType);
5045                 markRefsAsInitialized(workRegs, insnRegCount, uninitMap,
5046                     thisType, &failure);
5047                 if (!VERIFY_OK(failure))
5048                     break;
5049             }
5050             returnType = getMethodReturnType(calledMethod);
5051             setResultRegisterType(workRegs, insnRegCount,
5052                 returnType, &failure);
5053             justSetResult = true;
5054         }
5055         break;
5056     case OP_INVOKE_STATIC:
5057     case OP_INVOKE_STATIC_RANGE:
5058         {
5059             RegType returnType;
5060             Method* calledMethod;
5061             bool isRange;
5062 
5063             isRange =  (decInsn.opCode == OP_INVOKE_STATIC_RANGE);
5064             calledMethod = verifyInvocationArgs(meth, workRegs, insnRegCount,
5065                             &decInsn, uninitMap, METHOD_STATIC, isRange,
5066                             false, &failure);
5067             if (!VERIFY_OK(failure))
5068                 break;
5069 
5070             returnType = getMethodReturnType(calledMethod);
5071             setResultRegisterType(workRegs, insnRegCount, returnType, &failure);
5072             justSetResult = true;
5073         }
5074         break;
5075     case OP_INVOKE_INTERFACE:
5076     case OP_INVOKE_INTERFACE_RANGE:
5077         {
5078             RegType /*thisType,*/ returnType;
5079             Method* absMethod;
5080             bool isRange;
5081 
5082             isRange =  (decInsn.opCode == OP_INVOKE_INTERFACE_RANGE);
5083             absMethod = verifyInvocationArgs(meth, workRegs, insnRegCount,
5084                             &decInsn, uninitMap, METHOD_INTERFACE, isRange,
5085                             false, &failure);
5086             if (!VERIFY_OK(failure))
5087                 break;
5088 
5089 #if 0       /* can't do this here, fails on dalvik test 052-verifier-fun */
5090             /*
5091              * Get the type of the "this" arg, which should always be an
5092              * interface class.  Because we don't do a full merge on
5093              * interface classes, this might have reduced to Object.
5094              */
5095             thisType = getInvocationThis(workRegs, insnRegCount,
5096                         &decInsn, &failure);
5097             if (!VERIFY_OK(failure))
5098                 break;
5099 
5100             if (thisType == kRegTypeZero) {
5101                 /* null pointer always passes (and always fails at runtime) */
5102             } else {
5103                 ClassObject* thisClass;
5104 
5105                 thisClass = regTypeInitializedReferenceToClass(thisType);
5106                 if (thisClass == NULL) {
5107                     LOG_VFY("VFY: interface call on uninitialized\n");
5108                     failure = VERIFY_ERROR_GENERIC;
5109                     break;
5110                 }
5111 
5112                 /*
5113                  * Either "thisClass" needs to be the interface class that
5114                  * defined absMethod, or absMethod's class needs to be one
5115                  * of the interfaces implemented by "thisClass".  (Or, if
5116                  * we couldn't complete the merge, this will be Object.)
5117                  */
5118                 if (thisClass != absMethod->clazz &&
5119                     thisClass != gDvm.classJavaLangObject &&
5120                     !dvmImplements(thisClass, absMethod->clazz))
5121                 {
5122                     LOG_VFY("VFY: unable to match absMethod '%s' with %s interfaces\n",
5123                             absMethod->name, thisClass->descriptor);
5124                     failure = VERIFY_ERROR_GENERIC;
5125                     break;
5126                 }
5127             }
5128 #endif
5129 
5130             /*
5131              * We don't have an object instance, so we can't find the
5132              * concrete method.  However, all of the type information is
5133              * in the abstract method, so we're good.
5134              */
5135             returnType = getMethodReturnType(absMethod);
5136             setResultRegisterType(workRegs, insnRegCount, returnType, &failure);
5137             justSetResult = true;
5138         }
5139         break;
5140 
5141     case OP_NEG_INT:
5142     case OP_NOT_INT:
5143         checkUnop(workRegs, insnRegCount, &decInsn,
5144             kRegTypeInteger, kRegTypeInteger, &failure);
5145         break;
5146     case OP_NEG_LONG:
5147     case OP_NOT_LONG:
5148         checkUnop(workRegs, insnRegCount, &decInsn,
5149             kRegTypeLongLo, kRegTypeLongLo, &failure);
5150         break;
5151     case OP_NEG_FLOAT:
5152         checkUnop(workRegs, insnRegCount, &decInsn,
5153             kRegTypeFloat, kRegTypeFloat, &failure);
5154         break;
5155     case OP_NEG_DOUBLE:
5156         checkUnop(workRegs, insnRegCount, &decInsn,
5157             kRegTypeDoubleLo, kRegTypeDoubleLo, &failure);
5158         break;
5159     case OP_INT_TO_LONG:
5160         checkUnop(workRegs, insnRegCount, &decInsn,
5161             kRegTypeLongLo, kRegTypeInteger, &failure);
5162         break;
5163     case OP_INT_TO_FLOAT:
5164         checkUnop(workRegs, insnRegCount, &decInsn,
5165             kRegTypeFloat, kRegTypeInteger, &failure);
5166         break;
5167     case OP_INT_TO_DOUBLE:
5168         checkUnop(workRegs, insnRegCount, &decInsn,
5169             kRegTypeDoubleLo, kRegTypeInteger, &failure);
5170         break;
5171     case OP_LONG_TO_INT:
5172         checkUnop(workRegs, insnRegCount, &decInsn,
5173             kRegTypeInteger, kRegTypeLongLo, &failure);
5174         break;
5175     case OP_LONG_TO_FLOAT:
5176         checkUnop(workRegs, insnRegCount, &decInsn,
5177             kRegTypeFloat, kRegTypeLongLo, &failure);
5178         break;
5179     case OP_LONG_TO_DOUBLE:
5180         checkUnop(workRegs, insnRegCount, &decInsn,
5181             kRegTypeDoubleLo, kRegTypeLongLo, &failure);
5182         break;
5183     case OP_FLOAT_TO_INT:
5184         checkUnop(workRegs, insnRegCount, &decInsn,
5185             kRegTypeInteger, kRegTypeFloat, &failure);
5186         break;
5187     case OP_FLOAT_TO_LONG:
5188         checkUnop(workRegs, insnRegCount, &decInsn,
5189             kRegTypeLongLo, kRegTypeFloat, &failure);
5190         break;
5191     case OP_FLOAT_TO_DOUBLE:
5192         checkUnop(workRegs, insnRegCount, &decInsn,
5193             kRegTypeDoubleLo, kRegTypeFloat, &failure);
5194         break;
5195     case OP_DOUBLE_TO_INT:
5196         checkUnop(workRegs, insnRegCount, &decInsn,
5197             kRegTypeInteger, kRegTypeDoubleLo, &failure);
5198         break;
5199     case OP_DOUBLE_TO_LONG:
5200         checkUnop(workRegs, insnRegCount, &decInsn,
5201             kRegTypeLongLo, kRegTypeDoubleLo, &failure);
5202         break;
5203     case OP_DOUBLE_TO_FLOAT:
5204         checkUnop(workRegs, insnRegCount, &decInsn,
5205             kRegTypeFloat, kRegTypeDoubleLo, &failure);
5206         break;
5207     case OP_INT_TO_BYTE:
5208         checkUnop(workRegs, insnRegCount, &decInsn,
5209             kRegTypeByte, kRegTypeInteger, &failure);
5210         break;
5211     case OP_INT_TO_CHAR:
5212         checkUnop(workRegs, insnRegCount, &decInsn,
5213             kRegTypeChar, kRegTypeInteger, &failure);
5214         break;
5215     case OP_INT_TO_SHORT:
5216         checkUnop(workRegs, insnRegCount, &decInsn,
5217             kRegTypeShort, kRegTypeInteger, &failure);
5218         break;
5219 
5220     case OP_ADD_INT:
5221     case OP_SUB_INT:
5222     case OP_MUL_INT:
5223     case OP_REM_INT:
5224     case OP_DIV_INT:
5225     case OP_SHL_INT:
5226     case OP_SHR_INT:
5227     case OP_USHR_INT:
5228         checkBinop(workRegs, insnRegCount, &decInsn,
5229             kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, false, &failure);
5230         break;
5231     case OP_AND_INT:
5232     case OP_OR_INT:
5233     case OP_XOR_INT:
5234         checkBinop(workRegs, insnRegCount, &decInsn,
5235             kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, true, &failure);
5236         break;
5237     case OP_ADD_LONG:
5238     case OP_SUB_LONG:
5239     case OP_MUL_LONG:
5240     case OP_DIV_LONG:
5241     case OP_REM_LONG:
5242     case OP_AND_LONG:
5243     case OP_OR_LONG:
5244     case OP_XOR_LONG:
5245         checkBinop(workRegs, insnRegCount, &decInsn,
5246             kRegTypeLongLo, kRegTypeLongLo, kRegTypeLongLo, false, &failure);
5247         break;
5248     case OP_SHL_LONG:
5249     case OP_SHR_LONG:
5250     case OP_USHR_LONG:
5251         /* shift distance is Int, making these different from other binops */
5252         checkBinop(workRegs, insnRegCount, &decInsn,
5253             kRegTypeLongLo, kRegTypeLongLo, kRegTypeInteger, false, &failure);
5254         break;
5255     case OP_ADD_FLOAT:
5256     case OP_SUB_FLOAT:
5257     case OP_MUL_FLOAT:
5258     case OP_DIV_FLOAT:
5259     case OP_REM_FLOAT:
5260         checkBinop(workRegs, insnRegCount, &decInsn,
5261             kRegTypeFloat, kRegTypeFloat, kRegTypeFloat, false, &failure);
5262         break;
5263     case OP_ADD_DOUBLE:
5264     case OP_SUB_DOUBLE:
5265     case OP_MUL_DOUBLE:
5266     case OP_DIV_DOUBLE:
5267     case OP_REM_DOUBLE:
5268         checkBinop(workRegs, insnRegCount, &decInsn,
5269             kRegTypeDoubleLo, kRegTypeDoubleLo, kRegTypeDoubleLo, false,
5270             &failure);
5271         break;
5272     case OP_ADD_INT_2ADDR:
5273     case OP_SUB_INT_2ADDR:
5274     case OP_MUL_INT_2ADDR:
5275     case OP_REM_INT_2ADDR:
5276     case OP_SHL_INT_2ADDR:
5277     case OP_SHR_INT_2ADDR:
5278     case OP_USHR_INT_2ADDR:
5279         checkBinop2addr(workRegs, insnRegCount, &decInsn,
5280             kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, false, &failure);
5281         break;
5282     case OP_AND_INT_2ADDR:
5283     case OP_OR_INT_2ADDR:
5284     case OP_XOR_INT_2ADDR:
5285         checkBinop2addr(workRegs, insnRegCount, &decInsn,
5286             kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, true, &failure);
5287         break;
5288     case OP_DIV_INT_2ADDR:
5289         checkBinop2addr(workRegs, insnRegCount, &decInsn,
5290             kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, false, &failure);
5291         break;
5292     case OP_ADD_LONG_2ADDR:
5293     case OP_SUB_LONG_2ADDR:
5294     case OP_MUL_LONG_2ADDR:
5295     case OP_DIV_LONG_2ADDR:
5296     case OP_REM_LONG_2ADDR:
5297     case OP_AND_LONG_2ADDR:
5298     case OP_OR_LONG_2ADDR:
5299     case OP_XOR_LONG_2ADDR:
5300         checkBinop2addr(workRegs, insnRegCount, &decInsn,
5301             kRegTypeLongLo, kRegTypeLongLo, kRegTypeLongLo, false, &failure);
5302         break;
5303     case OP_SHL_LONG_2ADDR:
5304     case OP_SHR_LONG_2ADDR:
5305     case OP_USHR_LONG_2ADDR:
5306         checkBinop2addr(workRegs, insnRegCount, &decInsn,
5307             kRegTypeLongLo, kRegTypeLongLo, kRegTypeInteger, false, &failure);
5308         break;
5309     case OP_ADD_FLOAT_2ADDR:
5310     case OP_SUB_FLOAT_2ADDR:
5311     case OP_MUL_FLOAT_2ADDR:
5312     case OP_DIV_FLOAT_2ADDR:
5313     case OP_REM_FLOAT_2ADDR:
5314         checkBinop2addr(workRegs, insnRegCount, &decInsn,
5315             kRegTypeFloat, kRegTypeFloat, kRegTypeFloat, false, &failure);
5316         break;
5317     case OP_ADD_DOUBLE_2ADDR:
5318     case OP_SUB_DOUBLE_2ADDR:
5319     case OP_MUL_DOUBLE_2ADDR:
5320     case OP_DIV_DOUBLE_2ADDR:
5321     case OP_REM_DOUBLE_2ADDR:
5322         checkBinop2addr(workRegs, insnRegCount, &decInsn,
5323             kRegTypeDoubleLo, kRegTypeDoubleLo, kRegTypeDoubleLo, false,
5324             &failure);
5325         break;
5326     case OP_ADD_INT_LIT16:
5327     case OP_RSUB_INT:
5328     case OP_MUL_INT_LIT16:
5329     case OP_DIV_INT_LIT16:
5330     case OP_REM_INT_LIT16:
5331         checkLitop(workRegs, insnRegCount, &decInsn,
5332             kRegTypeInteger, kRegTypeInteger, false, &failure);
5333         break;
5334     case OP_AND_INT_LIT16:
5335     case OP_OR_INT_LIT16:
5336     case OP_XOR_INT_LIT16:
5337         checkLitop(workRegs, insnRegCount, &decInsn,
5338             kRegTypeInteger, kRegTypeInteger, true, &failure);
5339         break;
5340     case OP_ADD_INT_LIT8:
5341     case OP_RSUB_INT_LIT8:
5342     case OP_MUL_INT_LIT8:
5343     case OP_DIV_INT_LIT8:
5344     case OP_REM_INT_LIT8:
5345     case OP_SHL_INT_LIT8:
5346         checkLitop(workRegs, insnRegCount, &decInsn,
5347             kRegTypeInteger, kRegTypeInteger, false, &failure);
5348         break;
5349     case OP_SHR_INT_LIT8:
5350         tmpType = adjustForRightShift(workRegs, insnRegCount,
5351             decInsn.vB, decInsn.vC, false, &failure);
5352         checkLitop(workRegs, insnRegCount, &decInsn,
5353             tmpType, kRegTypeInteger, false, &failure);
5354         break;
5355     case OP_USHR_INT_LIT8:
5356         tmpType = adjustForRightShift(workRegs, insnRegCount,
5357             decInsn.vB, decInsn.vC, true, &failure);
5358         checkLitop(workRegs, insnRegCount, &decInsn,
5359             tmpType, kRegTypeInteger, false, &failure);
5360         break;
5361     case OP_AND_INT_LIT8:
5362     case OP_OR_INT_LIT8:
5363     case OP_XOR_INT_LIT8:
5364         checkLitop(workRegs, insnRegCount, &decInsn,
5365             kRegTypeInteger, kRegTypeInteger, true, &failure);
5366         break;
5367 
5368     /*
5369      * This falls into the general category of "optimized" instructions,
5370      * which don't generally appear during verification.  Because it's
5371      * inserted in the course of verification, we can expect to see it here.
5372      */
5373     case OP_THROW_VERIFICATION_ERROR:
5374         break;
5375 
5376     /*
5377      * Verifying "quickened" instructions is tricky, because we have
5378      * discarded the original field/method information.  The byte offsets
5379      * and vtable indices only have meaning in the context of an object
5380      * instance.
5381      *
5382      * If a piece of code declares a local reference variable, assigns
5383      * null to it, and then issues a virtual method call on it, we
5384      * cannot evaluate the method call during verification.  This situation
5385      * isn't hard to handle, since we know the call will always result in an
5386      * NPE, and the arguments and return value don't matter.  Any code that
5387      * depends on the result of the method call is inaccessible, so the
5388      * fact that we can't fully verify anything that comes after the bad
5389      * call is not a problem.
5390      *
5391      * We must also consider the case of multiple code paths, only some of
5392      * which involve a null reference.  We can completely verify the method
5393      * if we sidestep the results of executing with a null reference.
5394      * For example, if on the first pass through the code we try to do a
5395      * virtual method invocation through a null ref, we have to skip the
5396      * method checks and have the method return a "wildcard" type (which
5397      * merges with anything to become that other thing).  The move-result
5398      * will tell us if it's a reference, single-word numeric, or double-word
5399      * value.  We continue to perform the verification, and at the end of
5400      * the function any invocations that were never fully exercised are
5401      * marked as null-only.
5402      *
5403      * We would do something similar for the field accesses.  The field's
5404      * type, once known, can be used to recover the width of short integers.
5405      * If the object reference was null, the field-get returns the "wildcard"
5406      * type, which is acceptable for any operation.
5407      */
5408     case OP_EXECUTE_INLINE:
5409     case OP_INVOKE_DIRECT_EMPTY:
5410     case OP_IGET_QUICK:
5411     case OP_IGET_WIDE_QUICK:
5412     case OP_IGET_OBJECT_QUICK:
5413     case OP_IPUT_QUICK:
5414     case OP_IPUT_WIDE_QUICK:
5415     case OP_IPUT_OBJECT_QUICK:
5416     case OP_INVOKE_VIRTUAL_QUICK:
5417     case OP_INVOKE_VIRTUAL_QUICK_RANGE:
5418     case OP_INVOKE_SUPER_QUICK:
5419     case OP_INVOKE_SUPER_QUICK_RANGE:
5420         failure = VERIFY_ERROR_GENERIC;
5421         break;
5422 
5423     /* these should never appear */
5424     case OP_UNUSED_3E:
5425     case OP_UNUSED_3F:
5426     case OP_UNUSED_40:
5427     case OP_UNUSED_41:
5428     case OP_UNUSED_42:
5429     case OP_UNUSED_43:
5430     case OP_UNUSED_73:
5431     case OP_UNUSED_79:
5432     case OP_UNUSED_7A:
5433     case OP_UNUSED_E3:
5434     case OP_UNUSED_E4:
5435     case OP_UNUSED_E5:
5436     case OP_UNUSED_E6:
5437     case OP_UNUSED_E7:
5438     case OP_UNUSED_E8:
5439     case OP_UNUSED_E9:
5440     case OP_UNUSED_EA:
5441     case OP_UNUSED_EB:
5442     case OP_UNUSED_EC:
5443     case OP_UNUSED_EF:
5444     case OP_UNUSED_F1:
5445     case OP_UNUSED_FC:
5446     case OP_UNUSED_FD:
5447     case OP_UNUSED_FE:
5448     case OP_UNUSED_FF:
5449         failure = VERIFY_ERROR_GENERIC;
5450         break;
5451 
5452     /*
5453      * DO NOT add a "default" clause here.  Without it the compiler will
5454      * complain if an instruction is missing (which is desirable).
5455      */
5456     }
5457 
5458     if (!VERIFY_OK(failure)) {
5459         if (failure == VERIFY_ERROR_GENERIC || gDvm.optimizing) {
5460             /* immediate failure, reject class */
5461             LOG_VFY_METH(meth, "VFY:  rejecting opcode 0x%02x at 0x%04x\n",
5462                 decInsn.opCode, insnIdx);
5463             goto bail;
5464         } else {
5465             /* replace opcode and continue on */
5466             LOGD("VFY: replacing opcode 0x%02x at 0x%04x\n",
5467                 decInsn.opCode, insnIdx);
5468             if (!replaceFailingInstruction(meth, insnFlags, insnIdx, failure)) {
5469                 LOG_VFY_METH(meth, "VFY:  rejecting opcode 0x%02x at 0x%04x\n",
5470                     decInsn.opCode, insnIdx);
5471                 goto bail;
5472             }
5473             /* IMPORTANT: meth->insns may have been changed */
5474             insns = meth->insns + insnIdx;
5475 
5476             /* continue on as if we just handled a throw-verification-error */
5477             failure = VERIFY_ERROR_NONE;
5478             nextFlags = kInstrCanThrow;
5479         }
5480     }
5481 
5482     /*
5483      * If we didn't just set the result register, clear it out.  This
5484      * ensures that you can only use "move-result" immediately after the
5485      * result is set.
5486      */
5487     if (!justSetResult) {
5488         int reg = RESULT_REGISTER(insnRegCount);
5489         workRegs[reg] = workRegs[reg+1] = kRegTypeUnknown;
5490     }
5491 
5492     /*
5493      * Handle "continue".  Tag the next consecutive instruction.
5494      */
5495     if ((nextFlags & kInstrCanContinue) != 0) {
5496         int insnWidth = dvmInsnGetWidth(insnFlags, insnIdx);
5497         if (insnIdx+insnWidth >= insnsSize) {
5498             LOG_VFY_METH(meth,
5499                 "VFY: execution can walk off end of code area (from 0x%x)\n",
5500                 insnIdx);
5501             goto bail;
5502         }
5503 
5504         /*
5505          * The only way to get to a move-exception instruction is to get
5506          * thrown there.  Make sure the next instruction isn't one.
5507          */
5508         if (!checkMoveException(meth, insnIdx+insnWidth, "next"))
5509             goto bail;
5510 
5511         if (getRegisterLine(regTable, insnIdx+insnWidth) != NULL) {
5512             /*
5513              * Merge registers into what we have for the next instruction,
5514              * and set the "changed" flag if needed.
5515              */
5516             updateRegisters(meth, insnFlags, regTable, insnIdx+insnWidth,
5517                 workRegs);
5518         } else {
5519             /*
5520              * We're not recording register data for the next instruction,
5521              * so we don't know what the prior state was.  We have to
5522              * assume that something has changed and re-evaluate it.
5523              */
5524             dvmInsnSetChanged(insnFlags, insnIdx+insnWidth, true);
5525         }
5526     }
5527 
5528     /*
5529      * Handle "branch".  Tag the branch target.
5530      *
5531      * NOTE: instructions like OP_EQZ provide information about the state
5532      * of the register when the branch is taken or not taken.  For example,
5533      * somebody could get a reference field, check it for zero, and if the
5534      * branch is taken immediately store that register in a boolean field
5535      * since the value is known to be zero.  We do not currently account for
5536      * that, and will reject the code.
5537      */
5538     if ((nextFlags & kInstrCanBranch) != 0) {
5539         bool isConditional;
5540 
5541         if (!dvmGetBranchTarget(meth, insnFlags, insnIdx, &branchTarget,
5542                 &isConditional))
5543         {
5544             /* should never happen after static verification */
5545             LOG_VFY_METH(meth, "VFY: bad branch at %d\n", insnIdx);
5546             goto bail;
5547         }
5548         assert(isConditional || (nextFlags & kInstrCanContinue) == 0);
5549         assert(!isConditional || (nextFlags & kInstrCanContinue) != 0);
5550 
5551         if (!checkMoveException(meth, insnIdx+branchTarget, "branch"))
5552             goto bail;
5553 
5554         /* update branch target, set "changed" if appropriate */
5555         updateRegisters(meth, insnFlags, regTable, insnIdx+branchTarget,
5556             workRegs);
5557     }
5558 
5559     /*
5560      * Handle "switch".  Tag all possible branch targets.
5561      *
5562      * We've already verified that the table is structurally sound, so we
5563      * just need to walk through and tag the targets.
5564      */
5565     if ((nextFlags & kInstrCanSwitch) != 0) {
5566         int offsetToSwitch = insns[1] | (((s4)insns[2]) << 16);
5567         const u2* switchInsns = insns + offsetToSwitch;
5568         int switchCount = switchInsns[1];
5569         int offsetToTargets, targ;
5570 
5571         if ((*insns & 0xff) == OP_PACKED_SWITCH) {
5572             /* 0=sig, 1=count, 2/3=firstKey */
5573             offsetToTargets = 4;
5574         } else {
5575             /* 0=sig, 1=count, 2..count*2 = keys */
5576             assert((*insns & 0xff) == OP_SPARSE_SWITCH);
5577             offsetToTargets = 2 + 2*switchCount;
5578         }
5579 
5580         /* verify each switch target */
5581         for (targ = 0; targ < switchCount; targ++) {
5582             int offset, absOffset;
5583 
5584             /* offsets are 32-bit, and only partly endian-swapped */
5585             offset = switchInsns[offsetToTargets + targ*2] |
5586                      (((s4) switchInsns[offsetToTargets + targ*2 +1]) << 16);
5587             absOffset = insnIdx + offset;
5588 
5589             assert(absOffset >= 0 && absOffset < insnsSize);
5590 
5591             if (!checkMoveException(meth, absOffset, "switch"))
5592                 goto bail;
5593 
5594             updateRegisters(meth, insnFlags, regTable, absOffset, workRegs);
5595         }
5596     }
5597 
5598     /*
5599      * Handle instructions that can throw and that are sitting in a
5600      * "try" block.  (If they're not in a "try" block when they throw,
5601      * control transfers out of the method.)
5602      */
5603     if ((nextFlags & kInstrCanThrow) != 0 && dvmInsnIsInTry(insnFlags, insnIdx))
5604     {
5605         DexFile* pDexFile = meth->clazz->pDvmDex->pDexFile;
5606         const DexCode* pCode = dvmGetMethodCode(meth);
5607         DexCatchIterator iterator;
5608 
5609         if (dexFindCatchHandler(&iterator, pCode, insnIdx)) {
5610             for (;;) {
5611                 DexCatchHandler* handler = dexCatchIteratorNext(&iterator);
5612 
5613                 if (handler == NULL) {
5614                     break;
5615                 }
5616 
5617                 /* note we use entryRegs, not workRegs */
5618                 updateRegisters(meth, insnFlags, regTable, handler->address,
5619                     entryRegs);
5620             }
5621         }
5622     }
5623 
5624     /*
5625      * Update startGuess.  Advance to the next instruction of that's
5626      * possible, otherwise use the branch target if one was found.  If
5627      * neither of those exists we're in a return or throw; leave startGuess
5628      * alone and let the caller sort it out.
5629      */
5630     if ((nextFlags & kInstrCanContinue) != 0) {
5631         *pStartGuess = insnIdx + dvmInsnGetWidth(insnFlags, insnIdx);
5632     } else if ((nextFlags & kInstrCanBranch) != 0) {
5633         /* we're still okay if branchTarget is zero */
5634         *pStartGuess = insnIdx + branchTarget;
5635     }
5636 
5637     assert(*pStartGuess >= 0 && *pStartGuess < insnsSize &&
5638         dvmInsnGetWidth(insnFlags, *pStartGuess) != 0);
5639 
5640     result = true;
5641 
5642 bail:
5643     return result;
5644 }
5645 
5646 
5647 /*
5648  * callback function used in dumpRegTypes to print local vars
5649  * valid at a given address.
5650  */
logLocalsCb(void * cnxt,u2 reg,u4 startAddress,u4 endAddress,const char * name,const char * descriptor,const char * signature)5651 static void logLocalsCb(void *cnxt, u2 reg, u4 startAddress, u4 endAddress,
5652         const char *name, const char *descriptor,
5653         const char *signature)
5654 {
5655     int addr = *((int *)cnxt);
5656 
5657     if (addr >= (int) startAddress && addr < (int) endAddress)
5658     {
5659         LOGI("        %2d: '%s' %s\n", reg, name, descriptor);
5660     }
5661 }
5662 
5663 /*
5664  * Dump the register types for the specifed address to the log file.
5665  */
dumpRegTypes(const Method * meth,const InsnFlags * insnFlags,const RegType * addrRegs,int addr,const char * addrName,const UninitInstanceMap * uninitMap,int displayFlags)5666 static void dumpRegTypes(const Method* meth, const InsnFlags* insnFlags,
5667     const RegType* addrRegs, int addr, const char* addrName,
5668     const UninitInstanceMap* uninitMap, int displayFlags)
5669 {
5670     int regCount = meth->registersSize;
5671     int fullRegCount = regCount + kExtraRegs;
5672     bool branchTarget = dvmInsnIsBranchTarget(insnFlags, addr);
5673     int i;
5674 
5675     assert(addr >= 0 && addr < (int) dvmGetMethodInsnsSize(meth));
5676 
5677     int regCharSize = fullRegCount + (fullRegCount-1)/4 + 2 +1;
5678     char regChars[regCharSize +1];
5679     memset(regChars, ' ', regCharSize);
5680     regChars[0] = '[';
5681     if (regCount == 0)
5682         regChars[1] = ']';
5683     else
5684         regChars[1 + (regCount-1) + (regCount-1)/4 +1] = ']';
5685     regChars[regCharSize] = '\0';
5686 
5687     //const RegType* addrRegs = getRegisterLine(regTable, addr);
5688 
5689     for (i = 0; i < regCount + kExtraRegs; i++) {
5690         char tch;
5691 
5692         switch (addrRegs[i]) {
5693         case kRegTypeUnknown:       tch = '.';  break;
5694         case kRegTypeConflict:      tch = 'X';  break;
5695         case kRegTypeFloat:         tch = 'F';  break;
5696         case kRegTypeZero:          tch = '0';  break;
5697         case kRegTypeOne:           tch = '1';  break;
5698         case kRegTypeBoolean:       tch = 'Z';  break;
5699         case kRegTypePosByte:       tch = 'b';  break;
5700         case kRegTypeByte:          tch = 'B';  break;
5701         case kRegTypePosShort:      tch = 's';  break;
5702         case kRegTypeShort:         tch = 'S';  break;
5703         case kRegTypeChar:          tch = 'C';  break;
5704         case kRegTypeInteger:       tch = 'I';  break;
5705         case kRegTypeLongLo:        tch = 'J';  break;
5706         case kRegTypeLongHi:        tch = 'j';  break;
5707         case kRegTypeDoubleLo:      tch = 'D';  break;
5708         case kRegTypeDoubleHi:      tch = 'd';  break;
5709         default:
5710             if (regTypeIsReference(addrRegs[i])) {
5711                 if (regTypeIsUninitReference(addrRegs[i]))
5712                     tch = 'U';
5713                 else
5714                     tch = 'L';
5715             } else {
5716                 tch = '*';
5717                 assert(false);
5718             }
5719             break;
5720         }
5721 
5722         if (i < regCount)
5723             regChars[1 + i + (i/4)] = tch;
5724         else
5725             regChars[1 + i + (i/4) + 2] = tch;
5726     }
5727 
5728     if (addr == 0 && addrName != NULL)
5729         LOGI("%c%s %s\n", branchTarget ? '>' : ' ', addrName, regChars);
5730     else
5731         LOGI("%c0x%04x %s\n", branchTarget ? '>' : ' ', addr, regChars);
5732 
5733     if (displayFlags & DRT_SHOW_REF_TYPES) {
5734         for (i = 0; i < regCount + kExtraRegs; i++) {
5735             if (regTypeIsReference(addrRegs[i]) && addrRegs[i] != kRegTypeZero)
5736             {
5737                 ClassObject* clazz;
5738 
5739                 clazz = regTypeReferenceToClass(addrRegs[i], uninitMap);
5740                 assert(dvmValidateObject((Object*)clazz));
5741                 if (i < regCount) {
5742                     LOGI("        %2d: 0x%08x %s%s\n",
5743                         i, addrRegs[i],
5744                         regTypeIsUninitReference(addrRegs[i]) ? "[U]" : "",
5745                         clazz->descriptor);
5746                 } else {
5747                     LOGI("        RS: 0x%08x %s%s\n",
5748                         addrRegs[i],
5749                         regTypeIsUninitReference(addrRegs[i]) ? "[U]" : "",
5750                         clazz->descriptor);
5751                 }
5752             }
5753         }
5754     }
5755     if (displayFlags & DRT_SHOW_LOCALS) {
5756         dexDecodeDebugInfo(meth->clazz->pDvmDex->pDexFile,
5757                 dvmGetMethodCode(meth),
5758                 meth->clazz->descriptor,
5759                 meth->prototype.protoIdx,
5760                 meth->accessFlags,
5761                 NULL, logLocalsCb, &addr);
5762     }
5763 }
5764 
5765