1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * https://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19 package org.apache.bcel.verifier.structurals;
20
21 import org.apache.bcel.Const;
22 import org.apache.bcel.classfile.Constant;
23 import org.apache.bcel.classfile.ConstantClass;
24 import org.apache.bcel.classfile.ConstantDouble;
25 import org.apache.bcel.classfile.ConstantDynamic;
26 import org.apache.bcel.classfile.ConstantFloat;
27 import org.apache.bcel.classfile.ConstantInteger;
28 import org.apache.bcel.classfile.ConstantLong;
29 import org.apache.bcel.classfile.ConstantString;
30 // CHECKSTYLE:OFF (there are lots of references!)
31 import org.apache.bcel.generic.*;
32 //CHECKSTYLE:ON
33
34 /**
35 * This Visitor class may be used for a type-based Java Virtual Machine simulation.
36 *
37 * <p>
38 * It does not check for correct types on the OperandStack or in the LocalVariables; nor does it check their sizes are
39 * sufficiently big. Thus, to use this Visitor for bytecode verifying, you have to make sure externally that the type
40 * constraints of the Java Virtual Machine instructions are satisfied. An InstConstraintVisitor may be used for this.
41 * Anyway, this Visitor does not mandate it. For example, when you visitIADD(IADD o), then there are two stack slots
42 * popped and one stack slot containing a Type.INT is pushed (where you could also pop only one slot if you know there
43 * are two Type.INT on top of the stack). Monitor-specific behavior is not simulated.
44 * </p>
45 *
46 * <strong>Conventions:</strong>
47 *
48 * <p>
49 * Type.VOID will never be pushed onto the stack. Type.DOUBLE and Type.LONG that would normally take up two stack slots
50 * (like Double_HIGH and Double_LOW) are represented by a simple single Type.DOUBLE or Type.LONG object on the stack
51 * here.
52 * </p>
53 *
54 * <p>
55 * If a two-slot type is stored into a local variable, the next variable is given the type Type.UNKNOWN.
56 * </p>
57 *
58 * @see #visitDSTORE(DSTORE o)
59 * @see InstConstraintVisitor
60 */
61 public class ExecutionVisitor extends EmptyVisitor {
62
63 /**
64 * The executionframe we're operating on.
65 */
66 private Frame frame;
67
68 /**
69 * The ConstantPoolGen we're working with.
70 *
71 * @see #setConstantPoolGen(ConstantPoolGen)
72 */
73 private ConstantPoolGen cpg;
74
75 /**
76 * Constructs a new instance of this class.
77 */
78 public ExecutionVisitor() {
79 }
80
81 /**
82 * The LocalVariables from the current Frame we're operating on.
83 *
84 * @see #setFrame(Frame)
85 */
86 private LocalVariables locals() {
87 return frame.getLocals();
88 }
89
90 /**
91 * Sets the ConstantPoolGen needed for symbolic execution.
92 *
93 * @param cpg the constant pool generator.
94 */
95 public void setConstantPoolGen(final ConstantPoolGen cpg) { // TODO could be package-protected?
96 this.cpg = cpg;
97 }
98
99 /**
100 * The only method granting access to the single instance of the ExecutionVisitor class. Before actively using this
101 * instance, <strong>SET THE ConstantPoolGen FIRST</strong>.
102 *
103 * @param f the frame.
104 * @see #setConstantPoolGen(ConstantPoolGen)
105 */
106 public void setFrame(final Frame f) { // TODO could be package-protected?
107 this.frame = f;
108 }
109
110 /**
111 * The OperandStack from the current Frame we're operating on.
112 *
113 * @see #setFrame(Frame)
114 */
115 private OperandStack stack() {
116 return frame.getStack();
117 }
118
119 /// ** Symbolically executes the corresponding Java Virtual Machine instruction. */
120 // public void visitWIDE(WIDE o) {
121 // The WIDE instruction is modeled as a flag
122 // of the embedded instructions in BCEL.
123 // Therefore BCEL checks for possible errors
124 // when parsing in the .class file: We don't
125 // have even the possibility to care for WIDE
126 // here.
127 // }
128
129 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
130 @Override
131 public void visitAALOAD(final AALOAD o) {
132 stack().pop(); // pop the index int
133 // System.out.print(stack().peek());
134 final Type t = stack().pop(); // Pop Array type
135 if (t == Type.NULL) {
136 stack().push(Type.NULL);
137 } else {
138 final ArrayType at = (ArrayType) t;
139 stack().push(at.getElementType());
140 }
141 }
142
143 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
144 @Override
145 public void visitAASTORE(final AASTORE o) {
146 stack().pop(3);
147 }
148
149 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
150 @Override
151 public void visitACONST_NULL(final ACONST_NULL o) {
152 stack().push(Type.NULL);
153 }
154
155 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
156 @Override
157 public void visitALOAD(final ALOAD o) {
158 stack().push(locals().get(o.getIndex()));
159 }
160
161 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
162 @Override
163 public void visitANEWARRAY(final ANEWARRAY o) {
164 stack().pop(); // count
165 stack().push(new ArrayType(o.getType(cpg), 1));
166 }
167
168 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
169 @Override
170 public void visitARETURN(final ARETURN o) {
171 stack().pop();
172 }
173
174 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
175 @Override
176 public void visitARRAYLENGTH(final ARRAYLENGTH o) {
177 stack().pop();
178 stack().push(Type.INT);
179 }
180
181 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
182 @Override
183 public void visitASTORE(final ASTORE o) {
184 locals().set(o.getIndex(), stack().pop());
185 // System.err.println("TODO-DEBUG: set LV '"+o.getIndex()+"' to '"+locals().get(o.getIndex())+"'.");
186 }
187
188 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
189 @Override
190 public void visitATHROW(final ATHROW o) {
191 final Type t = stack().pop();
192 stack().clear();
193 if (t.equals(Type.NULL)) {
194 stack().push(Type.getType("Ljava/lang/NullPointerException;"));
195 } else {
196 stack().push(t);
197 }
198 }
199
200 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
201 @Override
202 public void visitBALOAD(final BALOAD o) {
203 stack().pop(2);
204 stack().push(Type.INT);
205 }
206
207 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
208 @Override
209 public void visitBASTORE(final BASTORE o) {
210 stack().pop(3);
211 }
212
213 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
214 @Override
215 public void visitBIPUSH(final BIPUSH o) {
216 stack().push(Type.INT);
217 }
218
219 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
220 @Override
221 public void visitCALOAD(final CALOAD o) {
222 stack().pop(2);
223 stack().push(Type.INT);
224 }
225
226 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
227 @Override
228 public void visitCASTORE(final CASTORE o) {
229 stack().pop(3);
230 }
231
232 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
233 @Override
234 public void visitCHECKCAST(final CHECKCAST o) {
235 // It's possibly wrong to do so, but SUN's
236 // ByteCode verifier seems to do (only) this, too.
237 // TODO: One could use a sophisticated analysis here to check
238 // if a type cannot possibly be cated to another and by
239 // so doing predict the ClassCastException at run-time.
240 stack().pop();
241 stack().push(o.getType(cpg));
242 }
243
244 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
245 @Override
246 public void visitD2F(final D2F o) {
247 stack().pop();
248 stack().push(Type.FLOAT);
249 }
250
251 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
252 @Override
253 public void visitD2I(final D2I o) {
254 stack().pop();
255 stack().push(Type.INT);
256 }
257
258 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
259 @Override
260 public void visitD2L(final D2L o) {
261 stack().pop();
262 stack().push(Type.LONG);
263 }
264
265 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
266 @Override
267 public void visitDADD(final DADD o) {
268 stack().pop(2);
269 stack().push(Type.DOUBLE);
270 }
271
272 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
273 @Override
274 public void visitDALOAD(final DALOAD o) {
275 stack().pop(2);
276 stack().push(Type.DOUBLE);
277 }
278
279 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
280 @Override
281 public void visitDASTORE(final DASTORE o) {
282 stack().pop(3);
283 }
284
285 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
286 @Override
287 public void visitDCMPG(final DCMPG o) {
288 stack().pop(2);
289 stack().push(Type.INT);
290 }
291
292 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
293 @Override
294 public void visitDCMPL(final DCMPL o) {
295 stack().pop(2);
296 stack().push(Type.INT);
297 }
298
299 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
300 @Override
301 public void visitDCONST(final DCONST o) {
302 stack().push(Type.DOUBLE);
303 }
304
305 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
306 @Override
307 public void visitDDIV(final DDIV o) {
308 stack().pop(2);
309 stack().push(Type.DOUBLE);
310 }
311
312 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
313 @Override
314 public void visitDLOAD(final DLOAD o) {
315 stack().push(Type.DOUBLE);
316 }
317
318 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
319 @Override
320 public void visitDMUL(final DMUL o) {
321 stack().pop(2);
322 stack().push(Type.DOUBLE);
323 }
324
325 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
326 @Override
327 public void visitDNEG(final DNEG o) {
328 stack().pop();
329 stack().push(Type.DOUBLE);
330 }
331
332 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
333 @Override
334 public void visitDREM(final DREM o) {
335 stack().pop(2);
336 stack().push(Type.DOUBLE);
337 }
338
339 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
340 @Override
341 public void visitDRETURN(final DRETURN o) {
342 stack().pop();
343 }
344
345 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
346 @Override
347 public void visitDSTORE(final DSTORE o) {
348 locals().set(o.getIndex(), stack().pop());
349 locals().set(o.getIndex() + 1, Type.UNKNOWN);
350 }
351
352 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
353 @Override
354 public void visitDSUB(final DSUB o) {
355 stack().pop(2);
356 stack().push(Type.DOUBLE);
357 }
358
359 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
360 @Override
361 public void visitDUP(final DUP o) {
362 final Type t = stack().pop();
363 stack().push(t);
364 stack().push(t);
365 }
366
367 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
368 @Override
369 public void visitDUP_X1(final DUP_X1 o) {
370 final Type w1 = stack().pop();
371 final Type w2 = stack().pop();
372 stack().push(w1);
373 stack().push(w2);
374 stack().push(w1);
375 }
376
377 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
378 @Override
379 public void visitDUP_X2(final DUP_X2 o) {
380 final Type w1 = stack().pop();
381 final Type w2 = stack().pop();
382 if (w2.getSize() == 2) {
383 stack().push(w1);
384 } else {
385 final Type w3 = stack().pop();
386 stack().push(w1);
387 stack().push(w3);
388 }
389 stack().push(w2);
390 stack().push(w1);
391 }
392
393 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
394 @Override
395 public void visitDUP2(final DUP2 o) {
396 final Type t = stack().pop();
397 if (t.getSize() == 2) {
398 stack().push(t);
399 } else { // t.getSize() is 1
400 final Type u = stack().pop();
401 stack().push(u);
402 stack().push(t);
403 stack().push(u);
404 }
405 stack().push(t);
406 }
407
408 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
409 @Override
410 public void visitDUP2_X1(final DUP2_X1 o) {
411 final Type t = stack().pop();
412 if (t.getSize() == 2) {
413 final Type u = stack().pop();
414 stack().push(t);
415 stack().push(u);
416 } else { // t.getSize() is1
417 final Type u = stack().pop();
418 final Type v = stack().pop();
419 stack().push(u);
420 stack().push(t);
421 stack().push(v);
422 stack().push(u);
423 }
424 stack().push(t);
425 }
426
427 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
428 @Override
429 public void visitDUP2_X2(final DUP2_X2 o) {
430 final Type t = stack().pop();
431 if (t.getSize() == 2) {
432 final Type u = stack().pop();
433 if (u.getSize() == 2) {
434 stack().push(t);
435 } else {
436 final Type v = stack().pop();
437 stack().push(t);
438 stack().push(v);
439 }
440 stack().push(u);
441 } else { // t.getSize() is 1
442 final Type u = stack().pop();
443 final Type v = stack().pop();
444 if (v.getSize() == 2) {
445 stack().push(u);
446 stack().push(t);
447 } else {
448 final Type w = stack().pop();
449 stack().push(u);
450 stack().push(t);
451 stack().push(w);
452 }
453 stack().push(v);
454 stack().push(u);
455 }
456 stack().push(t);
457 }
458
459 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
460 @Override
461 public void visitF2D(final F2D o) {
462 stack().pop();
463 stack().push(Type.DOUBLE);
464 }
465
466 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
467 @Override
468 public void visitF2I(final F2I o) {
469 stack().pop();
470 stack().push(Type.INT);
471 }
472
473 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
474 @Override
475 public void visitF2L(final F2L o) {
476 stack().pop();
477 stack().push(Type.LONG);
478 }
479
480 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
481 @Override
482 public void visitFADD(final FADD o) {
483 stack().pop(2);
484 stack().push(Type.FLOAT);
485 }
486
487 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
488 @Override
489 public void visitFALOAD(final FALOAD o) {
490 stack().pop(2);
491 stack().push(Type.FLOAT);
492 }
493
494 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
495 @Override
496 public void visitFASTORE(final FASTORE o) {
497 stack().pop(3);
498 }
499
500 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
501 @Override
502 public void visitFCMPG(final FCMPG o) {
503 stack().pop(2);
504 stack().push(Type.INT);
505 }
506
507 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
508 @Override
509 public void visitFCMPL(final FCMPL o) {
510 stack().pop(2);
511 stack().push(Type.INT);
512 }
513
514 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
515 @Override
516 public void visitFCONST(final FCONST o) {
517 stack().push(Type.FLOAT);
518 }
519
520 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
521 @Override
522 public void visitFDIV(final FDIV o) {
523 stack().pop(2);
524 stack().push(Type.FLOAT);
525 }
526
527 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
528 @Override
529 public void visitFLOAD(final FLOAD o) {
530 stack().push(Type.FLOAT);
531 }
532
533 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
534 @Override
535 public void visitFMUL(final FMUL o) {
536 stack().pop(2);
537 stack().push(Type.FLOAT);
538 }
539
540 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
541 @Override
542 public void visitFNEG(final FNEG o) {
543 stack().pop();
544 stack().push(Type.FLOAT);
545 }
546
547 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
548 @Override
549 public void visitFREM(final FREM o) {
550 stack().pop(2);
551 stack().push(Type.FLOAT);
552 }
553
554 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
555 @Override
556 public void visitFRETURN(final FRETURN o) {
557 stack().pop();
558 }
559
560 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
561 @Override
562 public void visitFSTORE(final FSTORE o) {
563 locals().set(o.getIndex(), stack().pop());
564 }
565
566 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
567 @Override
568 public void visitFSUB(final FSUB o) {
569 stack().pop(2);
570 stack().push(Type.FLOAT);
571 }
572
573 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
574 @Override
575 public void visitGETFIELD(final GETFIELD o) {
576 stack().pop();
577 Type t = o.getFieldType(cpg);
578 if (t.equals(Type.BOOLEAN) || t.equals(Type.CHAR) || t.equals(Type.BYTE) || t.equals(Type.SHORT)) {
579 t = Type.INT;
580 }
581 stack().push(t);
582 }
583
584 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
585 @Override
586 public void visitGETSTATIC(final GETSTATIC o) {
587 Type t = o.getFieldType(cpg);
588 if (t.equals(Type.BOOLEAN) || t.equals(Type.CHAR) || t.equals(Type.BYTE) || t.equals(Type.SHORT)) {
589 t = Type.INT;
590 }
591 stack().push(t);
592 }
593
594 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
595 @Override
596 public void visitGOTO(final GOTO o) {
597 // no stack changes.
598 }
599
600 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
601 @Override
602 public void visitGOTO_W(final GOTO_W o) {
603 // no stack changes.
604 }
605
606 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
607 @Override
608 public void visitI2B(final I2B o) {
609 stack().pop();
610 stack().push(Type.INT);
611 }
612
613 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
614 @Override
615 public void visitI2C(final I2C o) {
616 stack().pop();
617 stack().push(Type.INT);
618 }
619
620 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
621 @Override
622 public void visitI2D(final I2D o) {
623 stack().pop();
624 stack().push(Type.DOUBLE);
625 }
626
627 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
628 @Override
629 public void visitI2F(final I2F o) {
630 stack().pop();
631 stack().push(Type.FLOAT);
632 }
633
634 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
635 @Override
636 public void visitI2L(final I2L o) {
637 stack().pop();
638 stack().push(Type.LONG);
639 }
640
641 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
642 @Override
643 public void visitI2S(final I2S o) {
644 stack().pop();
645 stack().push(Type.INT);
646 }
647
648 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
649 @Override
650 public void visitIADD(final IADD o) {
651 stack().pop(2);
652 stack().push(Type.INT);
653 }
654
655 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
656 @Override
657 public void visitIALOAD(final IALOAD o) {
658 stack().pop(2);
659 stack().push(Type.INT);
660 }
661
662 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
663 @Override
664 public void visitIAND(final IAND o) {
665 stack().pop(2);
666 stack().push(Type.INT);
667 }
668
669 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
670 @Override
671 public void visitIASTORE(final IASTORE o) {
672 stack().pop(3);
673 }
674
675 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
676 @Override
677 public void visitICONST(final ICONST o) {
678 stack().push(Type.INT);
679 }
680
681 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
682 @Override
683 public void visitIDIV(final IDIV o) {
684 stack().pop(2);
685 stack().push(Type.INT);
686 }
687
688 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
689 @Override
690 public void visitIF_ACMPEQ(final IF_ACMPEQ o) {
691 stack().pop(2);
692 }
693
694 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
695 @Override
696 public void visitIF_ACMPNE(final IF_ACMPNE o) {
697 stack().pop(2);
698 }
699
700 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
701 @Override
702 public void visitIF_ICMPEQ(final IF_ICMPEQ o) {
703 stack().pop(2);
704 }
705
706 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
707 @Override
708 public void visitIF_ICMPGE(final IF_ICMPGE o) {
709 stack().pop(2);
710 }
711
712 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
713 @Override
714 public void visitIF_ICMPGT(final IF_ICMPGT o) {
715 stack().pop(2);
716 }
717
718 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
719 @Override
720 public void visitIF_ICMPLE(final IF_ICMPLE o) {
721 stack().pop(2);
722 }
723
724 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
725 @Override
726 public void visitIF_ICMPLT(final IF_ICMPLT o) {
727 stack().pop(2);
728 }
729
730 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
731 @Override
732 public void visitIF_ICMPNE(final IF_ICMPNE o) {
733 stack().pop(2);
734 }
735
736 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
737 @Override
738 public void visitIFEQ(final IFEQ o) {
739 stack().pop();
740 }
741
742 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
743 @Override
744 public void visitIFGE(final IFGE o) {
745 stack().pop();
746 }
747
748 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
749 @Override
750 public void visitIFGT(final IFGT o) {
751 stack().pop();
752 }
753
754 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
755 @Override
756 public void visitIFLE(final IFLE o) {
757 stack().pop();
758 }
759
760 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
761 @Override
762 public void visitIFLT(final IFLT o) {
763 stack().pop();
764 }
765
766 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
767 @Override
768 public void visitIFNE(final IFNE o) {
769 stack().pop();
770 }
771
772 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
773 @Override
774 public void visitIFNONNULL(final IFNONNULL o) {
775 stack().pop();
776 }
777
778 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
779 @Override
780 public void visitIFNULL(final IFNULL o) {
781 stack().pop();
782 }
783
784 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
785 @Override
786 public void visitIINC(final IINC o) {
787 // stack is not changed.
788 }
789
790 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
791 @Override
792 public void visitILOAD(final ILOAD o) {
793 stack().push(Type.INT);
794 }
795
796 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
797 @Override
798 public void visitIMUL(final IMUL o) {
799 stack().pop(2);
800 stack().push(Type.INT);
801 }
802
803 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
804 @Override
805 public void visitINEG(final INEG o) {
806 stack().pop();
807 stack().push(Type.INT);
808 }
809
810 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
811 @Override
812 public void visitINSTANCEOF(final INSTANCEOF o) {
813 stack().pop();
814 stack().push(Type.INT);
815 }
816
817 private void visitInvokedInternals(final InvokeInstruction o) {
818 stack().pop(o.getArgumentTypes(cpg).length);
819 // We are sure the invoked method will xRETURN eventually
820 // We simulate xRETURNs functionality here because we
821 // don't really "jump into" and simulate the invoked
822 // method.
823 if (o.getReturnType(cpg) != Type.VOID) {
824 Type t = o.getReturnType(cpg);
825 if (t.equals(Type.BOOLEAN) || t.equals(Type.CHAR) || t.equals(Type.BYTE) || t.equals(Type.SHORT)) {
826 t = Type.INT;
827 }
828 stack().push(t);
829 }
830 }
831
832 /**
833 * Symbolically executes the corresponding Java Virtual Machine instruction.
834 *
835 * @since 6.0
836 */
837 @Override
838 public void visitINVOKEDYNAMIC(final INVOKEDYNAMIC o) {
839 visitInvokedInternals(o);
840 }
841
842 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
843 @Override
844 public void visitINVOKEINTERFACE(final INVOKEINTERFACE o) {
845 stack().pop(); // objectref
846 stack().pop(o.getArgumentTypes(cpg).length);
847 // We are sure the invoked method will xRETURN eventually
848 // We simulate xRETURNs functionality here because we
849 // don't really "jump into" and simulate the invoked
850 // method.
851 if (o.getReturnType(cpg) != Type.VOID) {
852 Type t = o.getReturnType(cpg);
853 if (t.equals(Type.BOOLEAN) || t.equals(Type.CHAR) || t.equals(Type.BYTE) || t.equals(Type.SHORT)) {
854 t = Type.INT;
855 }
856 stack().push(t);
857 }
858 }
859
860 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
861 @Override
862 public void visitINVOKESPECIAL(final INVOKESPECIAL o) {
863 if (o.getMethodName(cpg).equals(Const.CONSTRUCTOR_NAME)) {
864 final UninitializedObjectType t = (UninitializedObjectType) stack().peek(o.getArgumentTypes(cpg).length);
865 if (t == Frame.getThis()) {
866 Frame.setThis(null);
867 }
868 stack().initializeObject(t);
869 locals().initializeObject(t);
870 }
871 stack().pop(); // objectref
872 stack().pop(o.getArgumentTypes(cpg).length);
873 // We are sure the invoked method will xRETURN eventually
874 // We simulate xRETURNs functionality here because we
875 // don't really "jump into" and simulate the invoked
876 // method.
877 if (o.getReturnType(cpg) != Type.VOID) {
878 Type t = o.getReturnType(cpg);
879 if (t.equals(Type.BOOLEAN) || t.equals(Type.CHAR) || t.equals(Type.BYTE) || t.equals(Type.SHORT)) {
880 t = Type.INT;
881 }
882 stack().push(t);
883 }
884 }
885
886 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
887 @Override
888 public void visitINVOKESTATIC(final INVOKESTATIC o) {
889 visitInvokedInternals(o);
890 }
891
892 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
893 @Override
894 public void visitINVOKEVIRTUAL(final INVOKEVIRTUAL o) {
895 stack().pop(); // objectref
896 stack().pop(o.getArgumentTypes(cpg).length);
897 // We are sure the invoked method will xRETURN eventually
898 // We simulate xRETURNs functionality here because we
899 // don't really "jump into" and simulate the invoked
900 // method.
901 if (o.getReturnType(cpg) != Type.VOID) {
902 Type t = o.getReturnType(cpg);
903 if (t.equals(Type.BOOLEAN) || t.equals(Type.CHAR) || t.equals(Type.BYTE) || t.equals(Type.SHORT)) {
904 t = Type.INT;
905 }
906 stack().push(t);
907 }
908 }
909
910 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
911 @Override
912 public void visitIOR(final IOR o) {
913 stack().pop(2);
914 stack().push(Type.INT);
915 }
916
917 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
918 @Override
919 public void visitIREM(final IREM o) {
920 stack().pop(2);
921 stack().push(Type.INT);
922 }
923
924 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
925 @Override
926 public void visitIRETURN(final IRETURN o) {
927 stack().pop();
928 }
929
930 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
931 @Override
932 public void visitISHL(final ISHL o) {
933 stack().pop(2);
934 stack().push(Type.INT);
935 }
936
937 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
938 @Override
939 public void visitISHR(final ISHR o) {
940 stack().pop(2);
941 stack().push(Type.INT);
942 }
943
944 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
945 @Override
946 public void visitISTORE(final ISTORE o) {
947 locals().set(o.getIndex(), stack().pop());
948 }
949
950 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
951 @Override
952 public void visitISUB(final ISUB o) {
953 stack().pop(2);
954 stack().push(Type.INT);
955 }
956
957 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
958 @Override
959 public void visitIUSHR(final IUSHR o) {
960 stack().pop(2);
961 stack().push(Type.INT);
962 }
963
964 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
965 @Override
966 public void visitIXOR(final IXOR o) {
967 stack().pop(2);
968 stack().push(Type.INT);
969 }
970
971 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
972 @Override
973 public void visitJSR(final JSR o) {
974 stack().push(new ReturnaddressType(o.physicalSuccessor()));
975 //System.err.println("TODO-----------:"+o.physicalSuccessor());
976 }
977
978 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
979 @Override
980 public void visitJSR_W(final JSR_W o) {
981 stack().push(new ReturnaddressType(o.physicalSuccessor()));
982 }
983
984 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
985 @Override
986 public void visitL2D(final L2D o) {
987 stack().pop();
988 stack().push(Type.DOUBLE);
989 }
990
991 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
992 @Override
993 public void visitL2F(final L2F o) {
994 stack().pop();
995 stack().push(Type.FLOAT);
996 }
997
998 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
999 @Override
1000 public void visitL2I(final L2I o) {
1001 stack().pop();
1002 stack().push(Type.INT);
1003 }
1004
1005 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1006 @Override
1007 public void visitLADD(final LADD o) {
1008 stack().pop(2);
1009 stack().push(Type.LONG);
1010 }
1011
1012 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1013 @Override
1014 public void visitLALOAD(final LALOAD o) {
1015 stack().pop(2);
1016 stack().push(Type.LONG);
1017 }
1018
1019 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1020 @Override
1021 public void visitLAND(final LAND o) {
1022 stack().pop(2);
1023 stack().push(Type.LONG);
1024 }
1025
1026 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1027 @Override
1028 public void visitLASTORE(final LASTORE o) {
1029 stack().pop(3);
1030 }
1031
1032 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1033 @Override
1034 public void visitLCMP(final LCMP o) {
1035 stack().pop(2);
1036 stack().push(Type.INT);
1037 }
1038
1039 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1040 @Override
1041 public void visitLCONST(final LCONST o) {
1042 stack().push(Type.LONG);
1043 }
1044
1045 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1046 @Override
1047 public void visitLDC(final LDC o) {
1048 final Constant c = cpg.getConstant(o.getIndex());
1049 if (c instanceof ConstantInteger) {
1050 stack().push(Type.INT);
1051 }
1052 if (c instanceof ConstantFloat) {
1053 stack().push(Type.FLOAT);
1054 }
1055 if (c instanceof ConstantString) {
1056 stack().push(Type.STRING);
1057 }
1058 if (c instanceof ConstantClass) {
1059 stack().push(Type.CLASS);
1060 }
1061 if (c instanceof ConstantDynamic) {
1062 stack().push(Type.OBJECT);
1063 }
1064 }
1065
1066 /**
1067 * Symbolically executes the corresponding Java Virtual Machine instruction.
1068 *
1069 * @param o the instruction.
1070 */
1071 public void visitLDC_W(final LDC_W o) {
1072 final Constant c = cpg.getConstant(o.getIndex());
1073 if (c instanceof ConstantInteger) {
1074 stack().push(Type.INT);
1075 }
1076 if (c instanceof ConstantFloat) {
1077 stack().push(Type.FLOAT);
1078 }
1079 if (c instanceof ConstantString) {
1080 stack().push(Type.STRING);
1081 }
1082 if (c instanceof ConstantClass) {
1083 stack().push(Type.CLASS);
1084 }
1085 }
1086
1087 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1088 @Override
1089 public void visitLDC2_W(final LDC2_W o) {
1090 final Constant c = cpg.getConstant(o.getIndex());
1091 if (c instanceof ConstantLong) {
1092 stack().push(Type.LONG);
1093 }
1094 if (c instanceof ConstantDouble) {
1095 stack().push(Type.DOUBLE);
1096 }
1097 }
1098
1099 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1100 @Override
1101 public void visitLDIV(final LDIV o) {
1102 stack().pop(2);
1103 stack().push(Type.LONG);
1104 }
1105
1106 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1107 @Override
1108 public void visitLLOAD(final LLOAD o) {
1109 stack().push(locals().get(o.getIndex()));
1110 }
1111
1112 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1113 @Override
1114 public void visitLMUL(final LMUL o) {
1115 stack().pop(2);
1116 stack().push(Type.LONG);
1117 }
1118
1119 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1120 @Override
1121 public void visitLNEG(final LNEG o) {
1122 stack().pop();
1123 stack().push(Type.LONG);
1124 }
1125
1126 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1127 @Override
1128 public void visitLOOKUPSWITCH(final LOOKUPSWITCH o) {
1129 stack().pop(); // key
1130 }
1131
1132 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1133 @Override
1134 public void visitLOR(final LOR o) {
1135 stack().pop(2);
1136 stack().push(Type.LONG);
1137 }
1138
1139 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1140 @Override
1141 public void visitLREM(final LREM o) {
1142 stack().pop(2);
1143 stack().push(Type.LONG);
1144 }
1145
1146 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1147 @Override
1148 public void visitLRETURN(final LRETURN o) {
1149 stack().pop();
1150 }
1151
1152 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1153 @Override
1154 public void visitLSHL(final LSHL o) {
1155 stack().pop(2);
1156 stack().push(Type.LONG);
1157 }
1158
1159 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1160 @Override
1161 public void visitLSHR(final LSHR o) {
1162 stack().pop(2);
1163 stack().push(Type.LONG);
1164 }
1165
1166 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1167 @Override
1168 public void visitLSTORE(final LSTORE o) {
1169 locals().set(o.getIndex(), stack().pop());
1170 locals().set(o.getIndex() + 1, Type.UNKNOWN);
1171 }
1172
1173 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1174 @Override
1175 public void visitLSUB(final LSUB o) {
1176 stack().pop(2);
1177 stack().push(Type.LONG);
1178 }
1179
1180 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1181 @Override
1182 public void visitLUSHR(final LUSHR o) {
1183 stack().pop(2);
1184 stack().push(Type.LONG);
1185 }
1186
1187 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1188 @Override
1189 public void visitLXOR(final LXOR o) {
1190 stack().pop(2);
1191 stack().push(Type.LONG);
1192 }
1193
1194 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1195 @Override
1196 public void visitMONITORENTER(final MONITORENTER o) {
1197 stack().pop();
1198 }
1199
1200 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1201 @Override
1202 public void visitMONITOREXIT(final MONITOREXIT o) {
1203 stack().pop();
1204 }
1205
1206 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1207 @Override
1208 public void visitMULTIANEWARRAY(final MULTIANEWARRAY o) {
1209 stack().pop(o.getDimensions());
1210 stack().push(o.getType(cpg));
1211 }
1212
1213 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1214 @Override
1215 public void visitNEW(final NEW o) {
1216 stack().push(new UninitializedObjectType((ObjectType) o.getType(cpg)));
1217 }
1218
1219 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1220 @Override
1221 public void visitNEWARRAY(final NEWARRAY o) {
1222 stack().pop();
1223 stack().push(o.getType());
1224 }
1225
1226 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1227 @Override
1228 public void visitNOP(final NOP o) {
1229 }
1230
1231 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1232 @Override
1233 public void visitPOP(final POP o) {
1234 stack().pop();
1235 }
1236
1237 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1238 @Override
1239 public void visitPOP2(final POP2 o) {
1240 final Type t = stack().pop();
1241 if (t.getSize() == 1) {
1242 stack().pop();
1243 }
1244 }
1245
1246 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1247 @Override
1248 public void visitPUTFIELD(final PUTFIELD o) {
1249 stack().pop(2);
1250 }
1251
1252 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1253 @Override
1254 public void visitPUTSTATIC(final PUTSTATIC o) {
1255 stack().pop();
1256 }
1257
1258 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1259 @Override
1260 public void visitRET(final RET o) {
1261 // do nothing, return address
1262 // is in the local variables.
1263 }
1264
1265 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1266 @Override
1267 public void visitRETURN(final RETURN o) {
1268 // do nothing.
1269 }
1270
1271 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1272 @Override
1273 public void visitSALOAD(final SALOAD o) {
1274 stack().pop(2);
1275 stack().push(Type.INT);
1276 }
1277
1278 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1279 @Override
1280 public void visitSASTORE(final SASTORE o) {
1281 stack().pop(3);
1282 }
1283
1284 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1285 @Override
1286 public void visitSIPUSH(final SIPUSH o) {
1287 stack().push(Type.INT);
1288 }
1289
1290 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1291 @Override
1292 public void visitSWAP(final SWAP o) {
1293 final Type t = stack().pop();
1294 final Type u = stack().pop();
1295 stack().push(t);
1296 stack().push(u);
1297 }
1298
1299 /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1300 @Override
1301 public void visitTABLESWITCH(final TABLESWITCH o) {
1302 stack().pop();
1303 }
1304 }