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

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