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