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