public void visitInvokeInstruction()

in src/main/java/org/apache/bcel/verifier/statics/Pass3aVerifier.java [434:502]


        public void visitInvokeInstruction(final InvokeInstruction o) {
            indexValid(o, o.getIndex());
            if (o instanceof INVOKEVIRTUAL || o instanceof INVOKESPECIAL || o instanceof INVOKESTATIC) {
                final Constant c = constantPoolGen.getConstant(o.getIndex());
                if (!(c instanceof ConstantMethodref)) {
                    constraintViolated(o, "Indexing a constant that's not a CONSTANT_Methodref but a '" + tostring(c) + "'.");
                } else {
                    // Constants are okay due to pass2.
                    final ConstantNameAndType cnat = (ConstantNameAndType) constantPoolGen.getConstant(((ConstantMethodref) c).getNameAndTypeIndex());
                    final ConstantUtf8 cutf8 = (ConstantUtf8) constantPoolGen.getConstant(cnat.getNameIndex());
                    if (cutf8.getBytes().equals(Const.CONSTRUCTOR_NAME) && !(o instanceof INVOKESPECIAL)) {
                        constraintViolated(o, "Only INVOKESPECIAL is allowed to invoke instance initialization methods.");
                    }
                    if (!cutf8.getBytes().equals(Const.CONSTRUCTOR_NAME) && cutf8.getBytes().startsWith("<")) {
                        constraintViolated(o, "No method with a name beginning with '<' other than the instance initialization methods"
                            + " may be called by the method invocation instructions.");
                    }
                }
            } else {
                final Constant c = constantPoolGen.getConstant(o.getIndex());
                if (!(c instanceof ConstantInterfaceMethodref) && !(c instanceof ConstantInvokeDynamic)) {
                    constraintViolated(o, "Indexing a constant that's not a CONSTANT_InterfaceMethodref/InvokeDynamic but a '" + tostring(c) + "'.");
                }
                // TODO: From time to time check if BCEL allows to detect if the
                // 'count' operand is consistent with the information in the
                // CONSTANT_InterfaceMethodref and if the last operand is zero.
                // By now, BCEL hides those two operands because they're superfluous.

                // Invoked method must not be <init> or <clinit>
                final ConstantNameAndType cnat = (ConstantNameAndType) constantPoolGen.getConstant(((ConstantCP) c).getNameAndTypeIndex());
                final String name = ((ConstantUtf8) constantPoolGen.getConstant(cnat.getNameIndex())).getBytes();
                if (name.equals(Const.CONSTRUCTOR_NAME)) {
                    constraintViolated(o, "Method to invoke must not be '" + Const.CONSTRUCTOR_NAME + "'.");
                }
                if (name.equals(Const.STATIC_INITIALIZER_NAME)) {
                    constraintViolated(o, "Method to invoke must not be '" + Const.STATIC_INITIALIZER_NAME + "'.");
                }
            }

            // The LoadClassType is the method-declaring class, so we have to check the other types.

            Type t = o.getReturnType(constantPoolGen);
            if (t instanceof ArrayType) {
                t = ((ArrayType) t).getBasicType();
            }
            if (t instanceof ObjectType) {
                final Verifier v = VerifierFactory.getVerifier(((ObjectType) t).getClassName());
                final VerificationResult vr = v.doPass2();
                if (vr.getStatus() != VerificationResult.VERIFIED_OK) {
                    constraintViolated(o, "Return type class/interface could not be verified successfully: '" + vr.getMessage() + "'.");
                }
            }

            final Type[] ts = o.getArgumentTypes(constantPoolGen);
            for (final Type element : ts) {
                t = element;
                if (t instanceof ArrayType) {
                    t = ((ArrayType) t).getBasicType();
                }
                if (t instanceof ObjectType) {
                    final Verifier v = VerifierFactory.getVerifier(((ObjectType) t).getClassName());
                    final VerificationResult vr = v.doPass2();
                    if (vr.getStatus() != VerificationResult.VERIFIED_OK) {
                        constraintViolated(o, "Argument type class/interface could not be verified successfully: '" + vr.getMessage() + "'.");
                    }
                }
            }

        }