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