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