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