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