CodeVerify.cpp revision 9a05976eec8b0644e7cd9f4d4e4ecd0e73e19dd8
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 */
40enum 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
59static 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 */
74typedef 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
108static void checkMergeTab();
109#endif
110static bool isInitMethod(const Method* meth);
111static RegType getInvocationThis(const RegisterLine* registerLine,\
112    const DecodedInstruction* pDecInsn, VerifyError* pFailure);
113static void verifyRegisterType(RegisterLine* registerLine, \
114    u4 vsrc, RegType checkType, VerifyError* pFailure);
115static bool doCodeVerification(VerifierData* vdata, RegisterTable* regTable);
116static bool verifyInstruction(const Method* meth, InsnFlags* insnFlags,\
117    RegisterTable* regTable, int insnIdx, UninitInstanceMap* uninitMap,
118    int* pStartGuess);
119static ClassObject* findCommonSuperclass(ClassObject* c1, ClassObject* c2);
120static 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" */
125enum {
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 */
186const 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 */
246static 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 */
267static 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 */
311static 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 */
334static 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 */
342static 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 */
365static 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 */
387static 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 */
421UninitInstanceMap* 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 */
476void 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 */
491static 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 */
525static 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) */
533static 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 */
539static 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") */
545static 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 */
557static 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 */
563static 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 */
576static inline RegType regTypeFromClass(ClassObject* clazz) {
577    return (u4) clazz;
578}
579
580/* return the RegType for the uninitialized reference in slot "uidx" */
581static 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 */
595static 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
604static 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 */
615static 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 */
702static 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 */
737static 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 */
777static 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
941bad_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 */
960static 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 */
1020static 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 */
1066static 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 */
1103static 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
1353bad_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
1361fail:
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 */
1377static 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 */
1413static 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 */
1426static 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
1453bail:
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 */
1467static 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
1487bail:
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 */
1501static 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 */
1586static 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 */
1708static 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 */
1721static 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 */
1758static 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 */
1781static inline RegisterLine* getRegisterLine(const RegisterTable* regTable,
1782    int insnIdx)
1783{
1784    return &regTable->registerLines[insnIdx];
1785}
1786
1787/*
1788 * Copy a register line.
1789 */
1790static 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 */
1810static 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 */
1821static 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 */
1837static 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 */
1878enum 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 */
1897static 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 */
1957static 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 */
1967static 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 */
1988static 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 */
2008static 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 */
2033static 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 */
2061static 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 */
2084static 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 */
2108static 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 */
2130static 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 */
2148static 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 */
2196static 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 */
2292static 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 */
2310static 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 */
2372static 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 */
2462static 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 */
2494static 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 */
2562static 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 */
2580static 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 */
2688static 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
2749bail:
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 */
2759static 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
2778bail:
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 */
2788static 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 */
2831static 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 */
2861static 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 */
2889static 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 */
2912static 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 */
2991static 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 */
3022static 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 */
3161static 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 */
3181static 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 */
3239static 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 */
3347void 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 */
3380void 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 */
3440static 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 */
3451bool 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
3549bail:
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 */
3606static 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
3777bail:
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 */
3796static 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;
4455aget_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;
4625aput_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;
4791iget_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;
4895iput_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;
5061sget_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;
5161sput_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
6055bail:
6056    return result;
6057}
6058
6059
6060/*
6061 * callback function used in dumpRegTypes to print local vars
6062 * valid at a given address.
6063 */
6064static 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 */
6079static 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