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 java.util.Objects;
022
023import org.apache.bcel.Const;
024import org.apache.bcel.Repository;
025import org.apache.bcel.classfile.Constant;
026import org.apache.bcel.classfile.ConstantClass;
027import org.apache.bcel.classfile.ConstantDouble;
028import org.apache.bcel.classfile.ConstantDynamic;
029import org.apache.bcel.classfile.ConstantFieldref;
030import org.apache.bcel.classfile.ConstantFloat;
031import org.apache.bcel.classfile.ConstantInteger;
032import org.apache.bcel.classfile.ConstantLong;
033import org.apache.bcel.classfile.ConstantString;
034import org.apache.bcel.classfile.Field;
035import org.apache.bcel.classfile.JavaClass;
036//CHECKSTYLE:OFF (there are lots of references!)
037import org.apache.bcel.generic.AALOAD;
038import org.apache.bcel.generic.AASTORE;
039import org.apache.bcel.generic.ACONST_NULL;
040import org.apache.bcel.generic.ALOAD;
041import org.apache.bcel.generic.ANEWARRAY;
042import org.apache.bcel.generic.ARETURN;
043import org.apache.bcel.generic.ARRAYLENGTH;
044import org.apache.bcel.generic.ASTORE;
045import org.apache.bcel.generic.ATHROW;
046import org.apache.bcel.generic.ArrayType;
047import org.apache.bcel.generic.BALOAD;
048import org.apache.bcel.generic.BASTORE;
049import org.apache.bcel.generic.BIPUSH;
050import org.apache.bcel.generic.BREAKPOINT;
051import org.apache.bcel.generic.BasicType;
052import org.apache.bcel.generic.CALOAD;
053import org.apache.bcel.generic.CASTORE;
054import org.apache.bcel.generic.CHECKCAST;
055import org.apache.bcel.generic.CPInstruction;
056import org.apache.bcel.generic.ConstantPoolGen;
057import org.apache.bcel.generic.D2F;
058import org.apache.bcel.generic.D2I;
059import org.apache.bcel.generic.D2L;
060import org.apache.bcel.generic.DADD;
061import org.apache.bcel.generic.DALOAD;
062import org.apache.bcel.generic.DASTORE;
063import org.apache.bcel.generic.DCMPG;
064import org.apache.bcel.generic.DCMPL;
065import org.apache.bcel.generic.DCONST;
066import org.apache.bcel.generic.DDIV;
067import org.apache.bcel.generic.DLOAD;
068import org.apache.bcel.generic.DMUL;
069import org.apache.bcel.generic.DNEG;
070import org.apache.bcel.generic.DREM;
071import org.apache.bcel.generic.DRETURN;
072import org.apache.bcel.generic.DSTORE;
073import org.apache.bcel.generic.DSUB;
074import org.apache.bcel.generic.DUP;
075import org.apache.bcel.generic.DUP2;
076import org.apache.bcel.generic.DUP2_X1;
077import org.apache.bcel.generic.DUP2_X2;
078import org.apache.bcel.generic.DUP_X1;
079import org.apache.bcel.generic.DUP_X2;
080import org.apache.bcel.generic.EmptyVisitor;
081import org.apache.bcel.generic.F2D;
082import org.apache.bcel.generic.F2I;
083import org.apache.bcel.generic.F2L;
084import org.apache.bcel.generic.FADD;
085import org.apache.bcel.generic.FALOAD;
086import org.apache.bcel.generic.FASTORE;
087import org.apache.bcel.generic.FCMPG;
088import org.apache.bcel.generic.FCMPL;
089import org.apache.bcel.generic.FCONST;
090import org.apache.bcel.generic.FDIV;
091import org.apache.bcel.generic.FLOAD;
092import org.apache.bcel.generic.FMUL;
093import org.apache.bcel.generic.FNEG;
094import org.apache.bcel.generic.FREM;
095import org.apache.bcel.generic.FRETURN;
096import org.apache.bcel.generic.FSTORE;
097import org.apache.bcel.generic.FSUB;
098import org.apache.bcel.generic.FieldInstruction;
099import org.apache.bcel.generic.GETFIELD;
100import org.apache.bcel.generic.GETSTATIC;
101import org.apache.bcel.generic.GOTO;
102import org.apache.bcel.generic.GOTO_W;
103import org.apache.bcel.generic.I2B;
104import org.apache.bcel.generic.I2C;
105import org.apache.bcel.generic.I2D;
106import org.apache.bcel.generic.I2F;
107import org.apache.bcel.generic.I2L;
108import org.apache.bcel.generic.I2S;
109import org.apache.bcel.generic.IADD;
110import org.apache.bcel.generic.IALOAD;
111import org.apache.bcel.generic.IAND;
112import org.apache.bcel.generic.IASTORE;
113import org.apache.bcel.generic.ICONST;
114import org.apache.bcel.generic.IDIV;
115import org.apache.bcel.generic.IFEQ;
116import org.apache.bcel.generic.IFGE;
117import org.apache.bcel.generic.IFGT;
118import org.apache.bcel.generic.IFLE;
119import org.apache.bcel.generic.IFLT;
120import org.apache.bcel.generic.IFNE;
121import org.apache.bcel.generic.IFNONNULL;
122import org.apache.bcel.generic.IFNULL;
123import org.apache.bcel.generic.IF_ACMPEQ;
124import org.apache.bcel.generic.IF_ACMPNE;
125import org.apache.bcel.generic.IF_ICMPEQ;
126import org.apache.bcel.generic.IF_ICMPGE;
127import org.apache.bcel.generic.IF_ICMPGT;
128import org.apache.bcel.generic.IF_ICMPLE;
129import org.apache.bcel.generic.IF_ICMPLT;
130import org.apache.bcel.generic.IF_ICMPNE;
131import org.apache.bcel.generic.IINC;
132import org.apache.bcel.generic.ILOAD;
133import org.apache.bcel.generic.IMPDEP1;
134import org.apache.bcel.generic.IMPDEP2;
135import org.apache.bcel.generic.IMUL;
136import org.apache.bcel.generic.INEG;
137import org.apache.bcel.generic.INSTANCEOF;
138import org.apache.bcel.generic.INVOKEDYNAMIC;
139import org.apache.bcel.generic.INVOKEINTERFACE;
140import org.apache.bcel.generic.INVOKESPECIAL;
141import org.apache.bcel.generic.INVOKESTATIC;
142import org.apache.bcel.generic.INVOKEVIRTUAL;
143import org.apache.bcel.generic.IOR;
144import org.apache.bcel.generic.IREM;
145import org.apache.bcel.generic.IRETURN;
146import org.apache.bcel.generic.ISHL;
147import org.apache.bcel.generic.ISHR;
148import org.apache.bcel.generic.ISTORE;
149import org.apache.bcel.generic.ISUB;
150import org.apache.bcel.generic.IUSHR;
151import org.apache.bcel.generic.IXOR;
152import org.apache.bcel.generic.Instruction;
153import org.apache.bcel.generic.InvokeInstruction;
154import org.apache.bcel.generic.JSR;
155import org.apache.bcel.generic.JSR_W;
156import org.apache.bcel.generic.L2D;
157import org.apache.bcel.generic.L2F;
158import org.apache.bcel.generic.L2I;
159import org.apache.bcel.generic.LADD;
160import org.apache.bcel.generic.LALOAD;
161import org.apache.bcel.generic.LAND;
162import org.apache.bcel.generic.LASTORE;
163import org.apache.bcel.generic.LCMP;
164import org.apache.bcel.generic.LCONST;
165import org.apache.bcel.generic.LDC;
166import org.apache.bcel.generic.LDC2_W;
167import org.apache.bcel.generic.LDC_W;
168import org.apache.bcel.generic.LDIV;
169import org.apache.bcel.generic.LLOAD;
170import org.apache.bcel.generic.LMUL;
171import org.apache.bcel.generic.LNEG;
172import org.apache.bcel.generic.LOOKUPSWITCH;
173import org.apache.bcel.generic.LOR;
174import org.apache.bcel.generic.LREM;
175import org.apache.bcel.generic.LRETURN;
176import org.apache.bcel.generic.LSHL;
177import org.apache.bcel.generic.LSHR;
178import org.apache.bcel.generic.LSTORE;
179import org.apache.bcel.generic.LSUB;
180import org.apache.bcel.generic.LUSHR;
181import org.apache.bcel.generic.LXOR;
182import org.apache.bcel.generic.LoadClass;
183import org.apache.bcel.generic.LoadInstruction;
184import org.apache.bcel.generic.LocalVariableInstruction;
185import org.apache.bcel.generic.MONITORENTER;
186import org.apache.bcel.generic.MONITOREXIT;
187import org.apache.bcel.generic.MULTIANEWARRAY;
188import org.apache.bcel.generic.MethodGen;
189import org.apache.bcel.generic.NEW;
190import org.apache.bcel.generic.NEWARRAY;
191import org.apache.bcel.generic.NOP;
192import org.apache.bcel.generic.ObjectType;
193import org.apache.bcel.generic.POP;
194import org.apache.bcel.generic.POP2;
195import org.apache.bcel.generic.PUTFIELD;
196import org.apache.bcel.generic.PUTSTATIC;
197import org.apache.bcel.generic.RET;
198import org.apache.bcel.generic.RETURN;
199import org.apache.bcel.generic.ReferenceType;
200import org.apache.bcel.generic.ReturnInstruction;
201import org.apache.bcel.generic.ReturnaddressType;
202import org.apache.bcel.generic.SALOAD;
203import org.apache.bcel.generic.SASTORE;
204import org.apache.bcel.generic.SIPUSH;
205import org.apache.bcel.generic.SWAP;
206import org.apache.bcel.generic.StackConsumer;
207import org.apache.bcel.generic.StackInstruction;
208import org.apache.bcel.generic.StackProducer;
209import org.apache.bcel.generic.StoreInstruction;
210import org.apache.bcel.generic.TABLESWITCH;
211import org.apache.bcel.generic.Type;
212import org.apache.bcel.verifier.VerificationResult;
213import org.apache.bcel.verifier.Verifier;
214import org.apache.bcel.verifier.VerifierFactory;
215import org.apache.bcel.verifier.exc.AssertionViolatedException;
216import org.apache.bcel.verifier.exc.StructuralCodeConstraintException;
217//CHECKSTYLE:ON
218
219/**
220 * A Visitor class testing for valid preconditions of JVM instructions. The instance of this class will throw a
221 * StructuralCodeConstraintException instance if an instruction is visitXXX()ed which has preconditions that are not
222 * satisfied. TODO: Currently, the JVM's behavior concerning monitors (MONITORENTER, MONITOREXIT) is not modeled in
223 * JustIce.
224 *
225 * @see StructuralCodeConstraintException
226 */
227public class InstConstraintVisitor extends EmptyVisitor {
228
229    private static final ObjectType GENERIC_ARRAY = ObjectType.getInstance(GenericArray.class.getName());
230
231    /**
232     * The Execution Frame we're working on.
233     *
234     * @see #setFrame(Frame f)
235     * @see #locals()
236     * @see #stack()
237     */
238    private Frame frame;
239
240    /**
241     * The ConstantPoolGen we're working on.
242     *
243     * @see #setConstantPoolGen(ConstantPoolGen cpg)
244     */
245    private ConstantPoolGen cpg;
246
247    /**
248     * The MethodGen we're working on.
249     *
250     * @see #setMethodGen(MethodGen mg)
251     */
252    private MethodGen mg;
253
254    /**
255     * The constructor. Constructs a new instance of this class.
256     */
257    public InstConstraintVisitor() {
258    }
259
260    /**
261     * Assures arrayref is of ArrayType or NULL; returns true if and only if arrayref is non-NULL.
262     *
263     * @throws StructuralCodeConstraintException Thrown if the above constraint is violated.
264     */
265    private boolean arrayrefOfArrayType(final Instruction o, final Type arrayref) {
266        if (!(arrayref instanceof ArrayType || arrayref.equals(Type.NULL))) {
267            constraintViolated(o, "The 'arrayref' does not refer to an array but is of type " + arrayref + ".");
268        }
269        return arrayref instanceof ArrayType;
270    }
271
272    private void checkArrayElementType(final BasicType expectedElementType, final Instruction o, final Type peek) {
273        if (Objects.equals(peek, Type.NULL)) {
274            return;
275        }
276        if (!(peek instanceof ArrayType)) {
277            constraintViolated(o, "Stack next-to-next-to-top must be of type " + expectedElementType + " but is '" + peek + "'.");
278        }
279        if (!((ArrayType) peek).isElementType(expectedElementType)) {
280            constraintViolated(o, "Stack next-to-next-to-top must be of type " + expectedElementType + " but is '" + peek + "'.");
281        }
282    }
283
284    private void checkTypeConstraint(final Type expected, final Instruction o, final int depth) {
285        final Type peek = stack().peek(depth);
286        if (!Objects.equals(expected, peek)) {
287            constraintViolated(o, "The value at the stack " + depth + " from the top is not of type '" + expected + "', but of type '" + peek + "'.");
288        }
289    }
290
291    private void checkTypeDoubleConstraint(final Instruction o, final int depth) {
292        checkTypeConstraint(Type.DOUBLE, o, depth);
293    }
294
295    private void checkTypeFloatConstraint(final Instruction o, final int depth) {
296        checkTypeConstraint(Type.FLOAT, o, depth);
297    }
298
299    private void checkTypeIntConstraint(final Instruction o, final int depth) {
300        checkTypeConstraint(Type.INT, o, depth);
301    }
302
303    private void checkTypeLongConstraint(final Instruction o, final int depth) {
304        checkTypeConstraint(Type.LONG, o, depth);
305    }
306
307    /**
308     * This method is called by the visitXXX() to notify the acceptor of this InstConstraintVisitor that a constraint
309     * violation has occurred. This is done by throwing an instance of a StructuralCodeConstraintException.
310     *
311     * @throws StructuralCodeConstraintException Always thrown.
312     */
313    private void constraintViolated(final Instruction violator, final String description) {
314        final String fqClassName = violator.getClass().getName();
315        throw new StructuralCodeConstraintException(
316            "Instruction " + fqClassName.substring(fqClassName.lastIndexOf('.') + 1) + " constraint violated: " + description);
317    }
318
319    private ObjectType getObjectType(final FieldInstruction o) {
320        final ReferenceType rt = o.getReferenceType(cpg);
321        if (rt instanceof ObjectType) {
322            return (ObjectType) rt;
323        }
324        constraintViolated(o, "expecting ObjectType but got " + rt);
325        return null;
326    }
327
328    /**
329     * Assures index is of type INT.
330     *
331     * @throws StructuralCodeConstraintException Thrown if the above constraint is not satisfied.
332     */
333    private void indexOfInt(final Instruction o, final Type index) {
334        if (!index.equals(Type.INT)) {
335            constraintViolated(o, "The 'index' is not of type int but of type " + index + ".");
336        }
337    }
338
339    /**
340     * The LocalVariables we're working on.
341     *
342     * @see #setFrame(Frame f)
343     */
344    private LocalVariables locals() {
345        return frame.getLocals();
346    }
347
348    /**
349     * Assures the ReferenceType r is initialized (or Type.NULL). Formally, this means (!(r instanceof
350     * UninitializedObjectType)), because there are no uninitialized array types.
351     *
352     * @throws StructuralCodeConstraintException Thrown if the above constraint is not satisfied.
353     */
354    private void referenceTypeIsInitialized(final Instruction o, final ReferenceType r) {
355        if (r instanceof UninitializedObjectType) {
356            constraintViolated(o, "Working on an uninitialized object '" + r + "'.");
357        }
358    }
359
360    /**
361     * Sets the ConstantPoolGen instance needed for constraint checking prior to execution.
362     *
363     * @param cpg The constant pool generator.
364     */
365    public void setConstantPoolGen(final ConstantPoolGen cpg) { // TODO could be package-protected?
366        this.cpg = cpg;
367    }
368
369    /**
370     * This returns the single instance of the InstConstraintVisitor class. To operate correctly, other values must have
371     * been set before actually using the instance. Use this method for performance reasons.
372     *
373     * @param f The frame to set.
374     * @see #setConstantPoolGen(ConstantPoolGen cpg)
375     * @see #setMethodGen(MethodGen mg)
376     */
377    public void setFrame(final Frame f) { // TODO could be package-protected?
378        this.frame = f;
379        // if (singleInstance.mg == null || singleInstance.cpg == null)
380        // throw new AssertionViolatedException("Forgot to set important values first.");
381    }
382
383    /**
384     * Sets the MethodGen instance needed for constraint checking prior to execution.
385     *
386     * @param mg The method generator.
387     */
388    public void setMethodGen(final MethodGen mg) {
389        this.mg = mg;
390    }
391
392    /*
393     * "generic"visitXXXX methods where XXXX is an interface therefore, we don't know the order of visiting; but we know these methods are called before the
394     * visitYYYY methods below
395     */
396
397    /**
398     * The OperandStack we're working on.
399     *
400     * @see #setFrame(Frame f)
401     */
402    private OperandStack stack() {
403        return frame.getStack();
404    }
405
406    /** Assures value is of type INT. */
407    private void valueOfInt(final Instruction o, final Type value) {
408        if (!value.equals(Type.INT)) {
409            constraintViolated(o, "The 'value' is not of type int but of type " + value + ".");
410        }
411    }
412
413    /**
414     * Ensures the specific preconditions of the said instruction.
415     */
416    @Override
417    public void visitAALOAD(final AALOAD o) {
418        final Type arrayref = stack().peek(1);
419        final Type index = stack().peek(0);
420
421        indexOfInt(o, index);
422        if (arrayrefOfArrayType(o, arrayref) && !(((ArrayType) arrayref).getElementType() instanceof ReferenceType)) {
423            constraintViolated(o, "The 'arrayref' does not refer to an array with elements of a ReferenceType but to an array of "
424                + ((ArrayType) arrayref).getElementType() + ".");
425        }
426        // referenceTypeIsInitialized(o, (ReferenceType) (((ArrayType) arrayref).getElementType()));
427    }
428
429    /**
430     * Ensures the specific preconditions of the said instruction.
431     */
432    @Override
433    public void visitAASTORE(final AASTORE o) {
434        final Type arrayref = stack().peek(2);
435        final Type index = stack().peek(1);
436        final Type value = stack().peek(0);
437        indexOfInt(o, index);
438        if (!(value instanceof ReferenceType)) {
439            constraintViolated(o, "The 'value' is not of a ReferenceType but of type " + value + ".");
440        }
441        // } else {
442            // referenceTypeIsInitialized(o, (ReferenceType) value);
443        // }
444        //
445        // Don't bother further with "referenceTypeIsInitialized()", there are no arrays
446        // of an uninitialized object type.
447        if (arrayrefOfArrayType(o, arrayref) && !(((ArrayType) arrayref).getElementType() instanceof ReferenceType)) {
448            constraintViolated(o, "The 'arrayref' does not refer to an array with elements of a ReferenceType but to an array of "
449                + ((ArrayType) arrayref).getElementType() + ".");
450        }
451        // No check for array element assignment compatibility. This is done at runtime.
452    }
453
454    /**
455     * Ensures the specific preconditions of the said instruction.
456     */
457    @Override
458    public void visitACONST_NULL(final ACONST_NULL o) {
459        // Nothing needs to be done here.
460    }
461
462    /**
463     * Ensures the specific preconditions of the said instruction.
464     */
465    @Override
466    public void visitALOAD(final ALOAD o) {
467        // visitLoadInstruction(LoadInstruction) is called before.
468
469        // Nothing else needs to be done here.
470    }
471
472    /**
473     * Ensures the specific preconditions of the said instruction.
474     */
475    @Override
476    public void visitANEWARRAY(final ANEWARRAY o) {
477        final Type peek = stack().peek();
478        if (!peek.equals(Type.INT)) {
479            constraintViolated(o, "The 'count' at the stack top is not of type '" + Type.INT + "' but of type '" + peek + "'.");
480            // The runtime constant pool item at that index must be a symbolic reference to a class,
481            // array, or interface type. See Pass 3a.
482        }
483    }
484
485    /**
486     * Ensures the specific preconditions of the said instruction.
487     */
488    @Override
489    public void visitARETURN(final ARETURN o) {
490        final Type peek = stack().peek();
491        if (!(peek instanceof ReferenceType)) {
492            constraintViolated(o, "The 'objectref' at the stack top is not of a ReferenceType but of type '" + peek + "'.");
493        }
494        referenceTypeIsInitialized(o, (ReferenceType) peek);
495
496        // The check below should already done via visitReturnInstruction(ReturnInstruction), see there.
497        // It cannot be done using Staerk-et-al's "set of object types" instead of a
498        // "wider cast object type", anyway.
499        // if (! objectref.isAssignmentCompatibleWith(mg.getReturnType() )) {
500        // constraintViolated(o, "The 'objectref' type "+objectref+
501        // " at the stack top is not assignment compatible with the return type '"+mg.getReturnType()+"' of the method.");
502        // }
503    }
504
505    /**
506     * Ensures the specific preconditions of the said instruction.
507     */
508    @Override
509    public void visitARRAYLENGTH(final ARRAYLENGTH o) {
510        arrayrefOfArrayType(o, stack().peek(0));
511    }
512
513    /**
514     * Ensures the specific preconditions of the said instruction.
515     */
516    @Override
517    public void visitASTORE(final ASTORE o) {
518        final Type peek = stack().peek();
519        if (!(peek instanceof ReferenceType || peek instanceof ReturnaddressType)) {
520            constraintViolated(o, "The 'objectref' is not of a ReferenceType or of ReturnaddressType but of " + peek + ".");
521        }
522        // if (stack().peek() instanceof ReferenceType) {
523        // referenceTypeIsInitialized(o, (ReferenceType) (stack().peek()) );
524        // }
525    }
526
527    /**
528     * Ensures the specific preconditions of the said instruction.
529     */
530    @Override
531    public void visitATHROW(final ATHROW o) {
532        try {
533            // It's stated that 'objectref' must be of a ReferenceType --- but since Throwable is
534            // not derived from an ArrayType, it follows that 'objectref' must be of an ObjectType or Type.NULL.
535            final Type peek = stack().peek();
536            if (!(peek instanceof ObjectType || peek.equals(Type.NULL))) {
537                constraintViolated(o, "The 'objectref' is not of an (initialized) ObjectType but of type " + peek + ".");
538            }
539            // NULL is a subclass of every class, so to speak.
540            if (peek.equals(Type.NULL)) {
541                return;
542            }
543            final ObjectType exc = (ObjectType) peek;
544            final ObjectType throwable = (ObjectType) Type.getType("Ljava/lang/Throwable;");
545            if (!exc.subclassOf(throwable) && !exc.equals(throwable)) {
546                constraintViolated(o, "The 'objectref' is not of class Throwable or of a subclass of Throwable, but of '" + peek + "'.");
547            }
548        } catch (final ClassNotFoundException e) {
549            // FIXME: maybe not the best way to handle this
550            throw new AssertionViolatedException("Missing class: " + e, e);
551        }
552    }
553
554    /*
555    /* "special"visitXXXX methods for one type of instruction each.
556     */
557
558    /**
559     * Ensures the specific preconditions of the said instruction.
560     */
561    @Override
562    public void visitBALOAD(final BALOAD o) {
563        final Type arrayref = stack().peek(1);
564        final Type index = stack().peek(0);
565        indexOfInt(o, index);
566        if (arrayrefOfArrayType(o, arrayref)
567            && !(((ArrayType) arrayref).isElementType(Type.BOOLEAN) || ((ArrayType) arrayref).isElementType(Type.BYTE))) {
568            constraintViolated(o, "The 'arrayref' does not refer to an array with elements of a Type.BYTE or Type.BOOLEAN but to an array of '"
569                + ((ArrayType) arrayref).getElementType() + "'.");
570        }
571    }
572
573    /**
574     * Ensures the specific preconditions of the said instruction.
575     */
576    @Override
577    public void visitBASTORE(final BASTORE o) {
578        final Type arrayref = stack().peek(2);
579        final Type index = stack().peek(1);
580        final Type value = stack().peek(0);
581        indexOfInt(o, index);
582        valueOfInt(o, value);
583        if (arrayrefOfArrayType(o, arrayref)
584            && !(((ArrayType) arrayref).isElementType(Type.BOOLEAN) || ((ArrayType) arrayref).isElementType(Type.BYTE))) {
585            constraintViolated(o, "The 'arrayref' does not refer to an array with elements of a Type.BYTE or Type.BOOLEAN but to an array of '"
586                + ((ArrayType) arrayref).getElementType() + "'.");
587        }
588    }
589
590    /**
591     * Ensures the specific preconditions of the said instruction.
592     */
593    @Override
594    public void visitBIPUSH(final BIPUSH o) {
595        // Nothing to do...
596    }
597
598    /**
599     * Ensures the specific preconditions of the said instruction.
600     */
601    @Override
602    public void visitBREAKPOINT(final BREAKPOINT o) {
603        throw new AssertionViolatedException("In this JustIce verification pass there should not occur an illegal instruction such as BREAKPOINT.");
604    }
605
606    /**
607     * Ensures the specific preconditions of the said instruction.
608     */
609    @Override
610    public void visitCALOAD(final CALOAD o) {
611        final Type arrayref = stack().peek(1);
612        final Type index = stack().peek(0);
613        indexOfInt(o, index);
614        if (arrayrefOfArrayType(o, arrayref) && !((ArrayType) arrayref).isElementType(Type.CHAR)) {
615            constraintViolated(o, "The 'arrayref' does not refer to an array with elements of type char but to an array of type "
616                + ((ArrayType) arrayref).getElementType() + ".");
617        }
618    }
619
620    /*
621     * "generic" visitYYYY methods where YYYY is a superclass.
622     * therefore, we know the order of visiting; we know
623     * these methods are called after the visitXXXX methods above.
624     */
625
626    /**
627     * Ensures the specific preconditions of the said instruction.
628     */
629    @Override
630    public void visitCASTORE(final CASTORE o) {
631        final Type arrayref = stack().peek(2);
632        final Type index = stack().peek(1);
633        final Type value = stack().peek(0);
634        indexOfInt(o, index);
635        valueOfInt(o, value);
636        if (arrayrefOfArrayType(o, arrayref) && !((ArrayType) arrayref).isElementType(Type.CHAR)) {
637            constraintViolated(o, "The 'arrayref' does not refer to an array with elements of type char but to an array of type "
638                + ((ArrayType) arrayref).getElementType() + ".");
639        }
640    }
641
642    /**
643     * Ensures the specific preconditions of the said instruction.
644     */
645    @Override
646    public void visitCHECKCAST(final CHECKCAST o) {
647        // The objectref must be of type reference.
648        final Type objectref = stack().peek(0);
649        if (!(objectref instanceof ReferenceType)) {
650            constraintViolated(o, "The 'objectref' is not of a ReferenceType but of type " + objectref + ".");
651        }
652        // else{
653        // referenceTypeIsInitialized(o, (ReferenceType) objectref);
654        // }
655        // The unsigned indexbyte1 and indexbyte2 are used to construct an index into the runtime constant pool of the
656        // current class (�3.6), where the value of the index is (indexbyte1 << 8) | indexbyte2. The runtime constant
657        // pool item at the index must be a symbolic reference to a class, array, or interface type.
658        final Constant c = cpg.getConstant(o.getIndex());
659        if (!(c instanceof ConstantClass)) {
660            constraintViolated(o, "The Constant at 'index' is not a ConstantClass, but '" + c + "'.");
661        }
662    }
663
664    /**
665     * Ensures the general preconditions of a CPInstruction instance.
666     */
667    @Override
668    public void visitCPInstruction(final CPInstruction o) {
669        final int idx = o.getIndex();
670        if (idx < 0 || idx >= cpg.getSize()) {
671            throw new AssertionViolatedException("Huh?! Constant pool index of instruction '" + o + "' illegal? Pass 3a should have checked this.");
672        }
673    }
674
675    /**
676     * Ensures the specific preconditions of the said instruction.
677     */
678    @Override
679    public void visitD2F(final D2F o) {
680        checkTypeDoubleConstraint(o, 0);
681    }
682
683    /**
684     * Ensures the specific preconditions of the said instruction.
685     */
686    @Override
687    public void visitD2I(final D2I o) {
688        checkTypeDoubleConstraint(o, 0);
689    }
690
691    /**
692     * Ensures the specific preconditions of the said instruction.
693     */
694    @Override
695    public void visitD2L(final D2L o) {
696        checkTypeDoubleConstraint(o, 0);
697    }
698
699    /**
700     * Ensures the specific preconditions of the said instruction.
701     */
702    @Override
703    public void visitDADD(final DADD o) {
704        checkTypeDoubleConstraint(o, 0);
705        checkTypeDoubleConstraint(o, 1);
706    }
707
708    /**
709     * Ensures the specific preconditions of the said instruction.
710     */
711    @Override
712    public void visitDALOAD(final DALOAD o) {
713        indexOfInt(o, stack().peek());
714        checkArrayElementType(Type.DOUBLE, o, stack().peek(1));
715    }
716
717    /**
718     * Ensures the specific preconditions of the said instruction.
719     */
720    @Override
721    public void visitDASTORE(final DASTORE o) {
722        checkTypeDoubleConstraint(o, 0);
723        indexOfInt(o, stack().peek(1));
724        checkArrayElementType(Type.DOUBLE, o, stack().peek(2));
725    }
726
727    /**
728     * Ensures the specific preconditions of the said instruction.
729     */
730    @Override
731    public void visitDCMPG(final DCMPG o) {
732        checkTypeDoubleConstraint(o, 0);
733        checkTypeDoubleConstraint(o, 1);
734    }
735
736    /**
737     * Ensures the specific preconditions of the said instruction.
738     */
739    @Override
740    public void visitDCMPL(final DCMPL o) {
741        checkTypeDoubleConstraint(o, 0);
742        checkTypeDoubleConstraint(o, 1);
743    }
744
745    /**
746     * Ensures the specific preconditions of the said instruction.
747     */
748    @Override
749    public void visitDCONST(final DCONST o) {
750        // There's nothing to be done here.
751    }
752
753    /**
754     * Ensures the specific preconditions of the said instruction.
755     */
756    @Override
757    public void visitDDIV(final DDIV o) {
758        checkTypeDoubleConstraint(o, 0);
759        checkTypeDoubleConstraint(o, 1);
760    }
761
762    /**
763     * Ensures the specific preconditions of the said instruction.
764     */
765    @Override
766    public void visitDLOAD(final DLOAD o) {
767        // visitLoadInstruction(LoadInstruction) is called before.
768
769        // Nothing else needs to be done here.
770    }
771
772    /**
773     * Ensures the specific preconditions of the said instruction.
774     */
775    @Override
776    public void visitDMUL(final DMUL o) {
777        checkTypeDoubleConstraint(o, 0);
778        checkTypeDoubleConstraint(o, 1);
779    }
780
781    /**
782     * Ensures the specific preconditions of the said instruction.
783     */
784    @Override
785    public void visitDNEG(final DNEG o) {
786        checkTypeDoubleConstraint(o, 0);
787    }
788
789    /**
790     * Ensures the specific preconditions of the said instruction.
791     */
792    @Override
793    public void visitDREM(final DREM o) {
794        checkTypeDoubleConstraint(o, 0);
795        checkTypeDoubleConstraint(o, 1);
796    }
797
798    /**
799     * Ensures the specific preconditions of the said instruction.
800     */
801    @Override
802    public void visitDRETURN(final DRETURN o) {
803        checkTypeDoubleConstraint(o, 0);
804    }
805
806    /**
807     * Ensures the specific preconditions of the said instruction.
808     */
809    @Override
810    public void visitDSTORE(final DSTORE o) {
811        // visitStoreInstruction(StoreInstruction) is called before.
812
813        // Nothing else needs to be done here.
814    }
815
816    /**
817     * Ensures the specific preconditions of the said instruction.
818     */
819    @Override
820    public void visitDSUB(final DSUB o) {
821        checkTypeDoubleConstraint(o, 0);
822        checkTypeDoubleConstraint(o, 1);
823    }
824
825    /**
826     * Ensures the specific preconditions of the said instruction.
827     */
828    @Override
829    public void visitDUP(final DUP o) {
830        final Type peek = stack().peek();
831        if (peek.getSize() != 1) {
832            constraintViolated(o,
833                "Won't DUP type on stack top '" + peek + "' because it must occupy exactly one slot, not '" + peek.getSize() + "'.");
834        }
835    }
836
837    /**
838     * Ensures the specific preconditions of the said instruction.
839     */
840    @Override
841    public void visitDUP_X1(final DUP_X1 o) {
842        final Type peek = stack().peek();
843        if (peek.getSize() != 1) {
844            constraintViolated(o, "Type on stack top '" + peek + "' should occupy exactly one slot, not '" + peek.getSize() + "'.");
845        }
846        final Type peek1 = stack().peek(1);
847        if (peek1.getSize() != 1) {
848            constraintViolated(o,
849                "Type on stack next-to-top '" + peek1 + "' should occupy exactly one slot, not '" + peek1.getSize() + "'.");
850        }
851    }
852
853    /**
854     * Ensures the specific preconditions of the said instruction.
855     */
856    @Override
857    public void visitDUP_X2(final DUP_X2 o) {
858        final Type peek = stack().peek();
859        if (peek.getSize() != 1) {
860            constraintViolated(o, "Stack top type must be of size 1, but is '" + peek + "' of size '" + peek.getSize() + "'.");
861        }
862        final Type peek1 = stack().peek(1);
863        if (peek1.getSize() == 2) {
864            return; // Form 2, okay.
865        }
866        // stack().peek(1).getSize == 1.
867        final Type peek2 = stack().peek(2);
868        if (peek2.getSize() != 1) {
869            constraintViolated(o, "If stack top's size is 1 and stack next-to-top's size is 1, stack next-to-next-to-top's size must also be 1, but is: '"
870                + peek2 + "' of size '" + peek2.getSize() + "'.");
871        }
872    }
873
874    /**
875     * Ensures the specific preconditions of the said instruction.
876     */
877    @Override
878    public void visitDUP2(final DUP2 o) {
879        final Type peek = stack().peek();
880        if (peek.getSize() == 2) {
881            return; // Form 2, okay.
882        }
883        // stack().peek().getSize() == 1.
884        final Type peek1 = stack().peek(1);
885        if (peek1.getSize() != 1) {
886            constraintViolated(o, "If stack top's size is 1, then stack next-to-top's size must also be 1. But it is '" + peek1 + "' of size '"
887                + peek1.getSize() + "'.");
888        }
889    }
890
891    /**
892     * Ensures the specific preconditions of the said instruction.
893     */
894    @Override
895    public void visitDUP2_X1(final DUP2_X1 o) {
896        final Type peek = stack().peek();
897        final Type peek1 = stack().peek(1);
898        if (peek.getSize() == 2) {
899            if (peek1.getSize() != 1) {
900                constraintViolated(o, "If stack top's size is 2, then stack next-to-top's size must be 1. But it is '" + peek1 + "' of size '"
901                    + peek1.getSize() + "'.");
902            }
903        } else { // stack top is of size 1
904            if (peek1.getSize() != 1) {
905                constraintViolated(o, "If stack top's size is 1, then stack next-to-top's size must also be 1. But it is '" + peek1 + "' of size '"
906                    + peek1.getSize() + "'.");
907            }
908            final Type peek2 = stack().peek(2);
909            if (peek2.getSize() != 1) {
910                constraintViolated(o, "If stack top's size is 1, then stack next-to-next-to-top's size must also be 1. But it is '" + peek2
911                    + "' of size '" + peek2.getSize() + "'.");
912            }
913        }
914    }
915
916    /**
917     * Ensures the specific preconditions of the said instruction.
918     */
919    @Override
920    public void visitDUP2_X2(final DUP2_X2 o) {
921        final Type peek = stack().peek(0);
922        final Type peek1 = stack().peek(1);
923        final Type peek2 = stack().peek(2);
924        if (peek.getSize() == 2) {
925            // stack top size is 2, next-to-top's size is 1
926            if (peek1.getSize() == 2 || peek2.getSize() == 1) {
927                return; // Form 2
928            }
929            constraintViolated(o, "If stack top's size is 2 and stack-next-to-top's size is 1,"
930                + " then stack next-to-next-to-top's size must also be 1. But it is '" + peek2 + "' of size '" + peek2.getSize() + "'.");
931        } else if (peek1.getSize() == 1 && (peek2.getSize() == 2 || stack().peek(3).getSize() == 1)) {
932            return; // Form 1
933        }
934        constraintViolated(o, "The operand sizes on the stack do not match any of the four forms of usage of this instruction.");
935    }
936
937    /**
938     * Ensures the specific preconditions of the said instruction.
939     */
940    @Override
941    public void visitF2D(final F2D o) {
942        checkTypeFloatConstraint(o, 0);
943    }
944
945    /**
946     * Ensures the specific preconditions of the said instruction.
947     */
948    @Override
949    public void visitF2I(final F2I o) {
950        checkTypeFloatConstraint(o, 0);
951    }
952
953    /**
954     * Ensures the specific preconditions of the said instruction.
955     */
956    @Override
957    public void visitF2L(final F2L o) {
958        checkTypeFloatConstraint(o, 0);
959    }
960
961    /**
962     * Ensures the specific preconditions of the said instruction.
963     */
964    @Override
965    public void visitFADD(final FADD o) {
966        checkTypeFloatConstraint(o, 0);
967        checkTypeFloatConstraint(o, 1);
968    }
969
970    /**
971     * Ensures the specific preconditions of the said instruction.
972     */
973    @Override
974    public void visitFALOAD(final FALOAD o) {
975        indexOfInt(o, stack().peek());
976        checkArrayElementType(Type.FLOAT, o, stack().peek(1));
977    }
978
979    /**
980     * Ensures the specific preconditions of the said instruction.
981     */
982    @Override
983    public void visitFASTORE(final FASTORE o) {
984        checkTypeFloatConstraint(o, 0);
985        indexOfInt(o, stack().peek(1));
986        checkArrayElementType(Type.FLOAT, o, stack().peek(2));
987    }
988
989    /**
990     * Ensures the specific preconditions of the said instruction.
991     */
992    @Override
993    public void visitFCMPG(final FCMPG o) {
994        checkTypeFloatConstraint(o, 0);
995        checkTypeFloatConstraint(o, 1);
996    }
997
998    /**
999     * Ensures the specific preconditions of the said instruction.
1000     */
1001    @Override
1002    public void visitFCMPL(final FCMPL o) {
1003        checkTypeFloatConstraint(o, 0);
1004        checkTypeFloatConstraint(o, 1);
1005    }
1006
1007    /**
1008     * Ensures the specific preconditions of the said instruction.
1009     */
1010    @Override
1011    public void visitFCONST(final FCONST o) {
1012        // nothing to do here.
1013    }
1014
1015    /**
1016     * Ensures the specific preconditions of the said instruction.
1017     */
1018    @Override
1019    public void visitFDIV(final FDIV o) {
1020        checkTypeFloatConstraint(o, 0);
1021        checkTypeFloatConstraint(o, 1);
1022    }
1023
1024    /**
1025     * Ensures the general preconditions of a FieldInstruction instance.
1026     */
1027    @Override
1028    public void visitFieldInstruction(final FieldInstruction o) {
1029        // visitLoadClass(o) has been called before: Every FieldOrMethod
1030        // implements LoadClass.
1031        // visitCPInstruction(o) has been called before.
1032        // A FieldInstruction may be: GETFIELD, GETSTATIC, PUTFIELD, PUTSTATIC
1033        final Constant c = cpg.getConstant(o.getIndex());
1034        if (!(c instanceof ConstantFieldref)) {
1035            constraintViolated(o, "Index '" + o.getIndex() + "' should refer to a CONSTANT_Fieldref_info structure, but refers to '" + c + "'.");
1036        }
1037        // the o.getClassType(cpg) type has passed pass 2; see visitLoadClass(o).
1038        final Type t = o.getType(cpg);
1039        if (t instanceof ObjectType) {
1040            final String name = ((ObjectType) t).getClassName();
1041            final Verifier v = VerifierFactory.getVerifier(name);
1042            final VerificationResult vr = v.doPass2();
1043            if (vr.getStatus() != VerificationResult.VERIFIED_OK) {
1044                constraintViolated(o, "Class '" + name + "' is referenced, but cannot be loaded and resolved: '" + vr + "'.");
1045            }
1046        }
1047    }
1048
1049    private Field visitFieldInstructionInternals(final FieldInstruction o) throws ClassNotFoundException {
1050        final String fieldName = o.getFieldName(cpg);
1051        final JavaClass jc = Repository.lookupClass(getObjectType(o).getClassName());
1052        final Field f = jc.findField(fieldName, o.getType(cpg));
1053        if (f == null) {
1054            throw new AssertionViolatedException("Field '" + fieldName + "' not found in " + jc.getClassName());
1055        }
1056        final Type value = stack().peek();
1057        final Type t = Type.getType(f.getSignature());
1058        Type shouldBe = t;
1059        if (shouldBe == Type.BOOLEAN || shouldBe == Type.BYTE || shouldBe == Type.CHAR || shouldBe == Type.SHORT) {
1060            shouldBe = Type.INT;
1061        }
1062        if (t instanceof ReferenceType) {
1063            if (value instanceof ReferenceType) {
1064                final ReferenceType rValue = (ReferenceType) value;
1065                referenceTypeIsInitialized(o, rValue);
1066                // TODO: This can possibly only be checked using Staerk-et-al's "set-of-object types", not
1067                // using "wider cast object types" created during verification.
1068                // Comment it out if you encounter problems. See also the analogon at visitPUTFIELD|visitPUTSTATIC.
1069                if (!rValue.isAssignmentCompatibleWith(shouldBe)) {
1070                    constraintViolated(o, "The stack top type '" + value + "' is not assignment compatible with '" + shouldBe + "'.");
1071                }
1072            } else {
1073                constraintViolated(o, "The stack top type '" + value + "' is not of a reference type as expected.");
1074            }
1075        } else if (shouldBe != value) {
1076            constraintViolated(o, "The stack top type '" + value + "' is not of type '" + shouldBe + "' as expected.");
1077        }
1078        return f;
1079    }
1080
1081    /**
1082     * Ensures the specific preconditions of the said instruction.
1083     */
1084    @Override
1085    public void visitFLOAD(final FLOAD o) {
1086        // visitLoadInstruction(LoadInstruction) is called before.
1087
1088        // Nothing else needs to be done here.
1089    }
1090
1091    /**
1092     * Ensures the specific preconditions of the said instruction.
1093     */
1094    @Override
1095    public void visitFMUL(final FMUL o) {
1096        checkTypeFloatConstraint(o, 0);
1097        checkTypeFloatConstraint(o, 1);
1098    }
1099
1100    /**
1101     * Ensures the specific preconditions of the said instruction.
1102     */
1103    @Override
1104    public void visitFNEG(final FNEG o) {
1105        checkTypeFloatConstraint(o, 0);
1106    }
1107
1108    /**
1109     * Ensures the specific preconditions of the said instruction.
1110     */
1111    @Override
1112    public void visitFREM(final FREM o) {
1113        checkTypeFloatConstraint(o, 0);
1114        checkTypeFloatConstraint(o, 1);
1115    }
1116
1117    /**
1118     * Ensures the specific preconditions of the said instruction.
1119     */
1120    @Override
1121    public void visitFRETURN(final FRETURN o) {
1122        checkTypeFloatConstraint(o, 0);
1123    }
1124
1125    /**
1126     * Ensures the specific preconditions of the said instruction.
1127     */
1128    @Override
1129    public void visitFSTORE(final FSTORE o) {
1130        // visitStoreInstruction(StoreInstruction) is called before.
1131
1132        // Nothing else needs to be done here.
1133    }
1134
1135    /**
1136     * Ensures the specific preconditions of the said instruction.
1137     */
1138    @Override
1139    public void visitFSUB(final FSUB o) {
1140        checkTypeFloatConstraint(o, 0);
1141        checkTypeFloatConstraint(o, 1);
1142    }
1143
1144    /**
1145     * Ensures the specific preconditions of the said instruction.
1146     */
1147    @Override
1148    public void visitGETFIELD(final GETFIELD o) {
1149        try {
1150            final Type objectref = stack().peek();
1151            if (!(objectref instanceof ObjectType || objectref == Type.NULL)) {
1152                constraintViolated(o, "Stack top should be an object reference that's not an array reference, but is '" + objectref + "'.");
1153            }
1154            final String fieldName = o.getFieldName(cpg);
1155
1156            final JavaClass jc = Repository.lookupClass(getObjectType(o).getClassName());
1157            final Field f = jc.findField(fieldName, o.getType(cpg));
1158            if (f == null) {
1159                throw new AssertionViolatedException("Field '" + fieldName + "' not found in " + jc.getClassName());
1160            }
1161            if (f.isProtected()) {
1162                final ObjectType classtype = getObjectType(o);
1163                final ObjectType curr = ObjectType.getInstance(mg.getClassName());
1164                if (classtype.equals(curr) || curr.subclassOf(classtype)) {
1165                    final Type t = stack().peek();
1166                    if (t == Type.NULL) {
1167                        return;
1168                    }
1169                    if (!(t instanceof ObjectType)) {
1170                        constraintViolated(o, "The 'objectref' must refer to an object that's not an array. Found instead: '" + t + "'.");
1171                    }
1172                    // final ObjectType objreftype = (ObjectType) t;
1173                    // if (!(objreftype.equals(curr) || objreftype.subclassOf(curr))) {
1174                        // TODO: One day move to Staerk-et-al's "Set of object types" instead of "wider" object types
1175                        // created during the verification.
1176                        // "Wider" object types don't allow us to check for things like that below.
1177                        // constraintViolated(o, "The referenced field has the ACC_PROTECTED modifier, "+
1178                        // "and it's a member of the current class or a superclass of the current class."+
1179                        // " However, the referenced object type '"+stack().peek()+
1180                        // "' is not the current class or a subclass of the current class.");
1181                    //}
1182                }
1183            }
1184            // TODO: Could go into Pass 3a.
1185            if (f.isStatic()) {
1186                constraintViolated(o, "Referenced field '" + f + "' is static which it shouldn't be.");
1187            }
1188        } catch (final ClassNotFoundException e) {
1189            // FIXME: maybe not the best way to handle this
1190            throw new AssertionViolatedException("Missing class: " + e, e);
1191        }
1192    }
1193
1194    /**
1195     * Ensures the specific preconditions of the said instruction.
1196     */
1197    @Override
1198    public void visitGETSTATIC(final GETSTATIC o) {
1199        // Field must be static: see Pass 3a.
1200    }
1201
1202    /**
1203     * Ensures the specific preconditions of the said instruction.
1204     */
1205    @Override
1206    public void visitGOTO(final GOTO o) {
1207        // nothing to do here.
1208    }
1209
1210    /**
1211     * Ensures the specific preconditions of the said instruction.
1212     */
1213    @Override
1214    public void visitGOTO_W(final GOTO_W o) {
1215        // nothing to do here.
1216    }
1217
1218    /**
1219     * Ensures the specific preconditions of the said instruction.
1220     */
1221    @Override
1222    public void visitI2B(final I2B o) {
1223        checkTypeIntConstraint(o, 0);
1224    }
1225
1226    /**
1227     * Ensures the specific preconditions of the said instruction.
1228     */
1229    @Override
1230    public void visitI2C(final I2C o) {
1231        checkTypeIntConstraint(o, 0);
1232    }
1233
1234    /**
1235     * Ensures the specific preconditions of the said instruction.
1236     */
1237    @Override
1238    public void visitI2D(final I2D o) {
1239        checkTypeIntConstraint(o, 0);
1240    }
1241
1242    /**
1243     * Ensures the specific preconditions of the said instruction.
1244     */
1245    @Override
1246    public void visitI2F(final I2F o) {
1247        checkTypeIntConstraint(o, 0);
1248    }
1249
1250    /**
1251     * Ensures the specific preconditions of the said instruction.
1252     */
1253    @Override
1254    public void visitI2L(final I2L o) {
1255        checkTypeIntConstraint(o, 0);
1256    }
1257
1258    /**
1259     * Ensures the specific preconditions of the said instruction.
1260     */
1261    @Override
1262    public void visitI2S(final I2S o) {
1263        checkTypeIntConstraint(o, 0);
1264    }
1265
1266    /**
1267     * Ensures the specific preconditions of the said instruction.
1268     */
1269    @Override
1270    public void visitIADD(final IADD o) {
1271        checkTypeIntConstraint(o, 0);
1272        checkTypeIntConstraint(o, 1);
1273    }
1274
1275    /**
1276     * Ensures the specific preconditions of the said instruction.
1277     */
1278    @Override
1279    public void visitIALOAD(final IALOAD o) {
1280        indexOfInt(o, stack().peek());
1281        checkArrayElementType(Type.INT, o, stack().peek(1));
1282    }
1283
1284    /**
1285     * Ensures the specific preconditions of the said instruction.
1286     */
1287    @Override
1288    public void visitIAND(final IAND o) {
1289        checkTypeIntConstraint(o, 0);
1290        checkTypeIntConstraint(o, 1);
1291    }
1292
1293    /**
1294     * Ensures the specific preconditions of the said instruction.
1295     */
1296    @Override
1297    public void visitIASTORE(final IASTORE o) {
1298        checkTypeIntConstraint(o, 0);
1299        indexOfInt(o, stack().peek(1));
1300        checkArrayElementType(Type.INT, o, stack().peek(2));
1301    }
1302
1303    /**
1304     * Ensures the specific preconditions of the said instruction.
1305     */
1306    @Override
1307    public void visitICONST(final ICONST o) {
1308        // nothing to do here.
1309    }
1310
1311    /**
1312     * Ensures the specific preconditions of the said instruction.
1313     */
1314    @Override
1315    public void visitIDIV(final IDIV o) {
1316        checkTypeIntConstraint(o, 0);
1317        checkTypeIntConstraint(o, 1);
1318    }
1319
1320    /**
1321     * Ensures the specific preconditions of the said instruction.
1322     */
1323    @Override
1324    public void visitIF_ACMPEQ(final IF_ACMPEQ o) {
1325        if (!(stack().peek() instanceof ReferenceType)) {
1326            constraintViolated(o, "The value at the stack top is not of a ReferenceType, but of type '" + stack().peek() + "'.");
1327        }
1328        // referenceTypeIsInitialized(o, (ReferenceType) (stack().peek()) );
1329        if (!(stack().peek(1) instanceof ReferenceType)) {
1330            constraintViolated(o, "The value at the stack next-to-top is not of a ReferenceType, but of type '" + stack().peek(1) + "'.");
1331        }
1332        // referenceTypeIsInitialized(o, (ReferenceType) (stack().peek(1)) );
1333    }
1334
1335    /**
1336     * Ensures the specific preconditions of the said instruction.
1337     */
1338    @Override
1339    public void visitIF_ACMPNE(final IF_ACMPNE o) {
1340        if (!(stack().peek() instanceof ReferenceType)) {
1341            constraintViolated(o, "The value at the stack top is not of a ReferenceType, but of type '" + stack().peek() + "'.");
1342            // referenceTypeIsInitialized(o, (ReferenceType) (stack().peek()) );
1343        }
1344        if (!(stack().peek(1) instanceof ReferenceType)) {
1345            constraintViolated(o, "The value at the stack next-to-top is not of a ReferenceType, but of type '" + stack().peek(1) + "'.");
1346            // referenceTypeIsInitialized(o, (ReferenceType) (stack().peek(1)) );
1347        }
1348    }
1349
1350    /**
1351     * Ensures the specific preconditions of the said instruction.
1352     */
1353    @Override
1354    public void visitIF_ICMPEQ(final IF_ICMPEQ o) {
1355        checkTypeIntConstraint(o, 0);
1356        checkTypeIntConstraint(o, 1);
1357    }
1358
1359    /**
1360     * Ensures the specific preconditions of the said instruction.
1361     */
1362    @Override
1363    public void visitIF_ICMPGE(final IF_ICMPGE o) {
1364        checkTypeIntConstraint(o, 0);
1365        checkTypeIntConstraint(o, 1);
1366    }
1367
1368    /**
1369     * Ensures the specific preconditions of the said instruction.
1370     */
1371    @Override
1372    public void visitIF_ICMPGT(final IF_ICMPGT o) {
1373        checkTypeIntConstraint(o, 0);
1374        checkTypeIntConstraint(o, 1);
1375    }
1376
1377    /**
1378     * Ensures the specific preconditions of the said instruction.
1379     */
1380    @Override
1381    public void visitIF_ICMPLE(final IF_ICMPLE o) {
1382        checkTypeIntConstraint(o, 0);
1383        checkTypeIntConstraint(o, 1);
1384    }
1385
1386    /**
1387     * Ensures the specific preconditions of the said instruction.
1388     */
1389    @Override
1390    public void visitIF_ICMPLT(final IF_ICMPLT o) {
1391        checkTypeIntConstraint(o, 0);
1392        checkTypeIntConstraint(o, 1);
1393    }
1394
1395    /**
1396     * Ensures the specific preconditions of the said instruction.
1397     */
1398    @Override
1399    public void visitIF_ICMPNE(final IF_ICMPNE o) {
1400        checkTypeIntConstraint(o, 0);
1401        checkTypeIntConstraint(o, 1);
1402    }
1403
1404    /**
1405     * Ensures the specific preconditions of the said instruction.
1406     */
1407    @Override
1408    public void visitIFEQ(final IFEQ o) {
1409        checkTypeIntConstraint(o, 0);
1410    }
1411
1412    /**
1413     * Ensures the specific preconditions of the said instruction.
1414     */
1415    @Override
1416    public void visitIFGE(final IFGE o) {
1417        checkTypeIntConstraint(o, 0);
1418    }
1419
1420    /**
1421     * Ensures the specific preconditions of the said instruction.
1422     */
1423    @Override
1424    public void visitIFGT(final IFGT o) {
1425        checkTypeIntConstraint(o, 0);
1426    }
1427
1428    /**
1429     * Ensures the specific preconditions of the said instruction.
1430     */
1431    @Override
1432    public void visitIFLE(final IFLE o) {
1433        checkTypeIntConstraint(o, 0);
1434    }
1435
1436    /**
1437     * Ensures the specific preconditions of the said instruction.
1438     */
1439    @Override
1440    public void visitIFLT(final IFLT o) {
1441        checkTypeIntConstraint(o, 0);
1442    }
1443
1444    /**
1445     * Ensures the specific preconditions of the said instruction.
1446     */
1447    @Override
1448    public void visitIFNE(final IFNE o) {
1449        checkTypeIntConstraint(o, 0);
1450    }
1451
1452    /**
1453     * Ensures the specific preconditions of the said instruction.
1454     */
1455    @Override
1456    public void visitIFNONNULL(final IFNONNULL o) {
1457        if (!(stack().peek() instanceof ReferenceType)) {
1458            constraintViolated(o, "The value at the stack top is not of a ReferenceType, but of type '" + stack().peek() + "'.");
1459        }
1460        referenceTypeIsInitialized(o, (ReferenceType) stack().peek());
1461    }
1462
1463    /**
1464     * Ensures the specific preconditions of the said instruction.
1465     */
1466    @Override
1467    public void visitIFNULL(final IFNULL o) {
1468        if (!(stack().peek() instanceof ReferenceType)) {
1469            constraintViolated(o, "The value at the stack top is not of a ReferenceType, but of type '" + stack().peek() + "'.");
1470        }
1471        referenceTypeIsInitialized(o, (ReferenceType) stack().peek());
1472    }
1473
1474    /**
1475     * Ensures the specific preconditions of the said instruction.
1476     */
1477    @Override
1478    public void visitIINC(final IINC o) {
1479        // Mhhh. In BCEL, at this time "IINC" is not a LocalVariableInstruction.
1480        if (locals().maxLocals() <= (o.getType(cpg).getSize() == 1 ? o.getIndex() : o.getIndex() + 1)) {
1481            constraintViolated(o, "The 'index' is not a valid index into the local variable array.");
1482        }
1483        indexOfInt(o, locals().get(o.getIndex()));
1484    }
1485
1486    /**
1487     * Ensures the specific preconditions of the said instruction.
1488     */
1489    @Override
1490    public void visitILOAD(final ILOAD o) {
1491        // All done by visitLocalVariableInstruction(), visitLoadInstruction()
1492    }
1493
1494    /**
1495     * Ensures the specific preconditions of the said instruction.
1496     */
1497    @Override
1498    public void visitIMPDEP1(final IMPDEP1 o) {
1499        throw new AssertionViolatedException("In this JustIce verification pass there should not occur an illegal instruction such as IMPDEP1.");
1500    }
1501
1502    /**
1503     * Ensures the specific preconditions of the said instruction.
1504     */
1505    @Override
1506    public void visitIMPDEP2(final IMPDEP2 o) {
1507        throw new AssertionViolatedException("In this JustIce verification pass there should not occur an illegal instruction such as IMPDEP2.");
1508    }
1509
1510    /**
1511     * Ensures the specific preconditions of the said instruction.
1512     */
1513    @Override
1514    public void visitIMUL(final IMUL o) {
1515        checkTypeIntConstraint(o, 0);
1516        checkTypeIntConstraint(o, 1);
1517    }
1518
1519    /**
1520     * Ensures the specific preconditions of the said instruction.
1521     */
1522    @Override
1523    public void visitINEG(final INEG o) {
1524        checkTypeIntConstraint(o, 0);
1525    }
1526
1527    /**
1528     * Ensures the specific preconditions of the said instruction.
1529     */
1530    @Override
1531    public void visitINSTANCEOF(final INSTANCEOF o) {
1532        // The objectref must be of type reference.
1533        final Type objectref = stack().peek(0);
1534        if (!(objectref instanceof ReferenceType)) {
1535            constraintViolated(o, "The 'objectref' is not of a ReferenceType but of type " + objectref + ".");
1536        }
1537        // else{
1538        // referenceTypeIsInitialized(o, (ReferenceType) objectref);
1539        // }
1540        // The unsigned indexbyte1 and indexbyte2 are used to construct an index into the runtime constant pool of the
1541        // current class (�3.6), where the value of the index is (indexbyte1 << 8) | indexbyte2. The runtime constant
1542        // pool item at the index must be a symbolic reference to a class, array, or interface type.
1543        final Constant c = cpg.getConstant(o.getIndex());
1544        if (!(c instanceof ConstantClass)) {
1545            constraintViolated(o, "The Constant at 'index' is not a ConstantClass, but '" + c + "'.");
1546        }
1547    }
1548
1549    /**
1550     * Ensures the specific preconditions of the said instruction.
1551     *
1552     * @since 6.0
1553     */
1554    @Override
1555    public void visitINVOKEDYNAMIC(final INVOKEDYNAMIC o) {
1556        throw new UnsupportedOperationException("INVOKEDYNAMIC instruction is not supported at this time");
1557    }
1558
1559    /**
1560     * Ensures the general preconditions of an InvokeInstruction instance.
1561     */
1562    @Override
1563    public void visitInvokeInstruction(final InvokeInstruction o) {
1564        // visitLoadClass(o) has been called before: Every FieldOrMethod
1565        // implements LoadClass.
1566        // visitCPInstruction(o) has been called before.
1567        // TODO
1568    }
1569
1570    /**
1571     * Ensures the specific preconditions of the said instruction.
1572     */
1573    @Override
1574    public void visitINVOKEINTERFACE(final INVOKEINTERFACE o) {
1575        // Method is not native, otherwise pass 3 would not happen.
1576        final int count = o.getCount();
1577        if (count == 0) {
1578            constraintViolated(o, "The 'count' argument must not be 0.");
1579        }
1580        // It is a ConstantInterfaceMethodref, Pass 3a made it sure.
1581        // TODO: Do we want to do anything with it?
1582        // ConstantInterfaceMethodref cimr = (ConstantInterfaceMethodref) (cpg.getConstant(o.getIndex()));
1583        // the o.getClassType(cpg) type has passed pass 2; see visitLoadClass(o).
1584        final Type t = o.getType(cpg);
1585        if (t instanceof ObjectType) {
1586            final String name = ((ObjectType) t).getClassName();
1587            final Verifier v = VerifierFactory.getVerifier(name);
1588            final VerificationResult vr = v.doPass2();
1589            if (vr.getStatus() != VerificationResult.VERIFIED_OK) {
1590                constraintViolated(o, "Class '" + name + "' is referenced, but cannot be loaded and resolved: '" + vr + "'.");
1591            }
1592        }
1593        final Type[] argTypes = o.getArgumentTypes(cpg);
1594        final int argCount = argTypes.length;
1595        for (int i = argCount - 1; i >= 0; i--) {
1596            final Type fromStack = stack().peek(argCount - 1 - i); // 0 to argCount - 1
1597            Type fromDesc = argTypes[i];
1598            if (fromDesc == Type.BOOLEAN || fromDesc == Type.BYTE || fromDesc == Type.CHAR || fromDesc == Type.SHORT) {
1599                fromDesc = Type.INT;
1600            }
1601            if (!fromStack.equals(fromDesc)) {
1602                if (fromStack instanceof ReferenceType && fromDesc instanceof ReferenceType) {
1603                    final ReferenceType rFromStack = (ReferenceType) fromStack;
1604                    // ReferenceType rFromDesc = (ReferenceType) fromDesc;
1605                    // TODO: This can only be checked when using Staerk-et-al's "set of object types"
1606                    // instead of a "wider cast object type" created during verification.
1607                    // if ( ! rFromStack.isAssignmentCompatibleWith(rFromDesc) ) {
1608                    // constraintViolated(o, "Expecting a '"+fromDesc+"' but found a '"+fromStack+
1609                    // "' on the stack (which is not assignment compatible).");
1610                    // }
1611                    referenceTypeIsInitialized(o, rFromStack);
1612                } else {
1613                    constraintViolated(o, "Expecting a '" + fromDesc + "' but found a '" + fromStack + "' on the stack.");
1614                }
1615            }
1616        }
1617        Type objRef = stack().peek(argCount);
1618        if (objRef == Type.NULL) {
1619            return;
1620        }
1621        if (!(objRef instanceof ReferenceType)) {
1622            constraintViolated(o, "Expecting a reference type as 'objectref' on the stack, not a '" + objRef + "'.");
1623        }
1624        referenceTypeIsInitialized(o, (ReferenceType) objRef);
1625        if (!(objRef instanceof ObjectType)) {
1626            if (!(objRef instanceof ArrayType)) { // could be a ReturnaddressType
1627                constraintViolated(o, "Expecting an ObjectType as 'objectref' on the stack, not a '" + objRef + "'.");
1628            } else {
1629                objRef = GENERIC_ARRAY;
1630            }
1631        }
1632        // String objRefClassName = ((ObjectType) objRef).getClassName();
1633        // String theInterface = o.getClassName(cpg);
1634        // TODO: This can only be checked if we're using Staerk-et-al's "set of object types"
1635        // instead of "wider cast object types" generated during verification.
1636        // if ( ! Repository.implementationOf(objRefClassName, theInterface) ) {
1637        // constraintViolated(o, "The 'objRef' item '" + objRef + "' does not implement '" + theInterface + "' as expected.");
1638        // }
1639        int countedCount = 1; // 1 for the objectref
1640        for (int i = 0; i < argCount; i++) {
1641            countedCount += argTypes[i].getSize();
1642        }
1643        if (count != countedCount) {
1644            constraintViolated(o, "The 'count' argument should probably read '" + countedCount + "' but is '" + count + "'.");
1645        }
1646    }
1647
1648    private int visitInvokeInternals(final InvokeInstruction o) throws ClassNotFoundException {
1649        final Type t = o.getType(cpg);
1650        if (t instanceof ObjectType) {
1651            final String name = ((ObjectType) t).getClassName();
1652            final Verifier v = VerifierFactory.getVerifier(name);
1653            final VerificationResult vr = v.doPass2();
1654            if (vr.getStatus() != VerificationResult.VERIFIED_OK) {
1655                constraintViolated(o, "Class '" + name + "' is referenced, but cannot be loaded and resolved: '" + vr + "'.");
1656            }
1657        }
1658        final Type[] argtypes = o.getArgumentTypes(cpg);
1659        final int nargs = argtypes.length;
1660
1661        for (int i = nargs - 1; i >= 0; i--) {
1662            final Type fromStack = stack().peek(nargs - 1 - i); // 0 to nargs-1
1663            Type fromDesc = argtypes[i];
1664            if (fromDesc == Type.BOOLEAN || fromDesc == Type.BYTE || fromDesc == Type.CHAR || fromDesc == Type.SHORT) {
1665                fromDesc = Type.INT;
1666            }
1667            if (!fromStack.equals(fromDesc)) {
1668                if (fromStack instanceof ReferenceType && fromDesc instanceof ReferenceType) {
1669                    final ReferenceType rFromStack = (ReferenceType) fromStack;
1670                    final ReferenceType rFromDesc = (ReferenceType) fromDesc;
1671                    // TODO: This can possibly only be checked when using Staerk-et-al's "set of object types" instead
1672                    // of a single "wider cast object type" created during verification.
1673                    if (!rFromStack.isAssignmentCompatibleWith(rFromDesc)) {
1674                        constraintViolated(o,
1675                            "Expecting a '" + fromDesc + "' but found a '" + fromStack + "' on the stack (which is not assignment compatible).");
1676                    }
1677                    referenceTypeIsInitialized(o, rFromStack);
1678                } else {
1679                    constraintViolated(o, "Expecting a '" + fromDesc + "' but found a '" + fromStack + "' on the stack.");
1680                }
1681            }
1682        }
1683        return nargs;
1684    }
1685
1686    /**
1687     * Ensures the specific preconditions of the said instruction.
1688     */
1689    @Override
1690    public void visitINVOKESPECIAL(final INVOKESPECIAL o) {
1691        try {
1692            // Don't init an object twice.
1693            if (o.getMethodName(cpg).equals(Const.CONSTRUCTOR_NAME) && !(stack().peek(o.getArgumentTypes(cpg).length) instanceof UninitializedObjectType)) {
1694                constraintViolated(o,
1695                    "Possibly initializing object twice."
1696                        + " A valid instruction sequence must not have an uninitialized object on the operand stack or in a local variable"
1697                        + " during a backwards branch, or in a local variable in code protected by an exception handler."
1698                        + " Please see The Java Virtual Machine Specification, Second Edition, 4.9.4 (pages 147 and 148) for details.");
1699            }
1700            // the o.getClassType(cpg) type has passed pass 2; see visitLoadClass(o).
1701            final int nargs = visitInvokeInternals(o);
1702            Type objref = stack().peek(nargs);
1703            if (objref == Type.NULL) {
1704                return;
1705            }
1706            if (!(objref instanceof ReferenceType)) {
1707                constraintViolated(o, "Expecting a reference type as 'objectref' on the stack, not a '" + objref + "'.");
1708            }
1709            String objRefClassName = null;
1710            if (!o.getMethodName(cpg).equals(Const.CONSTRUCTOR_NAME)) {
1711                referenceTypeIsInitialized(o, (ReferenceType) objref);
1712                if (!(objref instanceof ObjectType)) {
1713                    if (!(objref instanceof ArrayType)) { // could be a ReturnaddressType
1714                        constraintViolated(o, "Expecting an ObjectType as 'objectref' on the stack, not a '" + objref + "'.");
1715                    } else {
1716                        objref = GENERIC_ARRAY;
1717                    }
1718                }
1719
1720                objRefClassName = ((ObjectType) objref).getClassName();
1721            } else {
1722                if (!(objref instanceof UninitializedObjectType)) {
1723                    constraintViolated(o, "Expecting an UninitializedObjectType as 'objectref' on the stack, not a '" + objref
1724                        + "'. Otherwise, you couldn't invoke a method since an array has no methods (not to speak of a return address).");
1725                }
1726                objRefClassName = ((UninitializedObjectType) objref).getInitialized().getClassName();
1727            }
1728
1729            final String theClass = o.getClassName(cpg);
1730            if (!Repository.instanceOf(objRefClassName, theClass)) {
1731                constraintViolated(o, "The 'objref' item '" + objref + "' does not implement '" + theClass + "' as expected.");
1732            }
1733
1734        } catch (final ClassNotFoundException e) {
1735            // FIXME: maybe not the best way to handle this
1736            throw new AssertionViolatedException("Missing class: " + e, e);
1737        }
1738    }
1739
1740    /**
1741     * Ensures the specific preconditions of the said instruction.
1742     */
1743    @Override
1744    public void visitINVOKESTATIC(final INVOKESTATIC o) {
1745        try {
1746            // Method is not native, otherwise pass 3 would not happen.
1747            visitInvokeInternals(o);
1748        } catch (final ClassNotFoundException e) {
1749            // FIXME: maybe not the best way to handle this
1750            throw new AssertionViolatedException("Missing class: " + e, e);
1751        }
1752    }
1753
1754    /**
1755     * Ensures the specific preconditions of the said instruction.
1756     */
1757    @Override
1758    public void visitINVOKEVIRTUAL(final INVOKEVIRTUAL o) {
1759        try {
1760            // the o.getClassType(cpg) type has passed pass 2; see visitLoadClass(o).
1761
1762            final int nargs = visitInvokeInternals(o);
1763            Type objref = stack().peek(nargs);
1764            if (objref == Type.NULL) {
1765                return;
1766            }
1767            if (!(objref instanceof ReferenceType)) {
1768                constraintViolated(o, "Expecting a reference type as 'objectref' on the stack, not a '" + objref + "'.");
1769            }
1770            referenceTypeIsInitialized(o, (ReferenceType) objref);
1771            if (!(objref instanceof ObjectType)) {
1772                if (!(objref instanceof ArrayType)) { // could be a ReturnaddressType
1773                    constraintViolated(o, "Expecting an ObjectType as 'objectref' on the stack, not a '" + objref + "'.");
1774                } else {
1775                    objref = GENERIC_ARRAY;
1776                }
1777            }
1778            final String objRefClassName = ((ObjectType) objref).getClassName();
1779            final String theClass = o.getClassName(cpg);
1780            if (objref != GENERIC_ARRAY && !Repository.instanceOf(objRefClassName, theClass)) {
1781                constraintViolated(o, "The 'objref' item '" + objref + "' does not implement '" + theClass + "' as expected.");
1782            }
1783        } catch (final ClassNotFoundException e) {
1784            // FIXME: maybe not the best way to handle this
1785            throw new AssertionViolatedException("Missing class: " + e, e);
1786        }
1787    }
1788
1789    /**
1790     * Ensures the specific preconditions of the said instruction.
1791     */
1792    @Override
1793    public void visitIOR(final IOR o) {
1794        checkTypeIntConstraint(o, 0);
1795        checkTypeIntConstraint(o, 1);
1796    }
1797
1798    /**
1799     * Ensures the specific preconditions of the said instruction.
1800     */
1801    @Override
1802    public void visitIREM(final IREM o) {
1803        checkTypeIntConstraint(o, 0);
1804        checkTypeIntConstraint(o, 1);
1805    }
1806
1807    /**
1808     * Ensures the specific preconditions of the said instruction.
1809     */
1810    @Override
1811    public void visitIRETURN(final IRETURN o) {
1812        checkTypeIntConstraint(o, 0);
1813    }
1814
1815    /**
1816     * Ensures the specific preconditions of the said instruction.
1817     */
1818    @Override
1819    public void visitISHL(final ISHL o) {
1820        checkTypeIntConstraint(o, 0);
1821        checkTypeIntConstraint(o, 1);
1822    }
1823
1824    /**
1825     * Ensures the specific preconditions of the said instruction.
1826     */
1827    @Override
1828    public void visitISHR(final ISHR o) {
1829        checkTypeIntConstraint(o, 0);
1830        checkTypeIntConstraint(o, 1);
1831    }
1832
1833    /**
1834     * Ensures the specific preconditions of the said instruction.
1835     */
1836    @Override
1837    public void visitISTORE(final ISTORE o) {
1838        // visitStoreInstruction(StoreInstruction) is called before.
1839        // Nothing else needs to be done here.
1840    }
1841
1842    /**
1843     * Ensures the specific preconditions of the said instruction.
1844     */
1845    @Override
1846    public void visitISUB(final ISUB o) {
1847        checkTypeIntConstraint(o, 0);
1848        checkTypeIntConstraint(o, 1);
1849    }
1850
1851    /**
1852     * Ensures the specific preconditions of the said instruction.
1853     */
1854    @Override
1855    public void visitIUSHR(final IUSHR o) {
1856        checkTypeIntConstraint(o, 0);
1857        checkTypeIntConstraint(o, 1);
1858    }
1859
1860    /**
1861     * Ensures the specific preconditions of the said instruction.
1862     */
1863    @Override
1864    public void visitIXOR(final IXOR o) {
1865        checkTypeIntConstraint(o, 0);
1866        checkTypeIntConstraint(o, 1);
1867    }
1868
1869    /**
1870     * Ensures the specific preconditions of the said instruction.
1871     */
1872    @Override
1873    public void visitJSR(final JSR o) {
1874        // nothing to do here.
1875    }
1876
1877    /**
1878     * Ensures the specific preconditions of the said instruction.
1879     */
1880    @Override
1881    public void visitJSR_W(final JSR_W o) {
1882        // nothing to do here.
1883    }
1884
1885    /**
1886     * Ensures the specific preconditions of the said instruction.
1887     */
1888    @Override
1889    public void visitL2D(final L2D o) {
1890        checkTypeLongConstraint(o, 0);
1891    }
1892
1893    /**
1894     * Ensures the specific preconditions of the said instruction.
1895     */
1896    @Override
1897    public void visitL2F(final L2F o) {
1898        checkTypeLongConstraint(o, 0);
1899    }
1900
1901    /**
1902     * Ensures the specific preconditions of the said instruction.
1903     */
1904    @Override
1905    public void visitL2I(final L2I o) {
1906        checkTypeLongConstraint(o, 0);
1907    }
1908
1909    /**
1910     * Ensures the specific preconditions of the said instruction.
1911     */
1912    @Override
1913    public void visitLADD(final LADD o) {
1914        checkTypeLongConstraint(o, 0);
1915        checkTypeLongConstraint(o, 1);
1916    }
1917
1918    /**
1919     * Ensures the specific preconditions of the said instruction.
1920     */
1921    @Override
1922    public void visitLALOAD(final LALOAD o) {
1923        indexOfInt(o, stack().peek());
1924        checkArrayElementType(Type.LONG, o, stack().peek(1));
1925    }
1926
1927    /**
1928     * Ensures the specific preconditions of the said instruction.
1929     */
1930    @Override
1931    public void visitLAND(final LAND o) {
1932        checkTypeLongConstraint(o, 0);
1933        checkTypeLongConstraint(o, 1);
1934    }
1935
1936    /**
1937     * Ensures the specific preconditions of the said instruction.
1938     */
1939    @Override
1940    public void visitLASTORE(final LASTORE o) {
1941        checkTypeLongConstraint(o, 0);
1942        indexOfInt(o, stack().peek(1));
1943        checkArrayElementType(Type.LONG, o, stack().peek(2));
1944    }
1945
1946    /**
1947     * Ensures the specific preconditions of the said instruction.
1948     */
1949    @Override
1950    public void visitLCMP(final LCMP o) {
1951        checkTypeLongConstraint(o, 0);
1952        checkTypeLongConstraint(o, 1);
1953    }
1954
1955    /**
1956     * Ensures the specific preconditions of the said instruction.
1957     */
1958    @Override
1959    public void visitLCONST(final LCONST o) {
1960        // Nothing to do here.
1961    }
1962
1963    /**
1964     * Ensures the specific preconditions of the said instruction.
1965     */
1966    @Override
1967    public void visitLDC(final LDC o) {
1968        // visitCPInstruction is called first.
1969
1970        final Constant c = cpg.getConstant(o.getIndex());
1971        if (!(c instanceof ConstantInteger
1972                || c instanceof ConstantFloat
1973                || c instanceof ConstantString
1974                || c instanceof ConstantClass
1975                || c instanceof ConstantDynamic)) {
1976            constraintViolated(o,
1977                "Referenced constant should be a CONSTANT_Integer, a CONSTANT_Float, a CONSTANT_String, a CONSTANT_Class, or a CONSTANT_Dynamic but is '"
1978                        + c + "'.");
1979        }
1980    }
1981
1982    /**
1983     * Ensures the specific preconditions of the said instruction.
1984     *
1985     * @param o The instruction to visit.
1986     */
1987    public void visitLDC_W(final LDC_W o) {
1988        // visitCPInstruction is called first.
1989
1990        final Constant c = cpg.getConstant(o.getIndex());
1991        if (!(c instanceof ConstantInteger || c instanceof ConstantFloat || c instanceof ConstantString || c instanceof ConstantClass)) {
1992            constraintViolated(o,
1993                "Referenced constant should be a CONSTANT_Integer, a CONSTANT_Float, a CONSTANT_String or a CONSTANT_Class, but is '" + c + "'.");
1994        }
1995    }
1996
1997    /**
1998     * Ensures the specific preconditions of the said instruction.
1999     */
2000    @Override
2001    public void visitLDC2_W(final LDC2_W o) {
2002        // visitCPInstruction is called first.
2003
2004        final Constant c = cpg.getConstant(o.getIndex());
2005        if (!(c instanceof ConstantLong || c instanceof ConstantDouble)) {
2006            constraintViolated(o, "Referenced constant should be a CONSTANT_Integer, a CONSTANT_Float or a CONSTANT_String, but is '" + c + "'.");
2007        }
2008    }
2009
2010    /**
2011     * Ensures the specific preconditions of the said instruction.
2012     */
2013    @Override
2014    public void visitLDIV(final LDIV o) {
2015        checkTypeLongConstraint(o, 0);
2016        checkTypeLongConstraint(o, 1);
2017    }
2018
2019    /**
2020     * Ensures the specific preconditions of the said instruction.
2021     */
2022    @Override
2023    public void visitLLOAD(final LLOAD o) {
2024        // visitLoadInstruction(LoadInstruction) is called before.
2025
2026        // Nothing else needs to be done here.
2027    }
2028
2029    /**
2030     * Ensures the specific preconditions of the said instruction.
2031     */
2032    @Override
2033    public void visitLMUL(final LMUL o) {
2034        checkTypeLongConstraint(o, 0);
2035        checkTypeLongConstraint(o, 1);
2036    }
2037
2038    /**
2039     * Ensures the specific preconditions of the said instruction.
2040     */
2041    @Override
2042    public void visitLNEG(final LNEG o) {
2043        checkTypeLongConstraint(o, 0);
2044    }
2045
2046    /**
2047     * Assures the generic preconditions of a LoadClass instance. The referenced class is loaded and pass2-verified.
2048     */
2049    @Override
2050    public void visitLoadClass(final LoadClass o) {
2051        final ObjectType t = o.getLoadClassType(cpg);
2052        if (t != null) { // null means "no class is loaded"
2053            final Verifier v = VerifierFactory.getVerifier(t.getClassName());
2054            final VerificationResult vr = v.doPass2();
2055            if (vr.getStatus() != VerificationResult.VERIFIED_OK) {
2056                constraintViolated((Instruction) o,
2057                    "Class '" + o.getLoadClassType(cpg).getClassName() + "' is referenced, but cannot be loaded and resolved: '" + vr + "'.");
2058            }
2059        }
2060    }
2061
2062    /**
2063     * Assures the generic preconditions of a LoadInstruction instance.
2064     */
2065    @Override
2066    public void visitLoadInstruction(final LoadInstruction o) {
2067        // visitLocalVariableInstruction(o) is called before, because it is more generic.
2068
2069        // LOAD instructions must not read Type.UNKNOWN
2070        if (locals().get(o.getIndex()) == Type.UNKNOWN) {
2071            constraintViolated(o, "Read-Access on local variable " + o.getIndex() + " with unknown content.");
2072        }
2073
2074        // LOAD instructions, two-slot-values at index N must have Type.UNKNOWN
2075        // as a symbol for the higher halve at index N+1
2076        // [suppose some instruction put an int at N+1--- our double at N is defective]
2077        if (o.getType(cpg).getSize() == 2 && locals().get(o.getIndex() + 1) != Type.UNKNOWN) {
2078            constraintViolated(o,
2079                "Reading a two-locals value from local variables " + o.getIndex() + " and " + (o.getIndex() + 1) + " where the latter one is destroyed.");
2080        }
2081
2082        // LOAD instructions must read the correct type.
2083        if (!(o instanceof ALOAD)) {
2084            if (locals().get(o.getIndex()) != o.getType(cpg)) {
2085                constraintViolated(o, "Local Variable type and LOADing Instruction type mismatch: Local Variable: '" + locals().get(o.getIndex())
2086                    + "'; Instruction type: '" + o.getType(cpg) + "'.");
2087            }
2088        } else if (!(locals().get(o.getIndex()) instanceof ReferenceType)) {
2089            constraintViolated(o, "Local Variable type and LOADing Instruction type mismatch: Local Variable: '" + locals().get(o.getIndex())
2090                + "'; Instruction expects a ReferenceType.");
2091        }
2092        // ALOAD __IS ALLOWED__ to put uninitialized objects onto the stack!
2093        // referenceTypeIsInitialized(o, (ReferenceType) (locals().get(o.getIndex())));
2094
2095        // LOAD instructions must have enough free stack slots.
2096        if (stack().maxStack() - stack().slotsUsed() < o.getType(cpg).getSize()) {
2097            constraintViolated(o, "Not enough free stack slots to load a '" + o.getType(cpg) + "' onto the OperandStack.");
2098        }
2099    }
2100
2101    /**
2102     * Assures the generic preconditions of a LocalVariableInstruction instance. That is, the index of the local variable
2103     * must be valid.
2104     */
2105    @Override
2106    public void visitLocalVariableInstruction(final LocalVariableInstruction o) {
2107        if (locals().maxLocals() <= (o.getType(cpg).getSize() == 1 ? o.getIndex() : o.getIndex() + 1)) {
2108            constraintViolated(o, "The 'index' is not a valid index into the local variable array.");
2109        }
2110    }
2111
2112    /**
2113     * Ensures the specific preconditions of the said instruction.
2114     */
2115    @Override
2116    public void visitLOOKUPSWITCH(final LOOKUPSWITCH o) {
2117        checkTypeIntConstraint(o, 0);
2118        // See also pass 3a.
2119    }
2120
2121    /**
2122     * Ensures the specific preconditions of the said instruction.
2123     */
2124    @Override
2125    public void visitLOR(final LOR o) {
2126        checkTypeLongConstraint(o, 0);
2127        checkTypeLongConstraint(o, 1);
2128    }
2129
2130    /**
2131     * Ensures the specific preconditions of the said instruction.
2132     */
2133    @Override
2134    public void visitLREM(final LREM o) {
2135        checkTypeLongConstraint(o, 0);
2136        checkTypeLongConstraint(o, 1);
2137    }
2138
2139    /**
2140     * Ensures the specific preconditions of the said instruction.
2141     */
2142    @Override
2143    public void visitLRETURN(final LRETURN o) {
2144        checkTypeLongConstraint(o, 0);
2145    }
2146
2147    /**
2148     * Ensures the specific preconditions of the said instruction.
2149     */
2150    @Override
2151    public void visitLSHL(final LSHL o) {
2152        checkTypeIntConstraint(o, 0);
2153        checkTypeLongConstraint(o, 1);
2154    }
2155
2156    /**
2157     * Ensures the specific preconditions of the said instruction.
2158     */
2159    @Override
2160    public void visitLSHR(final LSHR o) {
2161        checkTypeIntConstraint(o, 0);
2162        checkTypeLongConstraint(o, 1);
2163    }
2164
2165    /**
2166     * Ensures the specific preconditions of the said instruction.
2167     */
2168    @Override
2169    public void visitLSTORE(final LSTORE o) {
2170        // visitStoreInstruction(StoreInstruction) is called before.
2171
2172        // Nothing else needs to be done here.
2173    }
2174
2175    /**
2176     * Ensures the specific preconditions of the said instruction.
2177     */
2178    @Override
2179    public void visitLSUB(final LSUB o) {
2180        checkTypeLongConstraint(o, 0);
2181        checkTypeLongConstraint(o, 1);
2182    }
2183
2184    /**
2185     * Ensures the specific preconditions of the said instruction.
2186     */
2187    @Override
2188    public void visitLUSHR(final LUSHR o) {
2189        checkTypeIntConstraint(o, 0);
2190        checkTypeLongConstraint(o, 1);
2191    }
2192
2193    /**
2194     * Ensures the specific preconditions of the said instruction.
2195     */
2196    @Override
2197    public void visitLXOR(final LXOR o) {
2198        checkTypeLongConstraint(o, 0);
2199        checkTypeLongConstraint(o, 1);
2200    }
2201
2202    /**
2203     * Ensures the specific preconditions of the said instruction.
2204     */
2205    @Override
2206    public void visitMONITORENTER(final MONITORENTER o) {
2207        if (!(stack().peek() instanceof ReferenceType)) {
2208            constraintViolated(o, "The stack top should be of a ReferenceType, but is '" + stack().peek() + "'.");
2209        }
2210        // referenceTypeIsInitialized(o, (ReferenceType) (stack().peek()) );
2211    }
2212
2213    /**
2214     * Ensures the specific preconditions of the said instruction.
2215     */
2216    @Override
2217    public void visitMONITOREXIT(final MONITOREXIT o) {
2218        if (!(stack().peek() instanceof ReferenceType)) {
2219            constraintViolated(o, "The stack top should be of a ReferenceType, but is '" + stack().peek() + "'.");
2220        }
2221        // referenceTypeIsInitialized(o, (ReferenceType) (stack().peek()) );
2222    }
2223
2224    /**
2225     * Ensures the specific preconditions of the said instruction.
2226     */
2227    @Override
2228    public void visitMULTIANEWARRAY(final MULTIANEWARRAY o) {
2229        final int dimensions = o.getDimensions();
2230        // Dimensions argument is okay: see Pass 3a.
2231        for (int i = 0; i < dimensions; i++) {
2232            if (stack().peek(i) != Type.INT) {
2233                constraintViolated(o, "The '" + dimensions + "' upper stack types should be 'int' but aren't.");
2234            }
2235        }
2236        // The runtime constant pool item at that index must be a symbolic reference to a class,
2237        // array, or interface type. See Pass 3a.
2238    }
2239
2240    /**
2241     * Ensures the specific preconditions of the said instruction.
2242     */
2243    @Override
2244    public void visitNEW(final NEW o) {
2245        // visitCPInstruction(CPInstruction) has been called before.
2246        // visitLoadClass(LoadClass) has been called before.
2247
2248        final Type t = o.getType(cpg);
2249        if (!(t instanceof ReferenceType)) {
2250            throw new AssertionViolatedException("NEW.getType() returning a non-reference type?.");
2251        }
2252        if (!(t instanceof ObjectType)) {
2253            constraintViolated(o, "Expecting a class type (ObjectType) to work on. Found: '" + t + "'.");
2254        }
2255        final ObjectType obj = (ObjectType) t;
2256
2257        // for example: Don't instantiate interfaces
2258        try {
2259            if (!obj.referencesClassExact()) {
2260                constraintViolated(o, "Expecting a class type (ObjectType) to work on. Found: '" + obj + "'.");
2261            }
2262        } catch (final ClassNotFoundException e) {
2263            constraintViolated(o, "Expecting a class type (ObjectType) to work on. Found: '" + obj + "'. which threw " + e);
2264        }
2265    }
2266
2267    /**
2268     * Ensures the specific preconditions of the said instruction.
2269     */
2270    @Override
2271    public void visitNEWARRAY(final NEWARRAY o) {
2272        checkTypeIntConstraint(o, 0);
2273    }
2274
2275    /**
2276     * Ensures the specific preconditions of the said instruction.
2277     */
2278    @Override
2279    public void visitNOP(final NOP o) {
2280        // nothing is to be done here.
2281    }
2282
2283    /**
2284     * Ensures the specific preconditions of the said instruction.
2285     */
2286    @Override
2287    public void visitPOP(final POP o) {
2288        if (stack().peek().getSize() != 1) {
2289            constraintViolated(o, "Stack top size should be 1 but stack top is '" + stack().peek() + "' of size '" + stack().peek().getSize() + "'.");
2290        }
2291    }
2292
2293    /**
2294     * Ensures the specific preconditions of the said instruction.
2295     */
2296    @Override
2297    public void visitPOP2(final POP2 o) {
2298        if (stack().peek().getSize() != 2) {
2299            constraintViolated(o, "Stack top size should be 2 but stack top is '" + stack().peek() + "' of size '" + stack().peek().getSize() + "'.");
2300        }
2301    }
2302
2303    /**
2304     * Ensures the specific preconditions of the said instruction.
2305     */
2306    @Override
2307    public void visitPUTFIELD(final PUTFIELD o) {
2308        try {
2309
2310            final Type objectref = stack().peek(1);
2311            if (!(objectref instanceof ObjectType || objectref == Type.NULL)) {
2312                constraintViolated(o, "Stack next-to-top should be an object reference that's not an array reference, but is '" + objectref + "'.");
2313            }
2314
2315            final Field f = visitFieldInstructionInternals(o);
2316
2317            if (f.isProtected()) {
2318                final ObjectType classtype = getObjectType(o);
2319                final ObjectType curr = ObjectType.getInstance(mg.getClassName());
2320
2321                if (classtype.equals(curr) || curr.subclassOf(classtype)) {
2322                    final Type tp = stack().peek(1);
2323                    if (tp == Type.NULL) {
2324                        return;
2325                    }
2326                    if (!(tp instanceof ObjectType)) {
2327                        constraintViolated(o, "The 'objectref' must refer to an object that's not an array. Found instead: '" + tp + "'.");
2328                    }
2329                    final ObjectType objreftype = (ObjectType) tp;
2330                    if (!(objreftype.equals(curr) || objreftype.subclassOf(curr))) {
2331                        constraintViolated(o,
2332                            "The referenced field has the ACC_PROTECTED modifier, and it's a member of the current class or"
2333                                + " a superclass of the current class. However, the referenced object type '" + stack().peek()
2334                                + "' is not the current class or a subclass of the current class.");
2335                    }
2336                }
2337            }
2338
2339            // TODO: Could go into Pass 3a.
2340            if (f.isStatic()) {
2341                constraintViolated(o, "Referenced field '" + f + "' is static which it shouldn't be.");
2342            }
2343
2344        } catch (final ClassNotFoundException e) {
2345            // FIXME: maybe not the best way to handle this
2346            throw new AssertionViolatedException("Missing class: " + e, e);
2347        }
2348    }
2349
2350    /**
2351     * Ensures the specific preconditions of the said instruction.
2352     */
2353    @Override
2354    public void visitPUTSTATIC(final PUTSTATIC o) {
2355        try {
2356            visitFieldInstructionInternals(o);
2357        } catch (final ClassNotFoundException e) {
2358            // FIXME: maybe not the best way to handle this
2359            throw new AssertionViolatedException("Missing class: " + e, e);
2360        }
2361    }
2362
2363    /**
2364     * Ensures the specific preconditions of the said instruction.
2365     */
2366    @Override
2367    public void visitRET(final RET o) {
2368        if (!(locals().get(o.getIndex()) instanceof ReturnaddressType)) {
2369            constraintViolated(o, "Expecting a ReturnaddressType in local variable " + o.getIndex() + ".");
2370        }
2371        if (locals().get(o.getIndex()) == ReturnaddressType.NO_TARGET) {
2372            throw new AssertionViolatedException("RET expecting a target.");
2373        }
2374        // Other constraints such as non-allowed overlapping subroutines are enforced
2375        // while building the Subroutines data structure.
2376    }
2377
2378    /**
2379     * Ensures the specific preconditions of the said instruction.
2380     */
2381    @Override
2382    public void visitRETURN(final RETURN o) {
2383        if (mg.getName().equals(Const.CONSTRUCTOR_NAME) && Frame.getThis() != null && !mg.getClassName().equals(Type.OBJECT.getClassName())) {
2384            constraintViolated(o, "Leaving a constructor that itself did not call a constructor.");
2385        }
2386    }
2387
2388    /**
2389     * Assures the generic preconditions of a ReturnInstruction instance.
2390     */
2391    @Override
2392    public void visitReturnInstruction(final ReturnInstruction o) {
2393        Type methodType = mg.getType();
2394        if (methodType == Type.BOOLEAN || methodType == Type.BYTE || methodType == Type.SHORT || methodType == Type.CHAR) {
2395            methodType = Type.INT;
2396        }
2397
2398        if (o instanceof RETURN) {
2399            if (methodType == Type.VOID) {
2400                return;
2401            }
2402            constraintViolated(o, "RETURN instruction in non-void method.");
2403        }
2404        if (o instanceof ARETURN) {
2405            if (methodType == Type.VOID) {
2406                constraintViolated(o, "ARETURN instruction in void method.");
2407            }
2408            if (stack().peek() == Type.NULL) {
2409                return;
2410            }
2411            if (!(stack().peek() instanceof ReferenceType)) {
2412                constraintViolated(o, "Reference type expected on top of stack, but is: '" + stack().peek() + "'.");
2413            }
2414            referenceTypeIsInitialized(o, (ReferenceType) stack().peek());
2415            // ReferenceType objectref = (ReferenceType) (stack().peek());
2416            // TODO: This can only be checked if using Staerk-et-al's "set of object types" instead of a
2417            // "wider cast object type" created during verification.
2418            // if (! (objectref.isAssignmentCompatibleWith(mg.getType())) ) {
2419            // constraintViolated(o, "Type on stack top which should be returned is a '"+stack().peek()+
2420            // "' which is not assignment compatible with the return type of this method, '"+mg.getType()+"'.");
2421            // }
2422        } else if (!methodType.equals(stack().peek())) {
2423            constraintViolated(o, "Current method has return type of '" + mg.getType() + "' expecting a '" + methodType
2424                + "' on top of the stack. But stack top is a '" + stack().peek() + "'.");
2425        }
2426    }
2427
2428    /**
2429     * Ensures the specific preconditions of the said instruction.
2430     */
2431    @Override
2432    public void visitSALOAD(final SALOAD o) {
2433        indexOfInt(o, stack().peek());
2434        checkArrayElementType(Type.SHORT, o, stack().peek(1));
2435    }
2436
2437    /**
2438     * Ensures the specific preconditions of the said instruction.
2439     */
2440    @Override
2441    public void visitSASTORE(final SASTORE o) {
2442        checkTypeIntConstraint(o, 0);
2443        indexOfInt(o, stack().peek(1));
2444        checkArrayElementType(Type.SHORT, o, stack().peek(2));
2445    }
2446
2447    /**
2448     * Ensures the specific preconditions of the said instruction.
2449     */
2450    @Override
2451    public void visitSIPUSH(final SIPUSH o) {
2452        // nothing to do here. Generic visitXXX() methods did the trick before.
2453    }
2454
2455    /**
2456     * Ensures the general preconditions of an instruction that accesses the stack. This method is here because BCEL has no
2457     * such superinterface for the stack accessing instructions; and there are funny unexpected exceptions in the semantices
2458     * of the superinterfaces and superclasses provided. E.g. SWAP is a StackConsumer, but DUP_X1 is not a StackProducer.
2459     * Therefore, this method is called by all StackProducer, StackConsumer, and StackInstruction instances via their
2460     * visitXXX() method. Unfortunately, as the superclasses and superinterfaces overlap, some instructions cause this
2461     * method to be called two or three times. [TODO: Fix this.]
2462     *
2463     * @see #visitStackConsumer(StackConsumer o)
2464     * @see #visitStackProducer(StackProducer o)
2465     * @see #visitStackInstruction(StackInstruction o)
2466     */
2467    private void visitStackAccessor(final Instruction o) {
2468        final int consume = o.consumeStack(cpg); // Stack values are always consumed first; then produced.
2469        if (consume > stack().slotsUsed()) {
2470            constraintViolated(o, "Cannot consume " + consume + " stack slots: only " + stack().slotsUsed() + " slot(s) left on stack!\nStack:\n" + stack());
2471        }
2472
2473        final int produce = o.produceStack(cpg) - o.consumeStack(cpg); // Stack values are always consumed first; then produced.
2474        if (produce + stack().slotsUsed() > stack().maxStack()) {
2475            constraintViolated(o, "Cannot produce " + produce + " stack slots: only " + (stack().maxStack() - stack().slotsUsed())
2476                + " free stack slot(s) left.\nStack:\n" + stack());
2477        }
2478    }
2479
2480    /**
2481     * Ensures the general preconditions of a StackConsumer instance.
2482     */
2483    @Override
2484    public void visitStackConsumer(final StackConsumer o) {
2485        visitStackAccessor((Instruction) o);
2486    }
2487
2488    /**
2489     * Ensures the general preconditions of a StackInstruction instance.
2490     */
2491    @Override
2492    public void visitStackInstruction(final StackInstruction o) {
2493        visitStackAccessor(o);
2494    }
2495
2496    /**
2497     * Ensures the general preconditions of a StackProducer instance.
2498     */
2499    @Override
2500    public void visitStackProducer(final StackProducer o) {
2501        visitStackAccessor((Instruction) o);
2502    }
2503
2504    /**
2505     * Assures the generic preconditions of a StoreInstruction instance.
2506     */
2507    @Override
2508    public void visitStoreInstruction(final StoreInstruction o) {
2509        // visitLocalVariableInstruction(o) is called before, because it is more generic.
2510
2511        if (stack().isEmpty()) { // Don't bother about 1 or 2 stack slots used. This check is implicitly done below while type checking.
2512            constraintViolated(o, "Cannot STORE: Stack to read from is empty.");
2513        }
2514
2515        if (!(o instanceof ASTORE)) {
2516            if (!(stack().peek() == o.getType(cpg))) { // the other xSTORE types are singletons in BCEL.
2517                constraintViolated(o,
2518                    "Stack top type and STOREing Instruction type mismatch: Stack top: '" + stack().peek() + "'; Instruction type: '" + o.getType(cpg) + "'.");
2519            }
2520        } else { // we deal with ASTORE
2521            final Type stacktop = stack().peek();
2522            if (!(stacktop instanceof ReferenceType) && !(stacktop instanceof ReturnaddressType)) {
2523                constraintViolated(o, "Stack top type and STOREing Instruction type mismatch: Stack top: '" + stack().peek()
2524                    + "'; Instruction expects a ReferenceType or a ReturnadressType.");
2525            }
2526            // if (stacktop instanceof ReferenceType) {
2527            // referenceTypeIsInitialized(o, (ReferenceType) stacktop);
2528            // }
2529        }
2530    }
2531
2532    /**
2533     * Ensures the specific preconditions of the said instruction.
2534     */
2535    @Override
2536    public void visitSWAP(final SWAP o) {
2537        if (stack().peek().getSize() != 1) {
2538            constraintViolated(o, "The value at the stack top is not of size '1', but of size '" + stack().peek().getSize() + "'.");
2539        }
2540        if (stack().peek(1).getSize() != 1) {
2541            constraintViolated(o, "The value at the stack next-to-top is not of size '1', but of size '" + stack().peek(1).getSize() + "'.");
2542        }
2543    }
2544
2545    /**
2546     * Ensures the specific preconditions of the said instruction.
2547     */
2548    @Override
2549    public void visitTABLESWITCH(final TABLESWITCH o) {
2550        indexOfInt(o, stack().peek());
2551        // See Pass 3a.
2552    }
2553
2554}