public void visitExceptionTable()

in src/main/java/org/apache/bcel/verifier/statics/Pass2Verifier.java [498:554]


        public void visitExceptionTable(final ExceptionTable obj) { // vmspec2 4.7.4
            try {
                // incorrectly named, it's the Exceptions attribute (vmspec2 4.7.4)
                checkIndex(obj, obj.getNameIndex(), CONST_Utf8);

                final String name = ((ConstantUtf8) cp.getConstant(obj.getNameIndex())).getBytes();
                if (!name.equals("Exceptions")) {
                    throw new ClassConstraintException(
                        "The Exceptions attribute '" + tostring(obj) + "' is not correctly named 'Exceptions' but '" + name + "'.");
                }

                final int[] excIndices = obj.getExceptionIndexTable();

                for (final int excIndice : excIndices) {
                    checkIndex(obj, excIndice, CONST_Class);

                    final ConstantClass cc = (ConstantClass) cp.getConstant(excIndice);
                    checkIndex(cc, cc.getNameIndex(), CONST_Utf8); // can't be sure this ConstantClass has already been visited (checked)!
                    // convert internal notation on-the-fly to external notation:
                    final String cname = Utility.pathToPackage(((ConstantUtf8) cp.getConstant(cc.getNameIndex())).getBytes());

                    Verifier v = VerifierFactory.getVerifier(cname);
                    VerificationResult vr = v.doPass1();

                    if (vr != VerificationResult.VR_OK) {
                        throw new ClassConstraintException("Exceptions attribute '" + tostring(obj) + "' references '" + cname
                            + "' as an Exception but it does not pass verification pass 1: " + vr);
                    }
                    // We cannot safely trust any other "instanceof" mechanism. We need to transitively verify
                    // the ancestor hierarchy.
                    JavaClass e = Repository.lookupClass(cname);
                    final JavaClass t = Repository.lookupClass(Type.THROWABLE.getClassName());
                    final JavaClass o = Repository.lookupClass(Type.OBJECT.getClassName());
                    while (e != o) {
                        if (e == t) {
                            break; // It's a subclass of Throwable, OKAY, leave.
                        }

                        v = VerifierFactory.getVerifier(e.getSuperclassName());
                        vr = v.doPass1();
                        if (vr != VerificationResult.VR_OK) {
                            throw new ClassConstraintException("Exceptions attribute '" + tostring(obj) + "' references '" + cname + "' as an Exception but '"
                                + e.getSuperclassName() + "' in the ancestor hierachy does not pass verification pass 1: " + vr);
                        }
                        e = Repository.lookupClass(e.getSuperclassName());
                    }
                    if (e != t) {
                        throw new ClassConstraintException("Exceptions attribute '" + tostring(obj) + "' references '" + cname
                            + "' as an Exception but it is not a subclass of '" + t.getClassName() + "'.");
                    }
                }

            } catch (final ClassNotFoundException e) {
                // FIXME: this might not be the best way to handle missing classes.
                throw new AssertionViolatedException("Missing class: " + e, e);
            }
        }