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