1 /* 2 * Javassist, a Java-bytecode translator toolkit. 3 * Copyright (C) 1999-2007 Shigeru Chiba, and others. All Rights Reserved. 4 * 5 * The contents of this file are subject to the Mozilla Public License Version 6 * 1.1 (the "License"); you may not use this file except in compliance with 7 * the License. Alternatively, the contents of this file may be used under 8 * the terms of the GNU Lesser General Public License Version 2.1 or later. 9 * 10 * Software distributed under the License is distributed on an "AS IS" basis, 11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 12 * for the specific language governing rights and limitations under the 13 * License. 14 */ 15 package javassist.bytecode.analysis; 16 17 import javassist.ClassPool; 18 import javassist.CtClass; 19 import javassist.NotFoundException; 20 import javassist.bytecode.BadBytecode; 21 import javassist.bytecode.CodeIterator; 22 import javassist.bytecode.ConstPool; 23 import javassist.bytecode.Descriptor; 24 import javassist.bytecode.MethodInfo; 25 import javassist.bytecode.Opcode; 26 27 /** 28 * Executor is responsible for modeling the effects of a JVM instruction on a frame. 29 * 30 * @author Jason T. Greene 31 */ 32 public class Executor implements Opcode { 33 private final ConstPool constPool; 34 private final ClassPool classPool; 35 private final Type STRING_TYPE; 36 private final Type CLASS_TYPE; 37 private final Type THROWABLE_TYPE; 38 private int lastPos; 39 Executor(ClassPool classPool, ConstPool constPool)40 public Executor(ClassPool classPool, ConstPool constPool) { 41 this.constPool = constPool; 42 this.classPool = classPool; 43 44 try { 45 STRING_TYPE = getType("java.lang.String"); 46 CLASS_TYPE = getType("java.lang.Class"); 47 THROWABLE_TYPE = getType("java.lang.Throwable"); 48 } catch (Exception e) { 49 throw new RuntimeException(e); 50 } 51 } 52 53 54 /** 55 * Execute the instruction, modeling the effects on the specified frame and subroutine. 56 * If a subroutine is passed, the access flags will be modified if this instruction accesses 57 * the local variable table. 58 * 59 * @param method the method containing the instruction 60 * @param pos the position of the instruction in the method 61 * @param iter the code iterator used to find the instruction 62 * @param frame the frame to modify to represent the result of the instruction 63 * @param subroutine the optional subroutine this instruction belongs to. 64 * @throws BadBytecode if the bytecode violates the jvm spec 65 */ execute(MethodInfo method, int pos, CodeIterator iter, Frame frame, Subroutine subroutine)66 public void execute(MethodInfo method, int pos, CodeIterator iter, Frame frame, Subroutine subroutine) throws BadBytecode { 67 this.lastPos = pos; 68 int opcode = iter.byteAt(pos); 69 70 71 // Declared opcode in order 72 switch (opcode) { 73 case NOP: 74 break; 75 case ACONST_NULL: 76 frame.push(Type.UNINIT); 77 break; 78 case ICONST_M1: 79 case ICONST_0: 80 case ICONST_1: 81 case ICONST_2: 82 case ICONST_3: 83 case ICONST_4: 84 case ICONST_5: 85 frame.push(Type.INTEGER); 86 break; 87 case LCONST_0: 88 case LCONST_1: 89 frame.push(Type.LONG); 90 frame.push(Type.TOP); 91 break; 92 case FCONST_0: 93 case FCONST_1: 94 case FCONST_2: 95 frame.push(Type.FLOAT); 96 break; 97 case DCONST_0: 98 case DCONST_1: 99 frame.push(Type.DOUBLE); 100 frame.push(Type.TOP); 101 break; 102 case BIPUSH: 103 case SIPUSH: 104 frame.push(Type.INTEGER); 105 break; 106 case LDC: 107 evalLDC(iter.byteAt(pos + 1), frame); 108 break; 109 case LDC_W : 110 case LDC2_W : 111 evalLDC(iter.u16bitAt(pos + 1), frame); 112 break; 113 case ILOAD: 114 evalLoad(Type.INTEGER, iter.byteAt(pos + 1), frame, subroutine); 115 break; 116 case LLOAD: 117 evalLoad(Type.LONG, iter.byteAt(pos + 1), frame, subroutine); 118 break; 119 case FLOAD: 120 evalLoad(Type.FLOAT, iter.byteAt(pos + 1), frame, subroutine); 121 break; 122 case DLOAD: 123 evalLoad(Type.DOUBLE, iter.byteAt(pos + 1), frame, subroutine); 124 break; 125 case ALOAD: 126 evalLoad(Type.OBJECT, iter.byteAt(pos + 1), frame, subroutine); 127 break; 128 case ILOAD_0: 129 case ILOAD_1: 130 case ILOAD_2: 131 case ILOAD_3: 132 evalLoad(Type.INTEGER, opcode - ILOAD_0, frame, subroutine); 133 break; 134 case LLOAD_0: 135 case LLOAD_1: 136 case LLOAD_2: 137 case LLOAD_3: 138 evalLoad(Type.LONG, opcode - LLOAD_0, frame, subroutine); 139 break; 140 case FLOAD_0: 141 case FLOAD_1: 142 case FLOAD_2: 143 case FLOAD_3: 144 evalLoad(Type.FLOAT, opcode - FLOAD_0, frame, subroutine); 145 break; 146 case DLOAD_0: 147 case DLOAD_1: 148 case DLOAD_2: 149 case DLOAD_3: 150 evalLoad(Type.DOUBLE, opcode - DLOAD_0, frame, subroutine); 151 break; 152 case ALOAD_0: 153 case ALOAD_1: 154 case ALOAD_2: 155 case ALOAD_3: 156 evalLoad(Type.OBJECT, opcode - ALOAD_0, frame, subroutine); 157 break; 158 case IALOAD: 159 evalArrayLoad(Type.INTEGER, frame); 160 break; 161 case LALOAD: 162 evalArrayLoad(Type.LONG, frame); 163 break; 164 case FALOAD: 165 evalArrayLoad(Type.FLOAT, frame); 166 break; 167 case DALOAD: 168 evalArrayLoad(Type.DOUBLE, frame); 169 break; 170 case AALOAD: 171 evalArrayLoad(Type.OBJECT, frame); 172 break; 173 case BALOAD: 174 case CALOAD: 175 case SALOAD: 176 evalArrayLoad(Type.INTEGER, frame); 177 break; 178 case ISTORE: 179 evalStore(Type.INTEGER, iter.byteAt(pos + 1), frame, subroutine); 180 break; 181 case LSTORE: 182 evalStore(Type.LONG, iter.byteAt(pos + 1), frame, subroutine); 183 break; 184 case FSTORE: 185 evalStore(Type.FLOAT, iter.byteAt(pos + 1), frame, subroutine); 186 break; 187 case DSTORE: 188 evalStore(Type.DOUBLE, iter.byteAt(pos + 1), frame, subroutine); 189 break; 190 case ASTORE: 191 evalStore(Type.OBJECT, iter.byteAt(pos + 1), frame, subroutine); 192 break; 193 case ISTORE_0: 194 case ISTORE_1: 195 case ISTORE_2: 196 case ISTORE_3: 197 evalStore(Type.INTEGER, opcode - ISTORE_0, frame, subroutine); 198 break; 199 case LSTORE_0: 200 case LSTORE_1: 201 case LSTORE_2: 202 case LSTORE_3: 203 evalStore(Type.LONG, opcode - LSTORE_0, frame, subroutine); 204 break; 205 case FSTORE_0: 206 case FSTORE_1: 207 case FSTORE_2: 208 case FSTORE_3: 209 evalStore(Type.FLOAT, opcode - FSTORE_0, frame, subroutine); 210 break; 211 case DSTORE_0: 212 case DSTORE_1: 213 case DSTORE_2: 214 case DSTORE_3: 215 evalStore(Type.DOUBLE, opcode - DSTORE_0, frame, subroutine); 216 break; 217 case ASTORE_0: 218 case ASTORE_1: 219 case ASTORE_2: 220 case ASTORE_3: 221 evalStore(Type.OBJECT, opcode - ASTORE_0, frame, subroutine); 222 break; 223 case IASTORE: 224 evalArrayStore(Type.INTEGER, frame); 225 break; 226 case LASTORE: 227 evalArrayStore(Type.LONG, frame); 228 break; 229 case FASTORE: 230 evalArrayStore(Type.FLOAT, frame); 231 break; 232 case DASTORE: 233 evalArrayStore(Type.DOUBLE, frame); 234 break; 235 case AASTORE: 236 evalArrayStore(Type.OBJECT, frame); 237 break; 238 case BASTORE: 239 case CASTORE: 240 case SASTORE: 241 evalArrayStore(Type.INTEGER, frame); 242 break; 243 case POP: 244 if (frame.pop() == Type.TOP) 245 throw new BadBytecode("POP can not be used with a category 2 value, pos = " + pos); 246 break; 247 case POP2: 248 frame.pop(); 249 frame.pop(); 250 break; 251 case DUP: { 252 Type type = frame.peek(); 253 if (type == Type.TOP) 254 throw new BadBytecode("DUP can not be used with a category 2 value, pos = " + pos); 255 256 frame.push(frame.peek()); 257 break; 258 } 259 case DUP_X1: 260 case DUP_X2: { 261 Type type = frame.peek(); 262 if (type == Type.TOP) 263 throw new BadBytecode("DUP can not be used with a category 2 value, pos = " + pos); 264 int end = frame.getTopIndex(); 265 int insert = end - (opcode - DUP_X1) - 1; 266 frame.push(type); 267 268 while (end > insert) { 269 frame.setStack(end, frame.getStack(end - 1)); 270 end--; 271 } 272 frame.setStack(insert, type); 273 break; 274 } 275 case DUP2: 276 frame.push(frame.getStack(frame.getTopIndex() - 1)); 277 frame.push(frame.getStack(frame.getTopIndex() - 1)); 278 break; 279 case DUP2_X1: 280 case DUP2_X2: { 281 int end = frame.getTopIndex(); 282 int insert = end - (opcode - DUP2_X1) - 1; 283 Type type1 = frame.getStack(frame.getTopIndex() - 1); 284 Type type2 = frame.peek(); 285 frame.push(type1); 286 frame.push(type2); 287 while (end > insert) { 288 frame.setStack(end, frame.getStack(end - 2)); 289 end--; 290 } 291 frame.setStack(insert, type2); 292 frame.setStack(insert - 1, type1); 293 break; 294 } 295 case SWAP: { 296 Type type1 = frame.pop(); 297 Type type2 = frame.pop(); 298 if (type1.getSize() == 2 || type2.getSize() == 2) 299 throw new BadBytecode("Swap can not be used with category 2 values, pos = " + pos); 300 frame.push(type1); 301 frame.push(type2); 302 break; 303 } 304 305 // Math 306 case IADD: 307 evalBinaryMath(Type.INTEGER, frame); 308 break; 309 case LADD: 310 evalBinaryMath(Type.LONG, frame); 311 break; 312 case FADD: 313 evalBinaryMath(Type.FLOAT, frame); 314 break; 315 case DADD: 316 evalBinaryMath(Type.DOUBLE, frame); 317 break; 318 case ISUB: 319 evalBinaryMath(Type.INTEGER, frame); 320 break; 321 case LSUB: 322 evalBinaryMath(Type.LONG, frame); 323 break; 324 case FSUB: 325 evalBinaryMath(Type.FLOAT, frame); 326 break; 327 case DSUB: 328 evalBinaryMath(Type.DOUBLE, frame); 329 break; 330 case IMUL: 331 evalBinaryMath(Type.INTEGER, frame); 332 break; 333 case LMUL: 334 evalBinaryMath(Type.LONG, frame); 335 break; 336 case FMUL: 337 evalBinaryMath(Type.FLOAT, frame); 338 break; 339 case DMUL: 340 evalBinaryMath(Type.DOUBLE, frame); 341 break; 342 case IDIV: 343 evalBinaryMath(Type.INTEGER, frame); 344 break; 345 case LDIV: 346 evalBinaryMath(Type.LONG, frame); 347 break; 348 case FDIV: 349 evalBinaryMath(Type.FLOAT, frame); 350 break; 351 case DDIV: 352 evalBinaryMath(Type.DOUBLE, frame); 353 break; 354 case IREM: 355 evalBinaryMath(Type.INTEGER, frame); 356 break; 357 case LREM: 358 evalBinaryMath(Type.LONG, frame); 359 break; 360 case FREM: 361 evalBinaryMath(Type.FLOAT, frame); 362 break; 363 case DREM: 364 evalBinaryMath(Type.DOUBLE, frame); 365 break; 366 367 // Unary 368 case INEG: 369 verifyAssignable(Type.INTEGER, simplePeek(frame)); 370 break; 371 case LNEG: 372 verifyAssignable(Type.LONG, simplePeek(frame)); 373 break; 374 case FNEG: 375 verifyAssignable(Type.FLOAT, simplePeek(frame)); 376 break; 377 case DNEG: 378 verifyAssignable(Type.DOUBLE, simplePeek(frame)); 379 break; 380 381 // Shifts 382 case ISHL: 383 evalShift(Type.INTEGER, frame); 384 break; 385 case LSHL: 386 evalShift(Type.LONG, frame); 387 break; 388 case ISHR: 389 evalShift(Type.INTEGER, frame); 390 break; 391 case LSHR: 392 evalShift(Type.LONG, frame); 393 break; 394 case IUSHR: 395 evalShift(Type.INTEGER,frame); 396 break; 397 case LUSHR: 398 evalShift(Type.LONG, frame); 399 break; 400 401 // Bitwise Math 402 case IAND: 403 evalBinaryMath(Type.INTEGER, frame); 404 break; 405 case LAND: 406 evalBinaryMath(Type.LONG, frame); 407 break; 408 case IOR: 409 evalBinaryMath(Type.INTEGER, frame); 410 break; 411 case LOR: 412 evalBinaryMath(Type.LONG, frame); 413 break; 414 case IXOR: 415 evalBinaryMath(Type.INTEGER, frame); 416 break; 417 case LXOR: 418 evalBinaryMath(Type.LONG, frame); 419 break; 420 421 case IINC: { 422 int index = iter.byteAt(pos + 1); 423 verifyAssignable(Type.INTEGER, frame.getLocal(index)); 424 access(index, Type.INTEGER, subroutine); 425 break; 426 } 427 428 // Conversion 429 case I2L: 430 verifyAssignable(Type.INTEGER, simplePop(frame)); 431 simplePush(Type.LONG, frame); 432 break; 433 case I2F: 434 verifyAssignable(Type.INTEGER, simplePop(frame)); 435 simplePush(Type.FLOAT, frame); 436 break; 437 case I2D: 438 verifyAssignable(Type.INTEGER, simplePop(frame)); 439 simplePush(Type.DOUBLE, frame); 440 break; 441 case L2I: 442 verifyAssignable(Type.LONG, simplePop(frame)); 443 simplePush(Type.INTEGER, frame); 444 break; 445 case L2F: 446 verifyAssignable(Type.LONG, simplePop(frame)); 447 simplePush(Type.FLOAT, frame); 448 break; 449 case L2D: 450 verifyAssignable(Type.LONG, simplePop(frame)); 451 simplePush(Type.DOUBLE, frame); 452 break; 453 case F2I: 454 verifyAssignable(Type.FLOAT, simplePop(frame)); 455 simplePush(Type.INTEGER, frame); 456 break; 457 case F2L: 458 verifyAssignable(Type.FLOAT, simplePop(frame)); 459 simplePush(Type.LONG, frame); 460 break; 461 case F2D: 462 verifyAssignable(Type.FLOAT, simplePop(frame)); 463 simplePush(Type.DOUBLE, frame); 464 break; 465 case D2I: 466 verifyAssignable(Type.DOUBLE, simplePop(frame)); 467 simplePush(Type.INTEGER, frame); 468 break; 469 case D2L: 470 verifyAssignable(Type.DOUBLE, simplePop(frame)); 471 simplePush(Type.LONG, frame); 472 break; 473 case D2F: 474 verifyAssignable(Type.DOUBLE, simplePop(frame)); 475 simplePush(Type.FLOAT, frame); 476 break; 477 case I2B: 478 case I2C: 479 case I2S: 480 verifyAssignable(Type.INTEGER, frame.peek()); 481 break; 482 case LCMP: 483 verifyAssignable(Type.LONG, simplePop(frame)); 484 verifyAssignable(Type.LONG, simplePop(frame)); 485 frame.push(Type.INTEGER); 486 break; 487 case FCMPL: 488 case FCMPG: 489 verifyAssignable(Type.FLOAT, simplePop(frame)); 490 verifyAssignable(Type.FLOAT, simplePop(frame)); 491 frame.push(Type.INTEGER); 492 break; 493 case DCMPL: 494 case DCMPG: 495 verifyAssignable(Type.DOUBLE, simplePop(frame)); 496 verifyAssignable(Type.DOUBLE, simplePop(frame)); 497 frame.push(Type.INTEGER); 498 break; 499 500 // Control flow 501 case IFEQ: 502 case IFNE: 503 case IFLT: 504 case IFGE: 505 case IFGT: 506 case IFLE: 507 verifyAssignable(Type.INTEGER, simplePop(frame)); 508 break; 509 case IF_ICMPEQ: 510 case IF_ICMPNE: 511 case IF_ICMPLT: 512 case IF_ICMPGE: 513 case IF_ICMPGT: 514 case IF_ICMPLE: 515 verifyAssignable(Type.INTEGER, simplePop(frame)); 516 verifyAssignable(Type.INTEGER, simplePop(frame)); 517 break; 518 case IF_ACMPEQ: 519 case IF_ACMPNE: 520 verifyAssignable(Type.OBJECT, simplePop(frame)); 521 verifyAssignable(Type.OBJECT, simplePop(frame)); 522 break; 523 case GOTO: 524 break; 525 case JSR: 526 frame.push(Type.RETURN_ADDRESS); 527 break; 528 case RET: 529 verifyAssignable(Type.RETURN_ADDRESS, frame.getLocal(iter.byteAt(pos + 1))); 530 break; 531 case TABLESWITCH: 532 case LOOKUPSWITCH: 533 case IRETURN: 534 verifyAssignable(Type.INTEGER, simplePop(frame)); 535 break; 536 case LRETURN: 537 verifyAssignable(Type.LONG, simplePop(frame)); 538 break; 539 case FRETURN: 540 verifyAssignable(Type.FLOAT, simplePop(frame)); 541 break; 542 case DRETURN: 543 verifyAssignable(Type.DOUBLE, simplePop(frame)); 544 break; 545 case ARETURN: 546 try { 547 CtClass returnType = Descriptor.getReturnType(method.getDescriptor(), classPool); 548 verifyAssignable(Type.get(returnType), simplePop(frame)); 549 } catch (NotFoundException e) { 550 throw new RuntimeException(e); 551 } 552 break; 553 case RETURN: 554 break; 555 case GETSTATIC: 556 evalGetField(opcode, iter.u16bitAt(pos + 1), frame); 557 break; 558 case PUTSTATIC: 559 evalPutField(opcode, iter.u16bitAt(pos + 1), frame); 560 break; 561 case GETFIELD: 562 evalGetField(opcode, iter.u16bitAt(pos + 1), frame); 563 break; 564 case PUTFIELD: 565 evalPutField(opcode, iter.u16bitAt(pos + 1), frame); 566 break; 567 case INVOKEVIRTUAL: 568 case INVOKESPECIAL: 569 case INVOKESTATIC: 570 evalInvokeMethod(opcode, iter.u16bitAt(pos + 1), frame); 571 break; 572 case INVOKEINTERFACE: 573 evalInvokeIntfMethod(opcode, iter.u16bitAt(pos + 1), frame); 574 break; 575 case 186: 576 throw new RuntimeException("Bad opcode 186"); 577 case NEW: 578 frame.push(resolveClassInfo(constPool.getClassInfo(iter.u16bitAt(pos + 1)))); 579 break; 580 case NEWARRAY: 581 evalNewArray(pos, iter, frame); 582 break; 583 case ANEWARRAY: 584 evalNewObjectArray(pos, iter, frame); 585 break; 586 case ARRAYLENGTH: { 587 Type array = simplePop(frame); 588 if (! array.isArray() && array != Type.UNINIT) 589 throw new BadBytecode("Array length passed a non-array [pos = " + pos + "]: " + array); 590 frame.push(Type.INTEGER); 591 break; 592 } 593 case ATHROW: 594 verifyAssignable(THROWABLE_TYPE, simplePop(frame)); 595 break; 596 case CHECKCAST: 597 verifyAssignable(Type.OBJECT, simplePop(frame)); 598 frame.push(typeFromDesc(constPool.getClassInfo(iter.u16bitAt(pos + 1)))); 599 break; 600 case INSTANCEOF: 601 verifyAssignable(Type.OBJECT, simplePop(frame)); 602 frame.push(Type.INTEGER); 603 break; 604 case MONITORENTER: 605 case MONITOREXIT: 606 verifyAssignable(Type.OBJECT, simplePop(frame)); 607 break; 608 case WIDE: 609 evalWide(pos, iter, frame, subroutine); 610 break; 611 case MULTIANEWARRAY: 612 evalNewObjectArray(pos, iter, frame); 613 break; 614 case IFNULL: 615 case IFNONNULL: 616 verifyAssignable(Type.OBJECT, simplePop(frame)); 617 break; 618 case GOTO_W: 619 break; 620 case JSR_W: 621 frame.push(Type.RETURN_ADDRESS); 622 break; 623 } 624 } 625 zeroExtend(Type type)626 private Type zeroExtend(Type type) { 627 if (type == Type.SHORT || type == Type.BYTE || type == Type.CHAR || type == Type.BOOLEAN) 628 return Type.INTEGER; 629 630 return type; 631 } 632 evalArrayLoad(Type expectedComponent, Frame frame)633 private void evalArrayLoad(Type expectedComponent, Frame frame) throws BadBytecode { 634 Type index = frame.pop(); 635 Type array = frame.pop(); 636 637 // Special case, an array defined by aconst_null 638 // TODO - we might need to be more inteligent about this 639 if (array == Type.UNINIT) { 640 verifyAssignable(Type.INTEGER, index); 641 if (expectedComponent == Type.OBJECT) { 642 simplePush(Type.UNINIT, frame); 643 } else { 644 simplePush(expectedComponent, frame); 645 } 646 return; 647 } 648 649 Type component = array.getComponent(); 650 651 if (component == null) 652 throw new BadBytecode("Not an array! [pos = " + lastPos + "]: " + component); 653 654 component = zeroExtend(component); 655 656 verifyAssignable(expectedComponent, component); 657 verifyAssignable(Type.INTEGER, index); 658 simplePush(component, frame); 659 } 660 evalArrayStore(Type expectedComponent, Frame frame)661 private void evalArrayStore(Type expectedComponent, Frame frame) throws BadBytecode { 662 Type value = simplePop(frame); 663 Type index = frame.pop(); 664 Type array = frame.pop(); 665 666 if (array == Type.UNINIT) { 667 verifyAssignable(Type.INTEGER, index); 668 return; 669 } 670 671 Type component = array.getComponent(); 672 673 if (component == null) 674 throw new BadBytecode("Not an array! [pos = " + lastPos + "]: " + component); 675 676 component = zeroExtend(component); 677 678 verifyAssignable(expectedComponent, component); 679 verifyAssignable(Type.INTEGER, index); 680 681 // This intentionally only checks for Object on aastore 682 // downconverting of an array (no casts) 683 // e.g. Object[] blah = new String[]; 684 // blah[2] = (Object) "test"; 685 // blah[3] = new Integer(); // compiler doesnt catch it (has legal bytecode), 686 // // but will throw arraystoreexception 687 if (expectedComponent == Type.OBJECT) { 688 verifyAssignable(expectedComponent, value); 689 } else { 690 verifyAssignable(component, value); 691 } 692 } 693 evalBinaryMath(Type expected, Frame frame)694 private void evalBinaryMath(Type expected, Frame frame) throws BadBytecode { 695 Type value2 = simplePop(frame); 696 Type value1 = simplePop(frame); 697 698 verifyAssignable(expected, value2); 699 verifyAssignable(expected, value1); 700 simplePush(value1, frame); 701 } 702 evalGetField(int opcode, int index, Frame frame)703 private void evalGetField(int opcode, int index, Frame frame) throws BadBytecode { 704 String desc = constPool.getFieldrefType(index); 705 Type type = zeroExtend(typeFromDesc(desc)); 706 707 if (opcode == GETFIELD) { 708 Type objectType = resolveClassInfo(constPool.getFieldrefClassName(index)); 709 verifyAssignable(objectType, simplePop(frame)); 710 } 711 712 simplePush(type, frame); 713 } 714 evalInvokeIntfMethod(int opcode, int index, Frame frame)715 private void evalInvokeIntfMethod(int opcode, int index, Frame frame) throws BadBytecode { 716 String desc = constPool.getInterfaceMethodrefType(index); 717 Type[] types = paramTypesFromDesc(desc); 718 int i = types.length; 719 720 while (i > 0) 721 verifyAssignable(zeroExtend(types[--i]), simplePop(frame)); 722 723 String classInfo = constPool.getInterfaceMethodrefClassName(index); 724 Type objectType = resolveClassInfo(classInfo); 725 verifyAssignable(objectType, simplePop(frame)); 726 727 Type returnType = returnTypeFromDesc(desc); 728 if (returnType != Type.VOID) 729 simplePush(zeroExtend(returnType), frame); 730 } 731 evalInvokeMethod(int opcode, int index, Frame frame)732 private void evalInvokeMethod(int opcode, int index, Frame frame) throws BadBytecode { 733 String desc = constPool.getMethodrefType(index); 734 Type[] types = paramTypesFromDesc(desc); 735 int i = types.length; 736 737 while (i > 0) 738 verifyAssignable(zeroExtend(types[--i]), simplePop(frame)); 739 740 if (opcode != INVOKESTATIC) { 741 Type objectType = resolveClassInfo(constPool.getMethodrefClassName(index)); 742 verifyAssignable(objectType, simplePop(frame)); 743 } 744 745 Type returnType = returnTypeFromDesc(desc); 746 if (returnType != Type.VOID) 747 simplePush(zeroExtend(returnType), frame); 748 } 749 750 evalLDC(int index, Frame frame)751 private void evalLDC(int index, Frame frame) throws BadBytecode { 752 int tag = constPool.getTag(index); 753 Type type; 754 switch (tag) { 755 case ConstPool.CONST_String: 756 type = STRING_TYPE; 757 break; 758 case ConstPool.CONST_Integer: 759 type = Type.INTEGER; 760 break; 761 case ConstPool.CONST_Float: 762 type = Type.FLOAT; 763 break; 764 case ConstPool.CONST_Long: 765 type = Type.LONG; 766 break; 767 case ConstPool.CONST_Double: 768 type = Type.DOUBLE; 769 break; 770 case ConstPool.CONST_Class: 771 type = CLASS_TYPE; 772 break; 773 default: 774 throw new BadBytecode("bad LDC [pos = " + lastPos + "]: " + tag); 775 } 776 777 simplePush(type, frame); 778 } 779 evalLoad(Type expected, int index, Frame frame, Subroutine subroutine)780 private void evalLoad(Type expected, int index, Frame frame, Subroutine subroutine) throws BadBytecode { 781 Type type = frame.getLocal(index); 782 783 verifyAssignable(expected, type); 784 785 simplePush(type, frame); 786 access(index, type, subroutine); 787 } 788 evalNewArray(int pos, CodeIterator iter, Frame frame)789 private void evalNewArray(int pos, CodeIterator iter, Frame frame) throws BadBytecode { 790 verifyAssignable(Type.INTEGER, simplePop(frame)); 791 Type type = null; 792 int typeInfo = iter.byteAt(pos + 1); 793 switch (typeInfo) { 794 case T_BOOLEAN: 795 type = getType("boolean[]"); 796 break; 797 case T_CHAR: 798 type = getType("char[]"); 799 break; 800 case T_BYTE: 801 type = getType("byte[]"); 802 break; 803 case T_SHORT: 804 type = getType("short[]"); 805 break; 806 case T_INT: 807 type = getType("int[]"); 808 break; 809 case T_LONG: 810 type = getType("long[]"); 811 break; 812 case T_FLOAT: 813 type = getType("float[]"); 814 break; 815 case T_DOUBLE: 816 type = getType("double[]"); 817 break; 818 default: 819 throw new BadBytecode("Invalid array type [pos = " + pos + "]: " + typeInfo); 820 821 } 822 823 frame.push(type); 824 } 825 evalNewObjectArray(int pos, CodeIterator iter, Frame frame)826 private void evalNewObjectArray(int pos, CodeIterator iter, Frame frame) throws BadBytecode { 827 // Convert to x[] format 828 Type type = resolveClassInfo(constPool.getClassInfo(iter.u16bitAt(pos + 1))); 829 String name = type.getCtClass().getName(); 830 int opcode = iter.byteAt(pos); 831 int dimensions; 832 833 if (opcode == MULTIANEWARRAY) { 834 dimensions = iter.byteAt(pos + 3); 835 } else { 836 name = name + "[]"; 837 dimensions = 1; 838 } 839 840 while (dimensions-- > 0) { 841 verifyAssignable(Type.INTEGER, simplePop(frame)); 842 } 843 844 simplePush(getType(name), frame); 845 } 846 evalPutField(int opcode, int index, Frame frame)847 private void evalPutField(int opcode, int index, Frame frame) throws BadBytecode { 848 String desc = constPool.getFieldrefType(index); 849 Type type = zeroExtend(typeFromDesc(desc)); 850 851 verifyAssignable(type, simplePop(frame)); 852 853 if (opcode == PUTFIELD) { 854 Type objectType = resolveClassInfo(constPool.getFieldrefClassName(index)); 855 verifyAssignable(objectType, simplePop(frame)); 856 } 857 } 858 evalShift(Type expected, Frame frame)859 private void evalShift(Type expected, Frame frame) throws BadBytecode { 860 Type value2 = simplePop(frame); 861 Type value1 = simplePop(frame); 862 863 verifyAssignable(Type.INTEGER, value2); 864 verifyAssignable(expected, value1); 865 simplePush(value1, frame); 866 } 867 evalStore(Type expected, int index, Frame frame, Subroutine subroutine)868 private void evalStore(Type expected, int index, Frame frame, Subroutine subroutine) throws BadBytecode { 869 Type type = simplePop(frame); 870 871 // RETURN_ADDRESS is allowed by ASTORE 872 if (! (expected == Type.OBJECT && type == Type.RETURN_ADDRESS)) 873 verifyAssignable(expected, type); 874 simpleSetLocal(index, type, frame); 875 access(index, type, subroutine); 876 } 877 evalWide(int pos, CodeIterator iter, Frame frame, Subroutine subroutine)878 private void evalWide(int pos, CodeIterator iter, Frame frame, Subroutine subroutine) throws BadBytecode { 879 int opcode = iter.byteAt(pos + 1); 880 int index = iter.u16bitAt(pos + 2); 881 switch (opcode) { 882 case ILOAD: 883 evalLoad(Type.INTEGER, index, frame, subroutine); 884 break; 885 case LLOAD: 886 evalLoad(Type.LONG, index, frame, subroutine); 887 break; 888 case FLOAD: 889 evalLoad(Type.FLOAT, index, frame, subroutine); 890 break; 891 case DLOAD: 892 evalLoad(Type.DOUBLE, index, frame, subroutine); 893 break; 894 case ALOAD: 895 evalLoad(Type.OBJECT, index, frame, subroutine); 896 break; 897 case ISTORE: 898 evalStore(Type.INTEGER, index, frame, subroutine); 899 break; 900 case LSTORE: 901 evalStore(Type.LONG, index, frame, subroutine); 902 break; 903 case FSTORE: 904 evalStore(Type.FLOAT, index, frame, subroutine); 905 break; 906 case DSTORE: 907 evalStore(Type.DOUBLE, index, frame, subroutine); 908 break; 909 case ASTORE: 910 evalStore(Type.OBJECT, index, frame, subroutine); 911 break; 912 case IINC: 913 verifyAssignable(Type.INTEGER, frame.getLocal(index)); 914 break; 915 case RET: 916 verifyAssignable(Type.RETURN_ADDRESS, frame.getLocal(index)); 917 break; 918 default: 919 throw new BadBytecode("Invalid WIDE operand [pos = " + pos + "]: " + opcode); 920 } 921 922 } 923 getType(String name)924 private Type getType(String name) throws BadBytecode { 925 try { 926 return Type.get(classPool.get(name)); 927 } catch (NotFoundException e) { 928 throw new BadBytecode("Could not find class [pos = " + lastPos + "]: " + name); 929 } 930 } 931 paramTypesFromDesc(String desc)932 private Type[] paramTypesFromDesc(String desc) throws BadBytecode { 933 CtClass classes[] = null; 934 try { 935 classes = Descriptor.getParameterTypes(desc, classPool); 936 } catch (NotFoundException e) { 937 throw new BadBytecode("Could not find class in descriptor [pos = " + lastPos + "]: " + e.getMessage()); 938 } 939 940 if (classes == null) 941 throw new BadBytecode("Could not obtain parameters for descriptor [pos = " + lastPos + "]: " + desc); 942 943 Type[] types = new Type[classes.length]; 944 for (int i = 0; i < types.length; i++) 945 types[i] = Type.get(classes[i]); 946 947 return types; 948 } 949 returnTypeFromDesc(String desc)950 private Type returnTypeFromDesc(String desc) throws BadBytecode { 951 CtClass clazz = null; 952 try { 953 clazz = Descriptor.getReturnType(desc, classPool); 954 } catch (NotFoundException e) { 955 throw new BadBytecode("Could not find class in descriptor [pos = " + lastPos + "]: " + e.getMessage()); 956 } 957 958 if (clazz == null) 959 throw new BadBytecode("Could not obtain return type for descriptor [pos = " + lastPos + "]: " + desc); 960 961 return Type.get(clazz); 962 } 963 simplePeek(Frame frame)964 private Type simplePeek(Frame frame) { 965 Type type = frame.peek(); 966 return (type == Type.TOP) ? frame.getStack(frame.getTopIndex() - 1) : type; 967 } 968 simplePop(Frame frame)969 private Type simplePop(Frame frame) { 970 Type type = frame.pop(); 971 return (type == Type.TOP) ? frame.pop() : type; 972 } 973 simplePush(Type type, Frame frame)974 private void simplePush(Type type, Frame frame) { 975 frame.push(type); 976 if (type.getSize() == 2) 977 frame.push(Type.TOP); 978 } 979 access(int index, Type type, Subroutine subroutine)980 private void access(int index, Type type, Subroutine subroutine) { 981 if (subroutine == null) 982 return; 983 subroutine.access(index); 984 if (type.getSize() == 2) 985 subroutine.access(index + 1); 986 } 987 simpleSetLocal(int index, Type type, Frame frame)988 private void simpleSetLocal(int index, Type type, Frame frame) { 989 frame.setLocal(index, type); 990 if (type.getSize() == 2) 991 frame.setLocal(index + 1, Type.TOP); 992 } 993 resolveClassInfo(String info)994 private Type resolveClassInfo(String info) throws BadBytecode { 995 CtClass clazz = null; 996 try { 997 if (info.charAt(0) == '[') { 998 clazz = Descriptor.toCtClass(info, classPool); 999 } else { 1000 clazz = classPool.get(info); 1001 } 1002 1003 } catch (NotFoundException e) { 1004 throw new BadBytecode("Could not find class in descriptor [pos = " + lastPos + "]: " + e.getMessage()); 1005 } 1006 1007 if (clazz == null) 1008 throw new BadBytecode("Could not obtain type for descriptor [pos = " + lastPos + "]: " + info); 1009 1010 return Type.get(clazz); 1011 } 1012 typeFromDesc(String desc)1013 private Type typeFromDesc(String desc) throws BadBytecode { 1014 CtClass clazz = null; 1015 try { 1016 clazz = Descriptor.toCtClass(desc, classPool); 1017 } catch (NotFoundException e) { 1018 throw new BadBytecode("Could not find class in descriptor [pos = " + lastPos + "]: " + e.getMessage()); 1019 } 1020 1021 if (clazz == null) 1022 throw new BadBytecode("Could not obtain type for descriptor [pos = " + lastPos + "]: " + desc); 1023 1024 return Type.get(clazz); 1025 } 1026 verifyAssignable(Type expected, Type type)1027 private void verifyAssignable(Type expected, Type type) throws BadBytecode { 1028 if (! expected.isAssignableFrom(type)) 1029 throw new BadBytecode("Expected type: " + expected + " Got: " + type + " [pos = " + lastPos + "]"); 1030 } 1031 } 1032