private void delayedPass2Checks()

in src/main/java/org/apache/bcel/verifier/statics/Pass3aVerifier.java [910:996]


    private void delayedPass2Checks() {

        final int[] instructionPositions = instructionList.getInstructionPositions();
        final int codeLength = code.getCode().length;

        /////////////////////
        // LineNumberTable //
        /////////////////////
        final LineNumberTable lnt = code.getLineNumberTable();
        if (lnt != null) {
            final LineNumber[] lineNumbers = lnt.getLineNumberTable();
            final IntList offsets = new IntList();
            lineNumberLoop: for (final LineNumber lineNumber : lineNumbers) { // may appear in any order.
                for (final int instructionPosition : instructionPositions) {
                    // TODO: Make this a binary search! The instructionPositions array is naturally ordered!
                    final int offset = lineNumber.getStartPC();
                    if (instructionPosition == offset) {
                        if (offsets.contains(offset)) {
                            addMessage("LineNumberTable attribute '" + code.getLineNumberTable() + "' refers to the same code offset ('" + offset
                                + "') more than once" + " which is violating the semantics [but is sometimes produced by IBM's 'jikes' compiler].");
                        } else {
                            offsets.add(offset);
                        }
                        continue lineNumberLoop;
                    }
                }
                throw new ClassConstraintException("Code attribute '" + tostring(code) + "' has a LineNumberTable attribute '" + code.getLineNumberTable()
                    + "' referring to a code offset ('" + lineNumber.getStartPC() + "') that does not exist.");
            }
        }

        ///////////////////////////
        // LocalVariableTable(s) //
        ///////////////////////////
        /*
         * We cannot use code.getLocalVariableTable() because there could be more than only one. This is a bug in BCEL.
         */
        final Attribute[] atts = code.getAttributes();
        for (final Attribute att : atts) {
            if (att instanceof LocalVariableTable) {
                ((LocalVariableTable) att).forEach(localVariable -> {
                    final int startpc = localVariable.getStartPC();
                    final int length = localVariable.getLength();

                    if (!contains(instructionPositions, startpc)) {
                        throw new ClassConstraintException("Code attribute '" + tostring(code) + "' has a LocalVariableTable attribute '"
                            + code.getLocalVariableTable() + "' referring to a code offset ('" + startpc + "') that does not exist.");
                    }
                    if (!contains(instructionPositions, startpc + length) && startpc + length != codeLength) {
                        throw new ClassConstraintException(
                            "Code attribute '" + tostring(code) + "' has a LocalVariableTable attribute '" + code.getLocalVariableTable()
                                + "' referring to a code offset start_pc+length ('" + (startpc + length) + "') that does not exist.");
                    }
                });
            }
        }

        ////////////////////
        // ExceptionTable //
        ////////////////////
        // In BCEL's "classfile" API, the startPC/endPC-notation is
        // inclusive/exclusive as in the Java Virtual Machine Specification.
        // WARNING: This is not true for BCEL's "generic" API.
        final CodeException[] exceptionTable = code.getExceptionTable();
        for (final CodeException element : exceptionTable) {
            final int startpc = element.getStartPC();
            final int endpc = element.getEndPC();
            final int handlerpc = element.getHandlerPC();
            if (startpc >= endpc) {
                throw new ClassConstraintException("Code attribute '" + tostring(code) + "' has an exception_table entry '" + element
                    + "' that has its start_pc ('" + startpc + "') not smaller than its end_pc ('" + endpc + "').");
            }
            if (!contains(instructionPositions, startpc)) {
                throw new ClassConstraintException("Code attribute '" + tostring(code) + "' has an exception_table entry '" + element
                    + "' that has a non-existant bytecode offset as its start_pc ('" + startpc + "').");
            }
            if (!contains(instructionPositions, endpc) && endpc != codeLength) {
                throw new ClassConstraintException("Code attribute '" + tostring(code) + "' has an exception_table entry '" + element
                    + "' that has a non-existant bytecode offset as its end_pc ('" + startpc + "') [that is also not equal to code_length ('" + codeLength
                    + "')].");
            }
            if (!contains(instructionPositions, handlerpc)) {
                throw new ClassConstraintException("Code attribute '" + tostring(code) + "' has an exception_table entry '" + element
                    + "' that has a non-existant bytecode offset as its handler_pc ('" + handlerpc + "').");
            }
        }
    }