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 classfile verification. This file contains the verifier entry 19 * points and the static constraint checks. 20 */ 21 #include "Dalvik.h" 22 #include "analysis/CodeVerify.h" 23 #include "libdex/DexCatch.h" 24 25 26 /* fwd */ 27 static bool verifyMethod(Method* meth); 28 static bool verifyInstructions(VerifierData* vdata); 29 30 31 /* 32 * Verify a class. 33 * 34 * By the time we get here, the value of gDvm.classVerifyMode should already 35 * have been factored in. If you want to call into the verifier even 36 * though verification is disabled, that's your business. 37 * 38 * Returns "true" on success. 39 */ 40 bool dvmVerifyClass(ClassObject* clazz) 41 { 42 int i; 43 44 if (dvmIsClassVerified(clazz)) { 45 ALOGD("Ignoring duplicate verify attempt on %s", clazz->descriptor); 46 return true; 47 } 48 49 for (i = 0; i < clazz->directMethodCount; i++) { 50 if (!verifyMethod(&clazz->directMethods[i])) { 51 LOG_VFY("Verifier rejected class %s", clazz->descriptor); 52 return false; 53 } 54 } 55 for (i = 0; i < clazz->virtualMethodCount; i++) { 56 if (!verifyMethod(&clazz->virtualMethods[i])) { 57 LOG_VFY("Verifier rejected class %s", clazz->descriptor); 58 return false; 59 } 60 } 61 62 return true; 63 } 64 65 66 /* 67 * Compute the width of the instruction at each address in the instruction 68 * stream, and store it in vdata->insnFlags. Addresses that are in the 69 * middle of an instruction, or that are part of switch table data, are not 70 * touched (so the caller should probably initialize "insnFlags" to zero). 71 * 72 * The "newInstanceCount" and "monitorEnterCount" fields in vdata are 73 * also set. 74 * 75 * Performs some static checks, notably: 76 * - opcode of first instruction begins at index 0 77 * - only documented instructions may appear 78 * - each instruction follows the last 79 * - last byte of last instruction is at (code_length-1) 80 * 81 * Logs an error and returns "false" on failure. 82 */ 83 static bool computeWidthsAndCountOps(VerifierData* vdata) 84 { 85 const Method* meth = vdata->method; 86 InsnFlags* insnFlags = vdata->insnFlags; 87 size_t insnCount = vdata->insnsSize; 88 const u2* insns = meth->insns; 89 bool result = false; 90 int newInstanceCount = 0; 91 int monitorEnterCount = 0; 92 int i; 93 94 for (i = 0; i < (int) insnCount; /**/) { 95 size_t width = dexGetWidthFromInstruction(insns); 96 if (width == 0) { 97 LOG_VFY_METH(meth, "VFY: invalid instruction (0x%04x)", *insns); 98 goto bail; 99 } else if (width > 65535) { 100 LOG_VFY_METH(meth, 101 "VFY: warning: unusually large instr width (%d)", width); 102 } 103 104 Opcode opcode = dexOpcodeFromCodeUnit(*insns); 105 if (opcode == OP_NEW_INSTANCE) 106 newInstanceCount++; 107 if (opcode == OP_MONITOR_ENTER) 108 monitorEnterCount++; 109 110 insnFlags[i] |= width; 111 i += width; 112 insns += width; 113 } 114 if (i != (int) vdata->insnsSize) { 115 LOG_VFY_METH(meth, "VFY: code did not end where expected (%d vs. %d)", 116 i, dvmGetMethodInsnsSize(meth)); 117 goto bail; 118 } 119 120 result = true; 121 vdata->newInstanceCount = newInstanceCount; 122 vdata->monitorEnterCount = monitorEnterCount; 123 124 bail: 125 return result; 126 } 127 128 /* 129 * Set the "in try" flags for all instructions protected by "try" statements. 130 * Also sets the "branch target" flags for exception handlers. 131 * 132 * Call this after widths have been set in "insnFlags". 133 * 134 * Returns "false" if something in the exception table looks fishy, but 135 * we're expecting the exception table to be somewhat sane. 136 */ 137 static bool scanTryCatchBlocks(const Method* meth, InsnFlags* insnFlags) 138 { 139 u4 insnsSize = dvmGetMethodInsnsSize(meth); 140 const DexCode* pCode = dvmGetMethodCode(meth); 141 u4 triesSize = pCode->triesSize; 142 const DexTry* pTries; 143 u4 idx; 144 145 if (triesSize == 0) { 146 return true; 147 } 148 149 pTries = dexGetTries(pCode); 150 151 for (idx = 0; idx < triesSize; idx++) { 152 const DexTry* pTry = &pTries[idx]; 153 u4 start = pTry->startAddr; 154 u4 end = start + pTry->insnCount; 155 u4 addr; 156 157 if ((start >= end) || (start >= insnsSize) || (end > insnsSize)) { 158 LOG_VFY_METH(meth, 159 "VFY: bad exception entry: startAddr=%d endAddr=%d (size=%d)", 160 start, end, insnsSize); 161 return false; 162 } 163 164 if (dvmInsnGetWidth(insnFlags, start) == 0) { 165 LOG_VFY_METH(meth, 166 "VFY: 'try' block starts inside an instruction (%d)", 167 start); 168 return false; 169 } 170 171 for (addr = start; addr < end; 172 addr += dvmInsnGetWidth(insnFlags, addr)) 173 { 174 assert(dvmInsnGetWidth(insnFlags, addr) != 0); 175 dvmInsnSetInTry(insnFlags, addr, true); 176 } 177 } 178 179 /* Iterate over each of the handlers to verify target addresses. */ 180 u4 handlersSize = dexGetHandlersSize(pCode); 181 u4 offset = dexGetFirstHandlerOffset(pCode); 182 for (idx = 0; idx < handlersSize; idx++) { 183 DexCatchIterator iterator; 184 dexCatchIteratorInit(&iterator, pCode, offset); 185 186 for (;;) { 187 DexCatchHandler* handler = dexCatchIteratorNext(&iterator); 188 u4 addr; 189 190 if (handler == NULL) { 191 break; 192 } 193 194 addr = handler->address; 195 if (dvmInsnGetWidth(insnFlags, addr) == 0) { 196 LOG_VFY_METH(meth, 197 "VFY: exception handler starts at bad address (%d)", 198 addr); 199 return false; 200 } 201 202 dvmInsnSetBranchTarget(insnFlags, addr, true); 203 } 204 205 offset = dexCatchIteratorGetEndOffset(&iterator, pCode); 206 } 207 208 return true; 209 } 210 211 /* 212 * Perform verification on a single method. 213 * 214 * We do this in three passes: 215 * (1) Walk through all code units, determining instruction locations, 216 * widths, and other characteristics. 217 * (2) Walk through all code units, performing static checks on 218 * operands. 219 * (3) Iterate through the method, checking type safety and looking 220 * for code flow problems. 221 * 222 * Some checks may be bypassed depending on the verification mode. We can't 223 * turn this stuff off completely if we want to do "exact" GC. 224 * 225 * TODO: cite source? 226 * Confirmed here: 227 * - code array must not be empty 228 * - (N/A) code_length must be less than 65536 229 * Confirmed by computeWidthsAndCountOps(): 230 * - opcode of first instruction begins at index 0 231 * - only documented instructions may appear 232 * - each instruction follows the last 233 * - last byte of last instruction is at (code_length-1) 234 */ 235 static bool verifyMethod(Method* meth) 236 { 237 bool result = false; 238 239 /* 240 * Verifier state blob. Various values will be cached here so we 241 * can avoid expensive lookups and pass fewer arguments around. 242 */ 243 VerifierData vdata; 244 #if 1 // ndef NDEBUG 245 memset(&vdata, 0x99, sizeof(vdata)); 246 #endif 247 248 vdata.method = meth; 249 vdata.insnsSize = dvmGetMethodInsnsSize(meth); 250 vdata.insnRegCount = meth->registersSize; 251 vdata.insnFlags = NULL; 252 vdata.uninitMap = NULL; 253 vdata.basicBlocks = NULL; 254 255 /* 256 * If there aren't any instructions, make sure that's expected, then 257 * exit successfully. Note: for native methods, meth->insns gets set 258 * to a native function pointer on first call, so don't use that as 259 * an indicator. 260 */ 261 if (vdata.insnsSize == 0) { 262 if (!dvmIsNativeMethod(meth) && !dvmIsAbstractMethod(meth)) { 263 LOG_VFY_METH(meth, 264 "VFY: zero-length code in concrete non-native method"); 265 goto bail; 266 } 267 268 goto success; 269 } 270 271 /* 272 * Sanity-check the register counts. ins + locals = registers, so make 273 * sure that ins <= registers. 274 */ 275 if (meth->insSize > meth->registersSize) { 276 LOG_VFY_METH(meth, "VFY: bad register counts (ins=%d regs=%d)", 277 meth->insSize, meth->registersSize); 278 goto bail; 279 } 280 281 /* 282 * Allocate and populate an array to hold instruction data. 283 * 284 * TODO: Consider keeping a reusable pre-allocated array sitting 285 * around for smaller methods. 286 */ 287 vdata.insnFlags = (InsnFlags*) calloc(vdata.insnsSize, sizeof(InsnFlags)); 288 if (vdata.insnFlags == NULL) 289 goto bail; 290 291 /* 292 * Compute the width of each instruction and store the result in insnFlags. 293 * Count up the #of occurrences of certain opcodes while we're at it. 294 */ 295 if (!computeWidthsAndCountOps(&vdata)) 296 goto bail; 297 298 /* 299 * Allocate a map to hold the classes of uninitialized instances. 300 */ 301 vdata.uninitMap = dvmCreateUninitInstanceMap(meth, vdata.insnFlags, 302 vdata.newInstanceCount); 303 if (vdata.uninitMap == NULL) 304 goto bail; 305 306 /* 307 * Set the "in try" flags for all instructions guarded by a "try" block. 308 * Also sets the "branch target" flag on exception handlers. 309 */ 310 if (!scanTryCatchBlocks(meth, vdata.insnFlags)) 311 goto bail; 312 313 /* 314 * Perform static instruction verification. Also sets the "branch 315 * target" flags. 316 */ 317 if (!verifyInstructions(&vdata)) 318 goto bail; 319 320 /* 321 * Do code-flow analysis. 322 * 323 * We could probably skip this for a method with no registers, but 324 * that's so rare that there's little point in checking. 325 */ 326 if (!dvmVerifyCodeFlow(&vdata)) { 327 //ALOGD("+++ %s failed code flow", meth->name); 328 goto bail; 329 } 330 331 success: 332 result = true; 333 334 bail: 335 dvmFreeVfyBasicBlocks(&vdata); 336 dvmFreeUninitInstanceMap(vdata.uninitMap); 337 free(vdata.insnFlags); 338 return result; 339 } 340 341 342 /* 343 * Verify an array data table. "curOffset" is the offset of the 344 * fill-array-data instruction. 345 */ 346 static bool checkArrayData(const Method* meth, u4 curOffset) 347 { 348 const u4 insnCount = dvmGetMethodInsnsSize(meth); 349 const u2* insns = meth->insns + curOffset; 350 const u2* arrayData; 351 u4 valueCount, valueWidth, tableSize; 352 s4 offsetToArrayData; 353 354 assert(curOffset < insnCount); 355 356 /* make sure the start of the array data table is in range */ 357 offsetToArrayData = insns[1] | (((s4)insns[2]) << 16); 358 if ((s4)curOffset + offsetToArrayData < 0 || 359 curOffset + offsetToArrayData + 2 >= insnCount) 360 { 361 LOG_VFY("VFY: invalid array data start: at %d, data offset %d, " 362 "count %d", 363 curOffset, offsetToArrayData, insnCount); 364 return false; 365 } 366 367 /* offset to array data table is a relative branch-style offset */ 368 arrayData = insns + offsetToArrayData; 369 370 /* make sure the table is 32-bit aligned */ 371 if ((((u4) arrayData) & 0x03) != 0) { 372 LOG_VFY("VFY: unaligned array data table: at %d, data offset %d", 373 curOffset, offsetToArrayData); 374 return false; 375 } 376 377 valueWidth = arrayData[1]; 378 valueCount = *(u4*)(&arrayData[2]); 379 380 tableSize = 4 + (valueWidth * valueCount + 1) / 2; 381 382 /* make sure the end of the switch is in range */ 383 if (curOffset + offsetToArrayData + tableSize > insnCount) { 384 LOG_VFY("VFY: invalid array data end: at %d, data offset %d, end %d, " 385 "count %d", 386 curOffset, offsetToArrayData, 387 curOffset + offsetToArrayData + tableSize, insnCount); 388 return false; 389 } 390 391 return true; 392 } 393 394 /* 395 * Perform static checks on a "new-instance" instruction. Specifically, 396 * make sure the class reference isn't for an array class. 397 * 398 * We don't need the actual class, just a pointer to the class name. 399 */ 400 static bool checkNewInstance(const DvmDex* pDvmDex, u4 idx) 401 { 402 const char* classDescriptor; 403 404 if (idx >= pDvmDex->pHeader->typeIdsSize) { 405 LOG_VFY("VFY: bad type index %d (max %d)", 406 idx, pDvmDex->pHeader->typeIdsSize); 407 return false; 408 } 409 410 classDescriptor = dexStringByTypeIdx(pDvmDex->pDexFile, idx); 411 if (classDescriptor[0] != 'L') { 412 LOG_VFY("VFY: can't call new-instance on type '%s'", 413 classDescriptor); 414 return false; 415 } 416 417 return true; 418 } 419 420 /* 421 * Perform static checks on a "new-array" instruction. Specifically, make 422 * sure they aren't creating an array of arrays that causes the number of 423 * dimensions to exceed 255. 424 */ 425 static bool checkNewArray(const DvmDex* pDvmDex, u4 idx) 426 { 427 const char* classDescriptor; 428 429 if (idx >= pDvmDex->pHeader->typeIdsSize) { 430 LOG_VFY("VFY: bad type index %d (max %d)", 431 idx, pDvmDex->pHeader->typeIdsSize); 432 return false; 433 } 434 435 classDescriptor = dexStringByTypeIdx(pDvmDex->pDexFile, idx); 436 437 int bracketCount = 0; 438 const char* cp = classDescriptor; 439 while (*cp++ == '[') 440 bracketCount++; 441 442 if (bracketCount == 0) { 443 /* The given class must be an array type. */ 444 LOG_VFY("VFY: can't new-array class '%s' (not an array)", 445 classDescriptor); 446 return false; 447 } else if (bracketCount > 255) { 448 /* It is illegal to create an array of more than 255 dimensions. */ 449 LOG_VFY("VFY: can't new-array class '%s' (exceeds limit)", 450 classDescriptor); 451 return false; 452 } 453 454 return true; 455 } 456 457 /* 458 * Perform static checks on an instruction that takes a class constant. 459 * Ensure that the class index is in the valid range. 460 */ 461 static bool checkTypeIndex(const DvmDex* pDvmDex, u4 idx) 462 { 463 if (idx >= pDvmDex->pHeader->typeIdsSize) { 464 LOG_VFY("VFY: bad type index %d (max %d)", 465 idx, pDvmDex->pHeader->typeIdsSize); 466 return false; 467 } 468 return true; 469 } 470 471 /* 472 * Perform static checks on a field get or set instruction. All we do 473 * here is ensure that the field index is in the valid range. 474 */ 475 static bool checkFieldIndex(const DvmDex* pDvmDex, u4 idx) 476 { 477 if (idx >= pDvmDex->pHeader->fieldIdsSize) { 478 LOG_VFY("VFY: bad field index %d (max %d)", 479 idx, pDvmDex->pHeader->fieldIdsSize); 480 return false; 481 } 482 return true; 483 } 484 485 /* 486 * Perform static checks on a method invocation instruction. All we do 487 * here is ensure that the method index is in the valid range. 488 */ 489 static bool checkMethodIndex(const DvmDex* pDvmDex, u4 idx) 490 { 491 if (idx >= pDvmDex->pHeader->methodIdsSize) { 492 LOG_VFY("VFY: bad method index %d (max %d)", 493 idx, pDvmDex->pHeader->methodIdsSize); 494 return false; 495 } 496 return true; 497 } 498 499 /* 500 * Ensure that the string index is in the valid range. 501 */ 502 static bool checkStringIndex(const DvmDex* pDvmDex, u4 idx) 503 { 504 if (idx >= pDvmDex->pHeader->stringIdsSize) { 505 LOG_VFY("VFY: bad string index %d (max %d)", 506 idx, pDvmDex->pHeader->stringIdsSize); 507 return false; 508 } 509 return true; 510 } 511 512 /* 513 * Ensure that the register index is valid for this method. 514 */ 515 static bool checkRegisterIndex(const Method* meth, u4 idx) 516 { 517 if (idx >= meth->registersSize) { 518 LOG_VFY("VFY: register index out of range (%d >= %d)", 519 idx, meth->registersSize); 520 return false; 521 } 522 return true; 523 } 524 525 /* 526 * Ensure that the wide register index is valid for this method. 527 */ 528 static bool checkWideRegisterIndex(const Method* meth, u4 idx) 529 { 530 if (idx+1 >= meth->registersSize) { 531 LOG_VFY("VFY: wide register index out of range (%d+1 >= %d)", 532 idx, meth->registersSize); 533 return false; 534 } 535 return true; 536 } 537 538 /* 539 * Check the register indices used in a "vararg" instruction, such as 540 * invoke-virtual or filled-new-array. 541 * 542 * vA holds word count (0-5), args[] have values. 543 * 544 * There are some tests we don't do here, e.g. we don't try to verify 545 * that invoking a method that takes a double is done with consecutive 546 * registers. This requires parsing the target method signature, which 547 * we will be doing later on during the code flow analysis. 548 */ 549 static bool checkVarargRegs(const Method* meth, 550 const DecodedInstruction* pDecInsn) 551 { 552 u2 registersSize = meth->registersSize; 553 unsigned int idx; 554 555 if (pDecInsn->vA > 5) { 556 LOG_VFY("VFY: invalid arg count (%d) in non-range invoke)", 557 pDecInsn->vA); 558 return false; 559 } 560 561 for (idx = 0; idx < pDecInsn->vA; idx++) { 562 if (pDecInsn->arg[idx] > registersSize) { 563 LOG_VFY("VFY: invalid reg index (%d) in non-range invoke (> %d)", 564 pDecInsn->arg[idx], registersSize); 565 return false; 566 } 567 } 568 569 return true; 570 } 571 572 /* 573 * Check the register indices used in a "vararg/range" instruction, such as 574 * invoke-virtual/range or filled-new-array/range. 575 * 576 * vA holds word count, vC holds index of first reg. 577 */ 578 static bool checkVarargRangeRegs(const Method* meth, 579 const DecodedInstruction* pDecInsn) 580 { 581 u2 registersSize = meth->registersSize; 582 583 /* 584 * vA/vC are unsigned 8-bit/16-bit quantities for /range instructions, 585 * so there's no risk of integer overflow when adding them here. 586 */ 587 if (pDecInsn->vA + pDecInsn->vC > registersSize) { 588 LOG_VFY("VFY: invalid reg index %d+%d in range invoke (> %d)", 589 pDecInsn->vA, pDecInsn->vC, registersSize); 590 return false; 591 } 592 593 return true; 594 } 595 596 /* 597 * Verify a switch table. "curOffset" is the offset of the switch 598 * instruction. 599 * 600 * Updates "insnFlags", setting the "branch target" flag. 601 */ 602 static bool checkSwitchTargets(const Method* meth, InsnFlags* insnFlags, 603 u4 curOffset) 604 { 605 const u4 insnCount = dvmGetMethodInsnsSize(meth); 606 const u2* insns = meth->insns + curOffset; 607 const u2* switchInsns; 608 u2 expectedSignature; 609 u4 switchCount, tableSize; 610 s4 offsetToSwitch, offsetToKeys, offsetToTargets; 611 s4 offset, absOffset; 612 u4 targ; 613 614 assert(curOffset < insnCount); 615 616 /* make sure the start of the switch is in range */ 617 offsetToSwitch = insns[1] | ((s4) insns[2]) << 16; 618 if ((s4) curOffset + offsetToSwitch < 0 || 619 curOffset + offsetToSwitch + 2 >= insnCount) 620 { 621 LOG_VFY("VFY: invalid switch start: at %d, switch offset %d, " 622 "count %d", 623 curOffset, offsetToSwitch, insnCount); 624 return false; 625 } 626 627 /* offset to switch table is a relative branch-style offset */ 628 switchInsns = insns + offsetToSwitch; 629 630 /* make sure the table is 32-bit aligned */ 631 if ((((u4) switchInsns) & 0x03) != 0) { 632 LOG_VFY("VFY: unaligned switch table: at %d, switch offset %d", 633 curOffset, offsetToSwitch); 634 return false; 635 } 636 637 switchCount = switchInsns[1]; 638 639 if ((*insns & 0xff) == OP_PACKED_SWITCH) { 640 /* 0=sig, 1=count, 2/3=firstKey */ 641 offsetToTargets = 4; 642 offsetToKeys = -1; 643 expectedSignature = kPackedSwitchSignature; 644 } else { 645 /* 0=sig, 1=count, 2..count*2 = keys */ 646 offsetToKeys = 2; 647 offsetToTargets = 2 + 2*switchCount; 648 expectedSignature = kSparseSwitchSignature; 649 } 650 tableSize = offsetToTargets + switchCount*2; 651 652 if (switchInsns[0] != expectedSignature) { 653 LOG_VFY("VFY: wrong signature for switch table (0x%04x, wanted 0x%04x)", 654 switchInsns[0], expectedSignature); 655 return false; 656 } 657 658 /* make sure the end of the switch is in range */ 659 if (curOffset + offsetToSwitch + tableSize > (u4) insnCount) { 660 LOG_VFY("VFY: invalid switch end: at %d, switch offset %d, end %d, " 661 "count %d", 662 curOffset, offsetToSwitch, curOffset + offsetToSwitch + tableSize, 663 insnCount); 664 return false; 665 } 666 667 /* for a sparse switch, verify the keys are in ascending order */ 668 if (offsetToKeys > 0 && switchCount > 1) { 669 s4 lastKey; 670 671 lastKey = switchInsns[offsetToKeys] | 672 (switchInsns[offsetToKeys+1] << 16); 673 for (targ = 1; targ < switchCount; targ++) { 674 s4 key = (s4) switchInsns[offsetToKeys + targ*2] | 675 (s4) (switchInsns[offsetToKeys + targ*2 +1] << 16); 676 if (key <= lastKey) { 677 LOG_VFY("VFY: invalid packed switch: last key=%d, this=%d", 678 lastKey, key); 679 return false; 680 } 681 682 lastKey = key; 683 } 684 } 685 686 /* verify each switch target */ 687 for (targ = 0; targ < switchCount; targ++) { 688 offset = (s4) switchInsns[offsetToTargets + targ*2] | 689 (s4) (switchInsns[offsetToTargets + targ*2 +1] << 16); 690 absOffset = curOffset + offset; 691 692 if (absOffset < 0 || absOffset >= (s4)insnCount || 693 !dvmInsnIsOpcode(insnFlags, absOffset)) 694 { 695 LOG_VFY("VFY: invalid switch target %d (-> %#x) at %#x[%d]", 696 offset, absOffset, curOffset, targ); 697 return false; 698 } 699 dvmInsnSetBranchTarget(insnFlags, absOffset, true); 700 } 701 702 return true; 703 } 704 705 /* 706 * Verify that the target of a branch instruction is valid. 707 * 708 * We don't expect code to jump directly into an exception handler, but 709 * it's valid to do so as long as the target isn't a "move-exception" 710 * instruction. We verify that in a later stage. 711 * 712 * The VM spec doesn't forbid an instruction from branching to itself, 713 * but the Dalvik spec declares that only certain instructions can do so. 714 * 715 * Updates "insnFlags", setting the "branch target" flag. 716 */ 717 static bool checkBranchTarget(const Method* meth, InsnFlags* insnFlags, 718 int curOffset, bool selfOkay) 719 { 720 const int insnCount = dvmGetMethodInsnsSize(meth); 721 s4 offset, absOffset; 722 bool isConditional; 723 724 if (!dvmGetBranchOffset(meth, insnFlags, curOffset, &offset, 725 &isConditional)) 726 return false; 727 728 if (!selfOkay && offset == 0) { 729 LOG_VFY_METH(meth, "VFY: branch offset of zero not allowed at %#x", 730 curOffset); 731 return false; 732 } 733 734 /* 735 * Check for 32-bit overflow. This isn't strictly necessary if we can 736 * depend on the VM to have identical "wrap-around" behavior, but 737 * it's unwise to depend on that. 738 */ 739 if (((s8) curOffset + (s8) offset) != (s8)(curOffset + offset)) { 740 LOG_VFY_METH(meth, "VFY: branch target overflow %#x +%d", 741 curOffset, offset); 742 return false; 743 } 744 absOffset = curOffset + offset; 745 if (absOffset < 0 || absOffset >= insnCount || 746 !dvmInsnIsOpcode(insnFlags, absOffset)) 747 { 748 LOG_VFY_METH(meth, 749 "VFY: invalid branch target %d (-> %#x) at %#x", 750 offset, absOffset, curOffset); 751 return false; 752 } 753 dvmInsnSetBranchTarget(insnFlags, absOffset, true); 754 755 return true; 756 } 757 758 759 /* 760 * Perform static verification on instructions. 761 * 762 * As a side effect, this sets the "branch target" flags in InsnFlags. 763 * 764 * "(CF)" items are handled during code-flow analysis. 765 * 766 * v3 4.10.1 767 * - target of each jump and branch instruction must be valid 768 * - targets of switch statements must be valid 769 * - operands referencing constant pool entries must be valid 770 * - (CF) operands of getfield, putfield, getstatic, putstatic must be valid 771 * - (new) verify operands of "quick" field ops 772 * - (CF) operands of method invocation instructions must be valid 773 * - (new) verify operands of "quick" method invoke ops 774 * - (CF) only invoke-direct can call a method starting with '<' 775 * - (CF) <clinit> must never be called explicitly 776 * - operands of instanceof, checkcast, new (and variants) must be valid 777 * - new-array[-type] limited to 255 dimensions 778 * - can't use "new" on an array class 779 * - (?) limit dimensions in multi-array creation 780 * - local variable load/store register values must be in valid range 781 * 782 * v3 4.11.1.2 783 * - branches must be within the bounds of the code array 784 * - targets of all control-flow instructions are the start of an instruction 785 * - register accesses fall within range of allocated registers 786 * - (N/A) access to constant pool must be of appropriate type 787 * - code does not end in the middle of an instruction 788 * - execution cannot fall off the end of the code 789 * - (earlier) for each exception handler, the "try" area must begin and 790 * end at the start of an instruction (end can be at the end of the code) 791 * - (earlier) for each exception handler, the handler must start at a valid 792 * instruction 793 */ 794 static bool verifyInstructions(VerifierData* vdata) 795 { 796 const Method* meth = vdata->method; 797 const DvmDex* pDvmDex = meth->clazz->pDvmDex; 798 InsnFlags* insnFlags = vdata->insnFlags; 799 const u2* insns = meth->insns; 800 unsigned int codeOffset; 801 802 /* the start of the method is a "branch target" */ 803 dvmInsnSetBranchTarget(insnFlags, 0, true); 804 805 for (codeOffset = 0; codeOffset < vdata->insnsSize; /**/) { 806 /* 807 * Pull the instruction apart. 808 */ 809 int width = dvmInsnGetWidth(insnFlags, codeOffset); 810 DecodedInstruction decInsn; 811 bool okay = true; 812 813 dexDecodeInstruction(meth->insns + codeOffset, &decInsn); 814 815 /* 816 * Check register, type, class, field, method, and string indices 817 * for out-of-range values. Do additional checks on branch targets 818 * and some special cases like new-instance and new-array. 819 */ 820 switch (decInsn.opcode) { 821 case OP_NOP: 822 case OP_RETURN_VOID: 823 /* nothing to check */ 824 break; 825 case OP_MOVE_RESULT: 826 case OP_MOVE_RESULT_OBJECT: 827 case OP_MOVE_EXCEPTION: 828 case OP_RETURN: 829 case OP_RETURN_OBJECT: 830 case OP_CONST_4: 831 case OP_CONST_16: 832 case OP_CONST: 833 case OP_CONST_HIGH16: 834 case OP_MONITOR_ENTER: 835 case OP_MONITOR_EXIT: 836 case OP_THROW: 837 okay &= checkRegisterIndex(meth, decInsn.vA); 838 break; 839 case OP_MOVE_RESULT_WIDE: 840 case OP_RETURN_WIDE: 841 case OP_CONST_WIDE_16: 842 case OP_CONST_WIDE_32: 843 case OP_CONST_WIDE: 844 case OP_CONST_WIDE_HIGH16: 845 okay &= checkWideRegisterIndex(meth, decInsn.vA); 846 break; 847 case OP_GOTO: 848 case OP_GOTO_16: 849 okay &= checkBranchTarget(meth, insnFlags, codeOffset, false); 850 break; 851 case OP_GOTO_32: 852 okay &= checkBranchTarget(meth, insnFlags, codeOffset, true); 853 break; 854 case OP_MOVE: 855 case OP_MOVE_FROM16: 856 case OP_MOVE_16: 857 case OP_MOVE_OBJECT: 858 case OP_MOVE_OBJECT_FROM16: 859 case OP_MOVE_OBJECT_16: 860 case OP_ARRAY_LENGTH: 861 case OP_NEG_INT: 862 case OP_NOT_INT: 863 case OP_NEG_FLOAT: 864 case OP_INT_TO_FLOAT: 865 case OP_FLOAT_TO_INT: 866 case OP_INT_TO_BYTE: 867 case OP_INT_TO_CHAR: 868 case OP_INT_TO_SHORT: 869 case OP_ADD_INT_2ADDR: 870 case OP_SUB_INT_2ADDR: 871 case OP_MUL_INT_2ADDR: 872 case OP_DIV_INT_2ADDR: 873 case OP_REM_INT_2ADDR: 874 case OP_AND_INT_2ADDR: 875 case OP_OR_INT_2ADDR: 876 case OP_XOR_INT_2ADDR: 877 case OP_SHL_INT_2ADDR: 878 case OP_SHR_INT_2ADDR: 879 case OP_USHR_INT_2ADDR: 880 case OP_ADD_FLOAT_2ADDR: 881 case OP_SUB_FLOAT_2ADDR: 882 case OP_MUL_FLOAT_2ADDR: 883 case OP_DIV_FLOAT_2ADDR: 884 case OP_REM_FLOAT_2ADDR: 885 case OP_ADD_INT_LIT16: 886 case OP_RSUB_INT: 887 case OP_MUL_INT_LIT16: 888 case OP_DIV_INT_LIT16: 889 case OP_REM_INT_LIT16: 890 case OP_AND_INT_LIT16: 891 case OP_OR_INT_LIT16: 892 case OP_XOR_INT_LIT16: 893 case OP_ADD_INT_LIT8: 894 case OP_RSUB_INT_LIT8: 895 case OP_MUL_INT_LIT8: 896 case OP_DIV_INT_LIT8: 897 case OP_REM_INT_LIT8: 898 case OP_AND_INT_LIT8: 899 case OP_OR_INT_LIT8: 900 case OP_XOR_INT_LIT8: 901 case OP_SHL_INT_LIT8: 902 case OP_SHR_INT_LIT8: 903 case OP_USHR_INT_LIT8: 904 okay &= checkRegisterIndex(meth, decInsn.vA); 905 okay &= checkRegisterIndex(meth, decInsn.vB); 906 break; 907 case OP_INT_TO_LONG: 908 case OP_INT_TO_DOUBLE: 909 case OP_FLOAT_TO_LONG: 910 case OP_FLOAT_TO_DOUBLE: 911 case OP_SHL_LONG_2ADDR: 912 case OP_SHR_LONG_2ADDR: 913 case OP_USHR_LONG_2ADDR: 914 okay &= checkWideRegisterIndex(meth, decInsn.vA); 915 okay &= checkRegisterIndex(meth, decInsn.vB); 916 break; 917 case OP_LONG_TO_INT: 918 case OP_LONG_TO_FLOAT: 919 case OP_DOUBLE_TO_INT: 920 case OP_DOUBLE_TO_FLOAT: 921 okay &= checkRegisterIndex(meth, decInsn.vA); 922 okay &= checkWideRegisterIndex(meth, decInsn.vB); 923 break; 924 case OP_MOVE_WIDE: 925 case OP_MOVE_WIDE_FROM16: 926 case OP_MOVE_WIDE_16: 927 case OP_DOUBLE_TO_LONG: 928 case OP_LONG_TO_DOUBLE: 929 case OP_NEG_DOUBLE: 930 case OP_NEG_LONG: 931 case OP_NOT_LONG: 932 case OP_ADD_LONG_2ADDR: 933 case OP_SUB_LONG_2ADDR: 934 case OP_MUL_LONG_2ADDR: 935 case OP_DIV_LONG_2ADDR: 936 case OP_REM_LONG_2ADDR: 937 case OP_AND_LONG_2ADDR: 938 case OP_OR_LONG_2ADDR: 939 case OP_XOR_LONG_2ADDR: 940 case OP_ADD_DOUBLE_2ADDR: 941 case OP_SUB_DOUBLE_2ADDR: 942 case OP_MUL_DOUBLE_2ADDR: 943 case OP_DIV_DOUBLE_2ADDR: 944 case OP_REM_DOUBLE_2ADDR: 945 okay &= checkWideRegisterIndex(meth, decInsn.vA); 946 okay &= checkWideRegisterIndex(meth, decInsn.vB); 947 break; 948 case OP_CONST_STRING: 949 case OP_CONST_STRING_JUMBO: 950 okay &= checkRegisterIndex(meth, decInsn.vA); 951 okay &= checkStringIndex(pDvmDex, decInsn.vB); 952 break; 953 case OP_CONST_CLASS: 954 case OP_CHECK_CAST: 955 okay &= checkRegisterIndex(meth, decInsn.vA); 956 okay &= checkTypeIndex(pDvmDex, decInsn.vB); 957 break; 958 case OP_INSTANCE_OF: 959 okay &= checkRegisterIndex(meth, decInsn.vA); 960 okay &= checkRegisterIndex(meth, decInsn.vB); 961 okay &= checkTypeIndex(pDvmDex, decInsn.vC); 962 break; 963 case OP_NEW_INSTANCE: 964 okay &= checkRegisterIndex(meth, decInsn.vA); 965 okay &= checkNewInstance(pDvmDex, decInsn.vB); 966 break; 967 case OP_NEW_ARRAY: 968 okay &= checkRegisterIndex(meth, decInsn.vA); 969 okay &= checkRegisterIndex(meth, decInsn.vB); 970 okay &= checkNewArray(pDvmDex, decInsn.vC); 971 break; 972 case OP_FILL_ARRAY_DATA: 973 okay &= checkRegisterIndex(meth, decInsn.vA); 974 okay &= checkArrayData(meth, codeOffset); 975 break; 976 case OP_PACKED_SWITCH: 977 okay &= checkRegisterIndex(meth, decInsn.vA); 978 okay &= checkSwitchTargets(meth, insnFlags, codeOffset); 979 break; 980 case OP_SPARSE_SWITCH: 981 okay &= checkRegisterIndex(meth, decInsn.vA); 982 okay &= checkSwitchTargets(meth, insnFlags, codeOffset); 983 break; 984 case OP_CMPL_FLOAT: 985 case OP_CMPG_FLOAT: 986 case OP_AGET: 987 case OP_AGET_OBJECT: 988 case OP_AGET_BOOLEAN: 989 case OP_AGET_BYTE: 990 case OP_AGET_CHAR: 991 case OP_AGET_SHORT: 992 case OP_APUT: 993 case OP_APUT_OBJECT: 994 case OP_APUT_BOOLEAN: 995 case OP_APUT_BYTE: 996 case OP_APUT_CHAR: 997 case OP_APUT_SHORT: 998 case OP_ADD_INT: 999 case OP_SUB_INT: 1000 case OP_MUL_INT: 1001 case OP_DIV_INT: 1002 case OP_REM_INT: 1003 case OP_AND_INT: 1004 case OP_OR_INT: 1005 case OP_XOR_INT: 1006 case OP_SHL_INT: 1007 case OP_SHR_INT: 1008 case OP_USHR_INT: 1009 case OP_ADD_FLOAT: 1010 case OP_SUB_FLOAT: 1011 case OP_MUL_FLOAT: 1012 case OP_DIV_FLOAT: 1013 case OP_REM_FLOAT: 1014 okay &= checkRegisterIndex(meth, decInsn.vA); 1015 okay &= checkRegisterIndex(meth, decInsn.vB); 1016 okay &= checkRegisterIndex(meth, decInsn.vC); 1017 break; 1018 case OP_AGET_WIDE: 1019 case OP_APUT_WIDE: 1020 okay &= checkWideRegisterIndex(meth, decInsn.vA); 1021 okay &= checkRegisterIndex(meth, decInsn.vB); 1022 okay &= checkRegisterIndex(meth, decInsn.vC); 1023 break; 1024 case OP_CMPL_DOUBLE: 1025 case OP_CMPG_DOUBLE: 1026 case OP_CMP_LONG: 1027 okay &= checkRegisterIndex(meth, decInsn.vA); 1028 okay &= checkWideRegisterIndex(meth, decInsn.vB); 1029 okay &= checkWideRegisterIndex(meth, decInsn.vC); 1030 break; 1031 case OP_ADD_DOUBLE: 1032 case OP_SUB_DOUBLE: 1033 case OP_MUL_DOUBLE: 1034 case OP_DIV_DOUBLE: 1035 case OP_REM_DOUBLE: 1036 case OP_ADD_LONG: 1037 case OP_SUB_LONG: 1038 case OP_MUL_LONG: 1039 case OP_DIV_LONG: 1040 case OP_REM_LONG: 1041 case OP_AND_LONG: 1042 case OP_OR_LONG: 1043 case OP_XOR_LONG: 1044 okay &= checkWideRegisterIndex(meth, decInsn.vA); 1045 okay &= checkWideRegisterIndex(meth, decInsn.vB); 1046 okay &= checkWideRegisterIndex(meth, decInsn.vC); 1047 break; 1048 case OP_SHL_LONG: 1049 case OP_SHR_LONG: 1050 case OP_USHR_LONG: 1051 okay &= checkWideRegisterIndex(meth, decInsn.vA); 1052 okay &= checkWideRegisterIndex(meth, decInsn.vB); 1053 okay &= checkRegisterIndex(meth, decInsn.vC); 1054 break; 1055 case OP_IF_EQ: 1056 case OP_IF_NE: 1057 case OP_IF_LT: 1058 case OP_IF_GE: 1059 case OP_IF_GT: 1060 case OP_IF_LE: 1061 okay &= checkRegisterIndex(meth, decInsn.vA); 1062 okay &= checkRegisterIndex(meth, decInsn.vB); 1063 okay &= checkBranchTarget(meth, insnFlags, codeOffset, false); 1064 break; 1065 case OP_IF_EQZ: 1066 case OP_IF_NEZ: 1067 case OP_IF_LTZ: 1068 case OP_IF_GEZ: 1069 case OP_IF_GTZ: 1070 case OP_IF_LEZ: 1071 okay &= checkRegisterIndex(meth, decInsn.vA); 1072 okay &= checkBranchTarget(meth, insnFlags, codeOffset, false); 1073 break; 1074 case OP_IGET: 1075 case OP_IGET_OBJECT: 1076 case OP_IGET_BOOLEAN: 1077 case OP_IGET_BYTE: 1078 case OP_IGET_CHAR: 1079 case OP_IGET_SHORT: 1080 case OP_IPUT: 1081 case OP_IPUT_OBJECT: 1082 case OP_IPUT_BOOLEAN: 1083 case OP_IPUT_BYTE: 1084 case OP_IPUT_CHAR: 1085 case OP_IPUT_SHORT: 1086 okay &= checkRegisterIndex(meth, decInsn.vA); 1087 okay &= checkRegisterIndex(meth, decInsn.vB); 1088 okay &= checkFieldIndex(pDvmDex, decInsn.vC); 1089 break; 1090 case OP_IGET_WIDE: 1091 case OP_IPUT_WIDE: 1092 okay &= checkWideRegisterIndex(meth, decInsn.vA); 1093 okay &= checkRegisterIndex(meth, decInsn.vB); 1094 okay &= checkFieldIndex(pDvmDex, decInsn.vC); 1095 break; 1096 case OP_SGET: 1097 case OP_SGET_OBJECT: 1098 case OP_SGET_BOOLEAN: 1099 case OP_SGET_BYTE: 1100 case OP_SGET_CHAR: 1101 case OP_SGET_SHORT: 1102 case OP_SPUT: 1103 case OP_SPUT_OBJECT: 1104 case OP_SPUT_BOOLEAN: 1105 case OP_SPUT_BYTE: 1106 case OP_SPUT_CHAR: 1107 case OP_SPUT_SHORT: 1108 okay &= checkRegisterIndex(meth, decInsn.vA); 1109 okay &= checkFieldIndex(pDvmDex, decInsn.vB); 1110 break; 1111 case OP_SGET_WIDE: 1112 case OP_SPUT_WIDE: 1113 okay &= checkWideRegisterIndex(meth, decInsn.vA); 1114 okay &= checkFieldIndex(pDvmDex, decInsn.vB); 1115 break; 1116 case OP_FILLED_NEW_ARRAY: 1117 /* decoder uses B, not C, for type ref */ 1118 okay &= checkTypeIndex(pDvmDex, decInsn.vB); 1119 okay &= checkVarargRegs(meth, &decInsn); 1120 break; 1121 case OP_FILLED_NEW_ARRAY_RANGE: 1122 okay &= checkTypeIndex(pDvmDex, decInsn.vB); 1123 okay &= checkVarargRangeRegs(meth, &decInsn); 1124 break; 1125 case OP_INVOKE_VIRTUAL: 1126 case OP_INVOKE_SUPER: 1127 case OP_INVOKE_DIRECT: 1128 case OP_INVOKE_STATIC: 1129 case OP_INVOKE_INTERFACE: 1130 /* decoder uses B, not C, for type ref */ 1131 okay &= checkMethodIndex(pDvmDex, decInsn.vB); 1132 okay &= checkVarargRegs(meth, &decInsn); 1133 break; 1134 case OP_INVOKE_VIRTUAL_RANGE: 1135 case OP_INVOKE_SUPER_RANGE: 1136 case OP_INVOKE_DIRECT_RANGE: 1137 case OP_INVOKE_STATIC_RANGE: 1138 case OP_INVOKE_INTERFACE_RANGE: 1139 okay &= checkMethodIndex(pDvmDex, decInsn.vB); 1140 okay &= checkVarargRangeRegs(meth, &decInsn); 1141 break; 1142 1143 /* verifier/optimizer output; we should never see these */ 1144 case OP_IGET_VOLATILE: 1145 case OP_IPUT_VOLATILE: 1146 case OP_SGET_VOLATILE: 1147 case OP_SPUT_VOLATILE: 1148 case OP_IGET_OBJECT_VOLATILE: 1149 case OP_IPUT_OBJECT_VOLATILE: 1150 case OP_SGET_OBJECT_VOLATILE: 1151 case OP_SPUT_OBJECT_VOLATILE: 1152 case OP_IGET_WIDE_VOLATILE: 1153 case OP_IPUT_WIDE_VOLATILE: 1154 case OP_SGET_WIDE_VOLATILE: 1155 case OP_SPUT_WIDE_VOLATILE: 1156 case OP_BREAKPOINT: 1157 case OP_THROW_VERIFICATION_ERROR: 1158 case OP_EXECUTE_INLINE: 1159 case OP_EXECUTE_INLINE_RANGE: 1160 case OP_INVOKE_OBJECT_INIT_RANGE: 1161 case OP_RETURN_VOID_BARRIER: 1162 case OP_IGET_QUICK: 1163 case OP_IGET_WIDE_QUICK: 1164 case OP_IGET_OBJECT_QUICK: 1165 case OP_IPUT_QUICK: 1166 case OP_IPUT_WIDE_QUICK: 1167 case OP_IPUT_OBJECT_QUICK: 1168 case OP_INVOKE_VIRTUAL_QUICK: 1169 case OP_INVOKE_VIRTUAL_QUICK_RANGE: 1170 case OP_INVOKE_SUPER_QUICK: 1171 case OP_INVOKE_SUPER_QUICK_RANGE: 1172 case OP_UNUSED_3E: 1173 case OP_UNUSED_3F: 1174 case OP_UNUSED_40: 1175 case OP_UNUSED_41: 1176 case OP_UNUSED_42: 1177 case OP_UNUSED_43: 1178 case OP_UNUSED_73: 1179 case OP_UNUSED_79: 1180 case OP_UNUSED_7A: 1181 case OP_UNUSED_FF: 1182 ALOGE("VFY: unexpected opcode %04x", decInsn.opcode); 1183 okay = false; 1184 break; 1185 1186 /* 1187 * DO NOT add a "default" clause here. Without it the compiler will 1188 * complain if an instruction is missing (which is desirable). 1189 */ 1190 } 1191 1192 if (!okay) { 1193 LOG_VFY_METH(meth, "VFY: rejecting opcode 0x%02x at 0x%04x", 1194 decInsn.opcode, codeOffset); 1195 return false; 1196 } 1197 1198 OpcodeFlags opFlags = dexGetFlagsFromOpcode(decInsn.opcode); 1199 if ((opFlags & VERIFY_GC_INST_MASK) != 0) { 1200 /* 1201 * This instruction is a GC point. If space is a concern, 1202 * the set of GC points could be reduced by eliminating 1203 * foward branches. 1204 * 1205 * TODO: we could also scan the targets of a "switch" statement, 1206 * and if none of them branch backward we could ignore that 1207 * instruction as well. 1208 */ 1209 dvmInsnSetGcPoint(insnFlags, codeOffset, true); 1210 } 1211 1212 assert(width > 0); 1213 codeOffset += width; 1214 insns += width; 1215 } 1216 1217 /* make sure the last instruction ends at the end of the insn area */ 1218 if (codeOffset != vdata->insnsSize) { 1219 LOG_VFY_METH(meth, 1220 "VFY: code did not end when expected (end at %d, count %d)", 1221 codeOffset, vdata->insnsSize); 1222 return false; 1223 } 1224 1225 return true; 1226 } 1227