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    public void setConstantPoolGen(final ConstantPoolGen cpg) { // TODO could be package-protected?
094        this.cpg = cpg;
095    }
096
097    /**
098     * The only method granting access to the single instance of the ExecutionVisitor class. Before actively using this
099     * instance, <B>SET THE ConstantPoolGen FIRST</B>.
100     *
101     * @see #setConstantPoolGen(ConstantPoolGen)
102     */
103    public void setFrame(final Frame f) { // TODO could be package-protected?
104        this.frame = f;
105    }
106
107    /**
108     * The OperandStack from the current Frame we're operating on.
109     *
110     * @see #setFrame(Frame)
111     */
112    private OperandStack stack() {
113        return frame.getStack();
114    }
115
116    /// ** Symbolically executes the corresponding Java Virtual Machine instruction. */
117    // public void visitWIDE(WIDE o) {
118    // The WIDE instruction is modeled as a flag
119    // of the embedded instructions in BCEL.
120    // Therefore BCEL checks for possible errors
121    // when parsing in the .class file: We don't
122    // have even the possibility to care for WIDE
123    // here.
124    // }
125
126    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
127    @Override
128    public void visitAALOAD(final AALOAD o) {
129        stack().pop(); // pop the index int
130        // System.out.print(stack().peek());
131        final Type t = stack().pop(); // Pop Array type
132        if (t == Type.NULL) {
133            stack().push(Type.NULL);
134        } else {
135            final ArrayType at = (ArrayType) t;
136            stack().push(at.getElementType());
137        }
138    }
139
140    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
141    @Override
142    public void visitAASTORE(final AASTORE o) {
143        stack().pop(3);
144    }
145
146    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
147    @Override
148    public void visitACONST_NULL(final ACONST_NULL o) {
149        stack().push(Type.NULL);
150    }
151
152    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
153    @Override
154    public void visitALOAD(final ALOAD o) {
155        stack().push(locals().get(o.getIndex()));
156    }
157
158    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
159    @Override
160    public void visitANEWARRAY(final ANEWARRAY o) {
161        stack().pop(); // count
162        stack().push(new ArrayType(o.getType(cpg), 1));
163    }
164
165    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
166    @Override
167    public void visitARETURN(final ARETURN o) {
168        stack().pop();
169    }
170
171    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
172    @Override
173    public void visitARRAYLENGTH(final ARRAYLENGTH o) {
174        stack().pop();
175        stack().push(Type.INT);
176    }
177
178    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
179    @Override
180    public void visitASTORE(final ASTORE o) {
181        locals().set(o.getIndex(), stack().pop());
182        // System.err.println("TODO-DEBUG: set LV '"+o.getIndex()+"' to '"+locals().get(o.getIndex())+"'.");
183    }
184
185    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
186    @Override
187    public void visitATHROW(final ATHROW o) {
188        final Type t = stack().pop();
189        stack().clear();
190        if (t.equals(Type.NULL)) {
191            stack().push(Type.getType("Ljava/lang/NullPointerException;"));
192        } else {
193            stack().push(t);
194        }
195    }
196
197    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
198    @Override
199    public void visitBALOAD(final BALOAD o) {
200        stack().pop(2);
201        stack().push(Type.INT);
202    }
203
204    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
205    @Override
206    public void visitBASTORE(final BASTORE o) {
207        stack().pop(3);
208    }
209
210    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
211    @Override
212    public void visitBIPUSH(final BIPUSH o) {
213        stack().push(Type.INT);
214    }
215
216    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
217    @Override
218    public void visitCALOAD(final CALOAD o) {
219        stack().pop(2);
220        stack().push(Type.INT);
221    }
222
223    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
224    @Override
225    public void visitCASTORE(final CASTORE o) {
226        stack().pop(3);
227    }
228
229    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
230    @Override
231    public void visitCHECKCAST(final CHECKCAST o) {
232        // It's possibly wrong to do so, but SUN's
233        // ByteCode verifier seems to do (only) this, too.
234        // TODO: One could use a sophisticated analysis here to check
235        // if a type cannot possibly be cated to another and by
236        // so doing predict the ClassCastException at run-time.
237        stack().pop();
238        stack().push(o.getType(cpg));
239    }
240
241    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
242    @Override
243    public void visitD2F(final D2F o) {
244        stack().pop();
245        stack().push(Type.FLOAT);
246    }
247
248    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
249    @Override
250    public void visitD2I(final D2I o) {
251        stack().pop();
252        stack().push(Type.INT);
253    }
254
255    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
256    @Override
257    public void visitD2L(final D2L o) {
258        stack().pop();
259        stack().push(Type.LONG);
260    }
261
262    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
263    @Override
264    public void visitDADD(final DADD o) {
265        stack().pop(2);
266        stack().push(Type.DOUBLE);
267    }
268
269    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
270    @Override
271    public void visitDALOAD(final DALOAD o) {
272        stack().pop(2);
273        stack().push(Type.DOUBLE);
274    }
275
276    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
277    @Override
278    public void visitDASTORE(final DASTORE o) {
279        stack().pop(3);
280    }
281
282    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
283    @Override
284    public void visitDCMPG(final DCMPG o) {
285        stack().pop(2);
286        stack().push(Type.INT);
287    }
288
289    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
290    @Override
291    public void visitDCMPL(final DCMPL o) {
292        stack().pop(2);
293        stack().push(Type.INT);
294    }
295
296    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
297    @Override
298    public void visitDCONST(final DCONST o) {
299        stack().push(Type.DOUBLE);
300    }
301
302    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
303    @Override
304    public void visitDDIV(final DDIV o) {
305        stack().pop(2);
306        stack().push(Type.DOUBLE);
307    }
308
309    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
310    @Override
311    public void visitDLOAD(final DLOAD o) {
312        stack().push(Type.DOUBLE);
313    }
314
315    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
316    @Override
317    public void visitDMUL(final DMUL o) {
318        stack().pop(2);
319        stack().push(Type.DOUBLE);
320    }
321
322    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
323    @Override
324    public void visitDNEG(final DNEG o) {
325        stack().pop();
326        stack().push(Type.DOUBLE);
327    }
328
329    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
330    @Override
331    public void visitDREM(final DREM o) {
332        stack().pop(2);
333        stack().push(Type.DOUBLE);
334    }
335
336    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
337    @Override
338    public void visitDRETURN(final DRETURN o) {
339        stack().pop();
340    }
341
342    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
343    @Override
344    public void visitDSTORE(final DSTORE o) {
345        locals().set(o.getIndex(), stack().pop());
346        locals().set(o.getIndex() + 1, Type.UNKNOWN);
347    }
348
349    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
350    @Override
351    public void visitDSUB(final DSUB o) {
352        stack().pop(2);
353        stack().push(Type.DOUBLE);
354    }
355
356    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
357    @Override
358    public void visitDUP(final DUP o) {
359        final Type t = stack().pop();
360        stack().push(t);
361        stack().push(t);
362    }
363
364    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
365    @Override
366    public void visitDUP_X1(final DUP_X1 o) {
367        final Type w1 = stack().pop();
368        final Type w2 = stack().pop();
369        stack().push(w1);
370        stack().push(w2);
371        stack().push(w1);
372    }
373
374    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
375    @Override
376    public void visitDUP_X2(final DUP_X2 o) {
377        final Type w1 = stack().pop();
378        final Type w2 = stack().pop();
379        if (w2.getSize() == 2) {
380            stack().push(w1);
381        } else {
382            final Type w3 = stack().pop();
383            stack().push(w1);
384            stack().push(w3);
385        }
386        stack().push(w2);
387        stack().push(w1);
388    }
389
390    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
391    @Override
392    public void visitDUP2(final DUP2 o) {
393        final Type t = stack().pop();
394        if (t.getSize() == 2) {
395            stack().push(t);
396        } else { // t.getSize() is 1
397            final Type u = stack().pop();
398            stack().push(u);
399            stack().push(t);
400            stack().push(u);
401        }
402        stack().push(t);
403    }
404
405    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
406    @Override
407    public void visitDUP2_X1(final DUP2_X1 o) {
408        final Type t = stack().pop();
409        if (t.getSize() == 2) {
410            final Type u = stack().pop();
411            stack().push(t);
412            stack().push(u);
413        } else { // t.getSize() is1
414            final Type u = stack().pop();
415            final Type v = stack().pop();
416            stack().push(u);
417            stack().push(t);
418            stack().push(v);
419            stack().push(u);
420        }
421        stack().push(t);
422    }
423
424    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
425    @Override
426    public void visitDUP2_X2(final DUP2_X2 o) {
427        final Type t = stack().pop();
428        if (t.getSize() == 2) {
429            final Type u = stack().pop();
430            if (u.getSize() == 2) {
431                stack().push(t);
432            } else {
433                final Type v = stack().pop();
434                stack().push(t);
435                stack().push(v);
436            }
437            stack().push(u);
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        }
453        stack().push(t);
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    private void visitInvokedInternals(final InvokeInstruction o) {
815        stack().pop(o.getArgumentTypes(cpg).length);
816        // We are sure the invoked method will xRETURN eventually
817        // We simulate xRETURNs functionality here because we
818        // don't really "jump into" and simulate the invoked
819        // method.
820        if (o.getReturnType(cpg) != Type.VOID) {
821            Type t = o.getReturnType(cpg);
822            if (t.equals(Type.BOOLEAN) || t.equals(Type.CHAR) || t.equals(Type.BYTE) || t.equals(Type.SHORT)) {
823                t = Type.INT;
824            }
825            stack().push(t);
826        }
827    }
828
829    /**
830     * Symbolically executes the corresponding Java Virtual Machine instruction.
831     *
832     * @since 6.0
833     */
834    @Override
835    public void visitINVOKEDYNAMIC(final INVOKEDYNAMIC o) {
836        visitInvokedInternals(o);
837    }
838
839    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
840    @Override
841    public void visitINVOKEINTERFACE(final INVOKEINTERFACE o) {
842        stack().pop(); // objectref
843        stack().pop(o.getArgumentTypes(cpg).length);
844        // We are sure the invoked method will xRETURN eventually
845        // We simulate xRETURNs functionality here because we
846        // don't really "jump into" and simulate the invoked
847        // method.
848        if (o.getReturnType(cpg) != Type.VOID) {
849            Type t = o.getReturnType(cpg);
850            if (t.equals(Type.BOOLEAN) || t.equals(Type.CHAR) || t.equals(Type.BYTE) || t.equals(Type.SHORT)) {
851                t = Type.INT;
852            }
853            stack().push(t);
854        }
855    }
856
857    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
858    @Override
859    public void visitINVOKESPECIAL(final INVOKESPECIAL o) {
860        if (o.getMethodName(cpg).equals(Const.CONSTRUCTOR_NAME)) {
861            final UninitializedObjectType t = (UninitializedObjectType) stack().peek(o.getArgumentTypes(cpg).length);
862            if (t == Frame.getThis()) {
863                Frame.setThis(null);
864            }
865            stack().initializeObject(t);
866            locals().initializeObject(t);
867        }
868        stack().pop(); // objectref
869        stack().pop(o.getArgumentTypes(cpg).length);
870        // We are sure the invoked method will xRETURN eventually
871        // We simulate xRETURNs functionality here because we
872        // don't really "jump into" and simulate the invoked
873        // method.
874        if (o.getReturnType(cpg) != Type.VOID) {
875            Type t = o.getReturnType(cpg);
876            if (t.equals(Type.BOOLEAN) || t.equals(Type.CHAR) || t.equals(Type.BYTE) || t.equals(Type.SHORT)) {
877                t = Type.INT;
878            }
879            stack().push(t);
880        }
881    }
882
883    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
884    @Override
885    public void visitINVOKESTATIC(final INVOKESTATIC o) {
886        visitInvokedInternals(o);
887    }
888
889    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
890    @Override
891    public void visitINVOKEVIRTUAL(final INVOKEVIRTUAL o) {
892        stack().pop(); // objectref
893        stack().pop(o.getArgumentTypes(cpg).length);
894        // We are sure the invoked method will xRETURN eventually
895        // We simulate xRETURNs functionality here because we
896        // don't really "jump into" and simulate the invoked
897        // method.
898        if (o.getReturnType(cpg) != Type.VOID) {
899            Type t = o.getReturnType(cpg);
900            if (t.equals(Type.BOOLEAN) || t.equals(Type.CHAR) || t.equals(Type.BYTE) || t.equals(Type.SHORT)) {
901                t = Type.INT;
902            }
903            stack().push(t);
904        }
905    }
906
907    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
908    @Override
909    public void visitIOR(final IOR o) {
910        stack().pop(2);
911        stack().push(Type.INT);
912    }
913
914    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
915    @Override
916    public void visitIREM(final IREM 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 visitIRETURN(final IRETURN o) {
924        stack().pop();
925    }
926
927    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
928    @Override
929    public void visitISHL(final ISHL o) {
930        stack().pop(2);
931        stack().push(Type.INT);
932    }
933
934    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
935    @Override
936    public void visitISHR(final ISHR 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 visitISTORE(final ISTORE o) {
944        locals().set(o.getIndex(), stack().pop());
945    }
946
947    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
948    @Override
949    public void visitISUB(final ISUB o) {
950        stack().pop(2);
951        stack().push(Type.INT);
952    }
953
954    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
955    @Override
956    public void visitIUSHR(final IUSHR 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 visitIXOR(final IXOR 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 visitJSR(final JSR o) {
971        stack().push(new ReturnaddressType(o.physicalSuccessor()));
972//System.err.println("TODO-----------:"+o.physicalSuccessor());
973    }
974
975    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
976    @Override
977    public void visitJSR_W(final JSR_W o) {
978        stack().push(new ReturnaddressType(o.physicalSuccessor()));
979    }
980
981    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
982    @Override
983    public void visitL2D(final L2D o) {
984        stack().pop();
985        stack().push(Type.DOUBLE);
986    }
987
988    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
989    @Override
990    public void visitL2F(final L2F o) {
991        stack().pop();
992        stack().push(Type.FLOAT);
993    }
994
995    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
996    @Override
997    public void visitL2I(final L2I o) {
998        stack().pop();
999        stack().push(Type.INT);
1000    }
1001
1002    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1003    @Override
1004    public void visitLADD(final LADD o) {
1005        stack().pop(2);
1006        stack().push(Type.LONG);
1007    }
1008
1009    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1010    @Override
1011    public void visitLALOAD(final LALOAD 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 visitLAND(final LAND 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 visitLASTORE(final LASTORE o) {
1026        stack().pop(3);
1027    }
1028
1029    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1030    @Override
1031    public void visitLCMP(final LCMP o) {
1032        stack().pop(2);
1033        stack().push(Type.INT);
1034    }
1035
1036    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1037    @Override
1038    public void visitLCONST(final LCONST o) {
1039        stack().push(Type.LONG);
1040    }
1041
1042    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1043    @Override
1044    public void visitLDC(final LDC o) {
1045        final Constant c = cpg.getConstant(o.getIndex());
1046        if (c instanceof ConstantInteger) {
1047            stack().push(Type.INT);
1048        }
1049        if (c instanceof ConstantFloat) {
1050            stack().push(Type.FLOAT);
1051        }
1052        if (c instanceof ConstantString) {
1053            stack().push(Type.STRING);
1054        }
1055        if (c instanceof ConstantClass) {
1056            stack().push(Type.CLASS);
1057        }
1058        if (c instanceof ConstantDynamic) {
1059            stack().push(Type.OBJECT);
1060        }
1061    }
1062
1063    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1064    public void visitLDC_W(final LDC_W o) {
1065        final Constant c = cpg.getConstant(o.getIndex());
1066        if (c instanceof ConstantInteger) {
1067            stack().push(Type.INT);
1068        }
1069        if (c instanceof ConstantFloat) {
1070            stack().push(Type.FLOAT);
1071        }
1072        if (c instanceof ConstantString) {
1073            stack().push(Type.STRING);
1074        }
1075        if (c instanceof ConstantClass) {
1076            stack().push(Type.CLASS);
1077        }
1078    }
1079
1080    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1081    @Override
1082    public void visitLDC2_W(final LDC2_W o) {
1083        final Constant c = cpg.getConstant(o.getIndex());
1084        if (c instanceof ConstantLong) {
1085            stack().push(Type.LONG);
1086        }
1087        if (c instanceof ConstantDouble) {
1088            stack().push(Type.DOUBLE);
1089        }
1090    }
1091
1092    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1093    @Override
1094    public void visitLDIV(final LDIV o) {
1095        stack().pop(2);
1096        stack().push(Type.LONG);
1097    }
1098
1099    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1100    @Override
1101    public void visitLLOAD(final LLOAD o) {
1102        stack().push(locals().get(o.getIndex()));
1103    }
1104
1105    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1106    @Override
1107    public void visitLMUL(final LMUL o) {
1108        stack().pop(2);
1109        stack().push(Type.LONG);
1110    }
1111
1112    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1113    @Override
1114    public void visitLNEG(final LNEG o) {
1115        stack().pop();
1116        stack().push(Type.LONG);
1117    }
1118
1119    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1120    @Override
1121    public void visitLOOKUPSWITCH(final LOOKUPSWITCH o) {
1122        stack().pop(); // key
1123    }
1124
1125    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1126    @Override
1127    public void visitLOR(final LOR o) {
1128        stack().pop(2);
1129        stack().push(Type.LONG);
1130    }
1131
1132    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1133    @Override
1134    public void visitLREM(final LREM 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 visitLRETURN(final LRETURN o) {
1142        stack().pop();
1143    }
1144
1145    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1146    @Override
1147    public void visitLSHL(final LSHL o) {
1148        stack().pop(2);
1149        stack().push(Type.LONG);
1150    }
1151
1152    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1153    @Override
1154    public void visitLSHR(final LSHR 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 visitLSTORE(final LSTORE o) {
1162        locals().set(o.getIndex(), stack().pop());
1163        locals().set(o.getIndex() + 1, Type.UNKNOWN);
1164    }
1165
1166    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1167    @Override
1168    public void visitLSUB(final LSUB o) {
1169        stack().pop(2);
1170        stack().push(Type.LONG);
1171    }
1172
1173    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1174    @Override
1175    public void visitLUSHR(final LUSHR 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 visitLXOR(final LXOR 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 visitMONITORENTER(final MONITORENTER o) {
1190        stack().pop();
1191    }
1192
1193    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1194    @Override
1195    public void visitMONITOREXIT(final MONITOREXIT o) {
1196        stack().pop();
1197    }
1198
1199    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1200    @Override
1201    public void visitMULTIANEWARRAY(final MULTIANEWARRAY o) {
1202        stack().pop(o.getDimensions());
1203        stack().push(o.getType(cpg));
1204    }
1205
1206    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1207    @Override
1208    public void visitNEW(final NEW o) {
1209        stack().push(new UninitializedObjectType((ObjectType) o.getType(cpg)));
1210    }
1211
1212    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1213    @Override
1214    public void visitNEWARRAY(final NEWARRAY o) {
1215        stack().pop();
1216        stack().push(o.getType());
1217    }
1218
1219    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1220    @Override
1221    public void visitNOP(final NOP o) {
1222    }
1223
1224    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1225    @Override
1226    public void visitPOP(final POP o) {
1227        stack().pop();
1228    }
1229
1230    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1231    @Override
1232    public void visitPOP2(final POP2 o) {
1233        final Type t = stack().pop();
1234        if (t.getSize() == 1) {
1235            stack().pop();
1236        }
1237    }
1238
1239    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1240    @Override
1241    public void visitPUTFIELD(final PUTFIELD o) {
1242        stack().pop(2);
1243    }
1244
1245    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1246    @Override
1247    public void visitPUTSTATIC(final PUTSTATIC o) {
1248        stack().pop();
1249    }
1250
1251    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1252    @Override
1253    public void visitRET(final RET o) {
1254        // do nothing, return address
1255        // is in the local variables.
1256    }
1257
1258    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1259    @Override
1260    public void visitRETURN(final RETURN o) {
1261        // do nothing.
1262    }
1263
1264    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1265    @Override
1266    public void visitSALOAD(final SALOAD o) {
1267        stack().pop(2);
1268        stack().push(Type.INT);
1269    }
1270
1271    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1272    @Override
1273    public void visitSASTORE(final SASTORE o) {
1274        stack().pop(3);
1275    }
1276
1277    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1278    @Override
1279    public void visitSIPUSH(final SIPUSH o) {
1280        stack().push(Type.INT);
1281    }
1282
1283    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1284    @Override
1285    public void visitSWAP(final SWAP o) {
1286        final Type t = stack().pop();
1287        final Type u = stack().pop();
1288        stack().push(t);
1289        stack().push(u);
1290    }
1291
1292    /** Symbolically executes the corresponding Java Virtual Machine instruction. */
1293    @Override
1294    public void visitTABLESWITCH(final TABLESWITCH o) {
1295        stack().pop();
1296    }
1297}