001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *   https://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied.  See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019package org.apache.bcel.verifier.structurals;
020
021import org.apache.bcel.Const;
022import org.apache.bcel.classfile.Constant;
023import org.apache.bcel.classfile.ConstantClass;
024import org.apache.bcel.classfile.ConstantDouble;
025import org.apache.bcel.classfile.ConstantDynamic;
026import org.apache.bcel.classfile.ConstantFloat;
027import org.apache.bcel.classfile.ConstantInteger;
028import org.apache.bcel.classfile.ConstantLong;
029import org.apache.bcel.classfile.ConstantString;
030// CHECKSTYLE:OFF (there are lots of references!)
031import org.apache.bcel.generic.*;
032//CHECKSTYLE:ON
033
034/**
035 * This Visitor class may be used for a type-based Java Virtual Machine simulation.
036 *
037 * <p>
038 * It does not check for correct types on the OperandStack or in the LocalVariables; nor does it check their sizes are
039 * sufficiently big. Thus, to use this Visitor for bytecode verifying, you have to make sure externally that the type
040 * constraints of the Java Virtual Machine instructions are satisfied. An InstConstraintVisitor may be used for this.
041 * Anyway, this Visitor does not mandate it. For example, when you visitIADD(IADD o), then there are two stack slots
042 * popped and one stack slot containing a Type.INT is pushed (where you could also pop only one slot if you know there
043 * are two Type.INT on top of the stack). Monitor-specific behavior is not simulated.
044 * </p>
045 *
046 * <strong>Conventions:</strong>
047 *
048 * <p>
049 * Type.VOID will never be pushed onto the stack. Type.DOUBLE and Type.LONG that would normally take up two stack slots
050 * (like Double_HIGH and Double_LOW) are represented by a simple single Type.DOUBLE or Type.LONG object on the stack
051 * here.
052 * </p>
053 *
054 * <p>
055 * If a two-slot type is stored into a local variable, the next variable is given the type Type.UNKNOWN.
056 * </p>
057 *
058 * @see #visitDSTORE(DSTORE o)
059 * @see InstConstraintVisitor
060 */
061public class ExecutionVisitor extends EmptyVisitor {
062
063    /**
064     * The executionframe we're operating on.
065     */
066    private Frame frame;
067
068    /**
069     * The ConstantPoolGen we're working with.
070     *
071     * @see #setConstantPoolGen(ConstantPoolGen)
072     */
073    private ConstantPoolGen cpg;
074
075    /**
076     * Constructs a new instance of this class.
077     */
078    public ExecutionVisitor() {
079    }
080
081    /**
082     * The LocalVariables from the current Frame we're operating on.
083     *
084     * @see #setFrame(Frame)
085     */
086    private LocalVariables locals() {
087        return frame.getLocals();
088    }
089
090    /**
091     * Sets the ConstantPoolGen needed for symbolic execution.
092     *
093     * @param cpg the constant pool generator.
094     */
095    public void setConstantPoolGen(final ConstantPoolGen cpg) { // TODO could be package-protected?
096        this.cpg = cpg;
097    }
098
099    /**
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}