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