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 ALOGE("Symmetry violation: %d,%d vs %d,%d", i, j, j, i); 254 dvmAbort(); 255 } 256 } 257 } 258 } 259 #endif 260 261 /* 262 * Determine whether we can convert "srcType" to "checkType", where 263 * "checkType" is one of the category-1 non-reference types. 264 * 265 * Constant derived types may become floats, but other values may not. 266 */ 267 static bool canConvertTo1nr(RegType srcType, RegType checkType) 268 { 269 static const char convTab 270 [kRegType1nrEND-kRegType1nrSTART+1][kRegType1nrEND-kRegType1nrSTART+1] = 271 { 272 /* chk: 0 1 Z y Y h H c i b B s S C I F */ 273 { /*0*/ 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, 274 { /*1*/ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, 275 { /*Z*/ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, 276 { /*y*/ 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, 277 { /*Y*/ 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1 }, 278 { /*h*/ 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1 }, 279 { /*H*/ 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1 }, 280 { /*c*/ 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1 }, 281 { /*i*/ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1 }, 282 { /*b*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0 }, 283 { /*B*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0 }, 284 { /*s*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0 }, 285 { /*S*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0 }, 286 { /*C*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0 }, 287 { /*I*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 }, 288 { /*F*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, 289 }; 290 291 assert(checkType >= kRegType1nrSTART && checkType <= kRegType1nrEND); 292 #if 0 293 if (checkType < kRegType1nrSTART || checkType > kRegType1nrEND) { 294 LOG_VFY("Unexpected checkType %d (srcType=%d)", checkType, srcType); 295 assert(false); 296 return false; 297 } 298 #endif 299 300 //printf("convTab[%d][%d] = %d\n", srcType, checkType, 301 // convTab[srcType-kRegType1nrSTART][checkType-kRegType1nrSTART]); 302 if (srcType >= kRegType1nrSTART && srcType <= kRegType1nrEND) 303 return (bool) convTab[srcType-kRegType1nrSTART][checkType-kRegType1nrSTART]; 304 305 return false; 306 } 307 308 /* 309 * Determine whether the category-2 types are compatible. 310 */ 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) 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 //ALOGI("Looking up '%s'", typeStr); 633 ClassObject* clazz; 634 clazz = dvmFindClassNoInit(pDescriptor, meth->clazz->classLoader); 635 if (clazz == NULL) { 636 dvmClearOptException(dvmThreadSelf()); 637 if (strchr(pDescriptor, '$') != NULL) { 638 ALOGV("VFY: unable to find class referenced in signature (%s)", 639 pDescriptor); 640 } else { 641 LOG_VFY("VFY: unable to find class referenced in signature (%s)", 642 pDescriptor); 643 } 644 645 if (pDescriptor[0] == '[') { 646 /* We are looking at an array descriptor. */ 647 648 /* 649 * There should never be a problem loading primitive arrays. 650 */ 651 if (pDescriptor[1] != 'L' && pDescriptor[1] != '[') { 652 LOG_VFY("VFY: invalid char in signature in '%s'", 653 pDescriptor); 654 *pFailure = VERIFY_ERROR_GENERIC; 655 } 656 657 /* 658 * Try to continue with base array type. This will let 659 * us pass basic stuff (e.g. get array len) that wouldn't 660 * fly with an Object. This is NOT correct if the 661 * missing type is a primitive array, but we should never 662 * have a problem loading those. (I'm not convinced this 663 * is correct or even useful. Just use Object here?) 664 */ 665 clazz = dvmFindClassNoInit("[Ljava/lang/Object;", 666 meth->clazz->classLoader); 667 } else if (pDescriptor[0] == 'L') { 668 /* 669 * We are looking at a non-array reference descriptor; 670 * try to continue with base reference type. 671 */ 672 clazz = gDvm.classJavaLangObject; 673 } else { 674 /* We are looking at a primitive type. */ 675 LOG_VFY("VFY: invalid char in signature in '%s'", pDescriptor); 676 *pFailure = VERIFY_ERROR_GENERIC; 677 } 678 679 if (clazz == NULL) { 680 *pFailure = VERIFY_ERROR_GENERIC; 681 } 682 } 683 684 if (dvmIsPrimitiveClass(clazz)) { 685 LOG_VFY("VFY: invalid use of primitive type '%s'", pDescriptor); 686 *pFailure = VERIFY_ERROR_GENERIC; 687 clazz = NULL; 688 } 689 690 return clazz; 691 } 692 693 /* 694 * Look up a class reference in a signature. Could be an arg or the 695 * return value. 696 * 697 * Advances "*pSig" to the last character in the signature (that is, to 698 * the ';'). 699 * 700 * NOTE: this is also expected to verify the signature. 701 */ 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 ALOGI("Could not find method %s.%s, referenced from method %s.%s", 1140 dotMissingClass.c_str(), methodName, 1141 dotMethClass.c_str(), meth->name); 1142 } 1143 1144 LOG_VFY("VFY: unable to resolve %s method %u: %s.%s %s", 1145 dvmMethodTypeStr(methodType), pDecInsn->vB, 1146 classDescriptor, methodName, methodDesc); 1147 free(methodDesc); 1148 if (VERIFY_OK(*pFailure)) /* not set for interface resolve */ 1149 *pFailure = VERIFY_ERROR_NO_METHOD; 1150 goto fail; 1151 } 1152 1153 /* 1154 * Only time you can explicitly call a method starting with '<' is when 1155 * making a "direct" invocation on "<init>". There are additional 1156 * restrictions but we don't enforce them here. 1157 */ 1158 if (resMethod->name[0] == '<') { 1159 if (methodType != METHOD_DIRECT || !isInitMethod(resMethod)) { 1160 LOG_VFY("VFY: invalid call to %s.%s", 1161 resMethod->clazz->descriptor, resMethod->name); 1162 goto bad_sig; 1163 } 1164 } 1165 1166 /* 1167 * See if the method type implied by the invoke instruction matches the 1168 * access flags for the target method. 1169 */ 1170 if (!isCorrectInvokeKind(methodType, resMethod)) { 1171 LOG_VFY("VFY: invoke type does not match method type of %s.%s", 1172 resMethod->clazz->descriptor, resMethod->name); 1173 goto fail; 1174 } 1175 1176 /* 1177 * If we're using invoke-super(method), make sure that the executing 1178 * method's class' superclass has a vtable entry for the target method. 1179 */ 1180 if (isSuper) { 1181 assert(methodType == METHOD_VIRTUAL); 1182 ClassObject* super = meth->clazz->super; 1183 if (super == NULL || resMethod->methodIndex > super->vtableCount) { 1184 char* desc = dexProtoCopyMethodDescriptor(&resMethod->prototype); 1185 LOG_VFY("VFY: invalid invoke-super from %s.%s to super %s.%s %s", 1186 meth->clazz->descriptor, meth->name, 1187 (super == NULL) ? "-" : super->descriptor, 1188 resMethod->name, desc); 1189 free(desc); 1190 *pFailure = VERIFY_ERROR_NO_METHOD; 1191 goto fail; 1192 } 1193 } 1194 1195 /* 1196 * We use vAA as our expected arg count, rather than resMethod->insSize, 1197 * because we need to match the call to the signature. Also, we might 1198 * might be calling through an abstract method definition (which doesn't 1199 * have register count values). 1200 */ 1201 sigOriginal = dexProtoCopyMethodDescriptor(&resMethod->prototype); 1202 sig = sigOriginal; 1203 expectedArgs = pDecInsn->vA; 1204 actualArgs = 0; 1205 1206 /* caught by static verifier */ 1207 assert(isRange || expectedArgs <= 5); 1208 1209 if (expectedArgs > meth->outsSize) { 1210 LOG_VFY("VFY: invalid arg count (%d) exceeds outsSize (%d)", 1211 expectedArgs, meth->outsSize); 1212 goto fail; 1213 } 1214 1215 if (*sig++ != '(') 1216 goto bad_sig; 1217 1218 /* 1219 * Check the "this" argument, which must be an instance of the class 1220 * that declared the method. For an interface class, we don't do the 1221 * full interface merge, so we can't do a rigorous check here (which 1222 * is okay since we have to do it at runtime). 1223 */ 1224 if (!dvmIsStaticMethod(resMethod)) { 1225 ClassObject* actualThisRef; 1226 RegType actualArgType; 1227 1228 actualArgType = getInvocationThis(registerLine, pDecInsn, pFailure); 1229 if (!VERIFY_OK(*pFailure)) 1230 goto fail; 1231 1232 if (regTypeIsUninitReference(actualArgType) && resMethod->name[0] != '<') 1233 { 1234 LOG_VFY("VFY: 'this' arg must be initialized"); 1235 goto fail; 1236 } 1237 if (methodType != METHOD_INTERFACE && actualArgType != kRegTypeZero) { 1238 actualThisRef = regTypeReferenceToClass(actualArgType, uninitMap); 1239 if (!dvmInstanceof(actualThisRef, resMethod->clazz)) { 1240 LOG_VFY("VFY: 'this' arg '%s' not instance of '%s'", 1241 actualThisRef->descriptor, 1242 resMethod->clazz->descriptor); 1243 goto fail; 1244 } 1245 } 1246 actualArgs++; 1247 } 1248 1249 /* 1250 * Process the target method's signature. This signature may or may not 1251 * have been verified, so we can't assume it's properly formed. 1252 */ 1253 while (*sig != '\0' && *sig != ')') { 1254 if (actualArgs >= expectedArgs) { 1255 LOG_VFY("VFY: expected %d args, found more (%c)", 1256 expectedArgs, *sig); 1257 goto bad_sig; 1258 } 1259 1260 u4 getReg; 1261 if (isRange) 1262 getReg = pDecInsn->vC + actualArgs; 1263 else 1264 getReg = pDecInsn->arg[actualArgs]; 1265 1266 switch (*sig) { 1267 case 'L': 1268 { 1269 ClassObject* clazz = lookupSignatureClass(meth, &sig, pFailure); 1270 if (!VERIFY_OK(*pFailure)) 1271 goto bad_sig; 1272 verifyRegisterType(registerLine, getReg, 1273 regTypeFromClass(clazz), pFailure); 1274 if (!VERIFY_OK(*pFailure)) { 1275 LOG_VFY("VFY: bad arg %d (into %s)", 1276 actualArgs, clazz->descriptor); 1277 goto bad_sig; 1278 } 1279 } 1280 actualArgs++; 1281 break; 1282 case '[': 1283 { 1284 ClassObject* clazz = 1285 lookupSignatureArrayClass(meth, &sig, pFailure); 1286 if (!VERIFY_OK(*pFailure)) 1287 goto bad_sig; 1288 verifyRegisterType(registerLine, getReg, 1289 regTypeFromClass(clazz), pFailure); 1290 if (!VERIFY_OK(*pFailure)) { 1291 LOG_VFY("VFY: bad arg %d (into %s)", 1292 actualArgs, clazz->descriptor); 1293 goto bad_sig; 1294 } 1295 } 1296 actualArgs++; 1297 break; 1298 case 'Z': 1299 verifyRegisterType(registerLine, getReg, kRegTypeBoolean, pFailure); 1300 actualArgs++; 1301 break; 1302 case 'C': 1303 verifyRegisterType(registerLine, getReg, kRegTypeChar, pFailure); 1304 actualArgs++; 1305 break; 1306 case 'B': 1307 verifyRegisterType(registerLine, getReg, kRegTypeByte, pFailure); 1308 actualArgs++; 1309 break; 1310 case 'I': 1311 verifyRegisterType(registerLine, getReg, kRegTypeInteger, pFailure); 1312 actualArgs++; 1313 break; 1314 case 'S': 1315 verifyRegisterType(registerLine, getReg, kRegTypeShort, pFailure); 1316 actualArgs++; 1317 break; 1318 case 'F': 1319 verifyRegisterType(registerLine, getReg, kRegTypeFloat, pFailure); 1320 actualArgs++; 1321 break; 1322 case 'D': 1323 verifyRegisterType(registerLine, getReg, kRegTypeDoubleLo, pFailure); 1324 actualArgs += 2; 1325 break; 1326 case 'J': 1327 verifyRegisterType(registerLine, getReg, kRegTypeLongLo, pFailure); 1328 actualArgs += 2; 1329 break; 1330 default: 1331 LOG_VFY("VFY: invocation target: bad signature type char '%c'", 1332 *sig); 1333 goto bad_sig; 1334 } 1335 1336 sig++; 1337 } 1338 if (*sig != ')') { 1339 char* desc = dexProtoCopyMethodDescriptor(&resMethod->prototype); 1340 LOG_VFY("VFY: invocation target: bad signature '%s'", desc); 1341 free(desc); 1342 goto bad_sig; 1343 } 1344 1345 if (actualArgs != expectedArgs) { 1346 LOG_VFY("VFY: expected %d args, found %d", expectedArgs, actualArgs); 1347 goto bad_sig; 1348 } 1349 1350 free(sigOriginal); 1351 return resMethod; 1352 1353 bad_sig: 1354 if (resMethod != NULL) { 1355 char* desc = dexProtoCopyMethodDescriptor(&resMethod->prototype); 1356 LOG_VFY("VFY: rejecting call to %s.%s %s", 1357 resMethod->clazz->descriptor, resMethod->name, desc); 1358 free(desc); 1359 } 1360 1361 fail: 1362 free(sigOriginal); 1363 if (*pFailure == VERIFY_ERROR_NONE) 1364 *pFailure = VERIFY_ERROR_GENERIC; 1365 return NULL; 1366 } 1367 1368 /* 1369 * Get the class object for the type of data stored in a field. This isn't 1370 * stored in the Field struct, so we have to recover it from the signature. 1371 * 1372 * This only works for reference types. Don't call this for primitive types. 1373 * 1374 * If we can't find the class, we return java.lang.Object, so that 1375 * verification can continue if a field is only accessed in trivial ways. 1376 */ 1377 static ClassObject* getFieldClass(const Method* meth, const Field* field) 1378 { 1379 ClassObject* fieldClass; 1380 const char* signature = field->signature; 1381 1382 if ((*signature == 'L') || (*signature == '[')) { 1383 fieldClass = dvmFindClassNoInit(signature, 1384 meth->clazz->classLoader); 1385 } else { 1386 return NULL; 1387 } 1388 1389 if (fieldClass == NULL) { 1390 dvmClearOptException(dvmThreadSelf()); 1391 ALOGV("VFY: unable to find class '%s' for field %s.%s, trying Object", 1392 field->signature, meth->clazz->descriptor, field->name); 1393 fieldClass = gDvm.classJavaLangObject; 1394 } else { 1395 assert(!dvmIsPrimitiveClass(fieldClass)); 1396 } 1397 return fieldClass; 1398 } 1399 1400 1401 /* 1402 * =========================================================================== 1403 * Register operations 1404 * =========================================================================== 1405 */ 1406 1407 /* 1408 * Get the type of register N. 1409 * 1410 * The register index was validated during the static pass, so we don't 1411 * need to check it here. 1412 */ 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 ALOGE("BUG: explicit set of high register type"); 1538 dvmAbort(); 1539 break; 1540 1541 default: 1542 /* can't switch for ref types, so we check explicitly */ 1543 if (regTypeIsReference(newType)) { 1544 insnRegs[vdst] = newType; 1545 1546 /* 1547 * In most circumstances we won't see a reference to a primitive 1548 * class here (e.g. "D"), since that would mean the object in the 1549 * register is actually a primitive type. It can happen as the 1550 * result of an assumed-successful check-cast instruction in 1551 * which the second argument refers to a primitive class. (In 1552 * practice, such an instruction will always throw an exception.) 1553 * 1554 * This is not an issue for instructions like const-class, where 1555 * the object in the register is a java.lang.Class instance. 1556 */ 1557 break; 1558 } 1559 /* bad type - fall through */ 1560 1561 case kRegTypeConflict: // should only be set during a merge 1562 ALOGE("BUG: set register to unknown type %d", newType); 1563 dvmAbort(); 1564 break; 1565 } 1566 1567 /* 1568 * Clear the monitor entry bits for this register. 1569 */ 1570 if (registerLine->monitorEntries != NULL) 1571 registerLine->monitorEntries[vdst] = 0; 1572 } 1573 1574 /* 1575 * Verify that the contents of the specified register have the specified 1576 * type (or can be converted to it through an implicit widening conversion). 1577 * 1578 * This will modify the type of the source register if it was originally 1579 * derived from a constant to prevent mixing of int/float and long/double. 1580 * 1581 * If "vsrc" is a reference, both it and the "vsrc" register must be 1582 * initialized ("vsrc" may be Zero). This will verify that the value in 1583 * the register is an instance of checkType, or if checkType is an 1584 * interface, verify that the register implements checkType. 1585 */ 1586 static void verifyRegisterType(RegisterLine* registerLine, u4 vsrc, 1587 RegType checkType, VerifyError* pFailure) 1588 { 1589 const RegType* insnRegs = registerLine->regTypes; 1590 RegType srcType = insnRegs[vsrc]; 1591 1592 //ALOGD("check-reg v%u = %d", vsrc, checkType); 1593 switch (checkType) { 1594 case kRegTypeFloat: 1595 case kRegTypeBoolean: 1596 case kRegTypePosByte: 1597 case kRegTypeByte: 1598 case kRegTypePosShort: 1599 case kRegTypeShort: 1600 case kRegTypeChar: 1601 case kRegTypeInteger: 1602 if (!canConvertTo1nr(srcType, checkType)) { 1603 LOG_VFY("VFY: register1 v%u type %d, wanted %d", 1604 vsrc, srcType, checkType); 1605 *pFailure = VERIFY_ERROR_GENERIC; 1606 break; 1607 } 1608 /* Update type if result is float */ 1609 if (checkType == kRegTypeFloat) { 1610 setRegisterType(registerLine, vsrc, checkType); 1611 } else { 1612 /* Update const type to actual type after use */ 1613 setRegisterType(registerLine, vsrc, constTypeToRegType(srcType)); 1614 } 1615 break; 1616 case kRegTypeLongLo: 1617 case kRegTypeDoubleLo: 1618 if (insnRegs[vsrc+1] != srcType+1) { 1619 LOG_VFY("VFY: register2 v%u-%u values %d,%d", 1620 vsrc, vsrc+1, insnRegs[vsrc], insnRegs[vsrc+1]); 1621 *pFailure = VERIFY_ERROR_GENERIC; 1622 break; 1623 } else if (!canConvertTo2(srcType, checkType)) { 1624 LOG_VFY("VFY: register2 v%u type %d, wanted %d", 1625 vsrc, srcType, checkType); 1626 *pFailure = VERIFY_ERROR_GENERIC; 1627 break; 1628 } 1629 /* Update type if source is from const */ 1630 if (srcType == kRegTypeConstLo) { 1631 setRegisterType(registerLine, vsrc, checkType); 1632 } 1633 break; 1634 case kRegTypeConstLo: 1635 case kRegTypeConstHi: 1636 case kRegTypeLongHi: 1637 case kRegTypeDoubleHi: 1638 case kRegTypeZero: 1639 case kRegTypeOne: 1640 case kRegTypeUnknown: 1641 case kRegTypeConflict: 1642 /* should never be checking for these explicitly */ 1643 assert(false); 1644 *pFailure = VERIFY_ERROR_GENERIC; 1645 return; 1646 case kRegTypeUninit: 1647 default: 1648 /* make sure checkType is initialized reference */ 1649 if (!regTypeIsReference(checkType)) { 1650 LOG_VFY("VFY: unexpected check type %d", checkType); 1651 assert(false); 1652 *pFailure = VERIFY_ERROR_GENERIC; 1653 break; 1654 } 1655 if (regTypeIsUninitReference(checkType)) { 1656 LOG_VFY("VFY: uninitialized ref not expected as reg check"); 1657 *pFailure = VERIFY_ERROR_GENERIC; 1658 break; 1659 } 1660 /* make sure srcType is initialized reference or always-NULL */ 1661 if (!regTypeIsReference(srcType)) { 1662 LOG_VFY("VFY: register1 v%u type %d, wanted ref", vsrc, srcType); 1663 *pFailure = VERIFY_ERROR_GENERIC; 1664 break; 1665 } 1666 if (regTypeIsUninitReference(srcType)) { 1667 LOG_VFY("VFY: register1 v%u holds uninitialized ref", vsrc); 1668 *pFailure = VERIFY_ERROR_GENERIC; 1669 break; 1670 } 1671 /* if the register isn't Zero, make sure it's an instance of check */ 1672 if (srcType != kRegTypeZero) { 1673 ClassObject* srcClass = regTypeInitializedReferenceToClass(srcType); 1674 ClassObject* checkClass = regTypeInitializedReferenceToClass(checkType); 1675 assert(srcClass != NULL); 1676 assert(checkClass != NULL); 1677 1678 if (dvmIsInterfaceClass(checkClass)) { 1679 /* 1680 * All objects implement all interfaces as far as the 1681 * verifier is concerned. The runtime has to sort it out. 1682 * See comments above findCommonSuperclass. 1683 */ 1684 /* 1685 if (srcClass != checkClass && 1686 !dvmImplements(srcClass, checkClass)) 1687 { 1688 LOG_VFY("VFY: %s does not implement %s", 1689 srcClass->descriptor, checkClass->descriptor); 1690 *pFailure = VERIFY_ERROR_GENERIC; 1691 } 1692 */ 1693 } else { 1694 if (!dvmInstanceof(srcClass, checkClass)) { 1695 LOG_VFY("VFY: %s is not instance of %s", 1696 srcClass->descriptor, checkClass->descriptor); 1697 *pFailure = VERIFY_ERROR_GENERIC; 1698 } 1699 } 1700 } 1701 break; 1702 } 1703 } 1704 1705 /* 1706 * Set the type of the "result" register. 1707 */ 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 ALOGE("VFY: unable to find type=%#x (idx=%d)", 1732 uninitType, regTypeToUninitIndex(uninitType)); 1733 *pFailure = VERIFY_ERROR_GENERIC; 1734 return; 1735 } 1736 initType = regTypeFromClass(clazz); 1737 1738 changed = 0; 1739 for (i = 0; i < insnRegCount; i++) { 1740 if (insnRegs[i] == uninitType) { 1741 insnRegs[i] = initType; 1742 changed++; 1743 } 1744 } 1745 //ALOGD("VFY: marked %d registers as initialized", changed); 1746 assert(changed > 0); 1747 1748 return; 1749 } 1750 1751 /* 1752 * We're creating a new instance of class C at address A. Any registers 1753 * holding instances previously created at address A must be initialized 1754 * by now. If not, we mark them as "conflict" to prevent them from being 1755 * used (otherwise, markRefsAsInitialized would mark the old ones and the 1756 * new ones at the same time). 1757 */ 1758 static void markUninitRefsAsInvalid(RegisterLine* registerLine, 1759 int insnRegCount, UninitInstanceMap* uninitMap, RegType uninitType) 1760 { 1761 RegType* insnRegs = registerLine->regTypes; 1762 int i, changed; 1763 1764 changed = 0; 1765 for (i = 0; i < insnRegCount; i++) { 1766 if (insnRegs[i] == uninitType) { 1767 insnRegs[i] = kRegTypeConflict; 1768 if (registerLine->monitorEntries != NULL) 1769 registerLine->monitorEntries[i] = 0; 1770 changed++; 1771 } 1772 } 1773 1774 //if (changed) 1775 // ALOGD("VFY: marked %d uninitialized registers as invalid", changed); 1776 } 1777 1778 /* 1779 * Find the register line for the specified instruction in the current method. 1780 */ 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 //ALOGI(" RESULT (changed=%d)", changed); 2649 //dumpRegTypes(vdata, targetRegs, 0, "rslt", NULL, 0); 2650 } 2651 #ifdef VERIFIER_STATS 2652 gDvm.verifierStats.mergeRegCount++; 2653 if (changed) 2654 gDvm.verifierStats.mergeRegChanged++; 2655 #endif 2656 2657 if (changed) 2658 dvmInsnSetChanged(insnFlags, nextInsn, true); 2659 } 2660 2661 return true; 2662 } 2663 2664 2665 /* 2666 * =========================================================================== 2667 * Utility functions 2668 * =========================================================================== 2669 */ 2670 2671 /* 2672 * Look up an instance field, specified by "fieldIdx", that is going to be 2673 * accessed in object "objType". This resolves the field and then verifies 2674 * that the class containing the field is an instance of the reference in 2675 * "objType". 2676 * 2677 * It is possible for "objType" to be kRegTypeZero, meaning that we might 2678 * have a null reference. This is a runtime problem, so we allow it, 2679 * skipping some of the type checks. 2680 * 2681 * In general, "objType" must be an initialized reference. However, we 2682 * allow it to be uninitialized if this is an "<init>" method and the field 2683 * is declared within the "objType" class. 2684 * 2685 * Returns an InstField on success, returns NULL and sets "*pFailure" 2686 * on failure. 2687 */ 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 //ALOGD("Tracking registers for [%d], total %d in %d units", 3150 // trackRegsFor, interestingCount-kExtraLines, insnsSize); 3151 3152 assert(storage - (u1*)regTable->lineAlloc == 3153 (int) (interestingCount * spacePerEntry)); 3154 assert(regTable->registerLines[0].regTypes != NULL); 3155 return true; 3156 } 3157 3158 /* 3159 * Free up any "hairy" structures associated with register lines. 3160 */ 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 //ALOGI("filled-new-array: %s -> %d", resClass->descriptor, expectedType); 3198 3199 /* 3200 * Verify each register. If "argCount" is bad, verifyRegisterType() 3201 * will run off the end of the list and fail. It's legal, if silly, 3202 * for argCount to be zero. 3203 */ 3204 for (ui = 0; ui < argCount; ui++) { 3205 u4 getReg; 3206 3207 if (isRange) 3208 getReg = pDecInsn->vC + ui; 3209 else 3210 getReg = pDecInsn->arg[ui]; 3211 3212 verifyRegisterType(registerLine, getReg, expectedType, pFailure); 3213 if (!VERIFY_OK(*pFailure)) { 3214 LOG_VFY("VFY: filled-new-array arg %u(%u) not valid", ui, getReg); 3215 return; 3216 } 3217 } 3218 } 3219 3220 3221 /* 3222 * Replace an instruction with "throw-verification-error". This allows us to 3223 * defer error reporting until the code path is first used. 3224 * 3225 * This is expected to be called during "just in time" verification, not 3226 * from within dexopt. (Verification failures in dexopt will result in 3227 * postponement of verification to first use of the class.) 3228 * 3229 * The throw-verification-error instruction requires two code units. Some 3230 * of the replaced instructions require three; the third code unit will 3231 * receive a "nop". The instruction's length will be left unchanged 3232 * in "insnFlags". 3233 * 3234 * The VM postpones setting of debugger breakpoints in unverified classes, 3235 * so there should be no clashes with the debugger. 3236 * 3237 * Returns "true" on success. 3238 */ 3239 static bool replaceFailingInstruction(const Method* meth, InsnFlags* insnFlags, 3240 int insnIdx, VerifyError failure) 3241 { 3242 VerifyErrorRefType refType; 3243 u2* oldInsns = (u2*) meth->insns + insnIdx; 3244 int width; 3245 3246 if (gDvm.optimizing) 3247 ALOGD("Weird: RFI during dexopt?"); 3248 3249 /* 3250 * Generate the new instruction out of the old. 3251 * 3252 * First, make sure this is an instruction we're expecting to stomp on. 3253 */ 3254 Opcode opcode = dexOpcodeFromCodeUnit(*oldInsns); 3255 switch (opcode) { 3256 case OP_CONST_CLASS: // insn[1] == class ref, 2 bytes 3257 case OP_CHECK_CAST: 3258 case OP_INSTANCE_OF: 3259 case OP_NEW_INSTANCE: 3260 case OP_NEW_ARRAY: 3261 case OP_FILLED_NEW_ARRAY: // insn[1] == class ref, 3 bytes 3262 case OP_FILLED_NEW_ARRAY_RANGE: 3263 refType = VERIFY_ERROR_REF_CLASS; 3264 break; 3265 3266 case OP_IGET: // insn[1] == field ref, 2 bytes 3267 case OP_IGET_BOOLEAN: 3268 case OP_IGET_BYTE: 3269 case OP_IGET_CHAR: 3270 case OP_IGET_SHORT: 3271 case OP_IGET_WIDE: 3272 case OP_IGET_OBJECT: 3273 case OP_IPUT: 3274 case OP_IPUT_BOOLEAN: 3275 case OP_IPUT_BYTE: 3276 case OP_IPUT_CHAR: 3277 case OP_IPUT_SHORT: 3278 case OP_IPUT_WIDE: 3279 case OP_IPUT_OBJECT: 3280 case OP_SGET: 3281 case OP_SGET_BOOLEAN: 3282 case OP_SGET_BYTE: 3283 case OP_SGET_CHAR: 3284 case OP_SGET_SHORT: 3285 case OP_SGET_WIDE: 3286 case OP_SGET_OBJECT: 3287 case OP_SPUT: 3288 case OP_SPUT_BOOLEAN: 3289 case OP_SPUT_BYTE: 3290 case OP_SPUT_CHAR: 3291 case OP_SPUT_SHORT: 3292 case OP_SPUT_WIDE: 3293 case OP_SPUT_OBJECT: 3294 refType = VERIFY_ERROR_REF_FIELD; 3295 break; 3296 3297 case OP_INVOKE_VIRTUAL: // insn[1] == method ref, 3 bytes 3298 case OP_INVOKE_VIRTUAL_RANGE: 3299 case OP_INVOKE_SUPER: 3300 case OP_INVOKE_SUPER_RANGE: 3301 case OP_INVOKE_DIRECT: 3302 case OP_INVOKE_DIRECT_RANGE: 3303 case OP_INVOKE_STATIC: 3304 case OP_INVOKE_STATIC_RANGE: 3305 case OP_INVOKE_INTERFACE: 3306 case OP_INVOKE_INTERFACE_RANGE: 3307 refType = VERIFY_ERROR_REF_METHOD; 3308 break; 3309 3310 default: 3311 /* could handle this in a generic way, but this is probably safer */ 3312 LOG_VFY("GLITCH: verifier asked to replace opcode 0x%02x", opcode); 3313 return false; 3314 } 3315 3316 assert((dexGetFlagsFromOpcode(opcode) & kInstrCanThrow) != 0); 3317 3318 /* write a NOP over the third code unit, if necessary */ 3319 width = dvmInsnGetWidth(insnFlags, insnIdx); 3320 switch (width) { 3321 case 2: 3322 case 4: 3323 /* nothing to do */ 3324 break; 3325 case 3: 3326 dvmUpdateCodeUnit(meth, oldInsns+2, OP_NOP); 3327 break; 3328 default: 3329 /* whoops */ 3330 ALOGE("ERROR: stomped a %d-unit instruction with a verifier error", 3331 width); 3332 dvmAbort(); 3333 } 3334 3335 /* encode the opcode, with the failure code in the high byte */ 3336 assert(width == 2 || width == 3); 3337 u2 newVal = OP_THROW_VERIFICATION_ERROR | 3338 (failure << 8) | (refType << (8 + kVerifyErrorRefTypeShift)); 3339 dvmUpdateCodeUnit(meth, oldInsns, newVal); 3340 3341 return true; 3342 } 3343 3344 /* 3345 * Handle a monitor-enter instruction. 3346 */ 3347 void handleMonitorEnter(RegisterLine* workLine, u4 regIdx, u4 insnIdx, 3348 VerifyError* pFailure) 3349 { 3350 if (!regTypeIsReference(getRegisterType(workLine, regIdx))) { 3351 LOG_VFY("VFY: monitor-enter on non-object"); 3352 *pFailure = VERIFY_ERROR_GENERIC; 3353 return; 3354 } 3355 3356 if (workLine->monitorEntries == NULL) { 3357 /* should only be true if monitor verification is disabled */ 3358 assert(!gDvm.monitorVerification); 3359 return; 3360 } 3361 3362 if (workLine->monitorStackTop == kMaxMonitorStackDepth) { 3363 LOG_VFY("VFY: monitor-enter stack overflow (%d)", 3364 kMaxMonitorStackDepth); 3365 *pFailure = VERIFY_ERROR_GENERIC; 3366 return; 3367 } 3368 3369 /* 3370 * Push an entry on the stack, and set a bit in the register flags to 3371 * indicate that it's associated with this register. 3372 */ 3373 workLine->monitorEntries[regIdx] |= 1 << workLine->monitorStackTop; 3374 workLine->monitorStack[workLine->monitorStackTop++] = insnIdx; 3375 } 3376 3377 /* 3378 * Handle a monitor-exit instruction. 3379 */ 3380 void handleMonitorExit(RegisterLine* workLine, u4 regIdx, u4 insnIdx, 3381 VerifyError* pFailure) 3382 { 3383 if (!regTypeIsReference(getRegisterType(workLine, regIdx))) { 3384 LOG_VFY("VFY: monitor-exit on non-object"); 3385 *pFailure = VERIFY_ERROR_GENERIC; 3386 return; 3387 } 3388 3389 if (workLine->monitorEntries == NULL) { 3390 /* should only be true if monitor verification is disabled */ 3391 assert(!gDvm.monitorVerification); 3392 return; 3393 } 3394 3395 if (workLine->monitorStackTop == 0) { 3396 LOG_VFY("VFY: monitor-exit stack underflow"); 3397 *pFailure = VERIFY_ERROR_GENERIC; 3398 return; 3399 } 3400 3401 /* 3402 * Confirm that the entry at the top of the stack is associated with 3403 * the register. Pop the top entry off. 3404 */ 3405 workLine->monitorStackTop--; 3406 #ifdef BUG_3215458_FIXED 3407 /* 3408 * TODO: This code can safely be enabled if know we are working on 3409 * a dex file of format version 036 or later. (That is, we'll need to 3410 * add a check for the version number.) 3411 */ 3412 if ((workLine->monitorEntries[regIdx] & (1 << workLine->monitorStackTop)) 3413 == 0) 3414 { 3415 LOG_VFY("VFY: monitor-exit bit %d not set: addr=0x%04x (bits[%d]=%#x)", 3416 workLine->monitorStackTop, insnIdx, regIdx, 3417 workLine->monitorEntries[regIdx]); 3418 *pFailure = VERIFY_ERROR_GENERIC; 3419 return; 3420 } 3421 #endif 3422 workLine->monitorStack[workLine->monitorStackTop] = 0; 3423 3424 /* 3425 * Clear the bit from the register flags. 3426 */ 3427 workLine->monitorEntries[regIdx] &= ~(1 << workLine->monitorStackTop); 3428 } 3429 3430 3431 /* 3432 * =========================================================================== 3433 * Entry point and driver loop 3434 * =========================================================================== 3435 */ 3436 3437 /* 3438 * One-time preparation. 3439 */ 3440 static void verifyPrep() 3441 { 3442 #ifndef NDEBUG 3443 /* only need to do this if the table was updated */ 3444 checkMergeTab(); 3445 #endif 3446 } 3447 3448 /* 3449 * Entry point for the detailed code-flow analysis of a single method. 3450 */ 3451 bool dvmVerifyCodeFlow(VerifierData* vdata) 3452 { 3453 bool result = false; 3454 const Method* meth = vdata->method; 3455 const int insnsSize = vdata->insnsSize; 3456 const bool generateRegisterMap = gDvm.generateRegisterMaps; 3457 RegisterTable regTable; 3458 3459 memset(®Table, 0, sizeof(regTable)); 3460 3461 #ifdef VERIFIER_STATS 3462 gDvm.verifierStats.methodsExamined++; 3463 if (vdata->monitorEnterCount) 3464 gDvm.verifierStats.monEnterMethods++; 3465 #endif 3466 3467 /* TODO: move this elsewhere -- we don't need to do this for every method */ 3468 verifyPrep(); 3469 3470 if (meth->registersSize * insnsSize > 4*1024*1024) { 3471 LOG_VFY_METH(meth, 3472 "VFY: warning: method is huge (regs=%d insnsSize=%d)", 3473 meth->registersSize, insnsSize); 3474 /* might be bogus data, might be some huge generated method */ 3475 } 3476 3477 /* 3478 * Create register lists, and initialize them to "Unknown". If we're 3479 * also going to create the register map, we need to retain the 3480 * register lists for a larger set of addresses. 3481 */ 3482 if (!initRegisterTable(vdata, ®Table, 3483 generateRegisterMap ? kTrackRegsGcPoints : kTrackRegsBranches)) 3484 goto bail; 3485 3486 vdata->registerLines = regTable.registerLines; 3487 3488 /* 3489 * Perform liveness analysis. 3490 * 3491 * We can do this before or after the main verifier pass. The choice 3492 * affects whether or not we see the effects of verifier instruction 3493 * changes, i.e. substitution of throw-verification-error. 3494 * 3495 * In practice the ordering doesn't really matter, because T-V-E 3496 * just prunes "can continue", creating regions of dead code (with 3497 * corresponding register map data that will never be used). 3498 */ 3499 if (generateRegisterMap && 3500 gDvm.registerMapMode == kRegisterMapModeLivePrecise) 3501 { 3502 /* 3503 * Compute basic blocks and predecessor lists. 3504 */ 3505 if (!dvmComputeVfyBasicBlocks(vdata)) 3506 goto bail; 3507 3508 /* 3509 * Compute liveness. 3510 */ 3511 if (!dvmComputeLiveness(vdata)) 3512 goto bail; 3513 } 3514 3515 /* 3516 * Initialize the types of the registers that correspond to the 3517 * method arguments. We can determine this from the method signature. 3518 */ 3519 if (!setTypesFromSignature(meth, regTable.registerLines[0].regTypes, 3520 vdata->uninitMap)) 3521 goto bail; 3522 3523 /* 3524 * Run the verifier. 3525 */ 3526 if (!doCodeVerification(vdata, ®Table)) 3527 goto bail; 3528 3529 /* 3530 * Generate a register map. 3531 */ 3532 if (generateRegisterMap) { 3533 RegisterMap* pMap = dvmGenerateRegisterMapV(vdata); 3534 if (pMap != NULL) { 3535 /* 3536 * Tuck it into the Method struct. It will either get used 3537 * directly or, if we're in dexopt, will be packed up and 3538 * appended to the DEX file. 3539 */ 3540 dvmSetRegisterMap((Method*)meth, pMap); 3541 } 3542 } 3543 3544 /* 3545 * Success. 3546 */ 3547 result = true; 3548 3549 bail: 3550 freeRegisterLineInnards(vdata); 3551 free(regTable.registerLines); 3552 free(regTable.lineAlloc); 3553 return result; 3554 } 3555 3556 /* 3557 * Grind through the instructions. 3558 * 3559 * The basic strategy is as outlined in v3 4.11.1.2: set the "changed" bit 3560 * on the first instruction, process it (setting additional "changed" bits), 3561 * and repeat until there are no more. 3562 * 3563 * v3 4.11.1.1 3564 * - (N/A) operand stack is always the same size 3565 * - operand stack [registers] contain the correct types of values 3566 * - local variables [registers] contain the correct types of values 3567 * - methods are invoked with the appropriate arguments 3568 * - fields are assigned using values of appropriate types 3569 * - opcodes have the correct type values in operand registers 3570 * - there is never an uninitialized class instance in a local variable in 3571 * code protected by an exception handler (operand stack is okay, because 3572 * the operand stack is discarded when an exception is thrown) [can't 3573 * know what's a local var w/o the debug info -- should fall out of 3574 * register typing] 3575 * 3576 * v3 4.11.1.2 3577 * - execution cannot fall off the end of the code 3578 * 3579 * (We also do many of the items described in the "static checks" sections, 3580 * because it's easier to do them here.) 3581 * 3582 * We need an array of RegType values, one per register, for every 3583 * instruction. If the method uses monitor-enter, we need extra data 3584 * for every register, and a stack for every "interesting" instruction. 3585 * In theory this could become quite large -- up to several megabytes for 3586 * a monster function. 3587 * 3588 * NOTE: 3589 * The spec forbids backward branches when there's an uninitialized reference 3590 * in a register. The idea is to prevent something like this: 3591 * loop: 3592 * move r1, r0 3593 * new-instance r0, MyClass 3594 * ... 3595 * if-eq rN, loop // once 3596 * initialize r0 3597 * 3598 * This leaves us with two different instances, both allocated by the 3599 * same instruction, but only one is initialized. The scheme outlined in 3600 * v3 4.11.1.4 wouldn't catch this, so they work around it by preventing 3601 * backward branches. We achieve identical results without restricting 3602 * code reordering by specifying that you can't execute the new-instance 3603 * instruction if a register contains an uninitialized instance created 3604 * by that same instrutcion. 3605 */ 3606 static bool doCodeVerification(VerifierData* vdata, RegisterTable* regTable) 3607 { 3608 const Method* meth = vdata->method; 3609 InsnFlags* insnFlags = vdata->insnFlags; 3610 UninitInstanceMap* uninitMap = vdata->uninitMap; 3611 const int insnsSize = dvmGetMethodInsnsSize(meth); 3612 bool result = false; 3613 bool debugVerbose = false; 3614 int insnIdx, startGuess; 3615 3616 /* 3617 * Begin by marking the first instruction as "changed". 3618 */ 3619 dvmInsnSetChanged(insnFlags, 0, true); 3620 3621 if (dvmWantVerboseVerification(meth)) { 3622 IF_ALOGI() { 3623 char* desc = dexProtoCopyMethodDescriptor(&meth->prototype); 3624 ALOGI("Now verifying: %s.%s %s (ins=%d regs=%d)", 3625 meth->clazz->descriptor, meth->name, desc, 3626 meth->insSize, meth->registersSize); 3627 ALOGI(" ------ [0 4 8 12 16 20 24 28 32 36"); 3628 free(desc); 3629 } 3630 debugVerbose = true; 3631 gDebugVerbose = true; 3632 } else { 3633 gDebugVerbose = false; 3634 } 3635 3636 startGuess = 0; 3637 3638 /* 3639 * Continue until no instructions are marked "changed". 3640 */ 3641 while (true) { 3642 /* 3643 * Find the first marked one. Use "startGuess" as a way to find 3644 * one quickly. 3645 */ 3646 for (insnIdx = startGuess; insnIdx < insnsSize; insnIdx++) { 3647 if (dvmInsnIsChanged(insnFlags, insnIdx)) 3648 break; 3649 } 3650 3651 if (insnIdx == insnsSize) { 3652 if (startGuess != 0) { 3653 /* try again, starting from the top */ 3654 startGuess = 0; 3655 continue; 3656 } else { 3657 /* all flags are clear */ 3658 break; 3659 } 3660 } 3661 3662 /* 3663 * We carry the working set of registers from instruction to 3664 * instruction. If this address can be the target of a branch 3665 * (or throw) instruction, or if we're skipping around chasing 3666 * "changed" flags, we need to load the set of registers from 3667 * the table. 3668 * 3669 * Because we always prefer to continue on to the next instruction, 3670 * we should never have a situation where we have a stray 3671 * "changed" flag set on an instruction that isn't a branch target. 3672 */ 3673 if (dvmInsnIsBranchTarget(insnFlags, insnIdx)) { 3674 RegisterLine* workLine = ®Table->workLine; 3675 3676 copyLineFromTable(workLine, regTable, insnIdx); 3677 } else { 3678 #ifndef NDEBUG 3679 /* 3680 * Sanity check: retrieve the stored register line (assuming 3681 * a full table) and make sure it actually matches. 3682 */ 3683 RegisterLine* registerLine = getRegisterLine(regTable, insnIdx); 3684 if (registerLine->regTypes != NULL && 3685 compareLineToTable(regTable, insnIdx, ®Table->workLine) != 0) 3686 { 3687 char* desc = dexProtoCopyMethodDescriptor(&meth->prototype); 3688 LOG_VFY("HUH? workLine diverged in %s.%s %s", 3689 meth->clazz->descriptor, meth->name, desc); 3690 free(desc); 3691 dumpRegTypes(vdata, registerLine, 0, "work", 3692 uninitMap, DRT_SHOW_REF_TYPES | DRT_SHOW_LOCALS); 3693 dumpRegTypes(vdata, registerLine, 0, "insn", 3694 uninitMap, DRT_SHOW_REF_TYPES | DRT_SHOW_LOCALS); 3695 } 3696 #endif 3697 } 3698 if (debugVerbose) { 3699 dumpRegTypes(vdata, ®Table->workLine, insnIdx, 3700 NULL, uninitMap, SHOW_REG_DETAILS); 3701 } 3702 3703 //ALOGI("process %s.%s %s %d", 3704 // meth->clazz->descriptor, meth->name, meth->descriptor, insnIdx); 3705 if (!verifyInstruction(meth, insnFlags, regTable, insnIdx, 3706 uninitMap, &startGuess)) 3707 { 3708 //ALOGD("+++ %s bailing at %d", meth->name, insnIdx); 3709 goto bail; 3710 } 3711 3712 /* 3713 * Clear "changed" and mark as visited. 3714 */ 3715 dvmInsnSetVisited(insnFlags, insnIdx, true); 3716 dvmInsnSetChanged(insnFlags, insnIdx, false); 3717 } 3718 3719 if (DEAD_CODE_SCAN && !IS_METHOD_FLAG_SET(meth, METHOD_ISWRITABLE)) { 3720 /* 3721 * Scan for dead code. There's nothing "evil" about dead code 3722 * (besides the wasted space), but it indicates a flaw somewhere 3723 * down the line, possibly in the verifier. 3724 * 3725 * If we've substituted "always throw" instructions into the stream, 3726 * we are almost certainly going to have some dead code. 3727 */ 3728 int deadStart = -1; 3729 for (insnIdx = 0; insnIdx < insnsSize; 3730 insnIdx += dvmInsnGetWidth(insnFlags, insnIdx)) 3731 { 3732 /* 3733 * Switch-statement data doesn't get "visited" by scanner. It 3734 * may or may not be preceded by a padding NOP (for alignment). 3735 */ 3736 int instr = meth->insns[insnIdx]; 3737 if (instr == kPackedSwitchSignature || 3738 instr == kSparseSwitchSignature || 3739 instr == kArrayDataSignature || 3740 (instr == OP_NOP && 3741 (meth->insns[insnIdx+1] == kPackedSwitchSignature || 3742 meth->insns[insnIdx+1] == kSparseSwitchSignature || 3743 meth->insns[insnIdx+1] == kArrayDataSignature))) 3744 { 3745 dvmInsnSetVisited(insnFlags, insnIdx, true); 3746 } 3747 3748 if (!dvmInsnIsVisited(insnFlags, insnIdx)) { 3749 if (deadStart < 0) 3750 deadStart = insnIdx; 3751 } else if (deadStart >= 0) { 3752 IF_ALOGD() { 3753 char* desc = 3754 dexProtoCopyMethodDescriptor(&meth->prototype); 3755 ALOGD("VFY: dead code 0x%04x-%04x in %s.%s %s", 3756 deadStart, insnIdx-1, 3757 meth->clazz->descriptor, meth->name, desc); 3758 free(desc); 3759 } 3760 3761 deadStart = -1; 3762 } 3763 } 3764 if (deadStart >= 0) { 3765 IF_ALOGD() { 3766 char* desc = dexProtoCopyMethodDescriptor(&meth->prototype); 3767 ALOGD("VFY: dead code 0x%04x-%04x in %s.%s %s", 3768 deadStart, insnIdx-1, 3769 meth->clazz->descriptor, meth->name, desc); 3770 free(desc); 3771 } 3772 } 3773 } 3774 3775 result = true; 3776 3777 bail: 3778 return result; 3779 } 3780 3781 3782 /* 3783 * Perform verification for a single instruction. 3784 * 3785 * This requires fully decoding the instruction to determine the effect 3786 * it has on registers. 3787 * 3788 * Finds zero or more following instructions and sets the "changed" flag 3789 * if execution at that point needs to be (re-)evaluated. Register changes 3790 * are merged into "regTypes" at the target addresses. Does not set or 3791 * clear any other flags in "insnFlags". 3792 * 3793 * This may alter meth->insns if we need to replace an instruction with 3794 * throw-verification-error. 3795 */ 3796 static bool verifyInstruction(const Method* meth, InsnFlags* insnFlags, 3797 RegisterTable* regTable, int insnIdx, UninitInstanceMap* uninitMap, 3798 int* pStartGuess) 3799 { 3800 const int insnsSize = dvmGetMethodInsnsSize(meth); 3801 const u2* insns = meth->insns + insnIdx; 3802 bool result = false; 3803 3804 #ifdef VERIFIER_STATS 3805 if (dvmInsnIsVisited(insnFlags, insnIdx)) { 3806 gDvm.verifierStats.instrsReexamined++; 3807 } else { 3808 gDvm.verifierStats.instrsExamined++; 3809 } 3810 #endif 3811 3812 /* 3813 * Once we finish decoding the instruction, we need to figure out where 3814 * we can go from here. There are three possible ways to transfer 3815 * control to another statement: 3816 * 3817 * (1) Continue to the next instruction. Applies to all but 3818 * unconditional branches, method returns, and exception throws. 3819 * (2) Branch to one or more possible locations. Applies to branches 3820 * and switch statements. 3821 * (3) Exception handlers. Applies to any instruction that can 3822 * throw an exception that is handled by an encompassing "try" 3823 * block. 3824 * 3825 * We can also return, in which case there is no successor instruction 3826 * from this point. 3827 * 3828 * The behavior can be determined from the OpcodeFlags. 3829 */ 3830 3831 RegisterLine* workLine = ®Table->workLine; 3832 const DexFile* pDexFile = meth->clazz->pDvmDex->pDexFile; 3833 ClassObject* resClass; 3834 s4 branchTarget = 0; 3835 const int insnRegCount = meth->registersSize; 3836 RegType tmpType; 3837 DecodedInstruction decInsn; 3838 bool justSetResult = false; 3839 VerifyError failure = VERIFY_ERROR_NONE; 3840 3841 #ifndef NDEBUG 3842 memset(&decInsn, 0x81, sizeof(decInsn)); 3843 #endif 3844 dexDecodeInstruction(insns, &decInsn); 3845 3846 int nextFlags = dexGetFlagsFromOpcode(decInsn.opcode); 3847 3848 /* 3849 * Make a copy of the previous register state. If the instruction 3850 * can throw an exception, we will copy/merge this into the "catch" 3851 * address rather than workLine, because we don't want the result 3852 * from the "successful" code path (e.g. a check-cast that "improves" 3853 * a type) to be visible to the exception handler. 3854 */ 3855 if ((nextFlags & kInstrCanThrow) != 0 && dvmInsnIsInTry(insnFlags, insnIdx)) 3856 { 3857 copyRegisterLine(®Table->savedLine, workLine, 3858 regTable->insnRegCountPlus); 3859 } else { 3860 #ifndef NDEBUG 3861 memset(regTable->savedLine.regTypes, 0xdd, 3862 regTable->insnRegCountPlus * sizeof(RegType)); 3863 #endif 3864 } 3865 3866 switch (decInsn.opcode) { 3867 case OP_NOP: 3868 /* 3869 * A "pure" NOP has no effect on anything. Data tables start with 3870 * a signature that looks like a NOP; if we see one of these in 3871 * the course of executing code then we have a problem. 3872 */ 3873 if (decInsn.vA != 0) { 3874 LOG_VFY("VFY: encountered data table in instruction stream"); 3875 failure = VERIFY_ERROR_GENERIC; 3876 } 3877 break; 3878 3879 case OP_MOVE: 3880 case OP_MOVE_FROM16: 3881 case OP_MOVE_16: 3882 copyRegister1(workLine, decInsn.vA, decInsn.vB, kTypeCategory1nr, 3883 &failure); 3884 break; 3885 case OP_MOVE_WIDE: 3886 case OP_MOVE_WIDE_FROM16: 3887 case OP_MOVE_WIDE_16: 3888 copyRegister2(workLine, decInsn.vA, decInsn.vB, &failure); 3889 break; 3890 case OP_MOVE_OBJECT: 3891 case OP_MOVE_OBJECT_FROM16: 3892 case OP_MOVE_OBJECT_16: 3893 copyRegister1(workLine, decInsn.vA, decInsn.vB, kTypeCategoryRef, 3894 &failure); 3895 break; 3896 3897 /* 3898 * The move-result instructions copy data out of a "pseudo-register" 3899 * with the results from the last method invocation. In practice we 3900 * might want to hold the result in an actual CPU register, so the 3901 * Dalvik spec requires that these only appear immediately after an 3902 * invoke or filled-new-array. 3903 * 3904 * These calls invalidate the "result" register. (This is now 3905 * redundant with the reset done below, but it can make the debug info 3906 * easier to read in some cases.) 3907 */ 3908 case OP_MOVE_RESULT: 3909 copyResultRegister1(workLine, insnRegCount, decInsn.vA, 3910 kTypeCategory1nr, &failure); 3911 break; 3912 case OP_MOVE_RESULT_WIDE: 3913 copyResultRegister2(workLine, insnRegCount, decInsn.vA, &failure); 3914 break; 3915 case OP_MOVE_RESULT_OBJECT: 3916 copyResultRegister1(workLine, insnRegCount, decInsn.vA, 3917 kTypeCategoryRef, &failure); 3918 break; 3919 3920 case OP_MOVE_EXCEPTION: 3921 /* 3922 * This statement can only appear as the first instruction in an 3923 * exception handler (though not all exception handlers need to 3924 * have one of these). We verify that as part of extracting the 3925 * exception type from the catch block list. 3926 * 3927 * "resClass" will hold the closest common superclass of all 3928 * exceptions that can be handled here. 3929 */ 3930 resClass = getCaughtExceptionType(meth, insnIdx, &failure); 3931 if (resClass == NULL) { 3932 assert(!VERIFY_OK(failure)); 3933 } else { 3934 setRegisterType(workLine, decInsn.vA, regTypeFromClass(resClass)); 3935 } 3936 break; 3937 3938 case OP_RETURN_VOID: 3939 if (!checkConstructorReturn(meth, workLine, insnRegCount)) { 3940 failure = VERIFY_ERROR_GENERIC; 3941 } else if (getMethodReturnType(meth) != kRegTypeUnknown) { 3942 LOG_VFY("VFY: return-void not expected"); 3943 failure = VERIFY_ERROR_GENERIC; 3944 } 3945 break; 3946 case OP_RETURN: 3947 if (!checkConstructorReturn(meth, workLine, insnRegCount)) { 3948 failure = VERIFY_ERROR_GENERIC; 3949 } else { 3950 /* check the method signature */ 3951 RegType returnType = getMethodReturnType(meth); 3952 checkTypeCategory(returnType, kTypeCategory1nr, &failure); 3953 if (!VERIFY_OK(failure)) 3954 LOG_VFY("VFY: return-1nr not expected"); 3955 3956 /* 3957 * javac generates synthetic functions that write byte values 3958 * into boolean fields. Also, it may use integer values for 3959 * boolean, byte, short, and character return types. 3960 */ 3961 RegType srcType = getRegisterType(workLine, decInsn.vA); 3962 if ((returnType == kRegTypeBoolean && srcType == kRegTypeByte) || 3963 ((returnType == kRegTypeBoolean || returnType == kRegTypeByte || 3964 returnType == kRegTypeShort || returnType == kRegTypeChar) && 3965 srcType == kRegTypeInteger)) 3966 returnType = srcType; 3967 3968 /* check the register contents */ 3969 verifyRegisterType(workLine, decInsn.vA, returnType, &failure); 3970 if (!VERIFY_OK(failure)) { 3971 LOG_VFY("VFY: return-1nr on invalid register v%d", 3972 decInsn.vA); 3973 } 3974 } 3975 break; 3976 case OP_RETURN_WIDE: 3977 if (!checkConstructorReturn(meth, workLine, insnRegCount)) { 3978 failure = VERIFY_ERROR_GENERIC; 3979 } else { 3980 RegType returnType; 3981 3982 /* check the method signature */ 3983 returnType = getMethodReturnType(meth); 3984 checkTypeCategory(returnType, kTypeCategory2, &failure); 3985 if (!VERIFY_OK(failure)) 3986 LOG_VFY("VFY: return-wide not expected"); 3987 3988 /* check the register contents */ 3989 verifyRegisterType(workLine, decInsn.vA, returnType, &failure); 3990 if (!VERIFY_OK(failure)) { 3991 LOG_VFY("VFY: return-wide on invalid register pair v%d", 3992 decInsn.vA); 3993 } 3994 } 3995 break; 3996 case OP_RETURN_OBJECT: 3997 if (!checkConstructorReturn(meth, workLine, insnRegCount)) { 3998 failure = VERIFY_ERROR_GENERIC; 3999 } else { 4000 RegType returnType = getMethodReturnType(meth); 4001 checkTypeCategory(returnType, kTypeCategoryRef, &failure); 4002 if (!VERIFY_OK(failure)) { 4003 LOG_VFY("VFY: return-object not expected"); 4004 break; 4005 } 4006 4007 /* returnType is the *expected* return type, not register value */ 4008 assert(returnType != kRegTypeZero); 4009 assert(!regTypeIsUninitReference(returnType)); 4010 4011 /* 4012 * Verify that the reference in vAA is an instance of the type 4013 * in "returnType". The Zero type is allowed here. If the 4014 * method is declared to return an interface, then any 4015 * initialized reference is acceptable. 4016 * 4017 * Note getClassFromRegister fails if the register holds an 4018 * uninitialized reference, so we do not allow them to be 4019 * returned. 4020 */ 4021 ClassObject* declClass; 4022 4023 declClass = regTypeInitializedReferenceToClass(returnType); 4024 resClass = getClassFromRegister(workLine, decInsn.vA, &failure); 4025 if (!VERIFY_OK(failure)) 4026 break; 4027 if (resClass != NULL) { 4028 if (!dvmIsInterfaceClass(declClass) && 4029 !dvmInstanceof(resClass, declClass)) 4030 { 4031 LOG_VFY("VFY: returning %s (cl=%p), declared %s (cl=%p)", 4032 resClass->descriptor, resClass->classLoader, 4033 declClass->descriptor, declClass->classLoader); 4034 failure = VERIFY_ERROR_GENERIC; 4035 break; 4036 } 4037 } 4038 } 4039 break; 4040 4041 case OP_CONST_4: 4042 case OP_CONST_16: 4043 case OP_CONST: 4044 /* could be boolean, int, float, or a null reference */ 4045 setRegisterType(workLine, decInsn.vA, 4046 determineCat1Const((s4)decInsn.vB)); 4047 break; 4048 case OP_CONST_HIGH16: 4049 /* could be boolean, int, float, or a null reference */ 4050 setRegisterType(workLine, decInsn.vA, 4051 determineCat1Const((s4) decInsn.vB << 16)); 4052 break; 4053 case OP_CONST_WIDE_16: 4054 case OP_CONST_WIDE_32: 4055 case OP_CONST_WIDE: 4056 case OP_CONST_WIDE_HIGH16: 4057 /* could be long or double; resolved upon use */ 4058 setRegisterType(workLine, decInsn.vA, kRegTypeConstLo); 4059 break; 4060 case OP_CONST_STRING: 4061 case OP_CONST_STRING_JUMBO: 4062 assert(gDvm.classJavaLangString != NULL); 4063 setRegisterType(workLine, decInsn.vA, 4064 regTypeFromClass(gDvm.classJavaLangString)); 4065 break; 4066 case OP_CONST_CLASS: 4067 assert(gDvm.classJavaLangClass != NULL); 4068 /* make sure we can resolve the class; access check is important */ 4069 resClass = dvmOptResolveClass(meth->clazz, decInsn.vB, &failure); 4070 if (resClass == NULL) { 4071 const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vB); 4072 dvmLogUnableToResolveClass(badClassDesc, meth); 4073 LOG_VFY("VFY: unable to resolve const-class %d (%s) in %s", 4074 decInsn.vB, badClassDesc, meth->clazz->descriptor); 4075 assert(failure != VERIFY_ERROR_GENERIC); 4076 } else { 4077 setRegisterType(workLine, decInsn.vA, 4078 regTypeFromClass(gDvm.classJavaLangClass)); 4079 } 4080 break; 4081 4082 case OP_MONITOR_ENTER: 4083 handleMonitorEnter(workLine, decInsn.vA, insnIdx, &failure); 4084 break; 4085 case OP_MONITOR_EXIT: 4086 /* 4087 * monitor-exit instructions are odd. They can throw exceptions, 4088 * but when they do they act as if they succeeded and the PC is 4089 * pointing to the following instruction. (This behavior goes back 4090 * to the need to handle asynchronous exceptions, a now-deprecated 4091 * feature that Dalvik doesn't support.) 4092 * 4093 * In practice we don't need to worry about this. The only 4094 * exceptions that can be thrown from monitor-exit are for a 4095 * null reference and -exit without a matching -enter. If the 4096 * structured locking checks are working, the former would have 4097 * failed on the -enter instruction, and the latter is impossible. 4098 * 4099 * This is fortunate, because issue 3221411 prevents us from 4100 * chasing the "can throw" path when monitor verification is 4101 * enabled. If we can fully verify the locking we can ignore 4102 * some catch blocks (which will show up as "dead" code when 4103 * we skip them here); if we can't, then the code path could be 4104 * "live" so we still need to check it. 4105 */ 4106 if (workLine->monitorEntries != NULL) 4107 nextFlags &= ~kInstrCanThrow; 4108 handleMonitorExit(workLine, decInsn.vA, insnIdx, &failure); 4109 break; 4110 4111 case OP_CHECK_CAST: 4112 /* 4113 * If this instruction succeeds, we will promote register vA to 4114 * the type in vB. (This could be a demotion -- not expected, so 4115 * we don't try to address it.) 4116 * 4117 * If it fails, an exception is thrown, which we deal with later 4118 * by ignoring the update to decInsn.vA when branching to a handler. 4119 */ 4120 resClass = dvmOptResolveClass(meth->clazz, decInsn.vB, &failure); 4121 if (resClass == NULL) { 4122 const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vB); 4123 dvmLogUnableToResolveClass(badClassDesc, meth); 4124 LOG_VFY("VFY: unable to resolve check-cast %d (%s) in %s", 4125 decInsn.vB, badClassDesc, meth->clazz->descriptor); 4126 assert(failure != VERIFY_ERROR_GENERIC); 4127 } else { 4128 RegType origType; 4129 4130 origType = getRegisterType(workLine, decInsn.vA); 4131 if (!regTypeIsReference(origType)) { 4132 LOG_VFY("VFY: check-cast on non-reference in v%u",decInsn.vA); 4133 failure = VERIFY_ERROR_GENERIC; 4134 break; 4135 } 4136 setRegisterType(workLine, decInsn.vA, regTypeFromClass(resClass)); 4137 } 4138 break; 4139 case OP_INSTANCE_OF: 4140 /* make sure we're checking a reference type */ 4141 tmpType = getRegisterType(workLine, decInsn.vB); 4142 if (!regTypeIsReference(tmpType)) { 4143 LOG_VFY("VFY: vB not a reference (%d)", tmpType); 4144 failure = VERIFY_ERROR_GENERIC; 4145 break; 4146 } 4147 4148 /* make sure we can resolve the class; access check is important */ 4149 resClass = dvmOptResolveClass(meth->clazz, decInsn.vC, &failure); 4150 if (resClass == NULL) { 4151 const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vC); 4152 dvmLogUnableToResolveClass(badClassDesc, meth); 4153 LOG_VFY("VFY: unable to resolve instanceof %d (%s) in %s", 4154 decInsn.vC, badClassDesc, meth->clazz->descriptor); 4155 assert(failure != VERIFY_ERROR_GENERIC); 4156 } else { 4157 /* result is boolean */ 4158 setRegisterType(workLine, decInsn.vA, kRegTypeBoolean); 4159 } 4160 break; 4161 4162 case OP_ARRAY_LENGTH: 4163 resClass = getClassFromRegister(workLine, decInsn.vB, &failure); 4164 if (!VERIFY_OK(failure)) 4165 break; 4166 if (resClass != NULL && !dvmIsArrayClass(resClass)) { 4167 LOG_VFY("VFY: array-length on non-array"); 4168 failure = VERIFY_ERROR_GENERIC; 4169 break; 4170 } 4171 setRegisterType(workLine, decInsn.vA, kRegTypeInteger); 4172 break; 4173 4174 case OP_NEW_INSTANCE: 4175 resClass = dvmOptResolveClass(meth->clazz, decInsn.vB, &failure); 4176 if (resClass == NULL) { 4177 const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vB); 4178 dvmLogUnableToResolveClass(badClassDesc, meth); 4179 LOG_VFY("VFY: unable to resolve new-instance %d (%s) in %s", 4180 decInsn.vB, badClassDesc, meth->clazz->descriptor); 4181 assert(failure != VERIFY_ERROR_GENERIC); 4182 } else { 4183 RegType uninitType; 4184 4185 /* can't create an instance of an interface or abstract class */ 4186 if (dvmIsAbstractClass(resClass) || dvmIsInterfaceClass(resClass)) { 4187 LOG_VFY("VFY: new-instance on interface or abstract class %s", 4188 resClass->descriptor); 4189 failure = VERIFY_ERROR_INSTANTIATION; 4190 break; 4191 } 4192 4193 /* add resolved class to uninit map if not already there */ 4194 int uidx = setUninitInstance(uninitMap, insnIdx, resClass); 4195 assert(uidx >= 0); 4196 uninitType = regTypeFromUninitIndex(uidx); 4197 4198 /* 4199 * Any registers holding previous allocations from this address 4200 * that have not yet been initialized must be marked invalid. 4201 */ 4202 markUninitRefsAsInvalid(workLine, insnRegCount, uninitMap, 4203 uninitType); 4204 4205 /* add the new uninitialized reference to the register ste */ 4206 setRegisterType(workLine, decInsn.vA, uninitType); 4207 } 4208 break; 4209 case OP_NEW_ARRAY: 4210 resClass = dvmOptResolveClass(meth->clazz, decInsn.vC, &failure); 4211 if (resClass == NULL) { 4212 const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vC); 4213 dvmLogUnableToResolveClass(badClassDesc, meth); 4214 LOG_VFY("VFY: unable to resolve new-array %d (%s) in %s", 4215 decInsn.vC, badClassDesc, meth->clazz->descriptor); 4216 assert(failure != VERIFY_ERROR_GENERIC); 4217 } else if (!dvmIsArrayClass(resClass)) { 4218 LOG_VFY("VFY: new-array on non-array class"); 4219 failure = VERIFY_ERROR_GENERIC; 4220 } else { 4221 /* make sure "size" register is valid type */ 4222 verifyRegisterType(workLine, decInsn.vB, kRegTypeInteger, &failure); 4223 /* set register type to array class */ 4224 setRegisterType(workLine, decInsn.vA, regTypeFromClass(resClass)); 4225 } 4226 break; 4227 case OP_FILLED_NEW_ARRAY: 4228 case OP_FILLED_NEW_ARRAY_RANGE: 4229 resClass = dvmOptResolveClass(meth->clazz, decInsn.vB, &failure); 4230 if (resClass == NULL) { 4231 const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vB); 4232 dvmLogUnableToResolveClass(badClassDesc, meth); 4233 LOG_VFY("VFY: unable to resolve filled-array %d (%s) in %s", 4234 decInsn.vB, badClassDesc, meth->clazz->descriptor); 4235 assert(failure != VERIFY_ERROR_GENERIC); 4236 } else if (!dvmIsArrayClass(resClass)) { 4237 LOG_VFY("VFY: filled-new-array on non-array class"); 4238 failure = VERIFY_ERROR_GENERIC; 4239 } else { 4240 bool isRange = (decInsn.opcode == OP_FILLED_NEW_ARRAY_RANGE); 4241 4242 /* check the arguments to the instruction */ 4243 verifyFilledNewArrayRegs(meth, workLine, &decInsn, 4244 resClass, isRange, &failure); 4245 /* filled-array result goes into "result" register */ 4246 setResultRegisterType(workLine, insnRegCount, 4247 regTypeFromClass(resClass)); 4248 justSetResult = true; 4249 } 4250 break; 4251 4252 case OP_CMPL_FLOAT: 4253 case OP_CMPG_FLOAT: 4254 verifyRegisterType(workLine, decInsn.vB, kRegTypeFloat, &failure); 4255 verifyRegisterType(workLine, decInsn.vC, kRegTypeFloat, &failure); 4256 setRegisterType(workLine, decInsn.vA, kRegTypeBoolean); 4257 break; 4258 case OP_CMPL_DOUBLE: 4259 case OP_CMPG_DOUBLE: 4260 verifyRegisterType(workLine, decInsn.vB, kRegTypeDoubleLo, &failure); 4261 verifyRegisterType(workLine, decInsn.vC, kRegTypeDoubleLo, &failure); 4262 setRegisterType(workLine, decInsn.vA, kRegTypeBoolean); 4263 break; 4264 case OP_CMP_LONG: 4265 verifyRegisterType(workLine, decInsn.vB, kRegTypeLongLo, &failure); 4266 verifyRegisterType(workLine, decInsn.vC, kRegTypeLongLo, &failure); 4267 setRegisterType(workLine, decInsn.vA, kRegTypeBoolean); 4268 break; 4269 4270 case OP_THROW: 4271 resClass = getClassFromRegister(workLine, decInsn.vA, &failure); 4272 if (VERIFY_OK(failure) && resClass != NULL) { 4273 if (!dvmInstanceof(resClass, gDvm.exThrowable)) { 4274 LOG_VFY("VFY: thrown class %s not instanceof Throwable", 4275 resClass->descriptor); 4276 failure = VERIFY_ERROR_GENERIC; 4277 } 4278 } 4279 break; 4280 4281 case OP_GOTO: 4282 case OP_GOTO_16: 4283 case OP_GOTO_32: 4284 /* no effect on or use of registers */ 4285 break; 4286 4287 case OP_PACKED_SWITCH: 4288 case OP_SPARSE_SWITCH: 4289 /* verify that vAA is an integer, or can be converted to one */ 4290 verifyRegisterType(workLine, decInsn.vA, kRegTypeInteger, &failure); 4291 break; 4292 4293 case OP_FILL_ARRAY_DATA: 4294 { 4295 RegType valueType; 4296 const u2 *arrayData; 4297 u2 elemWidth; 4298 4299 /* Similar to the verification done for APUT */ 4300 resClass = getClassFromRegister(workLine, decInsn.vA, &failure); 4301 if (!VERIFY_OK(failure)) 4302 break; 4303 4304 /* resClass can be null if the reg type is Zero */ 4305 if (resClass == NULL) 4306 break; 4307 4308 if (!dvmIsArrayClass(resClass) || resClass->arrayDim != 1 || 4309 resClass->elementClass->primitiveType == PRIM_NOT || 4310 resClass->elementClass->primitiveType == PRIM_VOID) 4311 { 4312 LOG_VFY("VFY: invalid fill-array-data on %s", 4313 resClass->descriptor); 4314 failure = VERIFY_ERROR_GENERIC; 4315 break; 4316 } 4317 4318 valueType = primitiveTypeToRegType( 4319 resClass->elementClass->primitiveType); 4320 assert(valueType != kRegTypeUnknown); 4321 4322 /* 4323 * Now verify if the element width in the table matches the element 4324 * width declared in the array 4325 */ 4326 arrayData = insns + (insns[1] | (((s4)insns[2]) << 16)); 4327 if (arrayData[0] != kArrayDataSignature) { 4328 LOG_VFY("VFY: invalid magic for array-data"); 4329 failure = VERIFY_ERROR_GENERIC; 4330 break; 4331 } 4332 4333 switch (resClass->elementClass->primitiveType) { 4334 case PRIM_BOOLEAN: 4335 case PRIM_BYTE: 4336 elemWidth = 1; 4337 break; 4338 case PRIM_CHAR: 4339 case PRIM_SHORT: 4340 elemWidth = 2; 4341 break; 4342 case PRIM_FLOAT: 4343 case PRIM_INT: 4344 elemWidth = 4; 4345 break; 4346 case PRIM_DOUBLE: 4347 case PRIM_LONG: 4348 elemWidth = 8; 4349 break; 4350 default: 4351 elemWidth = 0; 4352 break; 4353 } 4354 4355 /* 4356 * Since we don't compress the data in Dex, expect to see equal 4357 * width of data stored in the table and expected from the array 4358 * class. 4359 */ 4360 if (arrayData[1] != elemWidth) { 4361 LOG_VFY("VFY: array-data size mismatch (%d vs %d)", 4362 arrayData[1], elemWidth); 4363 failure = VERIFY_ERROR_GENERIC; 4364 } 4365 } 4366 break; 4367 4368 case OP_IF_EQ: 4369 case OP_IF_NE: 4370 { 4371 RegType type1, type2; 4372 4373 type1 = getRegisterType(workLine, decInsn.vA); 4374 type2 = getRegisterType(workLine, decInsn.vB); 4375 4376 /* both references? */ 4377 if (regTypeIsReference(type1) && regTypeIsReference(type2)) 4378 break; 4379 4380 /* both category-1nr? */ 4381 checkTypeCategory(type1, kTypeCategory1nr, &failure); 4382 checkTypeCategory(type2, kTypeCategory1nr, &failure); 4383 if (type1 == kRegTypeFloat || type2 == kRegTypeFloat) { 4384 failure = VERIFY_ERROR_GENERIC; 4385 } 4386 if (!VERIFY_OK(failure)) { 4387 LOG_VFY("VFY: args to if-eq/if-ne must both be refs or cat1"); 4388 break; 4389 } 4390 } 4391 break; 4392 case OP_IF_LT: 4393 case OP_IF_GE: 4394 case OP_IF_GT: 4395 case OP_IF_LE: 4396 tmpType = getRegisterType(workLine, decInsn.vA); 4397 checkTypeCategory(tmpType, kTypeCategory1nr, &failure); 4398 if (tmpType == kRegTypeFloat) { 4399 failure = VERIFY_ERROR_GENERIC; 4400 } 4401 if (!VERIFY_OK(failure)) { 4402 LOG_VFY("VFY: args to 'if' must be cat-1nr and not float"); 4403 break; 4404 } 4405 tmpType = getRegisterType(workLine, decInsn.vB); 4406 checkTypeCategory(tmpType, kTypeCategory1nr, &failure); 4407 if (tmpType == kRegTypeFloat) { 4408 failure = VERIFY_ERROR_GENERIC; 4409 } 4410 if (!VERIFY_OK(failure)) { 4411 LOG_VFY("VFY: args to 'if' must be cat-1nr and not float"); 4412 break; 4413 } 4414 break; 4415 case OP_IF_EQZ: 4416 case OP_IF_NEZ: 4417 tmpType = getRegisterType(workLine, decInsn.vA); 4418 if (regTypeIsReference(tmpType)) 4419 break; 4420 checkTypeCategory(tmpType, kTypeCategory1nr, &failure); 4421 if (tmpType == kRegTypeFloat) { 4422 failure = VERIFY_ERROR_GENERIC; 4423 } 4424 if (!VERIFY_OK(failure)) 4425 LOG_VFY("VFY: expected non-float cat-1 arg to if"); 4426 break; 4427 case OP_IF_LTZ: 4428 case OP_IF_GEZ: 4429 case OP_IF_GTZ: 4430 case OP_IF_LEZ: 4431 tmpType = getRegisterType(workLine, decInsn.vA); 4432 checkTypeCategory(tmpType, kTypeCategory1nr, &failure); 4433 if (tmpType == kRegTypeFloat) { 4434 failure = VERIFY_ERROR_GENERIC; 4435 } 4436 if (!VERIFY_OK(failure)) 4437 LOG_VFY("VFY: expected non-float cat-1 arg to if"); 4438 break; 4439 4440 case OP_AGET: 4441 tmpType = kRegTypeInteger; 4442 goto aget_1nr_common; 4443 case OP_AGET_BOOLEAN: 4444 tmpType = kRegTypeBoolean; 4445 goto aget_1nr_common; 4446 case OP_AGET_BYTE: 4447 tmpType = kRegTypeByte; 4448 goto aget_1nr_common; 4449 case OP_AGET_CHAR: 4450 tmpType = kRegTypeChar; 4451 goto aget_1nr_common; 4452 case OP_AGET_SHORT: 4453 tmpType = kRegTypeShort; 4454 goto aget_1nr_common; 4455 aget_1nr_common: 4456 { 4457 RegType srcType, indexType; 4458 4459 indexType = getRegisterType(workLine, decInsn.vC); 4460 checkArrayIndexType(meth, indexType, &failure); 4461 if (!VERIFY_OK(failure)) 4462 break; 4463 4464 resClass = getClassFromRegister(workLine, decInsn.vB, &failure); 4465 if (!VERIFY_OK(failure)) 4466 break; 4467 if (resClass != NULL) { 4468 /* verify the class */ 4469 if (!dvmIsArrayClass(resClass) || resClass->arrayDim != 1 || 4470 resClass->elementClass->primitiveType == PRIM_NOT) 4471 { 4472 LOG_VFY("VFY: invalid aget-1nr target %s", 4473 resClass->descriptor); 4474 failure = VERIFY_ERROR_GENERIC; 4475 break; 4476 } 4477 4478 /* make sure array type matches instruction */ 4479 srcType = primitiveTypeToRegType( 4480 resClass->elementClass->primitiveType); 4481 4482 /* correct if float */ 4483 if (srcType == kRegTypeFloat && tmpType == kRegTypeInteger) 4484 tmpType = kRegTypeFloat; 4485 4486 if (!checkFieldArrayStore1nr(tmpType, srcType)) { 4487 LOG_VFY("VFY: invalid aget-1nr, array type=%d with" 4488 " inst type=%d (on %s)", 4489 srcType, tmpType, resClass->descriptor); 4490 failure = VERIFY_ERROR_GENERIC; 4491 break; 4492 } 4493 } else { 4494 /* 4495 * Null array ref; this code path will fail at runtime. Label 4496 * result as zero to allow it to remain mergeable. 4497 */ 4498 tmpType = kRegTypeZero; 4499 } 4500 setRegisterType(workLine, decInsn.vA, tmpType); 4501 } 4502 break; 4503 4504 case OP_AGET_WIDE: 4505 { 4506 RegType dstType, indexType; 4507 4508 indexType = getRegisterType(workLine, decInsn.vC); 4509 checkArrayIndexType(meth, indexType, &failure); 4510 if (!VERIFY_OK(failure)) 4511 break; 4512 4513 resClass = getClassFromRegister(workLine, decInsn.vB, &failure); 4514 if (!VERIFY_OK(failure)) 4515 break; 4516 if (resClass != NULL) { 4517 /* verify the class */ 4518 if (!dvmIsArrayClass(resClass) || resClass->arrayDim != 1 || 4519 resClass->elementClass->primitiveType == PRIM_NOT) 4520 { 4521 LOG_VFY("VFY: invalid aget-wide target %s", 4522 resClass->descriptor); 4523 failure = VERIFY_ERROR_GENERIC; 4524 break; 4525 } 4526 4527 /* try to refine "dstType" */ 4528 switch (resClass->elementClass->primitiveType) { 4529 case PRIM_LONG: 4530 dstType = kRegTypeLongLo; 4531 break; 4532 case PRIM_DOUBLE: 4533 dstType = kRegTypeDoubleLo; 4534 break; 4535 default: 4536 LOG_VFY("VFY: invalid aget-wide on %s", 4537 resClass->descriptor); 4538 dstType = kRegTypeUnknown; 4539 failure = VERIFY_ERROR_GENERIC; 4540 break; 4541 } 4542 } else { 4543 /* 4544 * Null array ref; this code path will fail at runtime. We 4545 * know this is either long or double, so label it const. 4546 */ 4547 dstType = kRegTypeConstLo; 4548 } 4549 setRegisterType(workLine, decInsn.vA, dstType); 4550 } 4551 break; 4552 4553 case OP_AGET_OBJECT: 4554 { 4555 RegType dstType, indexType; 4556 4557 indexType = getRegisterType(workLine, decInsn.vC); 4558 checkArrayIndexType(meth, indexType, &failure); 4559 if (!VERIFY_OK(failure)) 4560 break; 4561 4562 /* get the class of the array we're pulling an object from */ 4563 resClass = getClassFromRegister(workLine, decInsn.vB, &failure); 4564 if (!VERIFY_OK(failure)) 4565 break; 4566 if (resClass != NULL) { 4567 ClassObject* elementClass; 4568 4569 assert(resClass != NULL); 4570 if (!dvmIsArrayClass(resClass)) { 4571 LOG_VFY("VFY: aget-object on non-array class"); 4572 failure = VERIFY_ERROR_GENERIC; 4573 break; 4574 } 4575 assert(resClass->elementClass != NULL); 4576 4577 /* 4578 * Find the element class. resClass->elementClass indicates 4579 * the basic type, which won't be what we want for a 4580 * multi-dimensional array. 4581 */ 4582 if (resClass->descriptor[1] == '[') { 4583 assert(resClass->arrayDim > 1); 4584 elementClass = dvmFindArrayClass(&resClass->descriptor[1], 4585 resClass->classLoader); 4586 } else if (resClass->descriptor[1] == 'L') { 4587 assert(resClass->arrayDim == 1); 4588 elementClass = resClass->elementClass; 4589 } else { 4590 LOG_VFY("VFY: aget-object on non-ref array class (%s)", 4591 resClass->descriptor); 4592 failure = VERIFY_ERROR_GENERIC; 4593 break; 4594 } 4595 4596 dstType = regTypeFromClass(elementClass); 4597 } else { 4598 /* 4599 * The array reference is NULL, so the current code path will 4600 * throw an exception. For proper merging with later code 4601 * paths, and correct handling of "if-eqz" tests on the 4602 * result of the array get, we want to treat this as a null 4603 * reference. 4604 */ 4605 dstType = kRegTypeZero; 4606 } 4607 setRegisterType(workLine, decInsn.vA, dstType); 4608 } 4609 break; 4610 case OP_APUT: 4611 tmpType = kRegTypeInteger; 4612 goto aput_1nr_common; 4613 case OP_APUT_BOOLEAN: 4614 tmpType = kRegTypeBoolean; 4615 goto aput_1nr_common; 4616 case OP_APUT_BYTE: 4617 tmpType = kRegTypeByte; 4618 goto aput_1nr_common; 4619 case OP_APUT_CHAR: 4620 tmpType = kRegTypeChar; 4621 goto aput_1nr_common; 4622 case OP_APUT_SHORT: 4623 tmpType = kRegTypeShort; 4624 goto aput_1nr_common; 4625 aput_1nr_common: 4626 { 4627 RegType srcType, dstType, indexType; 4628 4629 indexType = getRegisterType(workLine, decInsn.vC); 4630 checkArrayIndexType(meth, indexType, &failure); 4631 if (!VERIFY_OK(failure)) 4632 break; 4633 4634 srcType = getRegisterType(workLine, decInsn.vA); 4635 4636 /* correct if float */ 4637 if (srcType == kRegTypeFloat && tmpType == kRegTypeInteger) 4638 tmpType = kRegTypeFloat; 4639 4640 /* make sure the source register has the correct type */ 4641 if (!canConvertTo1nr(srcType, tmpType)) { 4642 LOG_VFY("VFY: invalid reg type %d on aput instr (need %d)", 4643 srcType, tmpType); 4644 failure = VERIFY_ERROR_GENERIC; 4645 break; 4646 } 4647 4648 resClass = getClassFromRegister(workLine, decInsn.vB, &failure); 4649 if (!VERIFY_OK(failure)) 4650 break; 4651 4652 /* resClass can be null if the reg type is Zero */ 4653 if (resClass == NULL) 4654 break; 4655 4656 if (!dvmIsArrayClass(resClass) || resClass->arrayDim != 1 || 4657 resClass->elementClass->primitiveType == PRIM_NOT) 4658 { 4659 LOG_VFY("VFY: invalid aput-1nr on %s", resClass->descriptor); 4660 failure = VERIFY_ERROR_GENERIC; 4661 break; 4662 } 4663 4664 /* verify that instruction matches array */ 4665 dstType = primitiveTypeToRegType( 4666 resClass->elementClass->primitiveType); 4667 4668 /* correct if float */ 4669 if (dstType == kRegTypeFloat && tmpType == kRegTypeInteger) 4670 tmpType = kRegTypeFloat; 4671 4672 verifyRegisterType(workLine, decInsn.vA, dstType, &failure); 4673 4674 if (dstType == kRegTypeUnknown || 4675 !checkFieldArrayStore1nr(tmpType, dstType)) { 4676 LOG_VFY("VFY: invalid aput-1nr on %s (inst=%d dst=%d)", 4677 resClass->descriptor, tmpType, dstType); 4678 failure = VERIFY_ERROR_GENERIC; 4679 break; 4680 } 4681 } 4682 break; 4683 case OP_APUT_WIDE: 4684 tmpType = getRegisterType(workLine, decInsn.vC); 4685 checkArrayIndexType(meth, tmpType, &failure); 4686 if (!VERIFY_OK(failure)) 4687 break; 4688 4689 resClass = getClassFromRegister(workLine, decInsn.vB, &failure); 4690 if (!VERIFY_OK(failure)) 4691 break; 4692 if (resClass != NULL) { 4693 /* verify the class and try to refine "dstType" */ 4694 if (!dvmIsArrayClass(resClass) || resClass->arrayDim != 1 || 4695 resClass->elementClass->primitiveType == PRIM_NOT) 4696 { 4697 LOG_VFY("VFY: invalid aput-wide on %s", 4698 resClass->descriptor); 4699 failure = VERIFY_ERROR_GENERIC; 4700 break; 4701 } 4702 4703 switch (resClass->elementClass->primitiveType) { 4704 case PRIM_LONG: 4705 verifyRegisterType(workLine, decInsn.vA, kRegTypeLongLo, &failure); 4706 break; 4707 case PRIM_DOUBLE: 4708 verifyRegisterType(workLine, decInsn.vA, kRegTypeDoubleLo, &failure); 4709 break; 4710 default: 4711 LOG_VFY("VFY: invalid aput-wide on %s", 4712 resClass->descriptor); 4713 failure = VERIFY_ERROR_GENERIC; 4714 break; 4715 } 4716 } 4717 break; 4718 case OP_APUT_OBJECT: 4719 tmpType = getRegisterType(workLine, decInsn.vC); 4720 checkArrayIndexType(meth, tmpType, &failure); 4721 if (!VERIFY_OK(failure)) 4722 break; 4723 4724 /* get the ref we're storing; Zero is okay, Uninit is not */ 4725 resClass = getClassFromRegister(workLine, decInsn.vA, &failure); 4726 if (!VERIFY_OK(failure)) 4727 break; 4728 if (resClass != NULL) { 4729 ClassObject* arrayClass; 4730 ClassObject* elementClass; 4731 4732 /* 4733 * Get the array class. If the array ref is null, we won't 4734 * have type information (and we'll crash at runtime with a 4735 * null pointer exception). 4736 */ 4737 arrayClass = getClassFromRegister(workLine, decInsn.vB, &failure); 4738 4739 if (arrayClass != NULL) { 4740 /* see if the array holds a compatible type */ 4741 if (!dvmIsArrayClass(arrayClass)) { 4742 LOG_VFY("VFY: invalid aput-object on %s", 4743 arrayClass->descriptor); 4744 failure = VERIFY_ERROR_GENERIC; 4745 break; 4746 } 4747 4748 /* 4749 * Find the element class. resClass->elementClass indicates 4750 * the basic type, which won't be what we want for a 4751 * multi-dimensional array. 4752 * 4753 * All we want to check here is that the element type is a 4754 * reference class. We *don't* check instanceof here, because 4755 * you can still put a String into a String[] after the latter 4756 * has been cast to an Object[]. 4757 */ 4758 if (arrayClass->descriptor[1] == '[') { 4759 assert(arrayClass->arrayDim > 1); 4760 elementClass = dvmFindArrayClass(&arrayClass->descriptor[1], 4761 arrayClass->classLoader); 4762 } else { 4763 assert(arrayClass->arrayDim == 1); 4764 elementClass = arrayClass->elementClass; 4765 } 4766 if (elementClass->primitiveType != PRIM_NOT) { 4767 LOG_VFY("VFY: invalid aput-object of %s into %s", 4768 resClass->descriptor, arrayClass->descriptor); 4769 failure = VERIFY_ERROR_GENERIC; 4770 break; 4771 } 4772 } 4773 } 4774 break; 4775 4776 case OP_IGET: 4777 tmpType = kRegTypeInteger; 4778 goto iget_1nr_common; 4779 case OP_IGET_BOOLEAN: 4780 tmpType = kRegTypeBoolean; 4781 goto iget_1nr_common; 4782 case OP_IGET_BYTE: 4783 tmpType = kRegTypeByte; 4784 goto iget_1nr_common; 4785 case OP_IGET_CHAR: 4786 tmpType = kRegTypeChar; 4787 goto iget_1nr_common; 4788 case OP_IGET_SHORT: 4789 tmpType = kRegTypeShort; 4790 goto iget_1nr_common; 4791 iget_1nr_common: 4792 { 4793 InstField* instField; 4794 RegType objType, fieldType; 4795 4796 objType = getRegisterType(workLine, decInsn.vB); 4797 instField = getInstField(meth, uninitMap, objType, decInsn.vC, 4798 &failure); 4799 if (!VERIFY_OK(failure)) 4800 break; 4801 4802 /* make sure the field's type is compatible with expectation */ 4803 fieldType = primSigCharToRegType(instField->signature[0]); 4804 4805 /* correct if float */ 4806 if (fieldType == kRegTypeFloat && tmpType == kRegTypeInteger) 4807 tmpType = kRegTypeFloat; 4808 4809 if (fieldType == kRegTypeUnknown || 4810 !checkFieldArrayStore1nr(tmpType, fieldType)) 4811 { 4812 LOG_VFY("VFY: invalid iget-1nr of %s.%s (inst=%d field=%d)", 4813 instField->clazz->descriptor, 4814 instField->name, tmpType, fieldType); 4815 failure = VERIFY_ERROR_GENERIC; 4816 break; 4817 } 4818 4819 setRegisterType(workLine, decInsn.vA, tmpType); 4820 } 4821 break; 4822 case OP_IGET_WIDE: 4823 { 4824 RegType dstType; 4825 InstField* instField; 4826 RegType objType; 4827 4828 objType = getRegisterType(workLine, decInsn.vB); 4829 instField = getInstField(meth, uninitMap, objType, decInsn.vC, 4830 &failure); 4831 if (!VERIFY_OK(failure)) 4832 break; 4833 /* check the type, which should be prim */ 4834 switch (instField->signature[0]) { 4835 case 'D': 4836 dstType = kRegTypeDoubleLo; 4837 break; 4838 case 'J': 4839 dstType = kRegTypeLongLo; 4840 break; 4841 default: 4842 LOG_VFY("VFY: invalid iget-wide of %s.%s", 4843 instField->clazz->descriptor, 4844 instField->name); 4845 dstType = kRegTypeUnknown; 4846 failure = VERIFY_ERROR_GENERIC; 4847 break; 4848 } 4849 if (VERIFY_OK(failure)) { 4850 setRegisterType(workLine, decInsn.vA, dstType); 4851 } 4852 } 4853 break; 4854 case OP_IGET_OBJECT: 4855 { 4856 ClassObject* fieldClass; 4857 InstField* instField; 4858 RegType objType; 4859 4860 objType = getRegisterType(workLine, decInsn.vB); 4861 instField = getInstField(meth, uninitMap, objType, decInsn.vC, 4862 &failure); 4863 if (!VERIFY_OK(failure)) 4864 break; 4865 fieldClass = getFieldClass(meth, instField); 4866 if (fieldClass == NULL) { 4867 /* class not found or primitive type */ 4868 LOG_VFY("VFY: unable to recover field class from '%s'", 4869 instField->signature); 4870 failure = VERIFY_ERROR_GENERIC; 4871 break; 4872 } 4873 if (VERIFY_OK(failure)) { 4874 assert(!dvmIsPrimitiveClass(fieldClass)); 4875 setRegisterType(workLine, decInsn.vA, 4876 regTypeFromClass(fieldClass)); 4877 } 4878 } 4879 break; 4880 case OP_IPUT: 4881 tmpType = kRegTypeInteger; 4882 goto iput_1nr_common; 4883 case OP_IPUT_BOOLEAN: 4884 tmpType = kRegTypeBoolean; 4885 goto iput_1nr_common; 4886 case OP_IPUT_BYTE: 4887 tmpType = kRegTypeByte; 4888 goto iput_1nr_common; 4889 case OP_IPUT_CHAR: 4890 tmpType = kRegTypeChar; 4891 goto iput_1nr_common; 4892 case OP_IPUT_SHORT: 4893 tmpType = kRegTypeShort; 4894 goto iput_1nr_common; 4895 iput_1nr_common: 4896 { 4897 RegType srcType, fieldType, objType; 4898 InstField* instField; 4899 4900 srcType = getRegisterType(workLine, decInsn.vA); 4901 4902 /* 4903 * javac generates synthetic functions that write byte values 4904 * into boolean fields. 4905 */ 4906 if (tmpType == kRegTypeBoolean && srcType == kRegTypeByte) 4907 tmpType = kRegTypeByte; 4908 4909 /* correct if float */ 4910 if (srcType == kRegTypeFloat && tmpType == kRegTypeInteger) 4911 tmpType = kRegTypeFloat; 4912 4913 /* make sure the source register has the correct type */ 4914 if (!canConvertTo1nr(srcType, tmpType)) { 4915 LOG_VFY("VFY: invalid reg type %d on iput instr (need %d)", 4916 srcType, tmpType); 4917 failure = VERIFY_ERROR_GENERIC; 4918 break; 4919 } 4920 4921 objType = getRegisterType(workLine, decInsn.vB); 4922 instField = getInstField(meth, uninitMap, objType, decInsn.vC, 4923 &failure); 4924 if (!VERIFY_OK(failure)) 4925 break; 4926 checkFinalFieldAccess(meth, instField, &failure); 4927 if (!VERIFY_OK(failure)) 4928 break; 4929 4930 /* get type of field we're storing into */ 4931 fieldType = primSigCharToRegType(instField->signature[0]); 4932 4933 /* correct if float */ 4934 if (fieldType == kRegTypeFloat && tmpType == kRegTypeInteger) 4935 tmpType = kRegTypeFloat; 4936 4937 if (fieldType == kRegTypeBoolean && srcType == kRegTypeByte) 4938 fieldType = kRegTypeByte; 4939 4940 verifyRegisterType(workLine, decInsn.vA, fieldType, &failure); 4941 4942 if (fieldType == kRegTypeUnknown || 4943 !checkFieldArrayStore1nr(tmpType, fieldType)) 4944 { 4945 LOG_VFY("VFY: invalid iput-1nr of %s.%s (inst=%d field=%d)", 4946 instField->clazz->descriptor, 4947 instField->name, tmpType, fieldType); 4948 failure = VERIFY_ERROR_GENERIC; 4949 break; 4950 } 4951 } 4952 break; 4953 case OP_IPUT_WIDE: 4954 tmpType = getRegisterType(workLine, decInsn.vA); 4955 { 4956 RegType typeHi = getRegisterType(workLine, decInsn.vA + 1); 4957 checkTypeCategory(tmpType, kTypeCategory2, &failure); 4958 checkWidePair(tmpType, typeHi, &failure); 4959 } 4960 if (!VERIFY_OK(failure)) 4961 break; 4962 4963 InstField* instField; 4964 RegType objType; 4965 4966 objType = getRegisterType(workLine, decInsn.vB); 4967 instField = getInstField(meth, uninitMap, objType, decInsn.vC, 4968 &failure); 4969 if (!VERIFY_OK(failure)) 4970 break; 4971 checkFinalFieldAccess(meth, instField, &failure); 4972 if (!VERIFY_OK(failure)) 4973 break; 4974 4975 /* check the type, which should be prim */ 4976 switch (instField->signature[0]) { 4977 case 'D': 4978 verifyRegisterType(workLine, decInsn.vA, kRegTypeDoubleLo, &failure); 4979 break; 4980 case 'J': 4981 verifyRegisterType(workLine, decInsn.vA, kRegTypeLongLo, &failure); 4982 break; 4983 default: 4984 LOG_VFY("VFY: invalid iput-wide of %s.%s", 4985 instField->clazz->descriptor, 4986 instField->name); 4987 failure = VERIFY_ERROR_GENERIC; 4988 break; 4989 } 4990 break; 4991 case OP_IPUT_OBJECT: 4992 { 4993 ClassObject* fieldClass; 4994 ClassObject* valueClass; 4995 InstField* instField; 4996 RegType objType, valueType; 4997 4998 objType = getRegisterType(workLine, decInsn.vB); 4999 instField = getInstField(meth, uninitMap, objType, decInsn.vC, 5000 &failure); 5001 if (!VERIFY_OK(failure)) 5002 break; 5003 checkFinalFieldAccess(meth, instField, &failure); 5004 if (!VERIFY_OK(failure)) 5005 break; 5006 5007 fieldClass = getFieldClass(meth, instField); 5008 if (fieldClass == NULL) { 5009 LOG_VFY("VFY: unable to recover field class from '%s'", 5010 instField->signature); 5011 failure = VERIFY_ERROR_GENERIC; 5012 break; 5013 } 5014 5015 valueType = getRegisterType(workLine, decInsn.vA); 5016 if (!regTypeIsReference(valueType)) { 5017 LOG_VFY("VFY: storing non-ref v%d into ref field '%s' (%s)", 5018 decInsn.vA, instField->name, 5019 fieldClass->descriptor); 5020 failure = VERIFY_ERROR_GENERIC; 5021 break; 5022 } 5023 if (valueType != kRegTypeZero) { 5024 valueClass = regTypeInitializedReferenceToClass(valueType); 5025 if (valueClass == NULL) { 5026 LOG_VFY("VFY: storing uninit ref v%d into ref field", 5027 decInsn.vA); 5028 failure = VERIFY_ERROR_GENERIC; 5029 break; 5030 } 5031 /* allow if field is any interface or field is base class */ 5032 if (!dvmIsInterfaceClass(fieldClass) && 5033 !dvmInstanceof(valueClass, fieldClass)) 5034 { 5035 LOG_VFY("VFY: storing type '%s' into field type '%s' (%s.%s)", 5036 valueClass->descriptor, fieldClass->descriptor, 5037 instField->clazz->descriptor, 5038 instField->name); 5039 failure = VERIFY_ERROR_GENERIC; 5040 break; 5041 } 5042 } 5043 } 5044 break; 5045 5046 case OP_SGET: 5047 tmpType = kRegTypeInteger; 5048 goto sget_1nr_common; 5049 case OP_SGET_BOOLEAN: 5050 tmpType = kRegTypeBoolean; 5051 goto sget_1nr_common; 5052 case OP_SGET_BYTE: 5053 tmpType = kRegTypeByte; 5054 goto sget_1nr_common; 5055 case OP_SGET_CHAR: 5056 tmpType = kRegTypeChar; 5057 goto sget_1nr_common; 5058 case OP_SGET_SHORT: 5059 tmpType = kRegTypeShort; 5060 goto sget_1nr_common; 5061 sget_1nr_common: 5062 { 5063 StaticField* staticField; 5064 RegType fieldType; 5065 5066 staticField = getStaticField(meth, decInsn.vB, &failure); 5067 if (!VERIFY_OK(failure)) 5068 break; 5069 5070 /* 5071 * Make sure the field's type is compatible with expectation. 5072 * We can get ourselves into trouble if we mix & match loads 5073 * and stores with different widths, so rather than just checking 5074 * "canConvertTo1nr" we require that the field types have equal 5075 * widths. 5076 */ 5077 fieldType = primSigCharToRegType(staticField->signature[0]); 5078 5079 /* correct if float */ 5080 if (fieldType == kRegTypeFloat && tmpType == kRegTypeInteger) 5081 tmpType = kRegTypeFloat; 5082 5083 if (!checkFieldArrayStore1nr(tmpType, fieldType)) { 5084 LOG_VFY("VFY: invalid sget-1nr of %s.%s (inst=%d actual=%d)", 5085 staticField->clazz->descriptor, 5086 staticField->name, tmpType, fieldType); 5087 failure = VERIFY_ERROR_GENERIC; 5088 break; 5089 } 5090 5091 setRegisterType(workLine, decInsn.vA, tmpType); 5092 } 5093 break; 5094 case OP_SGET_WIDE: 5095 { 5096 StaticField* staticField; 5097 RegType dstType; 5098 5099 staticField = getStaticField(meth, decInsn.vB, &failure); 5100 if (!VERIFY_OK(failure)) 5101 break; 5102 /* check the type, which should be prim */ 5103 switch (staticField->signature[0]) { 5104 case 'D': 5105 dstType = kRegTypeDoubleLo; 5106 break; 5107 case 'J': 5108 dstType = kRegTypeLongLo; 5109 break; 5110 default: 5111 LOG_VFY("VFY: invalid sget-wide of %s.%s", 5112 staticField->clazz->descriptor, 5113 staticField->name); 5114 dstType = kRegTypeUnknown; 5115 failure = VERIFY_ERROR_GENERIC; 5116 break; 5117 } 5118 if (VERIFY_OK(failure)) { 5119 setRegisterType(workLine, decInsn.vA, dstType); 5120 } 5121 } 5122 break; 5123 case OP_SGET_OBJECT: 5124 { 5125 StaticField* staticField; 5126 ClassObject* fieldClass; 5127 5128 staticField = getStaticField(meth, decInsn.vB, &failure); 5129 if (!VERIFY_OK(failure)) 5130 break; 5131 fieldClass = getFieldClass(meth, staticField); 5132 if (fieldClass == NULL) { 5133 LOG_VFY("VFY: unable to recover field class from '%s'", 5134 staticField->signature); 5135 failure = VERIFY_ERROR_GENERIC; 5136 break; 5137 } 5138 if (dvmIsPrimitiveClass(fieldClass)) { 5139 LOG_VFY("VFY: attempt to get prim field with sget-object"); 5140 failure = VERIFY_ERROR_GENERIC; 5141 break; 5142 } 5143 setRegisterType(workLine, decInsn.vA, regTypeFromClass(fieldClass)); 5144 } 5145 break; 5146 case OP_SPUT: 5147 tmpType = kRegTypeInteger; 5148 goto sput_1nr_common; 5149 case OP_SPUT_BOOLEAN: 5150 tmpType = kRegTypeBoolean; 5151 goto sput_1nr_common; 5152 case OP_SPUT_BYTE: 5153 tmpType = kRegTypeByte; 5154 goto sput_1nr_common; 5155 case OP_SPUT_CHAR: 5156 tmpType = kRegTypeChar; 5157 goto sput_1nr_common; 5158 case OP_SPUT_SHORT: 5159 tmpType = kRegTypeShort; 5160 goto sput_1nr_common; 5161 sput_1nr_common: 5162 { 5163 RegType srcType, fieldType; 5164 StaticField* staticField; 5165 5166 srcType = getRegisterType(workLine, decInsn.vA); 5167 5168 /* 5169 * javac generates synthetic functions that write byte values 5170 * into boolean fields. 5171 */ 5172 if (tmpType == kRegTypeBoolean && srcType == kRegTypeByte) 5173 tmpType = kRegTypeByte; 5174 5175 /* correct if float */ 5176 if (srcType == kRegTypeFloat && tmpType == kRegTypeInteger) 5177 tmpType = kRegTypeFloat; 5178 5179 /* make sure the source register has the correct type */ 5180 if (!canConvertTo1nr(srcType, tmpType)) { 5181 LOG_VFY("VFY: invalid reg type %d on sput instr (need %d)", 5182 srcType, tmpType); 5183 failure = VERIFY_ERROR_GENERIC; 5184 break; 5185 } 5186 5187 staticField = getStaticField(meth, decInsn.vB, &failure); 5188 if (!VERIFY_OK(failure)) 5189 break; 5190 checkFinalFieldAccess(meth, staticField, &failure); 5191 if (!VERIFY_OK(failure)) 5192 break; 5193 5194 /* 5195 * Get type of field we're storing into. We know that the 5196 * contents of the register match the instruction, but we also 5197 * need to ensure that the instruction matches the field type. 5198 * Using e.g. sput-short to write into a 32-bit integer field 5199 * can lead to trouble if we do 16-bit writes. 5200 */ 5201 fieldType = primSigCharToRegType(staticField->signature[0]); 5202 5203 /* correct if float */ 5204 if (fieldType == kRegTypeFloat && tmpType == kRegTypeInteger) 5205 tmpType = kRegTypeFloat; 5206 5207 if (fieldType == kRegTypeBoolean && srcType == kRegTypeByte) 5208 fieldType = kRegTypeByte; 5209 5210 verifyRegisterType(workLine, decInsn.vA, fieldType, &failure); 5211 5212 if (fieldType == kRegTypeUnknown || 5213 !checkFieldArrayStore1nr(tmpType, fieldType)) { 5214 LOG_VFY("VFY: invalid sput-1nr of %s.%s (inst=%d actual=%d)", 5215 staticField->clazz->descriptor, 5216 staticField->name, tmpType, fieldType); 5217 failure = VERIFY_ERROR_GENERIC; 5218 break; 5219 } 5220 } 5221 break; 5222 case OP_SPUT_WIDE: 5223 tmpType = getRegisterType(workLine, decInsn.vA); 5224 { 5225 RegType typeHi = getRegisterType(workLine, decInsn.vA + 1); 5226 checkTypeCategory(tmpType, kTypeCategory2, &failure); 5227 checkWidePair(tmpType, typeHi, &failure); 5228 } 5229 if (!VERIFY_OK(failure)) 5230 break; 5231 5232 StaticField* staticField; 5233 5234 staticField = getStaticField(meth, decInsn.vB, &failure); 5235 if (!VERIFY_OK(failure)) 5236 break; 5237 checkFinalFieldAccess(meth, staticField, &failure); 5238 if (!VERIFY_OK(failure)) 5239 break; 5240 5241 /* check the type, which should be prim */ 5242 switch (staticField->signature[0]) { 5243 case 'D': 5244 verifyRegisterType(workLine, decInsn.vA, kRegTypeDoubleLo, &failure); 5245 break; 5246 case 'J': 5247 verifyRegisterType(workLine, decInsn.vA, kRegTypeLongLo, &failure); 5248 break; 5249 default: 5250 LOG_VFY("VFY: invalid sput-wide of %s.%s", 5251 staticField->clazz->descriptor, 5252 staticField->name); 5253 failure = VERIFY_ERROR_GENERIC; 5254 break; 5255 } 5256 break; 5257 case OP_SPUT_OBJECT: 5258 { 5259 ClassObject* fieldClass; 5260 ClassObject* valueClass; 5261 StaticField* staticField; 5262 RegType valueType; 5263 5264 staticField = getStaticField(meth, decInsn.vB, &failure); 5265 if (!VERIFY_OK(failure)) 5266 break; 5267 checkFinalFieldAccess(meth, staticField, &failure); 5268 if (!VERIFY_OK(failure)) 5269 break; 5270 5271 fieldClass = getFieldClass(meth, staticField); 5272 if (fieldClass == NULL) { 5273 LOG_VFY("VFY: unable to recover field class from '%s'", 5274 staticField->signature); 5275 failure = VERIFY_ERROR_GENERIC; 5276 break; 5277 } 5278 5279 valueType = getRegisterType(workLine, decInsn.vA); 5280 if (!regTypeIsReference(valueType)) { 5281 LOG_VFY("VFY: storing non-ref v%d into ref field '%s' (%s)", 5282 decInsn.vA, staticField->name, 5283 fieldClass->descriptor); 5284 failure = VERIFY_ERROR_GENERIC; 5285 break; 5286 } 5287 if (valueType != kRegTypeZero) { 5288 valueClass = regTypeInitializedReferenceToClass(valueType); 5289 if (valueClass == NULL) { 5290 LOG_VFY("VFY: storing uninit ref v%d into ref field", 5291 decInsn.vA); 5292 failure = VERIFY_ERROR_GENERIC; 5293 break; 5294 } 5295 /* allow if field is any interface or field is base class */ 5296 if (!dvmIsInterfaceClass(fieldClass) && 5297 !dvmInstanceof(valueClass, fieldClass)) 5298 { 5299 LOG_VFY("VFY: storing type '%s' into field type '%s' (%s.%s)", 5300 valueClass->descriptor, fieldClass->descriptor, 5301 staticField->clazz->descriptor, 5302 staticField->name); 5303 failure = VERIFY_ERROR_GENERIC; 5304 break; 5305 } 5306 } 5307 } 5308 break; 5309 5310 case OP_INVOKE_VIRTUAL: 5311 case OP_INVOKE_VIRTUAL_RANGE: 5312 case OP_INVOKE_SUPER: 5313 case OP_INVOKE_SUPER_RANGE: 5314 { 5315 Method* calledMethod; 5316 RegType returnType; 5317 bool isRange; 5318 bool isSuper; 5319 5320 isRange = (decInsn.opcode == OP_INVOKE_VIRTUAL_RANGE || 5321 decInsn.opcode == OP_INVOKE_SUPER_RANGE); 5322 isSuper = (decInsn.opcode == OP_INVOKE_SUPER || 5323 decInsn.opcode == OP_INVOKE_SUPER_RANGE); 5324 5325 calledMethod = verifyInvocationArgs(meth, workLine, insnRegCount, 5326 &decInsn, uninitMap, METHOD_VIRTUAL, isRange, 5327 isSuper, &failure); 5328 if (!VERIFY_OK(failure)) 5329 break; 5330 returnType = getMethodReturnType(calledMethod); 5331 setResultRegisterType(workLine, insnRegCount, returnType); 5332 justSetResult = true; 5333 } 5334 break; 5335 case OP_INVOKE_DIRECT: 5336 case OP_INVOKE_DIRECT_RANGE: 5337 { 5338 RegType returnType; 5339 Method* calledMethod; 5340 bool isRange; 5341 5342 isRange = (decInsn.opcode == OP_INVOKE_DIRECT_RANGE); 5343 calledMethod = verifyInvocationArgs(meth, workLine, insnRegCount, 5344 &decInsn, uninitMap, METHOD_DIRECT, isRange, 5345 false, &failure); 5346 if (!VERIFY_OK(failure)) 5347 break; 5348 5349 /* 5350 * Some additional checks when calling <init>. We know from 5351 * the invocation arg check that the "this" argument is an 5352 * instance of calledMethod->clazz. Now we further restrict 5353 * that to require that calledMethod->clazz is the same as 5354 * this->clazz or this->super, allowing the latter only if 5355 * the "this" argument is the same as the "this" argument to 5356 * this method (which implies that we're in <init> ourselves). 5357 */ 5358 if (isInitMethod(calledMethod)) { 5359 RegType thisType; 5360 thisType = getInvocationThis(workLine, &decInsn, &failure); 5361 if (!VERIFY_OK(failure)) 5362 break; 5363 5364 /* no null refs allowed (?) */ 5365 if (thisType == kRegTypeZero) { 5366 LOG_VFY("VFY: unable to initialize null ref"); 5367 failure = VERIFY_ERROR_GENERIC; 5368 break; 5369 } 5370 5371 ClassObject* thisClass; 5372 5373 thisClass = regTypeReferenceToClass(thisType, uninitMap); 5374 assert(thisClass != NULL); 5375 5376 /* must be in same class or in superclass */ 5377 if (calledMethod->clazz == thisClass->super) { 5378 if (thisClass != meth->clazz) { 5379 LOG_VFY("VFY: invoke-direct <init> on super only " 5380 "allowed for 'this' in <init>"); 5381 failure = VERIFY_ERROR_GENERIC; 5382 break; 5383 } 5384 } else if (calledMethod->clazz != thisClass) { 5385 LOG_VFY("VFY: invoke-direct <init> must be on current " 5386 "class or super"); 5387 failure = VERIFY_ERROR_GENERIC; 5388 break; 5389 } 5390 5391 /* arg must be an uninitialized reference */ 5392 if (!regTypeIsUninitReference(thisType)) { 5393 LOG_VFY("VFY: can only initialize the uninitialized"); 5394 failure = VERIFY_ERROR_GENERIC; 5395 break; 5396 } 5397 5398 /* 5399 * Replace the uninitialized reference with an initialized 5400 * one, and clear the entry in the uninit map. We need to 5401 * do this for all registers that have the same object 5402 * instance in them, not just the "this" register. 5403 */ 5404 markRefsAsInitialized(workLine, insnRegCount, uninitMap, 5405 thisType, &failure); 5406 if (!VERIFY_OK(failure)) 5407 break; 5408 } 5409 returnType = getMethodReturnType(calledMethod); 5410 setResultRegisterType(workLine, insnRegCount, returnType); 5411 justSetResult = true; 5412 } 5413 break; 5414 case OP_INVOKE_STATIC: 5415 case OP_INVOKE_STATIC_RANGE: 5416 { 5417 RegType returnType; 5418 Method* calledMethod; 5419 bool isRange; 5420 5421 isRange = (decInsn.opcode == OP_INVOKE_STATIC_RANGE); 5422 calledMethod = verifyInvocationArgs(meth, workLine, insnRegCount, 5423 &decInsn, uninitMap, METHOD_STATIC, isRange, 5424 false, &failure); 5425 if (!VERIFY_OK(failure)) 5426 break; 5427 5428 returnType = getMethodReturnType(calledMethod); 5429 setResultRegisterType(workLine, insnRegCount, returnType); 5430 justSetResult = true; 5431 } 5432 break; 5433 case OP_INVOKE_INTERFACE: 5434 case OP_INVOKE_INTERFACE_RANGE: 5435 { 5436 RegType /*thisType,*/ returnType; 5437 Method* absMethod; 5438 bool isRange; 5439 5440 isRange = (decInsn.opcode == OP_INVOKE_INTERFACE_RANGE); 5441 absMethod = verifyInvocationArgs(meth, workLine, insnRegCount, 5442 &decInsn, uninitMap, METHOD_INTERFACE, isRange, 5443 false, &failure); 5444 if (!VERIFY_OK(failure)) 5445 break; 5446 5447 #if 0 /* can't do this here, fails on dalvik test 052-verifier-fun */ 5448 /* 5449 * Get the type of the "this" arg, which should always be an 5450 * interface class. Because we don't do a full merge on 5451 * interface classes, this might have reduced to Object. 5452 */ 5453 thisType = getInvocationThis(workLine, &decInsn, &failure); 5454 if (!VERIFY_OK(failure)) 5455 break; 5456 5457 if (thisType == kRegTypeZero) { 5458 /* null pointer always passes (and always fails at runtime) */ 5459 } else { 5460 ClassObject* thisClass; 5461 5462 thisClass = regTypeInitializedReferenceToClass(thisType); 5463 if (thisClass == NULL) { 5464 LOG_VFY("VFY: interface call on uninitialized"); 5465 failure = VERIFY_ERROR_GENERIC; 5466 break; 5467 } 5468 5469 /* 5470 * Either "thisClass" needs to be the interface class that 5471 * defined absMethod, or absMethod's class needs to be one 5472 * of the interfaces implemented by "thisClass". (Or, if 5473 * we couldn't complete the merge, this will be Object.) 5474 */ 5475 if (thisClass != absMethod->clazz && 5476 thisClass != gDvm.classJavaLangObject && 5477 !dvmImplements(thisClass, absMethod->clazz)) 5478 { 5479 LOG_VFY("VFY: unable to match absMethod '%s' with %s interfaces", 5480 absMethod->name, thisClass->descriptor); 5481 failure = VERIFY_ERROR_GENERIC; 5482 break; 5483 } 5484 } 5485 #endif 5486 5487 /* 5488 * We don't have an object instance, so we can't find the 5489 * concrete method. However, all of the type information is 5490 * in the abstract method, so we're good. 5491 */ 5492 returnType = getMethodReturnType(absMethod); 5493 setResultRegisterType(workLine, insnRegCount, returnType); 5494 justSetResult = true; 5495 } 5496 break; 5497 5498 case OP_NEG_INT: 5499 case OP_NOT_INT: 5500 checkUnop(workLine, &decInsn, 5501 kRegTypeInteger, kRegTypeInteger, &failure); 5502 break; 5503 case OP_NEG_LONG: 5504 case OP_NOT_LONG: 5505 checkUnop(workLine, &decInsn, 5506 kRegTypeLongLo, kRegTypeLongLo, &failure); 5507 break; 5508 case OP_NEG_FLOAT: 5509 checkUnop(workLine, &decInsn, 5510 kRegTypeFloat, kRegTypeFloat, &failure); 5511 break; 5512 case OP_NEG_DOUBLE: 5513 checkUnop(workLine, &decInsn, 5514 kRegTypeDoubleLo, kRegTypeDoubleLo, &failure); 5515 break; 5516 case OP_INT_TO_LONG: 5517 checkUnop(workLine, &decInsn, 5518 kRegTypeLongLo, kRegTypeInteger, &failure); 5519 break; 5520 case OP_INT_TO_FLOAT: 5521 checkUnop(workLine, &decInsn, 5522 kRegTypeFloat, kRegTypeInteger, &failure); 5523 break; 5524 case OP_INT_TO_DOUBLE: 5525 checkUnop(workLine, &decInsn, 5526 kRegTypeDoubleLo, kRegTypeInteger, &failure); 5527 break; 5528 case OP_LONG_TO_INT: 5529 checkUnop(workLine, &decInsn, 5530 kRegTypeInteger, kRegTypeLongLo, &failure); 5531 break; 5532 case OP_LONG_TO_FLOAT: 5533 checkUnop(workLine, &decInsn, 5534 kRegTypeFloat, kRegTypeLongLo, &failure); 5535 break; 5536 case OP_LONG_TO_DOUBLE: 5537 checkUnop(workLine, &decInsn, 5538 kRegTypeDoubleLo, kRegTypeLongLo, &failure); 5539 break; 5540 case OP_FLOAT_TO_INT: 5541 checkUnop(workLine, &decInsn, 5542 kRegTypeInteger, kRegTypeFloat, &failure); 5543 break; 5544 case OP_FLOAT_TO_LONG: 5545 checkUnop(workLine, &decInsn, 5546 kRegTypeLongLo, kRegTypeFloat, &failure); 5547 break; 5548 case OP_FLOAT_TO_DOUBLE: 5549 checkUnop(workLine, &decInsn, 5550 kRegTypeDoubleLo, kRegTypeFloat, &failure); 5551 break; 5552 case OP_DOUBLE_TO_INT: 5553 checkUnop(workLine, &decInsn, 5554 kRegTypeInteger, kRegTypeDoubleLo, &failure); 5555 break; 5556 case OP_DOUBLE_TO_LONG: 5557 checkUnop(workLine, &decInsn, 5558 kRegTypeLongLo, kRegTypeDoubleLo, &failure); 5559 break; 5560 case OP_DOUBLE_TO_FLOAT: 5561 checkUnop(workLine, &decInsn, 5562 kRegTypeFloat, kRegTypeDoubleLo, &failure); 5563 break; 5564 case OP_INT_TO_BYTE: 5565 checkUnop(workLine, &decInsn, 5566 kRegTypeByte, kRegTypeInteger, &failure); 5567 break; 5568 case OP_INT_TO_CHAR: 5569 checkUnop(workLine, &decInsn, 5570 kRegTypeChar, kRegTypeInteger, &failure); 5571 break; 5572 case OP_INT_TO_SHORT: 5573 checkUnop(workLine, &decInsn, 5574 kRegTypeShort, kRegTypeInteger, &failure); 5575 break; 5576 5577 case OP_ADD_INT: 5578 case OP_SUB_INT: 5579 case OP_MUL_INT: 5580 case OP_REM_INT: 5581 case OP_DIV_INT: 5582 case OP_SHL_INT: 5583 case OP_SHR_INT: 5584 case OP_USHR_INT: 5585 checkBinop(workLine, &decInsn, 5586 kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, false, &failure); 5587 break; 5588 case OP_AND_INT: 5589 case OP_OR_INT: 5590 case OP_XOR_INT: 5591 checkBinop(workLine, &decInsn, 5592 kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, true, &failure); 5593 break; 5594 case OP_ADD_LONG: 5595 case OP_SUB_LONG: 5596 case OP_MUL_LONG: 5597 case OP_DIV_LONG: 5598 case OP_REM_LONG: 5599 case OP_AND_LONG: 5600 case OP_OR_LONG: 5601 case OP_XOR_LONG: 5602 checkBinop(workLine, &decInsn, 5603 kRegTypeLongLo, kRegTypeLongLo, kRegTypeLongLo, false, &failure); 5604 break; 5605 case OP_SHL_LONG: 5606 case OP_SHR_LONG: 5607 case OP_USHR_LONG: 5608 /* shift distance is Int, making these different from other binops */ 5609 checkBinop(workLine, &decInsn, 5610 kRegTypeLongLo, kRegTypeLongLo, kRegTypeInteger, false, &failure); 5611 break; 5612 case OP_ADD_FLOAT: 5613 case OP_SUB_FLOAT: 5614 case OP_MUL_FLOAT: 5615 case OP_DIV_FLOAT: 5616 case OP_REM_FLOAT: 5617 checkBinop(workLine, &decInsn, 5618 kRegTypeFloat, kRegTypeFloat, kRegTypeFloat, false, &failure); 5619 break; 5620 case OP_ADD_DOUBLE: 5621 case OP_SUB_DOUBLE: 5622 case OP_MUL_DOUBLE: 5623 case OP_DIV_DOUBLE: 5624 case OP_REM_DOUBLE: 5625 checkBinop(workLine, &decInsn, 5626 kRegTypeDoubleLo, kRegTypeDoubleLo, kRegTypeDoubleLo, false, 5627 &failure); 5628 break; 5629 case OP_ADD_INT_2ADDR: 5630 case OP_SUB_INT_2ADDR: 5631 case OP_MUL_INT_2ADDR: 5632 case OP_REM_INT_2ADDR: 5633 case OP_SHL_INT_2ADDR: 5634 case OP_SHR_INT_2ADDR: 5635 case OP_USHR_INT_2ADDR: 5636 checkBinop2addr(workLine, &decInsn, 5637 kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, false, &failure); 5638 break; 5639 case OP_AND_INT_2ADDR: 5640 case OP_OR_INT_2ADDR: 5641 case OP_XOR_INT_2ADDR: 5642 checkBinop2addr(workLine, &decInsn, 5643 kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, true, &failure); 5644 break; 5645 case OP_DIV_INT_2ADDR: 5646 checkBinop2addr(workLine, &decInsn, 5647 kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, false, &failure); 5648 break; 5649 case OP_ADD_LONG_2ADDR: 5650 case OP_SUB_LONG_2ADDR: 5651 case OP_MUL_LONG_2ADDR: 5652 case OP_DIV_LONG_2ADDR: 5653 case OP_REM_LONG_2ADDR: 5654 case OP_AND_LONG_2ADDR: 5655 case OP_OR_LONG_2ADDR: 5656 case OP_XOR_LONG_2ADDR: 5657 checkBinop2addr(workLine, &decInsn, 5658 kRegTypeLongLo, kRegTypeLongLo, kRegTypeLongLo, false, &failure); 5659 break; 5660 case OP_SHL_LONG_2ADDR: 5661 case OP_SHR_LONG_2ADDR: 5662 case OP_USHR_LONG_2ADDR: 5663 checkBinop2addr(workLine, &decInsn, 5664 kRegTypeLongLo, kRegTypeLongLo, kRegTypeInteger, false, &failure); 5665 break; 5666 case OP_ADD_FLOAT_2ADDR: 5667 case OP_SUB_FLOAT_2ADDR: 5668 case OP_MUL_FLOAT_2ADDR: 5669 case OP_DIV_FLOAT_2ADDR: 5670 case OP_REM_FLOAT_2ADDR: 5671 checkBinop2addr(workLine, &decInsn, 5672 kRegTypeFloat, kRegTypeFloat, kRegTypeFloat, false, &failure); 5673 break; 5674 case OP_ADD_DOUBLE_2ADDR: 5675 case OP_SUB_DOUBLE_2ADDR: 5676 case OP_MUL_DOUBLE_2ADDR: 5677 case OP_DIV_DOUBLE_2ADDR: 5678 case OP_REM_DOUBLE_2ADDR: 5679 checkBinop2addr(workLine, &decInsn, 5680 kRegTypeDoubleLo, kRegTypeDoubleLo, kRegTypeDoubleLo, false, 5681 &failure); 5682 break; 5683 case OP_ADD_INT_LIT16: 5684 case OP_RSUB_INT: 5685 case OP_MUL_INT_LIT16: 5686 case OP_DIV_INT_LIT16: 5687 case OP_REM_INT_LIT16: 5688 checkLitop(workLine, &decInsn, 5689 kRegTypeInteger, kRegTypeInteger, false, &failure); 5690 break; 5691 case OP_AND_INT_LIT16: 5692 case OP_OR_INT_LIT16: 5693 case OP_XOR_INT_LIT16: 5694 checkLitop(workLine, &decInsn, 5695 kRegTypeInteger, kRegTypeInteger, true, &failure); 5696 break; 5697 case OP_ADD_INT_LIT8: 5698 case OP_RSUB_INT_LIT8: 5699 case OP_MUL_INT_LIT8: 5700 case OP_DIV_INT_LIT8: 5701 case OP_REM_INT_LIT8: 5702 case OP_SHL_INT_LIT8: 5703 checkLitop(workLine, &decInsn, 5704 kRegTypeInteger, kRegTypeInteger, false, &failure); 5705 break; 5706 case OP_SHR_INT_LIT8: 5707 tmpType = adjustForRightShift(workLine, 5708 decInsn.vB, decInsn.vC, false, &failure); 5709 checkLitop(workLine, &decInsn, 5710 tmpType, kRegTypeInteger, false, &failure); 5711 break; 5712 case OP_USHR_INT_LIT8: 5713 tmpType = adjustForRightShift(workLine, 5714 decInsn.vB, decInsn.vC, true, &failure); 5715 checkLitop(workLine, &decInsn, 5716 tmpType, kRegTypeInteger, false, &failure); 5717 break; 5718 case OP_AND_INT_LIT8: 5719 case OP_OR_INT_LIT8: 5720 case OP_XOR_INT_LIT8: 5721 checkLitop(workLine, &decInsn, 5722 kRegTypeInteger, kRegTypeInteger, true, &failure); 5723 break; 5724 5725 /* 5726 * This falls into the general category of "optimized" instructions, 5727 * which don't generally appear during verification. Because it's 5728 * inserted in the course of verification, we can expect to see it here. 5729 */ 5730 case OP_THROW_VERIFICATION_ERROR: 5731 break; 5732 5733 /* 5734 * Verifying "quickened" instructions is tricky, because we have 5735 * discarded the original field/method information. The byte offsets 5736 * and vtable indices only have meaning in the context of an object 5737 * instance. 5738 * 5739 * If a piece of code declares a local reference variable, assigns 5740 * null to it, and then issues a virtual method call on it, we 5741 * cannot evaluate the method call during verification. This situation 5742 * isn't hard to handle, since we know the call will always result in an 5743 * NPE, and the arguments and return value don't matter. Any code that 5744 * depends on the result of the method call is inaccessible, so the 5745 * fact that we can't fully verify anything that comes after the bad 5746 * call is not a problem. 5747 * 5748 * We must also consider the case of multiple code paths, only some of 5749 * which involve a null reference. We can completely verify the method 5750 * if we sidestep the results of executing with a null reference. 5751 * For example, if on the first pass through the code we try to do a 5752 * virtual method invocation through a null ref, we have to skip the 5753 * method checks and have the method return a "wildcard" type (which 5754 * merges with anything to become that other thing). The move-result 5755 * will tell us if it's a reference, single-word numeric, or double-word 5756 * value. We continue to perform the verification, and at the end of 5757 * the function any invocations that were never fully exercised are 5758 * marked as null-only. 5759 * 5760 * We would do something similar for the field accesses. The field's 5761 * type, once known, can be used to recover the width of short integers. 5762 * If the object reference was null, the field-get returns the "wildcard" 5763 * type, which is acceptable for any operation. 5764 */ 5765 case OP_EXECUTE_INLINE: 5766 case OP_EXECUTE_INLINE_RANGE: 5767 case OP_IGET_QUICK: 5768 case OP_IGET_WIDE_QUICK: 5769 case OP_IGET_OBJECT_QUICK: 5770 case OP_IPUT_QUICK: 5771 case OP_IPUT_WIDE_QUICK: 5772 case OP_IPUT_OBJECT_QUICK: 5773 case OP_INVOKE_VIRTUAL_QUICK: 5774 case OP_INVOKE_VIRTUAL_QUICK_RANGE: 5775 case OP_INVOKE_SUPER_QUICK: 5776 case OP_INVOKE_SUPER_QUICK_RANGE: 5777 /* fall through to failure */ 5778 5779 /* 5780 * These instructions are equivalent (from the verifier's point of view) 5781 * to the original form. The change was made for correctness rather 5782 * than improved performance (except for invoke-object-init, which 5783 * provides both). The substitution takes place after verification 5784 * completes, though, so we don't expect to see them here. 5785 */ 5786 case OP_INVOKE_OBJECT_INIT_RANGE: 5787 case OP_RETURN_VOID_BARRIER: 5788 case OP_IGET_VOLATILE: 5789 case OP_IGET_WIDE_VOLATILE: 5790 case OP_IGET_OBJECT_VOLATILE: 5791 case OP_IPUT_VOLATILE: 5792 case OP_IPUT_WIDE_VOLATILE: 5793 case OP_IPUT_OBJECT_VOLATILE: 5794 case OP_SGET_VOLATILE: 5795 case OP_SGET_WIDE_VOLATILE: 5796 case OP_SGET_OBJECT_VOLATILE: 5797 case OP_SPUT_VOLATILE: 5798 case OP_SPUT_WIDE_VOLATILE: 5799 case OP_SPUT_OBJECT_VOLATILE: 5800 /* fall through to failure */ 5801 5802 /* these should never appear during verification */ 5803 case OP_UNUSED_3E: 5804 case OP_UNUSED_3F: 5805 case OP_UNUSED_40: 5806 case OP_UNUSED_41: 5807 case OP_UNUSED_42: 5808 case OP_UNUSED_43: 5809 case OP_UNUSED_73: 5810 case OP_UNUSED_79: 5811 case OP_UNUSED_7A: 5812 case OP_BREAKPOINT: 5813 case OP_UNUSED_FF: 5814 failure = VERIFY_ERROR_GENERIC; 5815 break; 5816 5817 /* 5818 * DO NOT add a "default" clause here. Without it the compiler will 5819 * complain if an instruction is missing (which is desirable). 5820 */ 5821 } 5822 5823 if (!VERIFY_OK(failure)) { 5824 if (failure == VERIFY_ERROR_GENERIC || gDvm.optimizing) { 5825 /* immediate failure, reject class */ 5826 LOG_VFY_METH(meth, "VFY: rejecting opcode 0x%02x at 0x%04x", 5827 decInsn.opcode, insnIdx); 5828 goto bail; 5829 } else { 5830 /* replace opcode and continue on */ 5831 ALOGD("VFY: replacing opcode 0x%02x at 0x%04x", 5832 decInsn.opcode, insnIdx); 5833 if (!replaceFailingInstruction(meth, insnFlags, insnIdx, failure)) { 5834 LOG_VFY_METH(meth, "VFY: rejecting opcode 0x%02x at 0x%04x", 5835 decInsn.opcode, insnIdx); 5836 goto bail; 5837 } 5838 /* IMPORTANT: meth->insns may have been changed */ 5839 insns = meth->insns + insnIdx; 5840 5841 /* continue on as if we just handled a throw-verification-error */ 5842 failure = VERIFY_ERROR_NONE; 5843 nextFlags = kInstrCanThrow; 5844 } 5845 } 5846 5847 /* 5848 * If we didn't just set the result register, clear it out. This 5849 * ensures that you can only use "move-result" immediately after the 5850 * result is set. (We could check this statically, but it's not 5851 * expensive and it makes our debugging output cleaner.) 5852 */ 5853 if (!justSetResult) { 5854 int reg = RESULT_REGISTER(insnRegCount); 5855 setRegisterType(workLine, reg, kRegTypeUnknown); 5856 setRegisterType(workLine, reg+1, kRegTypeUnknown); 5857 } 5858 5859 /* 5860 * Handle "continue". Tag the next consecutive instruction. 5861 */ 5862 if ((nextFlags & kInstrCanContinue) != 0) { 5863 int insnWidth = dvmInsnGetWidth(insnFlags, insnIdx); 5864 if (insnIdx+insnWidth >= insnsSize) { 5865 LOG_VFY_METH(meth, 5866 "VFY: execution can walk off end of code area (from %#x)", 5867 insnIdx); 5868 goto bail; 5869 } 5870 5871 /* 5872 * The only way to get to a move-exception instruction is to get 5873 * thrown there. Make sure the next instruction isn't one. 5874 */ 5875 if (!checkMoveException(meth, insnIdx+insnWidth, "next")) 5876 goto bail; 5877 5878 if (getRegisterLine(regTable, insnIdx+insnWidth)->regTypes != NULL) { 5879 /* 5880 * Merge registers into what we have for the next instruction, 5881 * and set the "changed" flag if needed. 5882 */ 5883 if (!updateRegisters(meth, insnFlags, regTable, insnIdx+insnWidth, 5884 workLine)) 5885 goto bail; 5886 } else { 5887 /* 5888 * We're not recording register data for the next instruction, 5889 * so we don't know what the prior state was. We have to 5890 * assume that something has changed and re-evaluate it. 5891 */ 5892 dvmInsnSetChanged(insnFlags, insnIdx+insnWidth, true); 5893 } 5894 } 5895 5896 /* 5897 * Handle "branch". Tag the branch target. 5898 * 5899 * NOTE: instructions like OP_EQZ provide information about the state 5900 * of the register when the branch is taken or not taken. For example, 5901 * somebody could get a reference field, check it for zero, and if the 5902 * branch is taken immediately store that register in a boolean field 5903 * since the value is known to be zero. We do not currently account for 5904 * that, and will reject the code. 5905 * 5906 * TODO: avoid re-fetching the branch target 5907 */ 5908 if ((nextFlags & kInstrCanBranch) != 0) { 5909 bool isConditional; 5910 5911 if (!dvmGetBranchOffset(meth, insnFlags, insnIdx, &branchTarget, 5912 &isConditional)) 5913 { 5914 /* should never happen after static verification */ 5915 LOG_VFY_METH(meth, "VFY: bad branch at %d", insnIdx); 5916 goto bail; 5917 } 5918 assert(isConditional || (nextFlags & kInstrCanContinue) == 0); 5919 assert(!isConditional || (nextFlags & kInstrCanContinue) != 0); 5920 5921 if (!checkMoveException(meth, insnIdx+branchTarget, "branch")) 5922 goto bail; 5923 5924 /* update branch target, set "changed" if appropriate */ 5925 if (!updateRegisters(meth, insnFlags, regTable, insnIdx+branchTarget, 5926 workLine)) 5927 goto bail; 5928 } 5929 5930 /* 5931 * Handle "switch". Tag all possible branch targets. 5932 * 5933 * We've already verified that the table is structurally sound, so we 5934 * just need to walk through and tag the targets. 5935 */ 5936 if ((nextFlags & kInstrCanSwitch) != 0) { 5937 int offsetToSwitch = insns[1] | (((s4)insns[2]) << 16); 5938 const u2* switchInsns = insns + offsetToSwitch; 5939 int switchCount = switchInsns[1]; 5940 int offsetToTargets, targ; 5941 5942 if ((*insns & 0xff) == OP_PACKED_SWITCH) { 5943 /* 0=sig, 1=count, 2/3=firstKey */ 5944 offsetToTargets = 4; 5945 } else { 5946 /* 0=sig, 1=count, 2..count*2 = keys */ 5947 assert((*insns & 0xff) == OP_SPARSE_SWITCH); 5948 offsetToTargets = 2 + 2*switchCount; 5949 } 5950 5951 /* verify each switch target */ 5952 for (targ = 0; targ < switchCount; targ++) { 5953 int offset, absOffset; 5954 5955 /* offsets are 32-bit, and only partly endian-swapped */ 5956 offset = switchInsns[offsetToTargets + targ*2] | 5957 (((s4) switchInsns[offsetToTargets + targ*2 +1]) << 16); 5958 absOffset = insnIdx + offset; 5959 5960 assert(absOffset >= 0 && absOffset < insnsSize); 5961 5962 if (!checkMoveException(meth, absOffset, "switch")) 5963 goto bail; 5964 5965 if (!updateRegisters(meth, insnFlags, regTable, absOffset, 5966 workLine)) 5967 goto bail; 5968 } 5969 } 5970 5971 /* 5972 * Handle instructions that can throw and that are sitting in a 5973 * "try" block. (If they're not in a "try" block when they throw, 5974 * control transfers out of the method.) 5975 */ 5976 if ((nextFlags & kInstrCanThrow) != 0 && dvmInsnIsInTry(insnFlags, insnIdx)) 5977 { 5978 const DexCode* pCode = dvmGetMethodCode(meth); 5979 DexCatchIterator iterator; 5980 bool hasCatchAll = false; 5981 5982 if (dexFindCatchHandler(&iterator, pCode, insnIdx)) { 5983 for (;;) { 5984 DexCatchHandler* handler = dexCatchIteratorNext(&iterator); 5985 5986 if (handler == NULL) { 5987 break; 5988 } 5989 5990 if (handler->typeIdx == kDexNoIndex) 5991 hasCatchAll = true; 5992 5993 /* 5994 * Merge registers into the "catch" block. We want to 5995 * use the "savedRegs" rather than "workRegs", because 5996 * at runtime the exception will be thrown before the 5997 * instruction modifies any registers. 5998 */ 5999 if (!updateRegisters(meth, insnFlags, regTable, 6000 handler->address, ®Table->savedLine)) 6001 goto bail; 6002 } 6003 } 6004 6005 /* 6006 * If the monitor stack depth is nonzero, there must be a "catch all" 6007 * handler for this instruction. This does apply to monitor-exit 6008 * because of async exception handling. 6009 */ 6010 if (workLine->monitorStackTop != 0 && !hasCatchAll) { 6011 /* 6012 * The state in workLine reflects the post-execution state. 6013 * If the current instruction is a monitor-enter and the monitor 6014 * stack was empty, we don't need a catch-all (if it throws, 6015 * it will do so before grabbing the lock). 6016 */ 6017 if (!(decInsn.opcode == OP_MONITOR_ENTER && 6018 workLine->monitorStackTop == 1)) 6019 { 6020 LOG_VFY_METH(meth, 6021 "VFY: no catch-all for instruction at 0x%04x", insnIdx); 6022 goto bail; 6023 } 6024 } 6025 } 6026 6027 /* 6028 * If we're returning from the method, make sure our monitor stack 6029 * is empty. 6030 */ 6031 if ((nextFlags & kInstrCanReturn) != 0 && workLine->monitorStackTop != 0) { 6032 LOG_VFY_METH(meth, "VFY: return with stack depth=%d at 0x%04x", 6033 workLine->monitorStackTop, insnIdx); 6034 goto bail; 6035 } 6036 6037 /* 6038 * Update startGuess. Advance to the next instruction of that's 6039 * possible, otherwise use the branch target if one was found. If 6040 * neither of those exists we're in a return or throw; leave startGuess 6041 * alone and let the caller sort it out. 6042 */ 6043 if ((nextFlags & kInstrCanContinue) != 0) { 6044 *pStartGuess = insnIdx + dvmInsnGetWidth(insnFlags, insnIdx); 6045 } else if ((nextFlags & kInstrCanBranch) != 0) { 6046 /* we're still okay if branchTarget is zero */ 6047 *pStartGuess = insnIdx + branchTarget; 6048 } 6049 6050 assert(*pStartGuess >= 0 && *pStartGuess < insnsSize && 6051 dvmInsnGetWidth(insnFlags, *pStartGuess) != 0); 6052 6053 result = true; 6054 6055 bail: 6056 return result; 6057 } 6058 6059 6060 /* 6061 * callback function used in dumpRegTypes to print local vars 6062 * valid at a given address. 6063 */ 6064 static void logLocalsCb(void *cnxt, u2 reg, u4 startAddress, u4 endAddress, 6065 const char *name, const char *descriptor, 6066 const char *signature) 6067 { 6068 int addr = *((int *)cnxt); 6069 6070 if (addr >= (int) startAddress && addr < (int) endAddress) 6071 { 6072 ALOGI(" %2d: '%s' %s", reg, name, descriptor); 6073 } 6074 } 6075 6076 /* 6077 * Dump the register types for the specifed address to the log file. 6078 */ 6079 static void dumpRegTypes(const VerifierData* vdata, 6080 const RegisterLine* registerLine, int addr, const char* addrName, 6081 const UninitInstanceMap* uninitMap, int displayFlags) 6082 { 6083 const Method* meth = vdata->method; 6084 const InsnFlags* insnFlags = vdata->insnFlags; 6085 const RegType* addrRegs = registerLine->regTypes; 6086 int regCount = meth->registersSize; 6087 int fullRegCount = regCount + kExtraRegs; 6088 bool branchTarget = dvmInsnIsBranchTarget(insnFlags, addr); 6089 int i; 6090 6091 assert(addr >= 0 && addr < (int) dvmGetMethodInsnsSize(meth)); 6092 6093 int regCharSize = fullRegCount + (fullRegCount-1)/4 + 2 +1; 6094 char regChars[regCharSize +1]; 6095 memset(regChars, ' ', regCharSize); 6096 regChars[0] = '['; 6097 if (regCount == 0) 6098 regChars[1] = ']'; 6099 else 6100 regChars[1 + (regCount-1) + (regCount-1)/4 +1] = ']'; 6101 regChars[regCharSize] = '\0'; 6102 6103 for (i = 0; i < regCount + kExtraRegs; i++) { 6104 char tch; 6105 6106 switch (addrRegs[i]) { 6107 case kRegTypeUnknown: tch = '.'; break; 6108 case kRegTypeConflict: tch = 'X'; break; 6109 case kRegTypeZero: tch = '0'; break; 6110 case kRegTypeOne: tch = '1'; break; 6111 case kRegTypeBoolean: tch = 'Z'; break; 6112 case kRegTypeConstPosByte: tch = 'y'; break; 6113 case kRegTypeConstByte: tch = 'Y'; break; 6114 case kRegTypeConstPosShort: tch = 'h'; break; 6115 case kRegTypeConstShort: tch = 'H'; break; 6116 case kRegTypeConstChar: tch = 'c'; break; 6117 case kRegTypeConstInteger: tch = 'i'; break; 6118 case kRegTypePosByte: tch = 'b'; break; 6119 case kRegTypeByte: tch = 'B'; break; 6120 case kRegTypePosShort: tch = 's'; break; 6121 case kRegTypeShort: tch = 'S'; break; 6122 case kRegTypeChar: tch = 'C'; break; 6123 case kRegTypeInteger: tch = 'I'; break; 6124 case kRegTypeFloat: tch = 'F'; break; 6125 case kRegTypeConstLo: tch = 'N'; break; 6126 case kRegTypeConstHi: tch = 'n'; break; 6127 case kRegTypeLongLo: tch = 'J'; break; 6128 case kRegTypeLongHi: tch = 'j'; break; 6129 case kRegTypeDoubleLo: tch = 'D'; break; 6130 case kRegTypeDoubleHi: tch = 'd'; break; 6131 default: 6132 if (regTypeIsReference(addrRegs[i])) { 6133 if (regTypeIsUninitReference(addrRegs[i])) 6134 tch = 'U'; 6135 else 6136 tch = 'L'; 6137 } else { 6138 tch = '*'; 6139 assert(false); 6140 } 6141 break; 6142 } 6143 6144 if (i < regCount) 6145 regChars[1 + i + (i/4)] = tch; 6146 else 6147 regChars[1 + i + (i/4) + 2] = tch; 6148 } 6149 6150 if (addr == 0 && addrName != NULL) { 6151 ALOGI("%c%s %s mst=%d", branchTarget ? '>' : ' ', 6152 addrName, regChars, registerLine->monitorStackTop); 6153 } else { 6154 ALOGI("%c0x%04x %s mst=%d", branchTarget ? '>' : ' ', 6155 addr, regChars, registerLine->monitorStackTop); 6156 } 6157 if (displayFlags & DRT_SHOW_LIVENESS) { 6158 /* 6159 * We can't use registerLine->liveRegs because it might be the 6160 * "work line" rather than the copy from RegisterTable. 6161 */ 6162 BitVector* liveRegs = vdata->registerLines[addr].liveRegs; 6163 if (liveRegs != NULL) { 6164 char liveChars[regCharSize + 1]; 6165 memset(liveChars, ' ', regCharSize); 6166 liveChars[regCharSize] = '\0'; 6167 6168 for (i = 0; i < regCount; i++) { 6169 bool isLive = dvmIsBitSet(liveRegs, i); 6170 liveChars[i + 1 + (i / 4)] = isLive ? '+' : '-'; 6171 } 6172 ALOGI(" %s", liveChars); 6173 } else { 6174 ALOGI(" %c", '#'); 6175 } 6176 } 6177 6178 if (displayFlags & DRT_SHOW_REF_TYPES) { 6179 for (i = 0; i < regCount + kExtraRegs; i++) { 6180 if (regTypeIsReference(addrRegs[i]) && addrRegs[i] != kRegTypeZero) 6181 { 6182 ClassObject* clazz = regTypeReferenceToClass(addrRegs[i], uninitMap); 6183 assert(dvmIsHeapAddress((Object*)clazz)); 6184 if (i < regCount) { 6185 ALOGI(" %2d: 0x%08x %s%s", 6186 i, addrRegs[i], 6187 regTypeIsUninitReference(addrRegs[i]) ? "[U]" : "", 6188 clazz->descriptor); 6189 } else { 6190 ALOGI(" RS: 0x%08x %s%s", 6191 addrRegs[i], 6192 regTypeIsUninitReference(addrRegs[i]) ? "[U]" : "", 6193 clazz->descriptor); 6194 } 6195 } 6196 } 6197 } 6198 if (displayFlags & DRT_SHOW_LOCALS) { 6199 dexDecodeDebugInfo(meth->clazz->pDvmDex->pDexFile, 6200 dvmGetMethodCode(meth), 6201 meth->clazz->descriptor, 6202 meth->prototype.protoIdx, 6203 meth->accessFlags, 6204 NULL, logLocalsCb, &addr); 6205 } 6206 } 6207