// Enforced in pass 2 (also stated in the static constraints of the Code
// array in vmspec2), together with pass 1 (reading code_length bytes and
// interpreting them as code[]). So this must not be checked again here.
if (! (code.getCode().length < 65536)){// contradicts vmspec2 page 152 ("Limitations"), but is on page 134.
throw new StaticCodeInstructionConstraintException("Code array in code attribute '"+code+"' too big: must be smaller than 65536 bytes.");
}
// First opcode at offset 0: okay, that's clear. Nothing to do.
// Only instances of the instructions documented in Section 6.4 may appear in
// the code array.
// For BCEL's sake, we cannot handle WIDE stuff, but hopefully BCEL does its job right :)
// The last byte of the last instruction in the code array must be the byte at index
// code_length-1 : See the do_verify() comments. We actually don't iterate through the
// byte array, but use an InstructionList so we cannot check for this. But BCEL does
// things right, so it's implicitly okay.
// TODO: Check how BCEL handles (and will handle) instructions like IMPDEP1, IMPDEP2,
// BREAKPOINT... that BCEL knows about but which are illegal anyway.
// We currently go the safe way here.
InstructionHandle ih = instructionList.getStart();
while (ih != null){
Instruction i = ih.getInstruction();
if (i instanceof IMPDEP1){
throw new StaticCodeInstructionConstraintException("IMPDEP1 must not be in the code, it is an illegal instruction for _internal_ JVM use!");
}
if (i instanceof IMPDEP2){
throw new StaticCodeInstructionConstraintException("IMPDEP2 must not be in the code, it is an illegal instruction for _internal_ JVM use!");
}
if (i instanceof BREAKPOINT){
throw new StaticCodeInstructionConstraintException("BREAKPOINT must not be in the code, it is an illegal instruction for _internal_ JVM use!");
}
ih = ih.getNext();
}
// The original verifier seems to do this check here, too.
// An unreachable last instruction may also not fall through the
// end of the code, which is stupid -- but with the original
// verifier's subroutine semantics one cannot predict reachability.
Instruction last = instructionList.getEnd().getInstruction();
if (! ((last instanceof ReturnInstruction) ||
(last instanceof RET) ||
(last instanceof GotoInstruction) ||
(last instanceof ATHROW) )) // JSR / JSR_W would possibly RETurn and then fall off the code!
throw new StaticCodeInstructionConstraintException("Execution must not fall off the bottom of the code array. This constraint is enforced statically as some existing verifiers do - so it may be a false alarm if the last instruction is not reachable.");
}