You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Executor.java 35KB

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