CodeVerify.cpp revision 5a459d4a923cd2160026cc58e4d3da0858028320
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 LOGE("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, 0 }, 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 || opcode == OP_NEW_INSTANCE_JUMBO) 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 //LOGI("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 LOGV("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 LOGI("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 LOGV("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 LOGE("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 LOGE("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 //LOGD("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 LOGE("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 //LOGD("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 // LOGD("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 ®Table->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 //LOGI(" 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. We could 2837 * do something special if we can definitively identify it as a 2838 * float, but there's no real value in doing so. 2839 */ 2840 checkTypeCategory(regType, kTypeCategory1nr, pFailure); 2841 if (!VERIFY_OK(*pFailure)) { 2842 LOG_VFY_METH(meth, "Invalid reg type for array index (%d)", 2843 regType); 2844 } 2845 } 2846} 2847 2848/* 2849 * Check constraints on constructor return. Specifically, make sure that 2850 * the "this" argument got initialized. 2851 * 2852 * The "this" argument to <init> uses code offset kUninitThisArgAddr, which 2853 * puts it at the start of the list in slot 0. If we see a register with 2854 * an uninitialized slot 0 reference, we know it somehow didn't get 2855 * initialized. 2856 * 2857 * Returns "true" if all is well. 2858 */ 2859static bool checkConstructorReturn(const Method* meth, 2860 const RegisterLine* registerLine, const int insnRegCount) 2861{ 2862 const RegType* insnRegs = registerLine->regTypes; 2863 int i; 2864 2865 if (!isInitMethod(meth)) 2866 return true; 2867 2868 RegType uninitThis = regTypeFromUninitIndex(kUninitThisArgSlot); 2869 2870 for (i = 0; i < insnRegCount; i++) { 2871 if (insnRegs[i] == uninitThis) { 2872 LOG_VFY("VFY: <init> returning without calling superclass init"); 2873 return false; 2874 } 2875 } 2876 return true; 2877} 2878 2879/* 2880 * Verify that the target instruction is not "move-exception". It's important 2881 * that the only way to execute a move-exception is as the first instruction 2882 * of an exception handler. 2883 * 2884 * Returns "true" if all is well, "false" if the target instruction is 2885 * move-exception. 2886 */ 2887static bool checkMoveException(const Method* meth, int insnIdx, 2888 const char* logNote) 2889{ 2890 assert(insnIdx >= 0 && insnIdx < (int)dvmGetMethodInsnsSize(meth)); 2891 2892 if ((meth->insns[insnIdx] & 0xff) == OP_MOVE_EXCEPTION) { 2893 LOG_VFY("VFY: invalid use of move-exception"); 2894 return false; 2895 } 2896 return true; 2897} 2898 2899/* 2900 * For the "move-exception" instruction at "insnIdx", which must be at an 2901 * exception handler address, determine the first common superclass of 2902 * all exceptions that can land here. (For javac output, we're probably 2903 * looking at multiple spans of bytecode covered by one "try" that lands 2904 * at an exception-specific "catch", but in general the handler could be 2905 * shared for multiple exceptions.) 2906 * 2907 * Returns NULL if no matching exception handler can be found, or if the 2908 * exception is not a subclass of Throwable. 2909 */ 2910static ClassObject* getCaughtExceptionType(const Method* meth, int insnIdx, 2911 VerifyError* pFailure) 2912{ 2913 VerifyError localFailure; 2914 const DexCode* pCode; 2915 DexFile* pDexFile; 2916 ClassObject* commonSuper = NULL; 2917 u4 handlersSize; 2918 u4 offset; 2919 u4 i; 2920 2921 pDexFile = meth->clazz->pDvmDex->pDexFile; 2922 pCode = dvmGetMethodCode(meth); 2923 2924 if (pCode->triesSize != 0) { 2925 handlersSize = dexGetHandlersSize(pCode); 2926 offset = dexGetFirstHandlerOffset(pCode); 2927 } else { 2928 handlersSize = 0; 2929 offset = 0; 2930 } 2931 2932 for (i = 0; i < handlersSize; i++) { 2933 DexCatchIterator iterator; 2934 dexCatchIteratorInit(&iterator, pCode, offset); 2935 2936 for (;;) { 2937 const DexCatchHandler* handler = dexCatchIteratorNext(&iterator); 2938 2939 if (handler == NULL) { 2940 break; 2941 } 2942 2943 if (handler->address == (u4) insnIdx) { 2944 ClassObject* clazz; 2945 2946 if (handler->typeIdx == kDexNoIndex) 2947 clazz = gDvm.exThrowable; 2948 else 2949 clazz = dvmOptResolveClass(meth->clazz, handler->typeIdx, 2950 &localFailure); 2951 2952 if (clazz == NULL) { 2953 LOG_VFY("VFY: unable to resolve exception class %u (%s)", 2954 handler->typeIdx, 2955 dexStringByTypeIdx(pDexFile, handler->typeIdx)); 2956 /* TODO: do we want to keep going? If we don't fail 2957 * this we run the risk of having a non-Throwable 2958 * introduced at runtime. However, that won't pass 2959 * an instanceof test, so is essentially harmless. */ 2960 } else { 2961 if (commonSuper == NULL) 2962 commonSuper = clazz; 2963 else 2964 commonSuper = findCommonSuperclass(clazz, commonSuper); 2965 } 2966 } 2967 } 2968 2969 offset = dexCatchIteratorGetEndOffset(&iterator, pCode); 2970 } 2971 2972 if (commonSuper == NULL) { 2973 /* no catch blocks, or no catches with classes we can find */ 2974 LOG_VFY_METH(meth, 2975 "VFY: unable to find exception handler at addr %#x", insnIdx); 2976 *pFailure = VERIFY_ERROR_GENERIC; 2977 } else { 2978 // TODO: verify the class is an instance of Throwable? 2979 } 2980 2981 return commonSuper; 2982} 2983 2984/* 2985 * Helper for initRegisterTable. 2986 * 2987 * Returns an updated copy of "storage". 2988 */ 2989static u1* assignLineStorage(u1* storage, RegisterLine* line, 2990 bool trackMonitors, size_t regTypeSize, size_t monEntSize, size_t stackSize) 2991{ 2992 line->regTypes = (RegType*) storage; 2993 storage += regTypeSize; 2994 2995 if (trackMonitors) { 2996 line->monitorEntries = (MonitorEntries*) storage; 2997 storage += monEntSize; 2998 line->monitorStack = (u4*) storage; 2999 storage += stackSize; 3000 3001 assert(line->monitorStackTop == 0); 3002 } 3003 3004 return storage; 3005} 3006 3007/* 3008 * Initialize the RegisterTable. 3009 * 3010 * Every instruction address can have a different set of information about 3011 * what's in which register, but for verification purposes we only need to 3012 * store it at branch target addresses (because we merge into that). 3013 * 3014 * By zeroing out the regType storage we are effectively initializing the 3015 * register information to kRegTypeUnknown. 3016 * 3017 * We jump through some hoops here to minimize the total number of 3018 * allocations we have to perform per method verified. 3019 */ 3020static bool initRegisterTable(const VerifierData* vdata, 3021 RegisterTable* regTable, RegisterTrackingMode trackRegsFor) 3022{ 3023 const Method* meth = vdata->method; 3024 const int insnsSize = vdata->insnsSize; 3025 const InsnFlags* insnFlags = vdata->insnFlags; 3026 const int kExtraLines = 2; /* workLine, savedLine */ 3027 int i; 3028 3029 /* 3030 * Every address gets a RegisterLine struct. This is wasteful, but 3031 * not so much that it's worth chasing through an extra level of 3032 * indirection. 3033 */ 3034 regTable->insnRegCountPlus = meth->registersSize + kExtraRegs; 3035 regTable->registerLines = 3036 (RegisterLine*) calloc(insnsSize, sizeof(RegisterLine)); 3037 if (regTable->registerLines == NULL) 3038 return false; 3039 3040 assert(insnsSize > 0); 3041 3042 /* 3043 * Count up the number of "interesting" instructions. 3044 * 3045 * "All" means "every address that holds the start of an instruction". 3046 * "Branches" and "GcPoints" mean just those addresses. 3047 * 3048 * "GcPoints" fills about half the addresses, "Branches" about 15%. 3049 */ 3050 int interestingCount = kExtraLines; 3051 3052 for (i = 0; i < insnsSize; i++) { 3053 bool interesting; 3054 3055 switch (trackRegsFor) { 3056 case kTrackRegsAll: 3057 interesting = dvmInsnIsOpcode(insnFlags, i); 3058 break; 3059 case kTrackRegsGcPoints: 3060 interesting = dvmInsnIsGcPoint(insnFlags, i) || 3061 dvmInsnIsBranchTarget(insnFlags, i); 3062 break; 3063 case kTrackRegsBranches: 3064 interesting = dvmInsnIsBranchTarget(insnFlags, i); 3065 break; 3066 default: 3067 dvmAbort(); 3068 return false; 3069 } 3070 3071 if (interesting) 3072 interestingCount++; 3073 3074 /* count instructions, for display only */ 3075 //if (dvmInsnIsOpcode(insnFlags, i)) 3076 // insnCount++; 3077 } 3078 3079 /* 3080 * Allocate storage for the register type arrays. 3081 * TODO: set trackMonitors based on global config option 3082 */ 3083 size_t regTypeSize = regTable->insnRegCountPlus * sizeof(RegType); 3084 size_t monEntSize = regTable->insnRegCountPlus * sizeof(MonitorEntries); 3085 size_t stackSize = kMaxMonitorStackDepth * sizeof(u4); 3086 bool trackMonitors; 3087 3088 if (gDvm.monitorVerification) { 3089 trackMonitors = (vdata->monitorEnterCount != 0); 3090 } else { 3091 trackMonitors = false; 3092 } 3093 3094 size_t spacePerEntry = regTypeSize + 3095 (trackMonitors ? monEntSize + stackSize : 0); 3096 regTable->lineAlloc = calloc(interestingCount, spacePerEntry); 3097 if (regTable->lineAlloc == NULL) 3098 return false; 3099 3100#ifdef VERIFIER_STATS 3101 size_t totalSpace = interestingCount * spacePerEntry + 3102 insnsSize * sizeof(RegisterLine); 3103 if (gDvm.verifierStats.biggestAlloc < totalSpace) 3104 gDvm.verifierStats.biggestAlloc = totalSpace; 3105#endif 3106 3107 /* 3108 * Populate the sparse register line table. 3109 * 3110 * There is a RegisterLine associated with every address, but not 3111 * every RegisterLine has non-NULL pointers to storage for its fields. 3112 */ 3113 u1* storage = (u1*)regTable->lineAlloc; 3114 for (i = 0; i < insnsSize; i++) { 3115 bool interesting; 3116 3117 switch (trackRegsFor) { 3118 case kTrackRegsAll: 3119 interesting = dvmInsnIsOpcode(insnFlags, i); 3120 break; 3121 case kTrackRegsGcPoints: 3122 interesting = dvmInsnIsGcPoint(insnFlags, i) || 3123 dvmInsnIsBranchTarget(insnFlags, i); 3124 break; 3125 case kTrackRegsBranches: 3126 interesting = dvmInsnIsBranchTarget(insnFlags, i); 3127 break; 3128 default: 3129 dvmAbort(); 3130 return false; 3131 } 3132 3133 if (interesting) { 3134 storage = assignLineStorage(storage, ®Table->registerLines[i], 3135 trackMonitors, regTypeSize, monEntSize, stackSize); 3136 } 3137 } 3138 3139 /* 3140 * Grab storage for our "temporary" register lines. 3141 */ 3142 storage = assignLineStorage(storage, ®Table->workLine, 3143 trackMonitors, regTypeSize, monEntSize, stackSize); 3144 storage = assignLineStorage(storage, ®Table->savedLine, 3145 trackMonitors, regTypeSize, monEntSize, stackSize); 3146 3147 //LOGD("Tracking registers for [%d], total %d in %d units", 3148 // trackRegsFor, interestingCount-kExtraLines, insnsSize); 3149 3150 assert(storage - (u1*)regTable->lineAlloc == 3151 (int) (interestingCount * spacePerEntry)); 3152 assert(regTable->registerLines[0].regTypes != NULL); 3153 return true; 3154} 3155 3156/* 3157 * Free up any "hairy" structures associated with register lines. 3158 */ 3159static void freeRegisterLineInnards(VerifierData* vdata) 3160{ 3161 unsigned int idx; 3162 3163 if (vdata->registerLines == NULL) 3164 return; 3165 3166 for (idx = 0; idx < vdata->insnsSize; idx++) { 3167 BitVector* liveRegs = vdata->registerLines[idx].liveRegs; 3168 if (liveRegs != NULL) 3169 dvmFreeBitVector(liveRegs); 3170 } 3171} 3172 3173 3174/* 3175 * Verify that the arguments in a filled-new-array instruction are valid. 3176 * 3177 * "resClass" is the class refered to by pDecInsn->vB. 3178 */ 3179static void verifyFilledNewArrayRegs(const Method* meth, 3180 RegisterLine* registerLine, const DecodedInstruction* pDecInsn, 3181 ClassObject* resClass, bool isRange, VerifyError* pFailure) 3182{ 3183 u4 argCount = pDecInsn->vA; 3184 RegType expectedType; 3185 PrimitiveType elemType; 3186 unsigned int ui; 3187 3188 assert(dvmIsArrayClass(resClass)); 3189 elemType = resClass->elementClass->primitiveType; 3190 if (elemType == PRIM_NOT) { 3191 expectedType = regTypeFromClass(resClass->elementClass); 3192 } else { 3193 expectedType = primitiveTypeToRegType(elemType); 3194 } 3195 //LOGI("filled-new-array: %s -> %d", resClass->descriptor, expectedType); 3196 3197 /* 3198 * Verify each register. If "argCount" is bad, verifyRegisterType() 3199 * will run off the end of the list and fail. It's legal, if silly, 3200 * for argCount to be zero. 3201 */ 3202 for (ui = 0; ui < argCount; ui++) { 3203 u4 getReg; 3204 3205 if (isRange) 3206 getReg = pDecInsn->vC + ui; 3207 else 3208 getReg = pDecInsn->arg[ui]; 3209 3210 verifyRegisterType(registerLine, getReg, expectedType, pFailure); 3211 if (!VERIFY_OK(*pFailure)) { 3212 LOG_VFY("VFY: filled-new-array arg %u(%u) not valid", ui, getReg); 3213 return; 3214 } 3215 } 3216} 3217 3218 3219/* 3220 * Replace an instruction with "throw-verification-error". This allows us to 3221 * defer error reporting until the code path is first used. 3222 * 3223 * This is expected to be called during "just in time" verification, not 3224 * from within dexopt. (Verification failures in dexopt will result in 3225 * postponement of verification to first use of the class.) 3226 * 3227 * The throw-verification-error instruction requires two code units. Some 3228 * of the replaced instructions require three; the third code unit will 3229 * receive a "nop". The instruction's length will be left unchanged 3230 * in "insnFlags". If the erroring instruction is a jumbo instruction, 3231 * the throw-verification-error-jumbo instruction requires four code units. 3232 * Some jumbo instructions require five, and the fifth code unit will become 3233 * a "nop". 3234 * 3235 * The VM postpones setting of debugger breakpoints in unverified classes, 3236 * so there should be no clashes with the debugger. 3237 * 3238 * Returns "true" on success. 3239 */ 3240static bool replaceFailingInstruction(const Method* meth, InsnFlags* insnFlags, 3241 int insnIdx, VerifyError failure) 3242{ 3243 VerifyErrorRefType refType; 3244 u2* oldInsns = (u2*) meth->insns + insnIdx; 3245 int width; 3246 bool result = false; 3247 3248 if (gDvm.optimizing) 3249 LOGD("Weird: RFI during dexopt?"); 3250 3251 /* 3252 * Generate the new instruction out of the old. 3253 * 3254 * First, make sure this is an instruction we're expecting to stomp on. 3255 */ 3256 Opcode opcode = dexOpcodeFromCodeUnit(*oldInsns); 3257 switch (opcode) { 3258 case OP_CONST_CLASS: // insn[1] == class ref, 2 bytes 3259 case OP_CHECK_CAST: 3260 case OP_INSTANCE_OF: 3261 case OP_NEW_INSTANCE: 3262 case OP_NEW_ARRAY: 3263 case OP_FILLED_NEW_ARRAY: // insn[1] == class ref, 3 bytes 3264 case OP_FILLED_NEW_ARRAY_RANGE: 3265 case OP_CONST_CLASS_JUMBO: // insn[1/2] == class ref, 4 bytes 3266 case OP_CHECK_CAST_JUMBO: 3267 case OP_NEW_INSTANCE_JUMBO: 3268 case OP_INSTANCE_OF_JUMBO: // insn[1/2] == class ref, 5 bytes 3269 case OP_NEW_ARRAY_JUMBO: 3270 case OP_FILLED_NEW_ARRAY_JUMBO: 3271 refType = VERIFY_ERROR_REF_CLASS; 3272 break; 3273 3274 case OP_IGET: // insn[1] == field ref, 2 bytes 3275 case OP_IGET_BOOLEAN: 3276 case OP_IGET_BYTE: 3277 case OP_IGET_CHAR: 3278 case OP_IGET_SHORT: 3279 case OP_IGET_WIDE: 3280 case OP_IGET_OBJECT: 3281 case OP_IPUT: 3282 case OP_IPUT_BOOLEAN: 3283 case OP_IPUT_BYTE: 3284 case OP_IPUT_CHAR: 3285 case OP_IPUT_SHORT: 3286 case OP_IPUT_WIDE: 3287 case OP_IPUT_OBJECT: 3288 case OP_SGET: 3289 case OP_SGET_BOOLEAN: 3290 case OP_SGET_BYTE: 3291 case OP_SGET_CHAR: 3292 case OP_SGET_SHORT: 3293 case OP_SGET_WIDE: 3294 case OP_SGET_OBJECT: 3295 case OP_SPUT: 3296 case OP_SPUT_BOOLEAN: 3297 case OP_SPUT_BYTE: 3298 case OP_SPUT_CHAR: 3299 case OP_SPUT_SHORT: 3300 case OP_SPUT_WIDE: 3301 case OP_SPUT_OBJECT: 3302 case OP_SGET_JUMBO: // insn[1/2] == field ref, 4 bytes 3303 case OP_SGET_BOOLEAN_JUMBO: 3304 case OP_SGET_BYTE_JUMBO: 3305 case OP_SGET_CHAR_JUMBO: 3306 case OP_SGET_SHORT_JUMBO: 3307 case OP_SGET_WIDE_JUMBO: 3308 case OP_SGET_OBJECT_JUMBO: 3309 case OP_SPUT_JUMBO: 3310 case OP_SPUT_BOOLEAN_JUMBO: 3311 case OP_SPUT_BYTE_JUMBO: 3312 case OP_SPUT_CHAR_JUMBO: 3313 case OP_SPUT_SHORT_JUMBO: 3314 case OP_SPUT_WIDE_JUMBO: 3315 case OP_SPUT_OBJECT_JUMBO: 3316 case OP_IGET_JUMBO: // insn[1/2] == field ref, 5 bytes 3317 case OP_IGET_BOOLEAN_JUMBO: 3318 case OP_IGET_BYTE_JUMBO: 3319 case OP_IGET_CHAR_JUMBO: 3320 case OP_IGET_SHORT_JUMBO: 3321 case OP_IGET_WIDE_JUMBO: 3322 case OP_IGET_OBJECT_JUMBO: 3323 case OP_IPUT_JUMBO: 3324 case OP_IPUT_BOOLEAN_JUMBO: 3325 case OP_IPUT_BYTE_JUMBO: 3326 case OP_IPUT_CHAR_JUMBO: 3327 case OP_IPUT_SHORT_JUMBO: 3328 case OP_IPUT_WIDE_JUMBO: 3329 case OP_IPUT_OBJECT_JUMBO: 3330 refType = VERIFY_ERROR_REF_FIELD; 3331 break; 3332 3333 case OP_INVOKE_VIRTUAL: // insn[1] == method ref, 3 bytes 3334 case OP_INVOKE_VIRTUAL_RANGE: 3335 case OP_INVOKE_SUPER: 3336 case OP_INVOKE_SUPER_RANGE: 3337 case OP_INVOKE_DIRECT: 3338 case OP_INVOKE_DIRECT_RANGE: 3339 case OP_INVOKE_STATIC: 3340 case OP_INVOKE_STATIC_RANGE: 3341 case OP_INVOKE_INTERFACE: 3342 case OP_INVOKE_INTERFACE_RANGE: 3343 case OP_INVOKE_VIRTUAL_JUMBO: // insn[1/2] == method ref, 5 bytes 3344 case OP_INVOKE_SUPER_JUMBO: 3345 case OP_INVOKE_DIRECT_JUMBO: 3346 case OP_INVOKE_STATIC_JUMBO: 3347 case OP_INVOKE_INTERFACE_JUMBO: 3348 refType = VERIFY_ERROR_REF_METHOD; 3349 break; 3350 3351 default: 3352 /* could handle this in a generic way, but this is probably safer */ 3353 LOG_VFY("GLITCH: verifier asked to replace opcode 0x%02x", opcode); 3354 goto bail; 3355 } 3356 3357 assert((dexGetFlagsFromOpcode(opcode) & kInstrCanThrow) != 0); 3358 3359 /* write a NOP over the third code unit, if necessary */ 3360 width = dvmInsnGetWidth(insnFlags, insnIdx); 3361 switch (width) { 3362 case 2: 3363 case 4: 3364 /* nothing to do */ 3365 break; 3366 case 3: 3367 dvmUpdateCodeUnit(meth, oldInsns+2, OP_NOP); 3368 break; 3369 case 5: 3370 dvmUpdateCodeUnit(meth, oldInsns+4, OP_NOP); 3371 break; 3372 default: 3373 /* whoops */ 3374 LOGE("ERROR: stomped a %d-unit instruction with a verifier error", 3375 width); 3376 dvmAbort(); 3377 } 3378 3379 /* check for jumbo opcodes */ 3380 if (opcode > OP_DISPATCH_FF) { 3381 /* replace opcode and failure code */ 3382 assert(width == 4 || width == 5); 3383 u2 newVal = (u2) ((OP_THROW_VERIFICATION_ERROR_JUMBO << 8) | 3384 OP_DISPATCH_FF); 3385 dvmUpdateCodeUnit(meth, oldInsns, newVal); 3386 newVal = failure | (refType << kVerifyErrorRefTypeShift); 3387 dvmUpdateCodeUnit(meth, oldInsns+3, newVal); 3388 } else { 3389 /* encode the opcode, with the failure code in the high byte */ 3390 assert(width == 2 || width == 3); 3391 u2 newVal = OP_THROW_VERIFICATION_ERROR | 3392 (failure << 8) | (refType << (8 + kVerifyErrorRefTypeShift)); 3393 dvmUpdateCodeUnit(meth, oldInsns, newVal); 3394 } 3395 3396 result = true; 3397 3398bail: 3399 return result; 3400} 3401 3402/* 3403 * Handle a monitor-enter instruction. 3404 */ 3405void handleMonitorEnter(RegisterLine* workLine, u4 regIdx, u4 insnIdx, 3406 VerifyError* pFailure) 3407{ 3408 if (!regTypeIsReference(getRegisterType(workLine, regIdx))) { 3409 LOG_VFY("VFY: monitor-enter on non-object"); 3410 *pFailure = VERIFY_ERROR_GENERIC; 3411 return; 3412 } 3413 3414 if (workLine->monitorEntries == NULL) { 3415 /* should only be true if monitor verification is disabled */ 3416 assert(!gDvm.monitorVerification); 3417 return; 3418 } 3419 3420 if (workLine->monitorStackTop == kMaxMonitorStackDepth) { 3421 LOG_VFY("VFY: monitor-enter stack overflow (%d)", 3422 kMaxMonitorStackDepth); 3423 *pFailure = VERIFY_ERROR_GENERIC; 3424 return; 3425 } 3426 3427 /* 3428 * Push an entry on the stack, and set a bit in the register flags to 3429 * indicate that it's associated with this register. 3430 */ 3431 workLine->monitorEntries[regIdx] |= 1 << workLine->monitorStackTop; 3432 workLine->monitorStack[workLine->monitorStackTop++] = insnIdx; 3433} 3434 3435/* 3436 * Handle a monitor-exit instruction. 3437 */ 3438void handleMonitorExit(RegisterLine* workLine, u4 regIdx, u4 insnIdx, 3439 VerifyError* pFailure) 3440{ 3441 if (!regTypeIsReference(getRegisterType(workLine, regIdx))) { 3442 LOG_VFY("VFY: monitor-exit on non-object"); 3443 *pFailure = VERIFY_ERROR_GENERIC; 3444 return; 3445 } 3446 3447 if (workLine->monitorEntries == NULL) { 3448 /* should only be true if monitor verification is disabled */ 3449 assert(!gDvm.monitorVerification); 3450 return; 3451 } 3452 3453 if (workLine->monitorStackTop == 0) { 3454 LOG_VFY("VFY: monitor-exit stack underflow"); 3455 *pFailure = VERIFY_ERROR_GENERIC; 3456 return; 3457 } 3458 3459 /* 3460 * Confirm that the entry at the top of the stack is associated with 3461 * the register. Pop the top entry off. 3462 */ 3463 workLine->monitorStackTop--; 3464#ifdef BUG_3215458_FIXED 3465 /* 3466 * TODO: This code can safely be enabled if know we are working on 3467 * a dex file of format version 036 or later. (That is, we'll need to 3468 * add a check for the version number.) 3469 */ 3470 if ((workLine->monitorEntries[regIdx] & (1 << workLine->monitorStackTop)) 3471 == 0) 3472 { 3473 LOG_VFY("VFY: monitor-exit bit %d not set: addr=0x%04x (bits[%d]=%#x)", 3474 workLine->monitorStackTop, insnIdx, regIdx, 3475 workLine->monitorEntries[regIdx]); 3476 *pFailure = VERIFY_ERROR_GENERIC; 3477 return; 3478 } 3479#endif 3480 workLine->monitorStack[workLine->monitorStackTop] = 0; 3481 3482 /* 3483 * Clear the bit from the register flags. 3484 */ 3485 workLine->monitorEntries[regIdx] &= ~(1 << workLine->monitorStackTop); 3486} 3487 3488 3489/* 3490 * =========================================================================== 3491 * Entry point and driver loop 3492 * =========================================================================== 3493 */ 3494 3495/* 3496 * One-time preparation. 3497 */ 3498static void verifyPrep() 3499{ 3500#ifndef NDEBUG 3501 /* only need to do this if the table was updated */ 3502 checkMergeTab(); 3503#endif 3504} 3505 3506/* 3507 * Entry point for the detailed code-flow analysis of a single method. 3508 */ 3509bool dvmVerifyCodeFlow(VerifierData* vdata) 3510{ 3511 bool result = false; 3512 const Method* meth = vdata->method; 3513 const int insnsSize = vdata->insnsSize; 3514 const bool generateRegisterMap = gDvm.generateRegisterMaps; 3515 RegisterTable regTable; 3516 3517 memset(®Table, 0, sizeof(regTable)); 3518 3519#ifdef VERIFIER_STATS 3520 gDvm.verifierStats.methodsExamined++; 3521 if (vdata->monitorEnterCount) 3522 gDvm.verifierStats.monEnterMethods++; 3523#endif 3524 3525 /* TODO: move this elsewhere -- we don't need to do this for every method */ 3526 verifyPrep(); 3527 3528 if (meth->registersSize * insnsSize > 4*1024*1024) { 3529 LOG_VFY_METH(meth, 3530 "VFY: warning: method is huge (regs=%d insnsSize=%d)", 3531 meth->registersSize, insnsSize); 3532 /* might be bogus data, might be some huge generated method */ 3533 } 3534 3535 /* 3536 * Create register lists, and initialize them to "Unknown". If we're 3537 * also going to create the register map, we need to retain the 3538 * register lists for a larger set of addresses. 3539 */ 3540 if (!initRegisterTable(vdata, ®Table, 3541 generateRegisterMap ? kTrackRegsGcPoints : kTrackRegsBranches)) 3542 goto bail; 3543 3544 vdata->registerLines = regTable.registerLines; 3545 3546 /* 3547 * Perform liveness analysis. 3548 * 3549 * We can do this before or after the main verifier pass. The choice 3550 * affects whether or not we see the effects of verifier instruction 3551 * changes, i.e. substitution of throw-verification-error. 3552 * 3553 * In practice the ordering doesn't really matter, because T-V-E 3554 * just prunes "can continue", creating regions of dead code (with 3555 * corresponding register map data that will never be used). 3556 */ 3557 if (generateRegisterMap && 3558 gDvm.registerMapMode == kRegisterMapModeLivePrecise) 3559 { 3560 /* 3561 * Compute basic blocks and predecessor lists. 3562 */ 3563 if (!dvmComputeVfyBasicBlocks(vdata)) 3564 goto bail; 3565 3566 /* 3567 * Compute liveness. 3568 */ 3569 if (!dvmComputeLiveness(vdata)) 3570 goto bail; 3571 } 3572 3573 /* 3574 * Initialize the types of the registers that correspond to the 3575 * method arguments. We can determine this from the method signature. 3576 */ 3577 if (!setTypesFromSignature(meth, regTable.registerLines[0].regTypes, 3578 vdata->uninitMap)) 3579 goto bail; 3580 3581 /* 3582 * Run the verifier. 3583 */ 3584 if (!doCodeVerification(vdata, ®Table)) 3585 goto bail; 3586 3587 /* 3588 * Generate a register map. 3589 */ 3590 if (generateRegisterMap) { 3591 RegisterMap* pMap = dvmGenerateRegisterMapV(vdata); 3592 if (pMap != NULL) { 3593 /* 3594 * Tuck it into the Method struct. It will either get used 3595 * directly or, if we're in dexopt, will be packed up and 3596 * appended to the DEX file. 3597 */ 3598 dvmSetRegisterMap((Method*)meth, pMap); 3599 } 3600 } 3601 3602 /* 3603 * Success. 3604 */ 3605 result = true; 3606 3607bail: 3608 freeRegisterLineInnards(vdata); 3609 free(regTable.registerLines); 3610 free(regTable.lineAlloc); 3611 return result; 3612} 3613 3614/* 3615 * Grind through the instructions. 3616 * 3617 * The basic strategy is as outlined in v3 4.11.1.2: set the "changed" bit 3618 * on the first instruction, process it (setting additional "changed" bits), 3619 * and repeat until there are no more. 3620 * 3621 * v3 4.11.1.1 3622 * - (N/A) operand stack is always the same size 3623 * - operand stack [registers] contain the correct types of values 3624 * - local variables [registers] contain the correct types of values 3625 * - methods are invoked with the appropriate arguments 3626 * - fields are assigned using values of appropriate types 3627 * - opcodes have the correct type values in operand registers 3628 * - there is never an uninitialized class instance in a local variable in 3629 * code protected by an exception handler (operand stack is okay, because 3630 * the operand stack is discarded when an exception is thrown) [can't 3631 * know what's a local var w/o the debug info -- should fall out of 3632 * register typing] 3633 * 3634 * v3 4.11.1.2 3635 * - execution cannot fall off the end of the code 3636 * 3637 * (We also do many of the items described in the "static checks" sections, 3638 * because it's easier to do them here.) 3639 * 3640 * We need an array of RegType values, one per register, for every 3641 * instruction. If the method uses monitor-enter, we need extra data 3642 * for every register, and a stack for every "interesting" instruction. 3643 * In theory this could become quite large -- up to several megabytes for 3644 * a monster function. 3645 * 3646 * NOTE: 3647 * The spec forbids backward branches when there's an uninitialized reference 3648 * in a register. The idea is to prevent something like this: 3649 * loop: 3650 * move r1, r0 3651 * new-instance r0, MyClass 3652 * ... 3653 * if-eq rN, loop // once 3654 * initialize r0 3655 * 3656 * This leaves us with two different instances, both allocated by the 3657 * same instruction, but only one is initialized. The scheme outlined in 3658 * v3 4.11.1.4 wouldn't catch this, so they work around it by preventing 3659 * backward branches. We achieve identical results without restricting 3660 * code reordering by specifying that you can't execute the new-instance 3661 * instruction if a register contains an uninitialized instance created 3662 * by that same instrutcion. 3663 */ 3664static bool doCodeVerification(VerifierData* vdata, RegisterTable* regTable) 3665{ 3666 const Method* meth = vdata->method; 3667 InsnFlags* insnFlags = vdata->insnFlags; 3668 UninitInstanceMap* uninitMap = vdata->uninitMap; 3669 const int insnsSize = dvmGetMethodInsnsSize(meth); 3670 bool result = false; 3671 bool debugVerbose = false; 3672 int insnIdx, startGuess; 3673 3674 /* 3675 * Begin by marking the first instruction as "changed". 3676 */ 3677 dvmInsnSetChanged(insnFlags, 0, true); 3678 3679 if (dvmWantVerboseVerification(meth)) { 3680 IF_LOGI() { 3681 char* desc = dexProtoCopyMethodDescriptor(&meth->prototype); 3682 LOGI("Now verifying: %s.%s %s (ins=%d regs=%d)", 3683 meth->clazz->descriptor, meth->name, desc, 3684 meth->insSize, meth->registersSize); 3685 LOGI(" ------ [0 4 8 12 16 20 24 28 32 36"); 3686 free(desc); 3687 } 3688 debugVerbose = true; 3689 gDebugVerbose = true; 3690 } else { 3691 gDebugVerbose = false; 3692 } 3693 3694 startGuess = 0; 3695 3696 /* 3697 * Continue until no instructions are marked "changed". 3698 */ 3699 while (true) { 3700 /* 3701 * Find the first marked one. Use "startGuess" as a way to find 3702 * one quickly. 3703 */ 3704 for (insnIdx = startGuess; insnIdx < insnsSize; insnIdx++) { 3705 if (dvmInsnIsChanged(insnFlags, insnIdx)) 3706 break; 3707 } 3708 3709 if (insnIdx == insnsSize) { 3710 if (startGuess != 0) { 3711 /* try again, starting from the top */ 3712 startGuess = 0; 3713 continue; 3714 } else { 3715 /* all flags are clear */ 3716 break; 3717 } 3718 } 3719 3720 /* 3721 * We carry the working set of registers from instruction to 3722 * instruction. If this address can be the target of a branch 3723 * (or throw) instruction, or if we're skipping around chasing 3724 * "changed" flags, we need to load the set of registers from 3725 * the table. 3726 * 3727 * Because we always prefer to continue on to the next instruction, 3728 * we should never have a situation where we have a stray 3729 * "changed" flag set on an instruction that isn't a branch target. 3730 */ 3731 if (dvmInsnIsBranchTarget(insnFlags, insnIdx)) { 3732 RegisterLine* workLine = ®Table->workLine; 3733 3734 copyLineFromTable(workLine, regTable, insnIdx); 3735 } else { 3736#ifndef NDEBUG 3737 /* 3738 * Sanity check: retrieve the stored register line (assuming 3739 * a full table) and make sure it actually matches. 3740 */ 3741 RegisterLine* registerLine = getRegisterLine(regTable, insnIdx); 3742 if (registerLine->regTypes != NULL && 3743 compareLineToTable(regTable, insnIdx, ®Table->workLine) != 0) 3744 { 3745 char* desc = dexProtoCopyMethodDescriptor(&meth->prototype); 3746 LOG_VFY("HUH? workLine diverged in %s.%s %s", 3747 meth->clazz->descriptor, meth->name, desc); 3748 free(desc); 3749 dumpRegTypes(vdata, registerLine, 0, "work", 3750 uninitMap, DRT_SHOW_REF_TYPES | DRT_SHOW_LOCALS); 3751 dumpRegTypes(vdata, registerLine, 0, "insn", 3752 uninitMap, DRT_SHOW_REF_TYPES | DRT_SHOW_LOCALS); 3753 } 3754#endif 3755 } 3756 if (debugVerbose) { 3757 dumpRegTypes(vdata, ®Table->workLine, insnIdx, 3758 NULL, uninitMap, SHOW_REG_DETAILS); 3759 } 3760 3761 //LOGI("process %s.%s %s %d", 3762 // meth->clazz->descriptor, meth->name, meth->descriptor, insnIdx); 3763 if (!verifyInstruction(meth, insnFlags, regTable, insnIdx, 3764 uninitMap, &startGuess)) 3765 { 3766 //LOGD("+++ %s bailing at %d", meth->name, insnIdx); 3767 goto bail; 3768 } 3769 3770 /* 3771 * Clear "changed" and mark as visited. 3772 */ 3773 dvmInsnSetVisited(insnFlags, insnIdx, true); 3774 dvmInsnSetChanged(insnFlags, insnIdx, false); 3775 } 3776 3777 if (DEAD_CODE_SCAN && !IS_METHOD_FLAG_SET(meth, METHOD_ISWRITABLE)) { 3778 /* 3779 * Scan for dead code. There's nothing "evil" about dead code 3780 * (besides the wasted space), but it indicates a flaw somewhere 3781 * down the line, possibly in the verifier. 3782 * 3783 * If we've substituted "always throw" instructions into the stream, 3784 * we are almost certainly going to have some dead code. 3785 */ 3786 int deadStart = -1; 3787 for (insnIdx = 0; insnIdx < insnsSize; 3788 insnIdx += dvmInsnGetWidth(insnFlags, insnIdx)) 3789 { 3790 /* 3791 * Switch-statement data doesn't get "visited" by scanner. It 3792 * may or may not be preceded by a padding NOP (for alignment). 3793 */ 3794 int instr = meth->insns[insnIdx]; 3795 if (instr == kPackedSwitchSignature || 3796 instr == kSparseSwitchSignature || 3797 instr == kArrayDataSignature || 3798 (instr == OP_NOP && 3799 (meth->insns[insnIdx+1] == kPackedSwitchSignature || 3800 meth->insns[insnIdx+1] == kSparseSwitchSignature || 3801 meth->insns[insnIdx+1] == kArrayDataSignature))) 3802 { 3803 dvmInsnSetVisited(insnFlags, insnIdx, true); 3804 } 3805 3806 if (!dvmInsnIsVisited(insnFlags, insnIdx)) { 3807 if (deadStart < 0) 3808 deadStart = insnIdx; 3809 } else if (deadStart >= 0) { 3810 IF_LOGD() { 3811 char* desc = 3812 dexProtoCopyMethodDescriptor(&meth->prototype); 3813 LOGD("VFY: dead code 0x%04x-%04x in %s.%s %s", 3814 deadStart, insnIdx-1, 3815 meth->clazz->descriptor, meth->name, desc); 3816 free(desc); 3817 } 3818 3819 deadStart = -1; 3820 } 3821 } 3822 if (deadStart >= 0) { 3823 IF_LOGD() { 3824 char* desc = dexProtoCopyMethodDescriptor(&meth->prototype); 3825 LOGD("VFY: dead code 0x%04x-%04x in %s.%s %s", 3826 deadStart, insnIdx-1, 3827 meth->clazz->descriptor, meth->name, desc); 3828 free(desc); 3829 } 3830 } 3831 } 3832 3833 result = true; 3834 3835bail: 3836 return result; 3837} 3838 3839 3840/* 3841 * Perform verification for a single instruction. 3842 * 3843 * This requires fully decoding the instruction to determine the effect 3844 * it has on registers. 3845 * 3846 * Finds zero or more following instructions and sets the "changed" flag 3847 * if execution at that point needs to be (re-)evaluated. Register changes 3848 * are merged into "regTypes" at the target addresses. Does not set or 3849 * clear any other flags in "insnFlags". 3850 * 3851 * This may alter meth->insns if we need to replace an instruction with 3852 * throw-verification-error. 3853 */ 3854static bool verifyInstruction(const Method* meth, InsnFlags* insnFlags, 3855 RegisterTable* regTable, int insnIdx, UninitInstanceMap* uninitMap, 3856 int* pStartGuess) 3857{ 3858 const int insnsSize = dvmGetMethodInsnsSize(meth); 3859 const u2* insns = meth->insns + insnIdx; 3860 bool result = false; 3861 3862#ifdef VERIFIER_STATS 3863 if (dvmInsnIsVisited(insnFlags, insnIdx)) { 3864 gDvm.verifierStats.instrsReexamined++; 3865 } else { 3866 gDvm.verifierStats.instrsExamined++; 3867 } 3868#endif 3869 3870 /* 3871 * Once we finish decoding the instruction, we need to figure out where 3872 * we can go from here. There are three possible ways to transfer 3873 * control to another statement: 3874 * 3875 * (1) Continue to the next instruction. Applies to all but 3876 * unconditional branches, method returns, and exception throws. 3877 * (2) Branch to one or more possible locations. Applies to branches 3878 * and switch statements. 3879 * (3) Exception handlers. Applies to any instruction that can 3880 * throw an exception that is handled by an encompassing "try" 3881 * block. 3882 * 3883 * We can also return, in which case there is no successor instruction 3884 * from this point. 3885 * 3886 * The behavior can be determined from the OpcodeFlags. 3887 */ 3888 3889 RegisterLine* workLine = ®Table->workLine; 3890 const DexFile* pDexFile = meth->clazz->pDvmDex->pDexFile; 3891 ClassObject* resClass; 3892 s4 branchTarget = 0; 3893 const int insnRegCount = meth->registersSize; 3894 RegType tmpType; 3895 DecodedInstruction decInsn; 3896 bool justSetResult = false; 3897 VerifyError failure = VERIFY_ERROR_NONE; 3898 3899#ifndef NDEBUG 3900 memset(&decInsn, 0x81, sizeof(decInsn)); 3901#endif 3902 dexDecodeInstruction(insns, &decInsn); 3903 3904 int nextFlags = dexGetFlagsFromOpcode(decInsn.opcode); 3905 3906 /* 3907 * Make a copy of the previous register state. If the instruction 3908 * can throw an exception, we will copy/merge this into the "catch" 3909 * address rather than workLine, because we don't want the result 3910 * from the "successful" code path (e.g. a check-cast that "improves" 3911 * a type) to be visible to the exception handler. 3912 */ 3913 if ((nextFlags & kInstrCanThrow) != 0 && dvmInsnIsInTry(insnFlags, insnIdx)) 3914 { 3915 copyRegisterLine(®Table->savedLine, workLine, 3916 regTable->insnRegCountPlus); 3917 } else { 3918#ifndef NDEBUG 3919 memset(regTable->savedLine.regTypes, 0xdd, 3920 regTable->insnRegCountPlus * sizeof(RegType)); 3921#endif 3922 } 3923 3924 switch (decInsn.opcode) { 3925 case OP_NOP: 3926 /* 3927 * A "pure" NOP has no effect on anything. Data tables start with 3928 * a signature that looks like a NOP; if we see one of these in 3929 * the course of executing code then we have a problem. 3930 */ 3931 if (decInsn.vA != 0) { 3932 LOG_VFY("VFY: encountered data table in instruction stream"); 3933 failure = VERIFY_ERROR_GENERIC; 3934 } 3935 break; 3936 3937 case OP_MOVE: 3938 case OP_MOVE_FROM16: 3939 case OP_MOVE_16: 3940 copyRegister1(workLine, decInsn.vA, decInsn.vB, kTypeCategory1nr, 3941 &failure); 3942 break; 3943 case OP_MOVE_WIDE: 3944 case OP_MOVE_WIDE_FROM16: 3945 case OP_MOVE_WIDE_16: 3946 copyRegister2(workLine, decInsn.vA, decInsn.vB, &failure); 3947 break; 3948 case OP_MOVE_OBJECT: 3949 case OP_MOVE_OBJECT_FROM16: 3950 case OP_MOVE_OBJECT_16: 3951 copyRegister1(workLine, decInsn.vA, decInsn.vB, kTypeCategoryRef, 3952 &failure); 3953 break; 3954 3955 /* 3956 * The move-result instructions copy data out of a "pseudo-register" 3957 * with the results from the last method invocation. In practice we 3958 * might want to hold the result in an actual CPU register, so the 3959 * Dalvik spec requires that these only appear immediately after an 3960 * invoke or filled-new-array. 3961 * 3962 * These calls invalidate the "result" register. (This is now 3963 * redundant with the reset done below, but it can make the debug info 3964 * easier to read in some cases.) 3965 */ 3966 case OP_MOVE_RESULT: 3967 copyResultRegister1(workLine, insnRegCount, decInsn.vA, 3968 kTypeCategory1nr, &failure); 3969 break; 3970 case OP_MOVE_RESULT_WIDE: 3971 copyResultRegister2(workLine, insnRegCount, decInsn.vA, &failure); 3972 break; 3973 case OP_MOVE_RESULT_OBJECT: 3974 copyResultRegister1(workLine, insnRegCount, decInsn.vA, 3975 kTypeCategoryRef, &failure); 3976 break; 3977 3978 case OP_MOVE_EXCEPTION: 3979 /* 3980 * This statement can only appear as the first instruction in an 3981 * exception handler (though not all exception handlers need to 3982 * have one of these). We verify that as part of extracting the 3983 * exception type from the catch block list. 3984 * 3985 * "resClass" will hold the closest common superclass of all 3986 * exceptions that can be handled here. 3987 */ 3988 resClass = getCaughtExceptionType(meth, insnIdx, &failure); 3989 if (resClass == NULL) { 3990 assert(!VERIFY_OK(failure)); 3991 } else { 3992 setRegisterType(workLine, decInsn.vA, regTypeFromClass(resClass)); 3993 } 3994 break; 3995 3996 case OP_RETURN_VOID: 3997 if (!checkConstructorReturn(meth, workLine, insnRegCount)) { 3998 failure = VERIFY_ERROR_GENERIC; 3999 } else if (getMethodReturnType(meth) != kRegTypeUnknown) { 4000 LOG_VFY("VFY: return-void not expected"); 4001 failure = VERIFY_ERROR_GENERIC; 4002 } 4003 break; 4004 case OP_RETURN: 4005 if (!checkConstructorReturn(meth, workLine, insnRegCount)) { 4006 failure = VERIFY_ERROR_GENERIC; 4007 } else { 4008 /* check the method signature */ 4009 RegType returnType = getMethodReturnType(meth); 4010 checkTypeCategory(returnType, kTypeCategory1nr, &failure); 4011 if (!VERIFY_OK(failure)) 4012 LOG_VFY("VFY: return-1nr not expected"); 4013 4014 /* 4015 * javac generates synthetic functions that write byte values 4016 * into boolean fields. Also, it may use integer values for 4017 * boolean, byte, short, and character return types. 4018 */ 4019 RegType srcType = getRegisterType(workLine, decInsn.vA); 4020 if ((returnType == kRegTypeBoolean && srcType == kRegTypeByte) || 4021 ((returnType == kRegTypeBoolean || returnType == kRegTypeByte || 4022 returnType == kRegTypeShort || returnType == kRegTypeChar) && 4023 srcType == kRegTypeInteger)) 4024 returnType = srcType; 4025 4026 /* check the register contents */ 4027 verifyRegisterType(workLine, decInsn.vA, returnType, &failure); 4028 if (!VERIFY_OK(failure)) { 4029 LOG_VFY("VFY: return-1nr on invalid register v%d", 4030 decInsn.vA); 4031 } 4032 } 4033 break; 4034 case OP_RETURN_WIDE: 4035 if (!checkConstructorReturn(meth, workLine, insnRegCount)) { 4036 failure = VERIFY_ERROR_GENERIC; 4037 } else { 4038 RegType returnType; 4039 4040 /* check the method signature */ 4041 returnType = getMethodReturnType(meth); 4042 checkTypeCategory(returnType, kTypeCategory2, &failure); 4043 if (!VERIFY_OK(failure)) 4044 LOG_VFY("VFY: return-wide not expected"); 4045 4046 /* check the register contents */ 4047 verifyRegisterType(workLine, decInsn.vA, returnType, &failure); 4048 if (!VERIFY_OK(failure)) { 4049 LOG_VFY("VFY: return-wide on invalid register pair v%d", 4050 decInsn.vA); 4051 } 4052 } 4053 break; 4054 case OP_RETURN_OBJECT: 4055 if (!checkConstructorReturn(meth, workLine, insnRegCount)) { 4056 failure = VERIFY_ERROR_GENERIC; 4057 } else { 4058 RegType returnType = getMethodReturnType(meth); 4059 checkTypeCategory(returnType, kTypeCategoryRef, &failure); 4060 if (!VERIFY_OK(failure)) { 4061 LOG_VFY("VFY: return-object not expected"); 4062 break; 4063 } 4064 4065 /* returnType is the *expected* return type, not register value */ 4066 assert(returnType != kRegTypeZero); 4067 assert(!regTypeIsUninitReference(returnType)); 4068 4069 /* 4070 * Verify that the reference in vAA is an instance of the type 4071 * in "returnType". The Zero type is allowed here. If the 4072 * method is declared to return an interface, then any 4073 * initialized reference is acceptable. 4074 * 4075 * Note getClassFromRegister fails if the register holds an 4076 * uninitialized reference, so we do not allow them to be 4077 * returned. 4078 */ 4079 ClassObject* declClass; 4080 4081 declClass = regTypeInitializedReferenceToClass(returnType); 4082 resClass = getClassFromRegister(workLine, decInsn.vA, &failure); 4083 if (!VERIFY_OK(failure)) 4084 break; 4085 if (resClass != NULL) { 4086 if (!dvmIsInterfaceClass(declClass) && 4087 !dvmInstanceof(resClass, declClass)) 4088 { 4089 LOG_VFY("VFY: returning %s (cl=%p), declared %s (cl=%p)", 4090 resClass->descriptor, resClass->classLoader, 4091 declClass->descriptor, declClass->classLoader); 4092 failure = VERIFY_ERROR_GENERIC; 4093 break; 4094 } 4095 } 4096 } 4097 break; 4098 4099 case OP_CONST_4: 4100 case OP_CONST_16: 4101 case OP_CONST: 4102 /* could be boolean, int, float, or a null reference */ 4103 setRegisterType(workLine, decInsn.vA, 4104 determineCat1Const((s4)decInsn.vB)); 4105 break; 4106 case OP_CONST_HIGH16: 4107 /* could be boolean, int, float, or a null reference */ 4108 setRegisterType(workLine, decInsn.vA, 4109 determineCat1Const((s4) decInsn.vB << 16)); 4110 break; 4111 case OP_CONST_WIDE_16: 4112 case OP_CONST_WIDE_32: 4113 case OP_CONST_WIDE: 4114 case OP_CONST_WIDE_HIGH16: 4115 /* could be long or double; resolved upon use */ 4116 setRegisterType(workLine, decInsn.vA, kRegTypeConstLo); 4117 break; 4118 case OP_CONST_STRING: 4119 case OP_CONST_STRING_JUMBO: 4120 assert(gDvm.classJavaLangString != NULL); 4121 setRegisterType(workLine, decInsn.vA, 4122 regTypeFromClass(gDvm.classJavaLangString)); 4123 break; 4124 case OP_CONST_CLASS: 4125 case OP_CONST_CLASS_JUMBO: 4126 assert(gDvm.classJavaLangClass != NULL); 4127 /* make sure we can resolve the class; access check is important */ 4128 resClass = dvmOptResolveClass(meth->clazz, decInsn.vB, &failure); 4129 if (resClass == NULL) { 4130 const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vB); 4131 dvmLogUnableToResolveClass(badClassDesc, meth); 4132 LOG_VFY("VFY: unable to resolve const-class %d (%s) in %s", 4133 decInsn.vB, badClassDesc, meth->clazz->descriptor); 4134 assert(failure != VERIFY_ERROR_GENERIC); 4135 } else { 4136 setRegisterType(workLine, decInsn.vA, 4137 regTypeFromClass(gDvm.classJavaLangClass)); 4138 } 4139 break; 4140 4141 case OP_MONITOR_ENTER: 4142 handleMonitorEnter(workLine, decInsn.vA, insnIdx, &failure); 4143 break; 4144 case OP_MONITOR_EXIT: 4145 /* 4146 * monitor-exit instructions are odd. They can throw exceptions, 4147 * but when they do they act as if they succeeded and the PC is 4148 * pointing to the following instruction. (This behavior goes back 4149 * to the need to handle asynchronous exceptions, a now-deprecated 4150 * feature that Dalvik doesn't support.) 4151 * 4152 * In practice we don't need to worry about this. The only 4153 * exceptions that can be thrown from monitor-exit are for a 4154 * null reference and -exit without a matching -enter. If the 4155 * structured locking checks are working, the former would have 4156 * failed on the -enter instruction, and the latter is impossible. 4157 * 4158 * This is fortunate, because issue 3221411 prevents us from 4159 * chasing the "can throw" path when monitor verification is 4160 * enabled. If we can fully verify the locking we can ignore 4161 * some catch blocks (which will show up as "dead" code when 4162 * we skip them here); if we can't, then the code path could be 4163 * "live" so we still need to check it. 4164 */ 4165 if (workLine->monitorEntries != NULL) 4166 nextFlags &= ~kInstrCanThrow; 4167 handleMonitorExit(workLine, decInsn.vA, insnIdx, &failure); 4168 break; 4169 4170 case OP_CHECK_CAST: 4171 case OP_CHECK_CAST_JUMBO: 4172 /* 4173 * If this instruction succeeds, we will promote register vA to 4174 * the type in vB. (This could be a demotion -- not expected, so 4175 * we don't try to address it.) 4176 * 4177 * If it fails, an exception is thrown, which we deal with later 4178 * by ignoring the update to decInsn.vA when branching to a handler. 4179 */ 4180 resClass = dvmOptResolveClass(meth->clazz, decInsn.vB, &failure); 4181 if (resClass == NULL) { 4182 const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vB); 4183 dvmLogUnableToResolveClass(badClassDesc, meth); 4184 LOG_VFY("VFY: unable to resolve check-cast %d (%s) in %s", 4185 decInsn.vB, badClassDesc, meth->clazz->descriptor); 4186 assert(failure != VERIFY_ERROR_GENERIC); 4187 } else { 4188 RegType origType; 4189 4190 origType = getRegisterType(workLine, decInsn.vA); 4191 if (!regTypeIsReference(origType)) { 4192 LOG_VFY("VFY: check-cast on non-reference in v%u",decInsn.vA); 4193 failure = VERIFY_ERROR_GENERIC; 4194 break; 4195 } 4196 setRegisterType(workLine, decInsn.vA, regTypeFromClass(resClass)); 4197 } 4198 break; 4199 case OP_INSTANCE_OF: 4200 case OP_INSTANCE_OF_JUMBO: 4201 /* make sure we're checking a reference type */ 4202 tmpType = getRegisterType(workLine, decInsn.vB); 4203 if (!regTypeIsReference(tmpType)) { 4204 LOG_VFY("VFY: vB not a reference (%d)", tmpType); 4205 failure = VERIFY_ERROR_GENERIC; 4206 break; 4207 } 4208 4209 /* make sure we can resolve the class; access check is important */ 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 instanceof %d (%s) in %s", 4215 decInsn.vC, badClassDesc, meth->clazz->descriptor); 4216 assert(failure != VERIFY_ERROR_GENERIC); 4217 } else { 4218 /* result is boolean */ 4219 setRegisterType(workLine, decInsn.vA, kRegTypeBoolean); 4220 } 4221 break; 4222 4223 case OP_ARRAY_LENGTH: 4224 resClass = getClassFromRegister(workLine, decInsn.vB, &failure); 4225 if (!VERIFY_OK(failure)) 4226 break; 4227 if (resClass != NULL && !dvmIsArrayClass(resClass)) { 4228 LOG_VFY("VFY: array-length on non-array"); 4229 failure = VERIFY_ERROR_GENERIC; 4230 break; 4231 } 4232 setRegisterType(workLine, decInsn.vA, kRegTypeInteger); 4233 break; 4234 4235 case OP_NEW_INSTANCE: 4236 case OP_NEW_INSTANCE_JUMBO: 4237 resClass = dvmOptResolveClass(meth->clazz, decInsn.vB, &failure); 4238 if (resClass == NULL) { 4239 const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vB); 4240 dvmLogUnableToResolveClass(badClassDesc, meth); 4241 LOG_VFY("VFY: unable to resolve new-instance %d (%s) in %s", 4242 decInsn.vB, badClassDesc, meth->clazz->descriptor); 4243 assert(failure != VERIFY_ERROR_GENERIC); 4244 } else { 4245 RegType uninitType; 4246 4247 /* can't create an instance of an interface or abstract class */ 4248 if (dvmIsAbstractClass(resClass) || dvmIsInterfaceClass(resClass)) { 4249 LOG_VFY("VFY: new-instance on interface or abstract class %s", 4250 resClass->descriptor); 4251 failure = VERIFY_ERROR_INSTANTIATION; 4252 break; 4253 } 4254 4255 /* add resolved class to uninit map if not already there */ 4256 int uidx = setUninitInstance(uninitMap, insnIdx, resClass); 4257 assert(uidx >= 0); 4258 uninitType = regTypeFromUninitIndex(uidx); 4259 4260 /* 4261 * Any registers holding previous allocations from this address 4262 * that have not yet been initialized must be marked invalid. 4263 */ 4264 markUninitRefsAsInvalid(workLine, insnRegCount, uninitMap, 4265 uninitType); 4266 4267 /* add the new uninitialized reference to the register ste */ 4268 setRegisterType(workLine, decInsn.vA, uninitType); 4269 } 4270 break; 4271 case OP_NEW_ARRAY: 4272 case OP_NEW_ARRAY_JUMBO: 4273 resClass = dvmOptResolveClass(meth->clazz, decInsn.vC, &failure); 4274 if (resClass == NULL) { 4275 const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vC); 4276 dvmLogUnableToResolveClass(badClassDesc, meth); 4277 LOG_VFY("VFY: unable to resolve new-array %d (%s) in %s", 4278 decInsn.vC, badClassDesc, meth->clazz->descriptor); 4279 assert(failure != VERIFY_ERROR_GENERIC); 4280 } else if (!dvmIsArrayClass(resClass)) { 4281 LOG_VFY("VFY: new-array on non-array class"); 4282 failure = VERIFY_ERROR_GENERIC; 4283 } else { 4284 /* make sure "size" register is valid type */ 4285 verifyRegisterType(workLine, decInsn.vB, kRegTypeInteger, &failure); 4286 /* set register type to array class */ 4287 setRegisterType(workLine, decInsn.vA, regTypeFromClass(resClass)); 4288 } 4289 break; 4290 case OP_FILLED_NEW_ARRAY: 4291 case OP_FILLED_NEW_ARRAY_RANGE: 4292 case OP_FILLED_NEW_ARRAY_JUMBO: 4293 resClass = dvmOptResolveClass(meth->clazz, decInsn.vB, &failure); 4294 if (resClass == NULL) { 4295 const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vB); 4296 dvmLogUnableToResolveClass(badClassDesc, meth); 4297 LOG_VFY("VFY: unable to resolve filled-array %d (%s) in %s", 4298 decInsn.vB, badClassDesc, meth->clazz->descriptor); 4299 assert(failure != VERIFY_ERROR_GENERIC); 4300 } else if (!dvmIsArrayClass(resClass)) { 4301 LOG_VFY("VFY: filled-new-array on non-array class"); 4302 failure = VERIFY_ERROR_GENERIC; 4303 } else { 4304 bool isRange = (decInsn.opcode == OP_FILLED_NEW_ARRAY_RANGE || 4305 decInsn.opcode == OP_FILLED_NEW_ARRAY_JUMBO); 4306 4307 /* check the arguments to the instruction */ 4308 verifyFilledNewArrayRegs(meth, workLine, &decInsn, 4309 resClass, isRange, &failure); 4310 /* filled-array result goes into "result" register */ 4311 setResultRegisterType(workLine, insnRegCount, 4312 regTypeFromClass(resClass)); 4313 justSetResult = true; 4314 } 4315 break; 4316 4317 case OP_CMPL_FLOAT: 4318 case OP_CMPG_FLOAT: 4319 verifyRegisterType(workLine, decInsn.vB, kRegTypeFloat, &failure); 4320 verifyRegisterType(workLine, decInsn.vC, kRegTypeFloat, &failure); 4321 setRegisterType(workLine, decInsn.vA, kRegTypeBoolean); 4322 break; 4323 case OP_CMPL_DOUBLE: 4324 case OP_CMPG_DOUBLE: 4325 verifyRegisterType(workLine, decInsn.vB, kRegTypeDoubleLo, &failure); 4326 verifyRegisterType(workLine, decInsn.vC, kRegTypeDoubleLo, &failure); 4327 setRegisterType(workLine, decInsn.vA, kRegTypeBoolean); 4328 break; 4329 case OP_CMP_LONG: 4330 verifyRegisterType(workLine, decInsn.vB, kRegTypeLongLo, &failure); 4331 verifyRegisterType(workLine, decInsn.vC, kRegTypeLongLo, &failure); 4332 setRegisterType(workLine, decInsn.vA, kRegTypeBoolean); 4333 break; 4334 4335 case OP_THROW: 4336 resClass = getClassFromRegister(workLine, decInsn.vA, &failure); 4337 if (VERIFY_OK(failure) && resClass != NULL) { 4338 if (!dvmInstanceof(resClass, gDvm.exThrowable)) { 4339 LOG_VFY("VFY: thrown class %s not instanceof Throwable", 4340 resClass->descriptor); 4341 failure = VERIFY_ERROR_GENERIC; 4342 } 4343 } 4344 break; 4345 4346 case OP_GOTO: 4347 case OP_GOTO_16: 4348 case OP_GOTO_32: 4349 /* no effect on or use of registers */ 4350 break; 4351 4352 case OP_PACKED_SWITCH: 4353 case OP_SPARSE_SWITCH: 4354 /* verify that vAA is an integer, or can be converted to one */ 4355 verifyRegisterType(workLine, decInsn.vA, kRegTypeInteger, &failure); 4356 break; 4357 4358 case OP_FILL_ARRAY_DATA: 4359 { 4360 RegType valueType; 4361 const u2 *arrayData; 4362 u2 elemWidth; 4363 4364 /* Similar to the verification done for APUT */ 4365 resClass = getClassFromRegister(workLine, decInsn.vA, &failure); 4366 if (!VERIFY_OK(failure)) 4367 break; 4368 4369 /* resClass can be null if the reg type is Zero */ 4370 if (resClass == NULL) 4371 break; 4372 4373 if (!dvmIsArrayClass(resClass) || resClass->arrayDim != 1 || 4374 resClass->elementClass->primitiveType == PRIM_NOT || 4375 resClass->elementClass->primitiveType == PRIM_VOID) 4376 { 4377 LOG_VFY("VFY: invalid fill-array-data on %s", 4378 resClass->descriptor); 4379 failure = VERIFY_ERROR_GENERIC; 4380 break; 4381 } 4382 4383 valueType = primitiveTypeToRegType( 4384 resClass->elementClass->primitiveType); 4385 assert(valueType != kRegTypeUnknown); 4386 4387 /* 4388 * Now verify if the element width in the table matches the element 4389 * width declared in the array 4390 */ 4391 arrayData = insns + (insns[1] | (((s4)insns[2]) << 16)); 4392 if (arrayData[0] != kArrayDataSignature) { 4393 LOG_VFY("VFY: invalid magic for array-data"); 4394 failure = VERIFY_ERROR_GENERIC; 4395 break; 4396 } 4397 4398 switch (resClass->elementClass->primitiveType) { 4399 case PRIM_BOOLEAN: 4400 case PRIM_BYTE: 4401 elemWidth = 1; 4402 break; 4403 case PRIM_CHAR: 4404 case PRIM_SHORT: 4405 elemWidth = 2; 4406 break; 4407 case PRIM_FLOAT: 4408 case PRIM_INT: 4409 elemWidth = 4; 4410 break; 4411 case PRIM_DOUBLE: 4412 case PRIM_LONG: 4413 elemWidth = 8; 4414 break; 4415 default: 4416 elemWidth = 0; 4417 break; 4418 } 4419 4420 /* 4421 * Since we don't compress the data in Dex, expect to see equal 4422 * width of data stored in the table and expected from the array 4423 * class. 4424 */ 4425 if (arrayData[1] != elemWidth) { 4426 LOG_VFY("VFY: array-data size mismatch (%d vs %d)", 4427 arrayData[1], elemWidth); 4428 failure = VERIFY_ERROR_GENERIC; 4429 } 4430 } 4431 break; 4432 4433 case OP_IF_EQ: 4434 case OP_IF_NE: 4435 { 4436 RegType type1, type2; 4437 4438 type1 = getRegisterType(workLine, decInsn.vA); 4439 type2 = getRegisterType(workLine, decInsn.vB); 4440 4441 /* both references? */ 4442 if (regTypeIsReference(type1) && regTypeIsReference(type2)) 4443 break; 4444 4445 /* both category-1nr? */ 4446 checkTypeCategory(type1, kTypeCategory1nr, &failure); 4447 checkTypeCategory(type2, kTypeCategory1nr, &failure); 4448 if (!VERIFY_OK(failure)) { 4449 LOG_VFY("VFY: args to if-eq/if-ne must both be refs or cat1"); 4450 break; 4451 } 4452 } 4453 break; 4454 case OP_IF_LT: 4455 case OP_IF_GE: 4456 case OP_IF_GT: 4457 case OP_IF_LE: 4458 tmpType = getRegisterType(workLine, decInsn.vA); 4459 checkTypeCategory(tmpType, kTypeCategory1nr, &failure); 4460 if (!VERIFY_OK(failure)) { 4461 LOG_VFY("VFY: args to 'if' must be cat-1nr"); 4462 break; 4463 } 4464 tmpType = getRegisterType(workLine, decInsn.vB); 4465 checkTypeCategory(tmpType, kTypeCategory1nr, &failure); 4466 if (!VERIFY_OK(failure)) { 4467 LOG_VFY("VFY: args to 'if' must be cat-1nr"); 4468 break; 4469 } 4470 break; 4471 case OP_IF_EQZ: 4472 case OP_IF_NEZ: 4473 tmpType = getRegisterType(workLine, decInsn.vA); 4474 if (regTypeIsReference(tmpType)) 4475 break; 4476 checkTypeCategory(tmpType, kTypeCategory1nr, &failure); 4477 if (!VERIFY_OK(failure)) 4478 LOG_VFY("VFY: expected cat-1 arg to if"); 4479 break; 4480 case OP_IF_LTZ: 4481 case OP_IF_GEZ: 4482 case OP_IF_GTZ: 4483 case OP_IF_LEZ: 4484 tmpType = getRegisterType(workLine, decInsn.vA); 4485 checkTypeCategory(tmpType, kTypeCategory1nr, &failure); 4486 if (!VERIFY_OK(failure)) 4487 LOG_VFY("VFY: expected cat-1 arg to if"); 4488 break; 4489 4490 case OP_AGET: 4491 tmpType = kRegTypeConstInteger; 4492 goto aget_1nr_common; 4493 case OP_AGET_BOOLEAN: 4494 tmpType = kRegTypeBoolean; 4495 goto aget_1nr_common; 4496 case OP_AGET_BYTE: 4497 tmpType = kRegTypeByte; 4498 goto aget_1nr_common; 4499 case OP_AGET_CHAR: 4500 tmpType = kRegTypeChar; 4501 goto aget_1nr_common; 4502 case OP_AGET_SHORT: 4503 tmpType = kRegTypeShort; 4504 goto aget_1nr_common; 4505aget_1nr_common: 4506 { 4507 RegType srcType, indexType; 4508 4509 indexType = getRegisterType(workLine, decInsn.vC); 4510 checkArrayIndexType(meth, indexType, &failure); 4511 if (!VERIFY_OK(failure)) 4512 break; 4513 4514 resClass = getClassFromRegister(workLine, decInsn.vB, &failure); 4515 if (!VERIFY_OK(failure)) 4516 break; 4517 if (resClass != NULL) { 4518 /* verify the class */ 4519 if (!dvmIsArrayClass(resClass) || resClass->arrayDim != 1 || 4520 resClass->elementClass->primitiveType == PRIM_NOT) 4521 { 4522 LOG_VFY("VFY: invalid aget-1nr target %s", 4523 resClass->descriptor); 4524 failure = VERIFY_ERROR_GENERIC; 4525 break; 4526 } 4527 4528 /* make sure array type matches instruction */ 4529 srcType = primitiveTypeToRegType( 4530 resClass->elementClass->primitiveType); 4531 4532 /* differentiate between float and int */ 4533 if (srcType == kRegTypeFloat || srcType == kRegTypeInteger) 4534 tmpType = srcType; 4535 4536 if (!checkFieldArrayStore1nr(tmpType, srcType)) { 4537 LOG_VFY("VFY: invalid aget-1nr, array type=%d with" 4538 " inst type=%d (on %s)", 4539 srcType, tmpType, resClass->descriptor); 4540 failure = VERIFY_ERROR_GENERIC; 4541 break; 4542 } 4543 4544 } 4545 setRegisterType(workLine, decInsn.vA, tmpType); 4546 } 4547 break; 4548 4549 case OP_AGET_WIDE: 4550 { 4551 RegType dstType, indexType; 4552 4553 indexType = getRegisterType(workLine, decInsn.vC); 4554 checkArrayIndexType(meth, indexType, &failure); 4555 if (!VERIFY_OK(failure)) 4556 break; 4557 4558 resClass = getClassFromRegister(workLine, decInsn.vB, &failure); 4559 if (!VERIFY_OK(failure)) 4560 break; 4561 if (resClass != NULL) { 4562 /* verify the class */ 4563 if (!dvmIsArrayClass(resClass) || resClass->arrayDim != 1 || 4564 resClass->elementClass->primitiveType == PRIM_NOT) 4565 { 4566 LOG_VFY("VFY: invalid aget-wide target %s", 4567 resClass->descriptor); 4568 failure = VERIFY_ERROR_GENERIC; 4569 break; 4570 } 4571 4572 /* try to refine "dstType" */ 4573 switch (resClass->elementClass->primitiveType) { 4574 case PRIM_LONG: 4575 dstType = kRegTypeLongLo; 4576 break; 4577 case PRIM_DOUBLE: 4578 dstType = kRegTypeDoubleLo; 4579 break; 4580 default: 4581 LOG_VFY("VFY: invalid aget-wide on %s", 4582 resClass->descriptor); 4583 dstType = kRegTypeUnknown; 4584 failure = VERIFY_ERROR_GENERIC; 4585 break; 4586 } 4587 } else { 4588 /* 4589 * Null array ref; this code path will fail at runtime. We 4590 * know this is either long or double, so label it const. 4591 */ 4592 dstType = kRegTypeConstLo; 4593 } 4594 setRegisterType(workLine, decInsn.vA, dstType); 4595 } 4596 break; 4597 4598 case OP_AGET_OBJECT: 4599 { 4600 RegType dstType, indexType; 4601 4602 indexType = getRegisterType(workLine, decInsn.vC); 4603 checkArrayIndexType(meth, indexType, &failure); 4604 if (!VERIFY_OK(failure)) 4605 break; 4606 4607 /* get the class of the array we're pulling an object from */ 4608 resClass = getClassFromRegister(workLine, decInsn.vB, &failure); 4609 if (!VERIFY_OK(failure)) 4610 break; 4611 if (resClass != NULL) { 4612 ClassObject* elementClass; 4613 4614 assert(resClass != NULL); 4615 if (!dvmIsArrayClass(resClass)) { 4616 LOG_VFY("VFY: aget-object on non-array class"); 4617 failure = VERIFY_ERROR_GENERIC; 4618 break; 4619 } 4620 assert(resClass->elementClass != NULL); 4621 4622 /* 4623 * Find the element class. resClass->elementClass indicates 4624 * the basic type, which won't be what we want for a 4625 * multi-dimensional array. 4626 */ 4627 if (resClass->descriptor[1] == '[') { 4628 assert(resClass->arrayDim > 1); 4629 elementClass = dvmFindArrayClass(&resClass->descriptor[1], 4630 resClass->classLoader); 4631 } else if (resClass->descriptor[1] == 'L') { 4632 assert(resClass->arrayDim == 1); 4633 elementClass = resClass->elementClass; 4634 } else { 4635 LOG_VFY("VFY: aget-object on non-ref array class (%s)", 4636 resClass->descriptor); 4637 failure = VERIFY_ERROR_GENERIC; 4638 break; 4639 } 4640 4641 dstType = regTypeFromClass(elementClass); 4642 } else { 4643 /* 4644 * The array reference is NULL, so the current code path will 4645 * throw an exception. For proper merging with later code 4646 * paths, and correct handling of "if-eqz" tests on the 4647 * result of the array get, we want to treat this as a null 4648 * reference. 4649 */ 4650 dstType = kRegTypeZero; 4651 } 4652 setRegisterType(workLine, decInsn.vA, dstType); 4653 } 4654 break; 4655 case OP_APUT: 4656 tmpType = kRegTypeInteger; 4657 goto aput_1nr_common; 4658 case OP_APUT_BOOLEAN: 4659 tmpType = kRegTypeBoolean; 4660 goto aput_1nr_common; 4661 case OP_APUT_BYTE: 4662 tmpType = kRegTypeByte; 4663 goto aput_1nr_common; 4664 case OP_APUT_CHAR: 4665 tmpType = kRegTypeChar; 4666 goto aput_1nr_common; 4667 case OP_APUT_SHORT: 4668 tmpType = kRegTypeShort; 4669 goto aput_1nr_common; 4670aput_1nr_common: 4671 { 4672 RegType srcType, dstType, indexType; 4673 4674 indexType = getRegisterType(workLine, decInsn.vC); 4675 checkArrayIndexType(meth, indexType, &failure); 4676 if (!VERIFY_OK(failure)) 4677 break; 4678 4679 resClass = getClassFromRegister(workLine, decInsn.vB, &failure); 4680 if (!VERIFY_OK(failure)) 4681 break; 4682 4683 /* resClass can be null if the reg type is Zero */ 4684 if (resClass == NULL) 4685 break; 4686 4687 if (!dvmIsArrayClass(resClass) || resClass->arrayDim != 1 || 4688 resClass->elementClass->primitiveType == PRIM_NOT) 4689 { 4690 LOG_VFY("VFY: invalid aput-1nr on %s", resClass->descriptor); 4691 failure = VERIFY_ERROR_GENERIC; 4692 break; 4693 } 4694 4695 /* verify that instruction matches array */ 4696 dstType = primitiveTypeToRegType( 4697 resClass->elementClass->primitiveType); 4698 4699 /* correct if float */ 4700 if (dstType == kRegTypeFloat) 4701 tmpType = kRegTypeFloat; 4702 4703 /* make sure the source register has the correct type */ 4704 srcType = getRegisterType(workLine, decInsn.vA); 4705 if (!canConvertTo1nr(srcType, tmpType)) { 4706 LOG_VFY("VFY: invalid reg type %d on aput instr (need %d)", 4707 srcType, tmpType); 4708 failure = VERIFY_ERROR_GENERIC; 4709 break; 4710 } 4711 4712 verifyRegisterType(workLine, decInsn.vA, dstType, &failure); 4713 4714 if (!VERIFY_OK(failure) || dstType == kRegTypeUnknown || 4715 !checkFieldArrayStore1nr(tmpType, dstType)) { 4716 LOG_VFY("VFY: invalid aput-1nr on %s (inst=%d dst=%d)", 4717 resClass->descriptor, tmpType, dstType); 4718 failure = VERIFY_ERROR_GENERIC; 4719 break; 4720 } 4721 } 4722 break; 4723 case OP_APUT_WIDE: 4724 tmpType = getRegisterType(workLine, decInsn.vC); 4725 checkArrayIndexType(meth, tmpType, &failure); 4726 if (!VERIFY_OK(failure)) 4727 break; 4728 4729 resClass = getClassFromRegister(workLine, decInsn.vB, &failure); 4730 if (!VERIFY_OK(failure)) 4731 break; 4732 if (resClass != NULL) { 4733 /* verify the class and try to refine "dstType" */ 4734 if (!dvmIsArrayClass(resClass) || resClass->arrayDim != 1 || 4735 resClass->elementClass->primitiveType == PRIM_NOT) 4736 { 4737 LOG_VFY("VFY: invalid aput-wide on %s", 4738 resClass->descriptor); 4739 failure = VERIFY_ERROR_GENERIC; 4740 break; 4741 } 4742 4743 switch (resClass->elementClass->primitiveType) { 4744 case PRIM_LONG: 4745 verifyRegisterType(workLine, decInsn.vA, kRegTypeLongLo, &failure); 4746 break; 4747 case PRIM_DOUBLE: 4748 verifyRegisterType(workLine, decInsn.vA, kRegTypeDoubleLo, &failure); 4749 break; 4750 default: 4751 LOG_VFY("VFY: invalid aput-wide on %s", 4752 resClass->descriptor); 4753 failure = VERIFY_ERROR_GENERIC; 4754 break; 4755 } 4756 } 4757 break; 4758 case OP_APUT_OBJECT: 4759 tmpType = getRegisterType(workLine, decInsn.vC); 4760 checkArrayIndexType(meth, tmpType, &failure); 4761 if (!VERIFY_OK(failure)) 4762 break; 4763 4764 /* get the ref we're storing; Zero is okay, Uninit is not */ 4765 resClass = getClassFromRegister(workLine, decInsn.vA, &failure); 4766 if (!VERIFY_OK(failure)) 4767 break; 4768 if (resClass != NULL) { 4769 ClassObject* arrayClass; 4770 ClassObject* elementClass; 4771 4772 /* 4773 * Get the array class. If the array ref is null, we won't 4774 * have type information (and we'll crash at runtime with a 4775 * null pointer exception). 4776 */ 4777 arrayClass = getClassFromRegister(workLine, decInsn.vB, &failure); 4778 4779 if (arrayClass != NULL) { 4780 /* see if the array holds a compatible type */ 4781 if (!dvmIsArrayClass(arrayClass)) { 4782 LOG_VFY("VFY: invalid aput-object on %s", 4783 arrayClass->descriptor); 4784 failure = VERIFY_ERROR_GENERIC; 4785 break; 4786 } 4787 4788 /* 4789 * Find the element class. resClass->elementClass indicates 4790 * the basic type, which won't be what we want for a 4791 * multi-dimensional array. 4792 * 4793 * All we want to check here is that the element type is a 4794 * reference class. We *don't* check instanceof here, because 4795 * you can still put a String into a String[] after the latter 4796 * has been cast to an Object[]. 4797 */ 4798 if (arrayClass->descriptor[1] == '[') { 4799 assert(arrayClass->arrayDim > 1); 4800 elementClass = dvmFindArrayClass(&arrayClass->descriptor[1], 4801 arrayClass->classLoader); 4802 } else { 4803 assert(arrayClass->arrayDim == 1); 4804 elementClass = arrayClass->elementClass; 4805 } 4806 if (elementClass->primitiveType != PRIM_NOT) { 4807 LOG_VFY("VFY: invalid aput-object of %s into %s", 4808 resClass->descriptor, arrayClass->descriptor); 4809 failure = VERIFY_ERROR_GENERIC; 4810 break; 4811 } 4812 } 4813 } 4814 break; 4815 4816 case OP_IGET: 4817 case OP_IGET_JUMBO: 4818 tmpType = kRegTypeInteger; 4819 goto iget_1nr_common; 4820 case OP_IGET_BOOLEAN: 4821 case OP_IGET_BOOLEAN_JUMBO: 4822 tmpType = kRegTypeBoolean; 4823 goto iget_1nr_common; 4824 case OP_IGET_BYTE: 4825 case OP_IGET_BYTE_JUMBO: 4826 tmpType = kRegTypeByte; 4827 goto iget_1nr_common; 4828 case OP_IGET_CHAR: 4829 case OP_IGET_CHAR_JUMBO: 4830 tmpType = kRegTypeChar; 4831 goto iget_1nr_common; 4832 case OP_IGET_SHORT: 4833 case OP_IGET_SHORT_JUMBO: 4834 tmpType = kRegTypeShort; 4835 goto iget_1nr_common; 4836iget_1nr_common: 4837 { 4838 InstField* instField; 4839 RegType objType, fieldType; 4840 4841 objType = getRegisterType(workLine, decInsn.vB); 4842 instField = getInstField(meth, uninitMap, objType, decInsn.vC, 4843 &failure); 4844 if (!VERIFY_OK(failure)) 4845 break; 4846 4847 /* make sure the field's type is compatible with expectation */ 4848 fieldType = primSigCharToRegType(instField->signature[0]); 4849 4850 /* correct if float */ 4851 if (fieldType == kRegTypeFloat) 4852 tmpType = kRegTypeFloat; 4853 4854 if (fieldType == kRegTypeUnknown || 4855 !checkFieldArrayStore1nr(tmpType, fieldType)) 4856 { 4857 LOG_VFY("VFY: invalid iget-1nr of %s.%s (inst=%d field=%d)", 4858 instField->clazz->descriptor, 4859 instField->name, tmpType, fieldType); 4860 failure = VERIFY_ERROR_GENERIC; 4861 break; 4862 } 4863 4864 setRegisterType(workLine, decInsn.vA, tmpType); 4865 } 4866 break; 4867 case OP_IGET_WIDE: 4868 case OP_IGET_WIDE_JUMBO: 4869 { 4870 RegType dstType; 4871 InstField* instField; 4872 RegType objType; 4873 4874 objType = getRegisterType(workLine, decInsn.vB); 4875 instField = getInstField(meth, uninitMap, objType, decInsn.vC, 4876 &failure); 4877 if (!VERIFY_OK(failure)) 4878 break; 4879 /* check the type, which should be prim */ 4880 switch (instField->signature[0]) { 4881 case 'D': 4882 dstType = kRegTypeDoubleLo; 4883 break; 4884 case 'J': 4885 dstType = kRegTypeLongLo; 4886 break; 4887 default: 4888 LOG_VFY("VFY: invalid iget-wide of %s.%s", 4889 instField->clazz->descriptor, 4890 instField->name); 4891 dstType = kRegTypeUnknown; 4892 failure = VERIFY_ERROR_GENERIC; 4893 break; 4894 } 4895 if (VERIFY_OK(failure)) { 4896 setRegisterType(workLine, decInsn.vA, dstType); 4897 } 4898 } 4899 break; 4900 case OP_IGET_OBJECT: 4901 case OP_IGET_OBJECT_JUMBO: 4902 { 4903 ClassObject* fieldClass; 4904 InstField* instField; 4905 RegType objType; 4906 4907 objType = getRegisterType(workLine, decInsn.vB); 4908 instField = getInstField(meth, uninitMap, objType, decInsn.vC, 4909 &failure); 4910 if (!VERIFY_OK(failure)) 4911 break; 4912 fieldClass = getFieldClass(meth, instField); 4913 if (fieldClass == NULL) { 4914 /* class not found or primitive type */ 4915 LOG_VFY("VFY: unable to recover field class from '%s'", 4916 instField->signature); 4917 failure = VERIFY_ERROR_GENERIC; 4918 break; 4919 } 4920 if (VERIFY_OK(failure)) { 4921 assert(!dvmIsPrimitiveClass(fieldClass)); 4922 setRegisterType(workLine, decInsn.vA, 4923 regTypeFromClass(fieldClass)); 4924 } 4925 } 4926 break; 4927 case OP_IPUT: 4928 case OP_IPUT_JUMBO: 4929 tmpType = kRegTypeInteger; 4930 goto iput_1nr_common; 4931 case OP_IPUT_BOOLEAN: 4932 case OP_IPUT_BOOLEAN_JUMBO: 4933 tmpType = kRegTypeBoolean; 4934 goto iput_1nr_common; 4935 case OP_IPUT_BYTE: 4936 case OP_IPUT_BYTE_JUMBO: 4937 tmpType = kRegTypeByte; 4938 goto iput_1nr_common; 4939 case OP_IPUT_CHAR: 4940 case OP_IPUT_CHAR_JUMBO: 4941 tmpType = kRegTypeChar; 4942 goto iput_1nr_common; 4943 case OP_IPUT_SHORT: 4944 case OP_IPUT_SHORT_JUMBO: 4945 tmpType = kRegTypeShort; 4946 goto iput_1nr_common; 4947iput_1nr_common: 4948 { 4949 RegType srcType, fieldType, objType; 4950 InstField* instField; 4951 4952 objType = getRegisterType(workLine, decInsn.vB); 4953 instField = getInstField(meth, uninitMap, objType, decInsn.vC, 4954 &failure); 4955 if (!VERIFY_OK(failure)) 4956 break; 4957 checkFinalFieldAccess(meth, instField, &failure); 4958 if (!VERIFY_OK(failure)) 4959 break; 4960 4961 /* get type of field we're storing into */ 4962 fieldType = primSigCharToRegType(instField->signature[0]); 4963 srcType = getRegisterType(workLine, decInsn.vA); 4964 4965 /* correct if float */ 4966 if (fieldType == kRegTypeFloat) 4967 tmpType = kRegTypeFloat; 4968 4969 /* 4970 * javac generates synthetic functions that write byte values 4971 * into boolean fields. 4972 */ 4973 if (tmpType == kRegTypeBoolean && srcType == kRegTypeByte) 4974 tmpType = kRegTypeByte; 4975 if (fieldType == kRegTypeBoolean && srcType == kRegTypeByte) 4976 fieldType = kRegTypeByte; 4977 4978 /* make sure the source register has the correct type */ 4979 if (!canConvertTo1nr(srcType, tmpType)) { 4980 LOG_VFY("VFY: invalid reg type %d on iput instr (need %d)", 4981 srcType, tmpType); 4982 failure = VERIFY_ERROR_GENERIC; 4983 break; 4984 } 4985 4986 verifyRegisterType(workLine, decInsn.vA, fieldType, &failure); 4987 4988 if (!VERIFY_OK(failure) || fieldType == kRegTypeUnknown || 4989 !checkFieldArrayStore1nr(tmpType, fieldType)) 4990 { 4991 LOG_VFY("VFY: invalid iput-1nr of %s.%s (inst=%d field=%d)", 4992 instField->clazz->descriptor, 4993 instField->name, tmpType, fieldType); 4994 failure = VERIFY_ERROR_GENERIC; 4995 break; 4996 } 4997 } 4998 break; 4999 case OP_IPUT_WIDE: 5000 case OP_IPUT_WIDE_JUMBO: 5001 InstField* instField; 5002 RegType objType; 5003 5004 objType = getRegisterType(workLine, decInsn.vB); 5005 instField = getInstField(meth, uninitMap, objType, decInsn.vC, 5006 &failure); 5007 if (!VERIFY_OK(failure)) 5008 break; 5009 checkFinalFieldAccess(meth, instField, &failure); 5010 if (!VERIFY_OK(failure)) 5011 break; 5012 5013 /* check the type, which should be prim */ 5014 switch (instField->signature[0]) { 5015 case 'D': 5016 verifyRegisterType(workLine, decInsn.vA, kRegTypeDoubleLo, &failure); 5017 break; 5018 case 'J': 5019 verifyRegisterType(workLine, decInsn.vA, kRegTypeLongLo, &failure); 5020 break; 5021 default: 5022 LOG_VFY("VFY: invalid iput-wide of %s.%s", 5023 instField->clazz->descriptor, 5024 instField->name); 5025 failure = VERIFY_ERROR_GENERIC; 5026 break; 5027 } 5028 break; 5029 case OP_IPUT_OBJECT: 5030 case OP_IPUT_OBJECT_JUMBO: 5031 { 5032 ClassObject* fieldClass; 5033 ClassObject* valueClass; 5034 InstField* instField; 5035 RegType objType, valueType; 5036 5037 objType = getRegisterType(workLine, decInsn.vB); 5038 instField = getInstField(meth, uninitMap, objType, decInsn.vC, 5039 &failure); 5040 if (!VERIFY_OK(failure)) 5041 break; 5042 checkFinalFieldAccess(meth, instField, &failure); 5043 if (!VERIFY_OK(failure)) 5044 break; 5045 5046 fieldClass = getFieldClass(meth, instField); 5047 if (fieldClass == NULL) { 5048 LOG_VFY("VFY: unable to recover field class from '%s'", 5049 instField->signature); 5050 failure = VERIFY_ERROR_GENERIC; 5051 break; 5052 } 5053 5054 valueType = getRegisterType(workLine, decInsn.vA); 5055 if (!regTypeIsReference(valueType)) { 5056 LOG_VFY("VFY: storing non-ref v%d into ref field '%s' (%s)", 5057 decInsn.vA, instField->name, 5058 fieldClass->descriptor); 5059 failure = VERIFY_ERROR_GENERIC; 5060 break; 5061 } 5062 if (valueType != kRegTypeZero) { 5063 valueClass = regTypeInitializedReferenceToClass(valueType); 5064 if (valueClass == NULL) { 5065 LOG_VFY("VFY: storing uninit ref v%d into ref field", 5066 decInsn.vA); 5067 failure = VERIFY_ERROR_GENERIC; 5068 break; 5069 } 5070 /* allow if field is any interface or field is base class */ 5071 if (!dvmIsInterfaceClass(fieldClass) && 5072 !dvmInstanceof(valueClass, fieldClass)) 5073 { 5074 LOG_VFY("VFY: storing type '%s' into field type '%s' (%s.%s)", 5075 valueClass->descriptor, fieldClass->descriptor, 5076 instField->clazz->descriptor, 5077 instField->name); 5078 failure = VERIFY_ERROR_GENERIC; 5079 break; 5080 } 5081 } 5082 } 5083 break; 5084 5085 case OP_SGET: 5086 case OP_SGET_JUMBO: 5087 tmpType = kRegTypeInteger; 5088 goto sget_1nr_common; 5089 case OP_SGET_BOOLEAN: 5090 case OP_SGET_BOOLEAN_JUMBO: 5091 tmpType = kRegTypeBoolean; 5092 goto sget_1nr_common; 5093 case OP_SGET_BYTE: 5094 case OP_SGET_BYTE_JUMBO: 5095 tmpType = kRegTypeByte; 5096 goto sget_1nr_common; 5097 case OP_SGET_CHAR: 5098 case OP_SGET_CHAR_JUMBO: 5099 tmpType = kRegTypeChar; 5100 goto sget_1nr_common; 5101 case OP_SGET_SHORT: 5102 case OP_SGET_SHORT_JUMBO: 5103 tmpType = kRegTypeShort; 5104 goto sget_1nr_common; 5105sget_1nr_common: 5106 { 5107 StaticField* staticField; 5108 RegType fieldType; 5109 5110 staticField = getStaticField(meth, decInsn.vB, &failure); 5111 if (!VERIFY_OK(failure)) 5112 break; 5113 5114 /* 5115 * Make sure the field's type is compatible with expectation. 5116 * We can get ourselves into trouble if we mix & match loads 5117 * and stores with different widths, so rather than just checking 5118 * "canConvertTo1nr" we require that the field types have equal 5119 * widths. 5120 */ 5121 fieldType = primSigCharToRegType(staticField->signature[0]); 5122 5123 /* correct if float */ 5124 if (fieldType == kRegTypeFloat) 5125 tmpType = kRegTypeFloat; 5126 5127 if (!checkFieldArrayStore1nr(tmpType, fieldType)) { 5128 LOG_VFY("VFY: invalid sget-1nr of %s.%s (inst=%d actual=%d)", 5129 staticField->clazz->descriptor, 5130 staticField->name, tmpType, fieldType); 5131 failure = VERIFY_ERROR_GENERIC; 5132 break; 5133 } 5134 5135 setRegisterType(workLine, decInsn.vA, tmpType); 5136 } 5137 break; 5138 case OP_SGET_WIDE: 5139 case OP_SGET_WIDE_JUMBO: 5140 { 5141 StaticField* staticField; 5142 RegType dstType; 5143 5144 staticField = getStaticField(meth, decInsn.vB, &failure); 5145 if (!VERIFY_OK(failure)) 5146 break; 5147 /* check the type, which should be prim */ 5148 switch (staticField->signature[0]) { 5149 case 'D': 5150 dstType = kRegTypeDoubleLo; 5151 break; 5152 case 'J': 5153 dstType = kRegTypeLongLo; 5154 break; 5155 default: 5156 LOG_VFY("VFY: invalid sget-wide of %s.%s", 5157 staticField->clazz->descriptor, 5158 staticField->name); 5159 dstType = kRegTypeUnknown; 5160 failure = VERIFY_ERROR_GENERIC; 5161 break; 5162 } 5163 if (VERIFY_OK(failure)) { 5164 setRegisterType(workLine, decInsn.vA, dstType); 5165 } 5166 } 5167 break; 5168 case OP_SGET_OBJECT: 5169 case OP_SGET_OBJECT_JUMBO: 5170 { 5171 StaticField* staticField; 5172 ClassObject* fieldClass; 5173 5174 staticField = getStaticField(meth, decInsn.vB, &failure); 5175 if (!VERIFY_OK(failure)) 5176 break; 5177 fieldClass = getFieldClass(meth, staticField); 5178 if (fieldClass == NULL) { 5179 LOG_VFY("VFY: unable to recover field class from '%s'", 5180 staticField->signature); 5181 failure = VERIFY_ERROR_GENERIC; 5182 break; 5183 } 5184 if (dvmIsPrimitiveClass(fieldClass)) { 5185 LOG_VFY("VFY: attempt to get prim field with sget-object"); 5186 failure = VERIFY_ERROR_GENERIC; 5187 break; 5188 } 5189 setRegisterType(workLine, decInsn.vA, regTypeFromClass(fieldClass)); 5190 } 5191 break; 5192 case OP_SPUT: 5193 case OP_SPUT_JUMBO: 5194 tmpType = kRegTypeInteger; 5195 goto sput_1nr_common; 5196 case OP_SPUT_BOOLEAN: 5197 case OP_SPUT_BOOLEAN_JUMBO: 5198 tmpType = kRegTypeBoolean; 5199 goto sput_1nr_common; 5200 case OP_SPUT_BYTE: 5201 case OP_SPUT_BYTE_JUMBO: 5202 tmpType = kRegTypeByte; 5203 goto sput_1nr_common; 5204 case OP_SPUT_CHAR: 5205 case OP_SPUT_CHAR_JUMBO: 5206 tmpType = kRegTypeChar; 5207 goto sput_1nr_common; 5208 case OP_SPUT_SHORT: 5209 case OP_SPUT_SHORT_JUMBO: 5210 tmpType = kRegTypeShort; 5211 goto sput_1nr_common; 5212sput_1nr_common: 5213 { 5214 RegType srcType, fieldType; 5215 StaticField* staticField; 5216 5217 staticField = getStaticField(meth, decInsn.vB, &failure); 5218 if (!VERIFY_OK(failure)) 5219 break; 5220 checkFinalFieldAccess(meth, staticField, &failure); 5221 if (!VERIFY_OK(failure)) 5222 break; 5223 5224 /* 5225 * Get type of field we're storing into. We know that the 5226 * contents of the register match the instruction, but we also 5227 * need to ensure that the instruction matches the field type. 5228 * Using e.g. sput-short to write into a 32-bit integer field 5229 * can lead to trouble if we do 16-bit writes. 5230 */ 5231 fieldType = primSigCharToRegType(staticField->signature[0]); 5232 srcType = getRegisterType(workLine, decInsn.vA); 5233 5234 /* correct if float */ 5235 if (fieldType == kRegTypeFloat) 5236 tmpType = kRegTypeFloat; 5237 5238 /* 5239 * javac generates synthetic functions that write byte values 5240 * into boolean fields. 5241 */ 5242 if (tmpType == kRegTypeBoolean && srcType == kRegTypeByte) 5243 tmpType = kRegTypeByte; 5244 if (fieldType == kRegTypeBoolean && srcType == kRegTypeByte) 5245 fieldType = kRegTypeByte; 5246 5247 /* make sure the source register has the correct type */ 5248 if (!canConvertTo1nr(srcType, tmpType)) { 5249 LOG_VFY("VFY: invalid reg type %d on sput instr (need %d)", 5250 srcType, tmpType); 5251 failure = VERIFY_ERROR_GENERIC; 5252 break; 5253 } 5254 5255 verifyRegisterType(workLine, decInsn.vA, fieldType, &failure); 5256 5257 if (!VERIFY_OK(failure) || fieldType == kRegTypeUnknown || 5258 !checkFieldArrayStore1nr(tmpType, fieldType)) { 5259 LOG_VFY("VFY: invalid sput-1nr of %s.%s (inst=%d actual=%d)", 5260 staticField->clazz->descriptor, 5261 staticField->name, tmpType, fieldType); 5262 failure = VERIFY_ERROR_GENERIC; 5263 break; 5264 } 5265 } 5266 break; 5267 case OP_SPUT_WIDE: 5268 case OP_SPUT_WIDE_JUMBO: 5269 StaticField* staticField; 5270 5271 staticField = getStaticField(meth, decInsn.vB, &failure); 5272 if (!VERIFY_OK(failure)) 5273 break; 5274 checkFinalFieldAccess(meth, staticField, &failure); 5275 if (!VERIFY_OK(failure)) 5276 break; 5277 5278 /* check the type, which should be prim */ 5279 switch (staticField->signature[0]) { 5280 case 'D': 5281 verifyRegisterType(workLine, decInsn.vA, kRegTypeDoubleLo, &failure); 5282 break; 5283 case 'J': 5284 verifyRegisterType(workLine, decInsn.vA, kRegTypeLongLo, &failure); 5285 break; 5286 default: 5287 LOG_VFY("VFY: invalid sput-wide of %s.%s", 5288 staticField->clazz->descriptor, 5289 staticField->name); 5290 failure = VERIFY_ERROR_GENERIC; 5291 break; 5292 } 5293 break; 5294 case OP_SPUT_OBJECT: 5295 case OP_SPUT_OBJECT_JUMBO: 5296 { 5297 ClassObject* fieldClass; 5298 ClassObject* valueClass; 5299 StaticField* staticField; 5300 RegType valueType; 5301 5302 staticField = getStaticField(meth, decInsn.vB, &failure); 5303 if (!VERIFY_OK(failure)) 5304 break; 5305 checkFinalFieldAccess(meth, staticField, &failure); 5306 if (!VERIFY_OK(failure)) 5307 break; 5308 5309 fieldClass = getFieldClass(meth, staticField); 5310 if (fieldClass == NULL) { 5311 LOG_VFY("VFY: unable to recover field class from '%s'", 5312 staticField->signature); 5313 failure = VERIFY_ERROR_GENERIC; 5314 break; 5315 } 5316 5317 valueType = getRegisterType(workLine, decInsn.vA); 5318 if (!regTypeIsReference(valueType)) { 5319 LOG_VFY("VFY: storing non-ref v%d into ref field '%s' (%s)", 5320 decInsn.vA, staticField->name, 5321 fieldClass->descriptor); 5322 failure = VERIFY_ERROR_GENERIC; 5323 break; 5324 } 5325 if (valueType != kRegTypeZero) { 5326 valueClass = regTypeInitializedReferenceToClass(valueType); 5327 if (valueClass == NULL) { 5328 LOG_VFY("VFY: storing uninit ref v%d into ref field", 5329 decInsn.vA); 5330 failure = VERIFY_ERROR_GENERIC; 5331 break; 5332 } 5333 /* allow if field is any interface or field is base class */ 5334 if (!dvmIsInterfaceClass(fieldClass) && 5335 !dvmInstanceof(valueClass, fieldClass)) 5336 { 5337 LOG_VFY("VFY: storing type '%s' into field type '%s' (%s.%s)", 5338 valueClass->descriptor, fieldClass->descriptor, 5339 staticField->clazz->descriptor, 5340 staticField->name); 5341 failure = VERIFY_ERROR_GENERIC; 5342 break; 5343 } 5344 } 5345 } 5346 break; 5347 5348 case OP_INVOKE_VIRTUAL: 5349 case OP_INVOKE_VIRTUAL_RANGE: 5350 case OP_INVOKE_VIRTUAL_JUMBO: 5351 case OP_INVOKE_SUPER: 5352 case OP_INVOKE_SUPER_RANGE: 5353 case OP_INVOKE_SUPER_JUMBO: 5354 { 5355 Method* calledMethod; 5356 RegType returnType; 5357 bool isRange; 5358 bool isSuper; 5359 5360 isRange = (decInsn.opcode == OP_INVOKE_VIRTUAL_RANGE || 5361 decInsn.opcode == OP_INVOKE_VIRTUAL_JUMBO || 5362 decInsn.opcode == OP_INVOKE_SUPER_RANGE || 5363 decInsn.opcode == OP_INVOKE_SUPER_JUMBO); 5364 isSuper = (decInsn.opcode == OP_INVOKE_SUPER || 5365 decInsn.opcode == OP_INVOKE_SUPER_RANGE || 5366 decInsn.opcode == OP_INVOKE_SUPER_JUMBO); 5367 5368 calledMethod = verifyInvocationArgs(meth, workLine, insnRegCount, 5369 &decInsn, uninitMap, METHOD_VIRTUAL, isRange, 5370 isSuper, &failure); 5371 if (!VERIFY_OK(failure)) 5372 break; 5373 returnType = getMethodReturnType(calledMethod); 5374 setResultRegisterType(workLine, insnRegCount, returnType); 5375 justSetResult = true; 5376 } 5377 break; 5378 case OP_INVOKE_DIRECT: 5379 case OP_INVOKE_DIRECT_RANGE: 5380 case OP_INVOKE_DIRECT_JUMBO: 5381 { 5382 RegType returnType; 5383 Method* calledMethod; 5384 bool isRange; 5385 5386 isRange = (decInsn.opcode == OP_INVOKE_DIRECT_RANGE || 5387 decInsn.opcode == OP_INVOKE_DIRECT_JUMBO); 5388 calledMethod = verifyInvocationArgs(meth, workLine, insnRegCount, 5389 &decInsn, uninitMap, METHOD_DIRECT, isRange, 5390 false, &failure); 5391 if (!VERIFY_OK(failure)) 5392 break; 5393 5394 /* 5395 * Some additional checks when calling <init>. We know from 5396 * the invocation arg check that the "this" argument is an 5397 * instance of calledMethod->clazz. Now we further restrict 5398 * that to require that calledMethod->clazz is the same as 5399 * this->clazz or this->super, allowing the latter only if 5400 * the "this" argument is the same as the "this" argument to 5401 * this method (which implies that we're in <init> ourselves). 5402 */ 5403 if (isInitMethod(calledMethod)) { 5404 RegType thisType; 5405 thisType = getInvocationThis(workLine, &decInsn, &failure); 5406 if (!VERIFY_OK(failure)) 5407 break; 5408 5409 /* no null refs allowed (?) */ 5410 if (thisType == kRegTypeZero) { 5411 LOG_VFY("VFY: unable to initialize null ref"); 5412 failure = VERIFY_ERROR_GENERIC; 5413 break; 5414 } 5415 5416 ClassObject* thisClass; 5417 5418 thisClass = regTypeReferenceToClass(thisType, uninitMap); 5419 assert(thisClass != NULL); 5420 5421 /* must be in same class or in superclass */ 5422 if (calledMethod->clazz == thisClass->super) { 5423 if (thisClass != meth->clazz) { 5424 LOG_VFY("VFY: invoke-direct <init> on super only " 5425 "allowed for 'this' in <init>"); 5426 failure = VERIFY_ERROR_GENERIC; 5427 break; 5428 } 5429 } else if (calledMethod->clazz != thisClass) { 5430 LOG_VFY("VFY: invoke-direct <init> must be on current " 5431 "class or super"); 5432 failure = VERIFY_ERROR_GENERIC; 5433 break; 5434 } 5435 5436 /* arg must be an uninitialized reference */ 5437 if (!regTypeIsUninitReference(thisType)) { 5438 LOG_VFY("VFY: can only initialize the uninitialized"); 5439 failure = VERIFY_ERROR_GENERIC; 5440 break; 5441 } 5442 5443 /* 5444 * Replace the uninitialized reference with an initialized 5445 * one, and clear the entry in the uninit map. We need to 5446 * do this for all registers that have the same object 5447 * instance in them, not just the "this" register. 5448 */ 5449 markRefsAsInitialized(workLine, insnRegCount, uninitMap, 5450 thisType, &failure); 5451 if (!VERIFY_OK(failure)) 5452 break; 5453 } 5454 returnType = getMethodReturnType(calledMethod); 5455 setResultRegisterType(workLine, insnRegCount, returnType); 5456 justSetResult = true; 5457 } 5458 break; 5459 case OP_INVOKE_STATIC: 5460 case OP_INVOKE_STATIC_RANGE: 5461 case OP_INVOKE_STATIC_JUMBO: 5462 { 5463 RegType returnType; 5464 Method* calledMethod; 5465 bool isRange; 5466 5467 isRange = (decInsn.opcode == OP_INVOKE_STATIC_RANGE || 5468 decInsn.opcode == OP_INVOKE_STATIC_JUMBO); 5469 calledMethod = verifyInvocationArgs(meth, workLine, insnRegCount, 5470 &decInsn, uninitMap, METHOD_STATIC, isRange, 5471 false, &failure); 5472 if (!VERIFY_OK(failure)) 5473 break; 5474 5475 returnType = getMethodReturnType(calledMethod); 5476 setResultRegisterType(workLine, insnRegCount, returnType); 5477 justSetResult = true; 5478 } 5479 break; 5480 case OP_INVOKE_INTERFACE: 5481 case OP_INVOKE_INTERFACE_RANGE: 5482 case OP_INVOKE_INTERFACE_JUMBO: 5483 { 5484 RegType /*thisType,*/ returnType; 5485 Method* absMethod; 5486 bool isRange; 5487 5488 isRange = (decInsn.opcode == OP_INVOKE_INTERFACE_RANGE || 5489 decInsn.opcode == OP_INVOKE_INTERFACE_JUMBO); 5490 absMethod = verifyInvocationArgs(meth, workLine, insnRegCount, 5491 &decInsn, uninitMap, METHOD_INTERFACE, isRange, 5492 false, &failure); 5493 if (!VERIFY_OK(failure)) 5494 break; 5495 5496#if 0 /* can't do this here, fails on dalvik test 052-verifier-fun */ 5497 /* 5498 * Get the type of the "this" arg, which should always be an 5499 * interface class. Because we don't do a full merge on 5500 * interface classes, this might have reduced to Object. 5501 */ 5502 thisType = getInvocationThis(workLine, &decInsn, &failure); 5503 if (!VERIFY_OK(failure)) 5504 break; 5505 5506 if (thisType == kRegTypeZero) { 5507 /* null pointer always passes (and always fails at runtime) */ 5508 } else { 5509 ClassObject* thisClass; 5510 5511 thisClass = regTypeInitializedReferenceToClass(thisType); 5512 if (thisClass == NULL) { 5513 LOG_VFY("VFY: interface call on uninitialized"); 5514 failure = VERIFY_ERROR_GENERIC; 5515 break; 5516 } 5517 5518 /* 5519 * Either "thisClass" needs to be the interface class that 5520 * defined absMethod, or absMethod's class needs to be one 5521 * of the interfaces implemented by "thisClass". (Or, if 5522 * we couldn't complete the merge, this will be Object.) 5523 */ 5524 if (thisClass != absMethod->clazz && 5525 thisClass != gDvm.classJavaLangObject && 5526 !dvmImplements(thisClass, absMethod->clazz)) 5527 { 5528 LOG_VFY("VFY: unable to match absMethod '%s' with %s interfaces", 5529 absMethod->name, thisClass->descriptor); 5530 failure = VERIFY_ERROR_GENERIC; 5531 break; 5532 } 5533 } 5534#endif 5535 5536 /* 5537 * We don't have an object instance, so we can't find the 5538 * concrete method. However, all of the type information is 5539 * in the abstract method, so we're good. 5540 */ 5541 returnType = getMethodReturnType(absMethod); 5542 setResultRegisterType(workLine, insnRegCount, returnType); 5543 justSetResult = true; 5544 } 5545 break; 5546 5547 case OP_NEG_INT: 5548 case OP_NOT_INT: 5549 checkUnop(workLine, &decInsn, 5550 kRegTypeInteger, kRegTypeInteger, &failure); 5551 break; 5552 case OP_NEG_LONG: 5553 case OP_NOT_LONG: 5554 checkUnop(workLine, &decInsn, 5555 kRegTypeLongLo, kRegTypeLongLo, &failure); 5556 break; 5557 case OP_NEG_FLOAT: 5558 checkUnop(workLine, &decInsn, 5559 kRegTypeFloat, kRegTypeFloat, &failure); 5560 break; 5561 case OP_NEG_DOUBLE: 5562 checkUnop(workLine, &decInsn, 5563 kRegTypeDoubleLo, kRegTypeDoubleLo, &failure); 5564 break; 5565 case OP_INT_TO_LONG: 5566 checkUnop(workLine, &decInsn, 5567 kRegTypeLongLo, kRegTypeInteger, &failure); 5568 break; 5569 case OP_INT_TO_FLOAT: 5570 checkUnop(workLine, &decInsn, 5571 kRegTypeFloat, kRegTypeInteger, &failure); 5572 break; 5573 case OP_INT_TO_DOUBLE: 5574 checkUnop(workLine, &decInsn, 5575 kRegTypeDoubleLo, kRegTypeInteger, &failure); 5576 break; 5577 case OP_LONG_TO_INT: 5578 checkUnop(workLine, &decInsn, 5579 kRegTypeInteger, kRegTypeLongLo, &failure); 5580 break; 5581 case OP_LONG_TO_FLOAT: 5582 checkUnop(workLine, &decInsn, 5583 kRegTypeFloat, kRegTypeLongLo, &failure); 5584 break; 5585 case OP_LONG_TO_DOUBLE: 5586 checkUnop(workLine, &decInsn, 5587 kRegTypeDoubleLo, kRegTypeLongLo, &failure); 5588 break; 5589 case OP_FLOAT_TO_INT: 5590 checkUnop(workLine, &decInsn, 5591 kRegTypeInteger, kRegTypeFloat, &failure); 5592 break; 5593 case OP_FLOAT_TO_LONG: 5594 checkUnop(workLine, &decInsn, 5595 kRegTypeLongLo, kRegTypeFloat, &failure); 5596 break; 5597 case OP_FLOAT_TO_DOUBLE: 5598 checkUnop(workLine, &decInsn, 5599 kRegTypeDoubleLo, kRegTypeFloat, &failure); 5600 break; 5601 case OP_DOUBLE_TO_INT: 5602 checkUnop(workLine, &decInsn, 5603 kRegTypeInteger, kRegTypeDoubleLo, &failure); 5604 break; 5605 case OP_DOUBLE_TO_LONG: 5606 checkUnop(workLine, &decInsn, 5607 kRegTypeLongLo, kRegTypeDoubleLo, &failure); 5608 break; 5609 case OP_DOUBLE_TO_FLOAT: 5610 checkUnop(workLine, &decInsn, 5611 kRegTypeFloat, kRegTypeDoubleLo, &failure); 5612 break; 5613 case OP_INT_TO_BYTE: 5614 checkUnop(workLine, &decInsn, 5615 kRegTypeByte, kRegTypeInteger, &failure); 5616 break; 5617 case OP_INT_TO_CHAR: 5618 checkUnop(workLine, &decInsn, 5619 kRegTypeChar, kRegTypeInteger, &failure); 5620 break; 5621 case OP_INT_TO_SHORT: 5622 checkUnop(workLine, &decInsn, 5623 kRegTypeShort, kRegTypeInteger, &failure); 5624 break; 5625 5626 case OP_ADD_INT: 5627 case OP_SUB_INT: 5628 case OP_MUL_INT: 5629 case OP_REM_INT: 5630 case OP_DIV_INT: 5631 case OP_SHL_INT: 5632 case OP_SHR_INT: 5633 case OP_USHR_INT: 5634 checkBinop(workLine, &decInsn, 5635 kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, false, &failure); 5636 break; 5637 case OP_AND_INT: 5638 case OP_OR_INT: 5639 case OP_XOR_INT: 5640 checkBinop(workLine, &decInsn, 5641 kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, true, &failure); 5642 break; 5643 case OP_ADD_LONG: 5644 case OP_SUB_LONG: 5645 case OP_MUL_LONG: 5646 case OP_DIV_LONG: 5647 case OP_REM_LONG: 5648 case OP_AND_LONG: 5649 case OP_OR_LONG: 5650 case OP_XOR_LONG: 5651 checkBinop(workLine, &decInsn, 5652 kRegTypeLongLo, kRegTypeLongLo, kRegTypeLongLo, false, &failure); 5653 break; 5654 case OP_SHL_LONG: 5655 case OP_SHR_LONG: 5656 case OP_USHR_LONG: 5657 /* shift distance is Int, making these different from other binops */ 5658 checkBinop(workLine, &decInsn, 5659 kRegTypeLongLo, kRegTypeLongLo, kRegTypeInteger, false, &failure); 5660 break; 5661 case OP_ADD_FLOAT: 5662 case OP_SUB_FLOAT: 5663 case OP_MUL_FLOAT: 5664 case OP_DIV_FLOAT: 5665 case OP_REM_FLOAT: 5666 checkBinop(workLine, &decInsn, 5667 kRegTypeFloat, kRegTypeFloat, kRegTypeFloat, false, &failure); 5668 break; 5669 case OP_ADD_DOUBLE: 5670 case OP_SUB_DOUBLE: 5671 case OP_MUL_DOUBLE: 5672 case OP_DIV_DOUBLE: 5673 case OP_REM_DOUBLE: 5674 checkBinop(workLine, &decInsn, 5675 kRegTypeDoubleLo, kRegTypeDoubleLo, kRegTypeDoubleLo, false, 5676 &failure); 5677 break; 5678 case OP_ADD_INT_2ADDR: 5679 case OP_SUB_INT_2ADDR: 5680 case OP_MUL_INT_2ADDR: 5681 case OP_REM_INT_2ADDR: 5682 case OP_SHL_INT_2ADDR: 5683 case OP_SHR_INT_2ADDR: 5684 case OP_USHR_INT_2ADDR: 5685 checkBinop2addr(workLine, &decInsn, 5686 kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, false, &failure); 5687 break; 5688 case OP_AND_INT_2ADDR: 5689 case OP_OR_INT_2ADDR: 5690 case OP_XOR_INT_2ADDR: 5691 checkBinop2addr(workLine, &decInsn, 5692 kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, true, &failure); 5693 break; 5694 case OP_DIV_INT_2ADDR: 5695 checkBinop2addr(workLine, &decInsn, 5696 kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, false, &failure); 5697 break; 5698 case OP_ADD_LONG_2ADDR: 5699 case OP_SUB_LONG_2ADDR: 5700 case OP_MUL_LONG_2ADDR: 5701 case OP_DIV_LONG_2ADDR: 5702 case OP_REM_LONG_2ADDR: 5703 case OP_AND_LONG_2ADDR: 5704 case OP_OR_LONG_2ADDR: 5705 case OP_XOR_LONG_2ADDR: 5706 checkBinop2addr(workLine, &decInsn, 5707 kRegTypeLongLo, kRegTypeLongLo, kRegTypeLongLo, false, &failure); 5708 break; 5709 case OP_SHL_LONG_2ADDR: 5710 case OP_SHR_LONG_2ADDR: 5711 case OP_USHR_LONG_2ADDR: 5712 checkBinop2addr(workLine, &decInsn, 5713 kRegTypeLongLo, kRegTypeLongLo, kRegTypeInteger, false, &failure); 5714 break; 5715 case OP_ADD_FLOAT_2ADDR: 5716 case OP_SUB_FLOAT_2ADDR: 5717 case OP_MUL_FLOAT_2ADDR: 5718 case OP_DIV_FLOAT_2ADDR: 5719 case OP_REM_FLOAT_2ADDR: 5720 checkBinop2addr(workLine, &decInsn, 5721 kRegTypeFloat, kRegTypeFloat, kRegTypeFloat, false, &failure); 5722 break; 5723 case OP_ADD_DOUBLE_2ADDR: 5724 case OP_SUB_DOUBLE_2ADDR: 5725 case OP_MUL_DOUBLE_2ADDR: 5726 case OP_DIV_DOUBLE_2ADDR: 5727 case OP_REM_DOUBLE_2ADDR: 5728 checkBinop2addr(workLine, &decInsn, 5729 kRegTypeDoubleLo, kRegTypeDoubleLo, kRegTypeDoubleLo, false, 5730 &failure); 5731 break; 5732 case OP_ADD_INT_LIT16: 5733 case OP_RSUB_INT: 5734 case OP_MUL_INT_LIT16: 5735 case OP_DIV_INT_LIT16: 5736 case OP_REM_INT_LIT16: 5737 checkLitop(workLine, &decInsn, 5738 kRegTypeInteger, kRegTypeInteger, false, &failure); 5739 break; 5740 case OP_AND_INT_LIT16: 5741 case OP_OR_INT_LIT16: 5742 case OP_XOR_INT_LIT16: 5743 checkLitop(workLine, &decInsn, 5744 kRegTypeInteger, kRegTypeInteger, true, &failure); 5745 break; 5746 case OP_ADD_INT_LIT8: 5747 case OP_RSUB_INT_LIT8: 5748 case OP_MUL_INT_LIT8: 5749 case OP_DIV_INT_LIT8: 5750 case OP_REM_INT_LIT8: 5751 case OP_SHL_INT_LIT8: 5752 checkLitop(workLine, &decInsn, 5753 kRegTypeInteger, kRegTypeInteger, false, &failure); 5754 break; 5755 case OP_SHR_INT_LIT8: 5756 tmpType = adjustForRightShift(workLine, 5757 decInsn.vB, decInsn.vC, false, &failure); 5758 checkLitop(workLine, &decInsn, 5759 tmpType, kRegTypeInteger, false, &failure); 5760 break; 5761 case OP_USHR_INT_LIT8: 5762 tmpType = adjustForRightShift(workLine, 5763 decInsn.vB, decInsn.vC, true, &failure); 5764 checkLitop(workLine, &decInsn, 5765 tmpType, kRegTypeInteger, false, &failure); 5766 break; 5767 case OP_AND_INT_LIT8: 5768 case OP_OR_INT_LIT8: 5769 case OP_XOR_INT_LIT8: 5770 checkLitop(workLine, &decInsn, 5771 kRegTypeInteger, kRegTypeInteger, true, &failure); 5772 break; 5773 5774 /* 5775 * This falls into the general category of "optimized" instructions, 5776 * which don't generally appear during verification. Because it's 5777 * inserted in the course of verification, we can expect to see it here. 5778 */ 5779 case OP_THROW_VERIFICATION_ERROR: 5780 case OP_THROW_VERIFICATION_ERROR_JUMBO: 5781 break; 5782 5783 /* 5784 * Verifying "quickened" instructions is tricky, because we have 5785 * discarded the original field/method information. The byte offsets 5786 * and vtable indices only have meaning in the context of an object 5787 * instance. 5788 * 5789 * If a piece of code declares a local reference variable, assigns 5790 * null to it, and then issues a virtual method call on it, we 5791 * cannot evaluate the method call during verification. This situation 5792 * isn't hard to handle, since we know the call will always result in an 5793 * NPE, and the arguments and return value don't matter. Any code that 5794 * depends on the result of the method call is inaccessible, so the 5795 * fact that we can't fully verify anything that comes after the bad 5796 * call is not a problem. 5797 * 5798 * We must also consider the case of multiple code paths, only some of 5799 * which involve a null reference. We can completely verify the method 5800 * if we sidestep the results of executing with a null reference. 5801 * For example, if on the first pass through the code we try to do a 5802 * virtual method invocation through a null ref, we have to skip the 5803 * method checks and have the method return a "wildcard" type (which 5804 * merges with anything to become that other thing). The move-result 5805 * will tell us if it's a reference, single-word numeric, or double-word 5806 * value. We continue to perform the verification, and at the end of 5807 * the function any invocations that were never fully exercised are 5808 * marked as null-only. 5809 * 5810 * We would do something similar for the field accesses. The field's 5811 * type, once known, can be used to recover the width of short integers. 5812 * If the object reference was null, the field-get returns the "wildcard" 5813 * type, which is acceptable for any operation. 5814 */ 5815 case OP_EXECUTE_INLINE: 5816 case OP_EXECUTE_INLINE_RANGE: 5817 case OP_IGET_QUICK: 5818 case OP_IGET_WIDE_QUICK: 5819 case OP_IGET_OBJECT_QUICK: 5820 case OP_IPUT_QUICK: 5821 case OP_IPUT_WIDE_QUICK: 5822 case OP_IPUT_OBJECT_QUICK: 5823 case OP_INVOKE_VIRTUAL_QUICK: 5824 case OP_INVOKE_VIRTUAL_QUICK_RANGE: 5825 case OP_INVOKE_SUPER_QUICK: 5826 case OP_INVOKE_SUPER_QUICK_RANGE: 5827 /* fall through to failure */ 5828 5829 /* 5830 * These instructions are equivalent (from the verifier's point of view) 5831 * to the original form. The change was made for correctness rather 5832 * than improved performance (except for invoke-object-init, which 5833 * provides both). The substitution takes place after verification 5834 * completes, though, so we don't expect to see them here. 5835 */ 5836 case OP_INVOKE_OBJECT_INIT_RANGE: 5837 case OP_INVOKE_OBJECT_INIT_JUMBO: 5838 case OP_RETURN_VOID_BARRIER: 5839 case OP_IGET_VOLATILE: 5840 case OP_IGET_VOLATILE_JUMBO: 5841 case OP_IGET_WIDE_VOLATILE: 5842 case OP_IGET_WIDE_VOLATILE_JUMBO: 5843 case OP_IGET_OBJECT_VOLATILE: 5844 case OP_IGET_OBJECT_VOLATILE_JUMBO: 5845 case OP_IPUT_VOLATILE: 5846 case OP_IPUT_VOLATILE_JUMBO: 5847 case OP_IPUT_WIDE_VOLATILE: 5848 case OP_IPUT_WIDE_VOLATILE_JUMBO: 5849 case OP_IPUT_OBJECT_VOLATILE: 5850 case OP_IPUT_OBJECT_VOLATILE_JUMBO: 5851 case OP_SGET_VOLATILE: 5852 case OP_SGET_VOLATILE_JUMBO: 5853 case OP_SGET_WIDE_VOLATILE: 5854 case OP_SGET_WIDE_VOLATILE_JUMBO: 5855 case OP_SGET_OBJECT_VOLATILE: 5856 case OP_SGET_OBJECT_VOLATILE_JUMBO: 5857 case OP_SPUT_VOLATILE: 5858 case OP_SPUT_VOLATILE_JUMBO: 5859 case OP_SPUT_WIDE_VOLATILE: 5860 case OP_SPUT_WIDE_VOLATILE_JUMBO: 5861 case OP_SPUT_OBJECT_VOLATILE: 5862 case OP_SPUT_OBJECT_VOLATILE_JUMBO: 5863 /* fall through to failure */ 5864 5865 /* these should never appear during verification */ 5866 case OP_UNUSED_3E: 5867 case OP_UNUSED_3F: 5868 case OP_UNUSED_40: 5869 case OP_UNUSED_41: 5870 case OP_UNUSED_42: 5871 case OP_UNUSED_43: 5872 case OP_UNUSED_73: 5873 case OP_UNUSED_79: 5874 case OP_UNUSED_7A: 5875 case OP_BREAKPOINT: 5876 case OP_DISPATCH_FF: 5877 case OP_UNUSED_27FF: 5878 case OP_UNUSED_28FF: 5879 case OP_UNUSED_29FF: 5880 case OP_UNUSED_2AFF: 5881 case OP_UNUSED_2BFF: 5882 case OP_UNUSED_2CFF: 5883 case OP_UNUSED_2DFF: 5884 case OP_UNUSED_2EFF: 5885 case OP_UNUSED_2FFF: 5886 case OP_UNUSED_30FF: 5887 case OP_UNUSED_31FF: 5888 case OP_UNUSED_32FF: 5889 case OP_UNUSED_33FF: 5890 case OP_UNUSED_34FF: 5891 case OP_UNUSED_35FF: 5892 case OP_UNUSED_36FF: 5893 case OP_UNUSED_37FF: 5894 case OP_UNUSED_38FF: 5895 case OP_UNUSED_39FF: 5896 case OP_UNUSED_3AFF: 5897 case OP_UNUSED_3BFF: 5898 case OP_UNUSED_3CFF: 5899 case OP_UNUSED_3DFF: 5900 case OP_UNUSED_3EFF: 5901 case OP_UNUSED_3FFF: 5902 case OP_UNUSED_40FF: 5903 case OP_UNUSED_41FF: 5904 case OP_UNUSED_42FF: 5905 case OP_UNUSED_43FF: 5906 case OP_UNUSED_44FF: 5907 case OP_UNUSED_45FF: 5908 case OP_UNUSED_46FF: 5909 case OP_UNUSED_47FF: 5910 case OP_UNUSED_48FF: 5911 case OP_UNUSED_49FF: 5912 case OP_UNUSED_4AFF: 5913 case OP_UNUSED_4BFF: 5914 case OP_UNUSED_4CFF: 5915 case OP_UNUSED_4DFF: 5916 case OP_UNUSED_4EFF: 5917 case OP_UNUSED_4FFF: 5918 case OP_UNUSED_50FF: 5919 case OP_UNUSED_51FF: 5920 case OP_UNUSED_52FF: 5921 case OP_UNUSED_53FF: 5922 case OP_UNUSED_54FF: 5923 case OP_UNUSED_55FF: 5924 case OP_UNUSED_56FF: 5925 case OP_UNUSED_57FF: 5926 case OP_UNUSED_58FF: 5927 case OP_UNUSED_59FF: 5928 case OP_UNUSED_5AFF: 5929 case OP_UNUSED_5BFF: 5930 case OP_UNUSED_5CFF: 5931 case OP_UNUSED_5DFF: 5932 case OP_UNUSED_5EFF: 5933 case OP_UNUSED_5FFF: 5934 case OP_UNUSED_60FF: 5935 case OP_UNUSED_61FF: 5936 case OP_UNUSED_62FF: 5937 case OP_UNUSED_63FF: 5938 case OP_UNUSED_64FF: 5939 case OP_UNUSED_65FF: 5940 case OP_UNUSED_66FF: 5941 case OP_UNUSED_67FF: 5942 case OP_UNUSED_68FF: 5943 case OP_UNUSED_69FF: 5944 case OP_UNUSED_6AFF: 5945 case OP_UNUSED_6BFF: 5946 case OP_UNUSED_6CFF: 5947 case OP_UNUSED_6DFF: 5948 case OP_UNUSED_6EFF: 5949 case OP_UNUSED_6FFF: 5950 case OP_UNUSED_70FF: 5951 case OP_UNUSED_71FF: 5952 case OP_UNUSED_72FF: 5953 case OP_UNUSED_73FF: 5954 case OP_UNUSED_74FF: 5955 case OP_UNUSED_75FF: 5956 case OP_UNUSED_76FF: 5957 case OP_UNUSED_77FF: 5958 case OP_UNUSED_78FF: 5959 case OP_UNUSED_79FF: 5960 case OP_UNUSED_7AFF: 5961 case OP_UNUSED_7BFF: 5962 case OP_UNUSED_7CFF: 5963 case OP_UNUSED_7DFF: 5964 case OP_UNUSED_7EFF: 5965 case OP_UNUSED_7FFF: 5966 case OP_UNUSED_80FF: 5967 case OP_UNUSED_81FF: 5968 case OP_UNUSED_82FF: 5969 case OP_UNUSED_83FF: 5970 case OP_UNUSED_84FF: 5971 case OP_UNUSED_85FF: 5972 case OP_UNUSED_86FF: 5973 case OP_UNUSED_87FF: 5974 case OP_UNUSED_88FF: 5975 case OP_UNUSED_89FF: 5976 case OP_UNUSED_8AFF: 5977 case OP_UNUSED_8BFF: 5978 case OP_UNUSED_8CFF: 5979 case OP_UNUSED_8DFF: 5980 case OP_UNUSED_8EFF: 5981 case OP_UNUSED_8FFF: 5982 case OP_UNUSED_90FF: 5983 case OP_UNUSED_91FF: 5984 case OP_UNUSED_92FF: 5985 case OP_UNUSED_93FF: 5986 case OP_UNUSED_94FF: 5987 case OP_UNUSED_95FF: 5988 case OP_UNUSED_96FF: 5989 case OP_UNUSED_97FF: 5990 case OP_UNUSED_98FF: 5991 case OP_UNUSED_99FF: 5992 case OP_UNUSED_9AFF: 5993 case OP_UNUSED_9BFF: 5994 case OP_UNUSED_9CFF: 5995 case OP_UNUSED_9DFF: 5996 case OP_UNUSED_9EFF: 5997 case OP_UNUSED_9FFF: 5998 case OP_UNUSED_A0FF: 5999 case OP_UNUSED_A1FF: 6000 case OP_UNUSED_A2FF: 6001 case OP_UNUSED_A3FF: 6002 case OP_UNUSED_A4FF: 6003 case OP_UNUSED_A5FF: 6004 case OP_UNUSED_A6FF: 6005 case OP_UNUSED_A7FF: 6006 case OP_UNUSED_A8FF: 6007 case OP_UNUSED_A9FF: 6008 case OP_UNUSED_AAFF: 6009 case OP_UNUSED_ABFF: 6010 case OP_UNUSED_ACFF: 6011 case OP_UNUSED_ADFF: 6012 case OP_UNUSED_AEFF: 6013 case OP_UNUSED_AFFF: 6014 case OP_UNUSED_B0FF: 6015 case OP_UNUSED_B1FF: 6016 case OP_UNUSED_B2FF: 6017 case OP_UNUSED_B3FF: 6018 case OP_UNUSED_B4FF: 6019 case OP_UNUSED_B5FF: 6020 case OP_UNUSED_B6FF: 6021 case OP_UNUSED_B7FF: 6022 case OP_UNUSED_B8FF: 6023 case OP_UNUSED_B9FF: 6024 case OP_UNUSED_BAFF: 6025 case OP_UNUSED_BBFF: 6026 case OP_UNUSED_BCFF: 6027 case OP_UNUSED_BDFF: 6028 case OP_UNUSED_BEFF: 6029 case OP_UNUSED_BFFF: 6030 case OP_UNUSED_C0FF: 6031 case OP_UNUSED_C1FF: 6032 case OP_UNUSED_C2FF: 6033 case OP_UNUSED_C3FF: 6034 case OP_UNUSED_C4FF: 6035 case OP_UNUSED_C5FF: 6036 case OP_UNUSED_C6FF: 6037 case OP_UNUSED_C7FF: 6038 case OP_UNUSED_C8FF: 6039 case OP_UNUSED_C9FF: 6040 case OP_UNUSED_CAFF: 6041 case OP_UNUSED_CBFF: 6042 case OP_UNUSED_CCFF: 6043 case OP_UNUSED_CDFF: 6044 case OP_UNUSED_CEFF: 6045 case OP_UNUSED_CFFF: 6046 case OP_UNUSED_D0FF: 6047 case OP_UNUSED_D1FF: 6048 case OP_UNUSED_D2FF: 6049 case OP_UNUSED_D3FF: 6050 case OP_UNUSED_D4FF: 6051 case OP_UNUSED_D5FF: 6052 case OP_UNUSED_D6FF: 6053 case OP_UNUSED_D7FF: 6054 case OP_UNUSED_D8FF: 6055 case OP_UNUSED_D9FF: 6056 case OP_UNUSED_DAFF: 6057 case OP_UNUSED_DBFF: 6058 case OP_UNUSED_DCFF: 6059 case OP_UNUSED_DDFF: 6060 case OP_UNUSED_DEFF: 6061 case OP_UNUSED_DFFF: 6062 case OP_UNUSED_E0FF: 6063 case OP_UNUSED_E1FF: 6064 case OP_UNUSED_E2FF: 6065 case OP_UNUSED_E3FF: 6066 case OP_UNUSED_E4FF: 6067 case OP_UNUSED_E5FF: 6068 case OP_UNUSED_E6FF: 6069 case OP_UNUSED_E7FF: 6070 case OP_UNUSED_E8FF: 6071 case OP_UNUSED_E9FF: 6072 case OP_UNUSED_EAFF: 6073 case OP_UNUSED_EBFF: 6074 case OP_UNUSED_ECFF: 6075 case OP_UNUSED_EDFF: 6076 case OP_UNUSED_EEFF: 6077 case OP_UNUSED_EFFF: 6078 case OP_UNUSED_F0FF: 6079 case OP_UNUSED_F1FF: 6080 failure = VERIFY_ERROR_GENERIC; 6081 break; 6082 6083 /* 6084 * DO NOT add a "default" clause here. Without it the compiler will 6085 * complain if an instruction is missing (which is desirable). 6086 */ 6087 } 6088 6089 if (!VERIFY_OK(failure)) { 6090 if (failure == VERIFY_ERROR_GENERIC || gDvm.optimizing) { 6091 /* immediate failure, reject class */ 6092 LOG_VFY_METH(meth, "VFY: rejecting opcode 0x%02x at 0x%04x", 6093 decInsn.opcode, insnIdx); 6094 goto bail; 6095 } else { 6096 /* replace opcode and continue on */ 6097 LOGD("VFY: replacing opcode 0x%02x at 0x%04x", 6098 decInsn.opcode, insnIdx); 6099 if (!replaceFailingInstruction(meth, insnFlags, insnIdx, failure)) { 6100 LOG_VFY_METH(meth, "VFY: rejecting opcode 0x%02x at 0x%04x", 6101 decInsn.opcode, insnIdx); 6102 goto bail; 6103 } 6104 /* IMPORTANT: meth->insns may have been changed */ 6105 insns = meth->insns + insnIdx; 6106 6107 /* continue on as if we just handled a throw-verification-error */ 6108 failure = VERIFY_ERROR_NONE; 6109 nextFlags = kInstrCanThrow; 6110 } 6111 } 6112 6113 /* 6114 * If we didn't just set the result register, clear it out. This 6115 * ensures that you can only use "move-result" immediately after the 6116 * result is set. (We could check this statically, but it's not 6117 * expensive and it makes our debugging output cleaner.) 6118 */ 6119 if (!justSetResult) { 6120 int reg = RESULT_REGISTER(insnRegCount); 6121 setRegisterType(workLine, reg, kRegTypeUnknown); 6122 setRegisterType(workLine, reg+1, kRegTypeUnknown); 6123 } 6124 6125 /* 6126 * Handle "continue". Tag the next consecutive instruction. 6127 */ 6128 if ((nextFlags & kInstrCanContinue) != 0) { 6129 int insnWidth = dvmInsnGetWidth(insnFlags, insnIdx); 6130 if (insnIdx+insnWidth >= insnsSize) { 6131 LOG_VFY_METH(meth, 6132 "VFY: execution can walk off end of code area (from %#x)", 6133 insnIdx); 6134 goto bail; 6135 } 6136 6137 /* 6138 * The only way to get to a move-exception instruction is to get 6139 * thrown there. Make sure the next instruction isn't one. 6140 */ 6141 if (!checkMoveException(meth, insnIdx+insnWidth, "next")) 6142 goto bail; 6143 6144 if (getRegisterLine(regTable, insnIdx+insnWidth)->regTypes != NULL) { 6145 /* 6146 * Merge registers into what we have for the next instruction, 6147 * and set the "changed" flag if needed. 6148 */ 6149 if (!updateRegisters(meth, insnFlags, regTable, insnIdx+insnWidth, 6150 workLine)) 6151 goto bail; 6152 } else { 6153 /* 6154 * We're not recording register data for the next instruction, 6155 * so we don't know what the prior state was. We have to 6156 * assume that something has changed and re-evaluate it. 6157 */ 6158 dvmInsnSetChanged(insnFlags, insnIdx+insnWidth, true); 6159 } 6160 } 6161 6162 /* 6163 * Handle "branch". Tag the branch target. 6164 * 6165 * NOTE: instructions like OP_EQZ provide information about the state 6166 * of the register when the branch is taken or not taken. For example, 6167 * somebody could get a reference field, check it for zero, and if the 6168 * branch is taken immediately store that register in a boolean field 6169 * since the value is known to be zero. We do not currently account for 6170 * that, and will reject the code. 6171 * 6172 * TODO: avoid re-fetching the branch target 6173 */ 6174 if ((nextFlags & kInstrCanBranch) != 0) { 6175 bool isConditional; 6176 6177 if (!dvmGetBranchOffset(meth, insnFlags, insnIdx, &branchTarget, 6178 &isConditional)) 6179 { 6180 /* should never happen after static verification */ 6181 LOG_VFY_METH(meth, "VFY: bad branch at %d", insnIdx); 6182 goto bail; 6183 } 6184 assert(isConditional || (nextFlags & kInstrCanContinue) == 0); 6185 assert(!isConditional || (nextFlags & kInstrCanContinue) != 0); 6186 6187 if (!checkMoveException(meth, insnIdx+branchTarget, "branch")) 6188 goto bail; 6189 6190 /* update branch target, set "changed" if appropriate */ 6191 if (!updateRegisters(meth, insnFlags, regTable, insnIdx+branchTarget, 6192 workLine)) 6193 goto bail; 6194 } 6195 6196 /* 6197 * Handle "switch". Tag all possible branch targets. 6198 * 6199 * We've already verified that the table is structurally sound, so we 6200 * just need to walk through and tag the targets. 6201 */ 6202 if ((nextFlags & kInstrCanSwitch) != 0) { 6203 int offsetToSwitch = insns[1] | (((s4)insns[2]) << 16); 6204 const u2* switchInsns = insns + offsetToSwitch; 6205 int switchCount = switchInsns[1]; 6206 int offsetToTargets, targ; 6207 6208 if ((*insns & 0xff) == OP_PACKED_SWITCH) { 6209 /* 0=sig, 1=count, 2/3=firstKey */ 6210 offsetToTargets = 4; 6211 } else { 6212 /* 0=sig, 1=count, 2..count*2 = keys */ 6213 assert((*insns & 0xff) == OP_SPARSE_SWITCH); 6214 offsetToTargets = 2 + 2*switchCount; 6215 } 6216 6217 /* verify each switch target */ 6218 for (targ = 0; targ < switchCount; targ++) { 6219 int offset, absOffset; 6220 6221 /* offsets are 32-bit, and only partly endian-swapped */ 6222 offset = switchInsns[offsetToTargets + targ*2] | 6223 (((s4) switchInsns[offsetToTargets + targ*2 +1]) << 16); 6224 absOffset = insnIdx + offset; 6225 6226 assert(absOffset >= 0 && absOffset < insnsSize); 6227 6228 if (!checkMoveException(meth, absOffset, "switch")) 6229 goto bail; 6230 6231 if (!updateRegisters(meth, insnFlags, regTable, absOffset, 6232 workLine)) 6233 goto bail; 6234 } 6235 } 6236 6237 /* 6238 * Handle instructions that can throw and that are sitting in a 6239 * "try" block. (If they're not in a "try" block when they throw, 6240 * control transfers out of the method.) 6241 */ 6242 if ((nextFlags & kInstrCanThrow) != 0 && dvmInsnIsInTry(insnFlags, insnIdx)) 6243 { 6244 const DexCode* pCode = dvmGetMethodCode(meth); 6245 DexCatchIterator iterator; 6246 bool hasCatchAll = false; 6247 6248 if (dexFindCatchHandler(&iterator, pCode, insnIdx)) { 6249 for (;;) { 6250 DexCatchHandler* handler = dexCatchIteratorNext(&iterator); 6251 6252 if (handler == NULL) { 6253 break; 6254 } 6255 6256 if (handler->typeIdx == kDexNoIndex) 6257 hasCatchAll = true; 6258 6259 /* 6260 * Merge registers into the "catch" block. We want to 6261 * use the "savedRegs" rather than "workRegs", because 6262 * at runtime the exception will be thrown before the 6263 * instruction modifies any registers. 6264 */ 6265 if (!updateRegisters(meth, insnFlags, regTable, 6266 handler->address, ®Table->savedLine)) 6267 goto bail; 6268 } 6269 } 6270 6271 /* 6272 * If the monitor stack depth is nonzero, there must be a "catch all" 6273 * handler for this instruction. This does apply to monitor-exit 6274 * because of async exception handling. 6275 */ 6276 if (workLine->monitorStackTop != 0 && !hasCatchAll) { 6277 /* 6278 * The state in workLine reflects the post-execution state. 6279 * If the current instruction is a monitor-enter and the monitor 6280 * stack was empty, we don't need a catch-all (if it throws, 6281 * it will do so before grabbing the lock). 6282 */ 6283 if (!(decInsn.opcode == OP_MONITOR_ENTER && 6284 workLine->monitorStackTop == 1)) 6285 { 6286 LOG_VFY_METH(meth, 6287 "VFY: no catch-all for instruction at 0x%04x", insnIdx); 6288 goto bail; 6289 } 6290 } 6291 } 6292 6293 /* 6294 * If we're returning from the method, make sure our monitor stack 6295 * is empty. 6296 */ 6297 if ((nextFlags & kInstrCanReturn) != 0 && workLine->monitorStackTop != 0) { 6298 LOG_VFY_METH(meth, "VFY: return with stack depth=%d at 0x%04x", 6299 workLine->monitorStackTop, insnIdx); 6300 goto bail; 6301 } 6302 6303 /* 6304 * Update startGuess. Advance to the next instruction of that's 6305 * possible, otherwise use the branch target if one was found. If 6306 * neither of those exists we're in a return or throw; leave startGuess 6307 * alone and let the caller sort it out. 6308 */ 6309 if ((nextFlags & kInstrCanContinue) != 0) { 6310 *pStartGuess = insnIdx + dvmInsnGetWidth(insnFlags, insnIdx); 6311 } else if ((nextFlags & kInstrCanBranch) != 0) { 6312 /* we're still okay if branchTarget is zero */ 6313 *pStartGuess = insnIdx + branchTarget; 6314 } 6315 6316 assert(*pStartGuess >= 0 && *pStartGuess < insnsSize && 6317 dvmInsnGetWidth(insnFlags, *pStartGuess) != 0); 6318 6319 result = true; 6320 6321bail: 6322 return result; 6323} 6324 6325 6326/* 6327 * callback function used in dumpRegTypes to print local vars 6328 * valid at a given address. 6329 */ 6330static void logLocalsCb(void *cnxt, u2 reg, u4 startAddress, u4 endAddress, 6331 const char *name, const char *descriptor, 6332 const char *signature) 6333{ 6334 int addr = *((int *)cnxt); 6335 6336 if (addr >= (int) startAddress && addr < (int) endAddress) 6337 { 6338 LOGI(" %2d: '%s' %s", reg, name, descriptor); 6339 } 6340} 6341 6342/* 6343 * Dump the register types for the specifed address to the log file. 6344 */ 6345static void dumpRegTypes(const VerifierData* vdata, 6346 const RegisterLine* registerLine, int addr, const char* addrName, 6347 const UninitInstanceMap* uninitMap, int displayFlags) 6348{ 6349 const Method* meth = vdata->method; 6350 const InsnFlags* insnFlags = vdata->insnFlags; 6351 const RegType* addrRegs = registerLine->regTypes; 6352 int regCount = meth->registersSize; 6353 int fullRegCount = regCount + kExtraRegs; 6354 bool branchTarget = dvmInsnIsBranchTarget(insnFlags, addr); 6355 int i; 6356 6357 assert(addr >= 0 && addr < (int) dvmGetMethodInsnsSize(meth)); 6358 6359 int regCharSize = fullRegCount + (fullRegCount-1)/4 + 2 +1; 6360 char regChars[regCharSize +1]; 6361 memset(regChars, ' ', regCharSize); 6362 regChars[0] = '['; 6363 if (regCount == 0) 6364 regChars[1] = ']'; 6365 else 6366 regChars[1 + (regCount-1) + (regCount-1)/4 +1] = ']'; 6367 regChars[regCharSize] = '\0'; 6368 6369 for (i = 0; i < regCount + kExtraRegs; i++) { 6370 char tch; 6371 6372 switch (addrRegs[i]) { 6373 case kRegTypeUnknown: tch = '.'; break; 6374 case kRegTypeConflict: tch = 'X'; break; 6375 case kRegTypeZero: tch = '0'; break; 6376 case kRegTypeOne: tch = '1'; break; 6377 case kRegTypeBoolean: tch = 'Z'; break; 6378 case kRegTypeConstPosByte: tch = 'y'; break; 6379 case kRegTypeConstByte: tch = 'Y'; break; 6380 case kRegTypeConstPosShort: tch = 'h'; break; 6381 case kRegTypeConstShort: tch = 'H'; break; 6382 case kRegTypeConstChar: tch = 'c'; break; 6383 case kRegTypeConstInteger: tch = 'i'; break; 6384 case kRegTypePosByte: tch = 'b'; break; 6385 case kRegTypeByte: tch = 'B'; break; 6386 case kRegTypePosShort: tch = 's'; break; 6387 case kRegTypeShort: tch = 'S'; break; 6388 case kRegTypeChar: tch = 'C'; break; 6389 case kRegTypeInteger: tch = 'I'; break; 6390 case kRegTypeFloat: tch = 'F'; break; 6391 case kRegTypeConstLo: tch = 'N'; break; 6392 case kRegTypeConstHi: tch = 'n'; break; 6393 case kRegTypeLongLo: tch = 'J'; break; 6394 case kRegTypeLongHi: tch = 'j'; break; 6395 case kRegTypeDoubleLo: tch = 'D'; break; 6396 case kRegTypeDoubleHi: tch = 'd'; break; 6397 default: 6398 if (regTypeIsReference(addrRegs[i])) { 6399 if (regTypeIsUninitReference(addrRegs[i])) 6400 tch = 'U'; 6401 else 6402 tch = 'L'; 6403 } else { 6404 tch = '*'; 6405 assert(false); 6406 } 6407 break; 6408 } 6409 6410 if (i < regCount) 6411 regChars[1 + i + (i/4)] = tch; 6412 else 6413 regChars[1 + i + (i/4) + 2] = tch; 6414 } 6415 6416 if (addr == 0 && addrName != NULL) { 6417 LOGI("%c%s %s mst=%d", branchTarget ? '>' : ' ', 6418 addrName, regChars, registerLine->monitorStackTop); 6419 } else { 6420 LOGI("%c0x%04x %s mst=%d", branchTarget ? '>' : ' ', 6421 addr, regChars, registerLine->monitorStackTop); 6422 } 6423 if (displayFlags & DRT_SHOW_LIVENESS) { 6424 /* 6425 * We can't use registerLine->liveRegs because it might be the 6426 * "work line" rather than the copy from RegisterTable. 6427 */ 6428 BitVector* liveRegs = vdata->registerLines[addr].liveRegs; 6429 if (liveRegs != NULL) { 6430 char liveChars[regCharSize + 1]; 6431 memset(liveChars, ' ', regCharSize); 6432 liveChars[regCharSize] = '\0'; 6433 6434 for (i = 0; i < regCount; i++) { 6435 bool isLive = dvmIsBitSet(liveRegs, i); 6436 liveChars[i + 1 + (i / 4)] = isLive ? '+' : '-'; 6437 } 6438 LOGI(" %s", liveChars); 6439 } else { 6440 LOGI(" %c", '#'); 6441 } 6442 } 6443 6444 if (displayFlags & DRT_SHOW_REF_TYPES) { 6445 for (i = 0; i < regCount + kExtraRegs; i++) { 6446 if (regTypeIsReference(addrRegs[i]) && addrRegs[i] != kRegTypeZero) 6447 { 6448 ClassObject* clazz = regTypeReferenceToClass(addrRegs[i], uninitMap); 6449 assert(dvmIsHeapAddress((Object*)clazz)); 6450 if (i < regCount) { 6451 LOGI(" %2d: 0x%08x %s%s", 6452 i, addrRegs[i], 6453 regTypeIsUninitReference(addrRegs[i]) ? "[U]" : "", 6454 clazz->descriptor); 6455 } else { 6456 LOGI(" RS: 0x%08x %s%s", 6457 addrRegs[i], 6458 regTypeIsUninitReference(addrRegs[i]) ? "[U]" : "", 6459 clazz->descriptor); 6460 } 6461 } 6462 } 6463 } 6464 if (displayFlags & DRT_SHOW_LOCALS) { 6465 dexDecodeDebugInfo(meth->clazz->pDvmDex->pDexFile, 6466 dvmGetMethodCode(meth), 6467 meth->clazz->descriptor, 6468 meth->prototype.protoIdx, 6469 meth->accessFlags, 6470 NULL, logLocalsCb, &addr); 6471 } 6472} 6473