package org.apache.bcel.verifier.statics;
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2001 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" and
* "Apache BCEL" must not be used to endorse or promote products
* derived from this software without prior written permission. For
* written permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* "Apache BCEL", nor may "Apache" appear in their name, without
* prior written permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* .
*/
import org.apache.bcel.*;
import org.apache.bcel.generic.*;
import org.apache.bcel.classfile.*;
import org.apache.bcel.verifier.*;
import org.apache.bcel.verifier.exc.*;
/**
* This PassVerifier verifies a class file according to
* pass 3, static part as described in The Java Virtual
* Machine Specification, 2nd edition.
* More detailed information is to be found at the do_verify()
* method's documentation.
*
* @version $Id: Pass3aVerifier.java,v 1.3 2002/06/13 09:32:50 enver Exp $
* @author Enver Haase
* @see #do_verify()
*/
public final class Pass3aVerifier extends PassVerifier{
/** The Verifier that created this. */
private Verifier myOwner;
/**
* The method number to verify.
* This is the index in the array returned
* by JavaClass.getMethods().
*/
private int method_no;
/** The one and only InstructionList object used by an instance of this class. It's here for performance reasons by do_verify() and its callees. */
InstructionList instructionList;
/** The one and only Code object used by an instance of this class. It's here for performance reasons by do_verify() and its callees. */
Code code;
/** Should only be instantiated by a Verifier. */
public Pass3aVerifier(Verifier owner, int method_no){
myOwner = owner;
this.method_no = method_no;
}
/**
* Pass 3a is the verification of static constraints of
* JVM code (such as legal targets of branch instructions).
* This is the part of pass 3 where you do not need data
* flow analysis.
* JustIce also delays the checks for a correct exception
* table of a Code attribute and correct line number entries
* in a LineNumberTable attribute of a Code attribute (which
* conceptually belong to pass 2) to this pass. Also, most
* of the check for valid local variable entries in a
* LocalVariableTable attribute of a Code attribute is
* delayed until this pass.
* All these checks need access to the code array of the
* Code attribute.
*
* @throws InvalidMethodException if the method to verify does not exist.
*/
public VerificationResult do_verify(){
if (myOwner.doPass2().equals(VerificationResult.VR_OK)){
// Okay, class file was loaded correctly by Pass 1
// and satisfies static constraints of Pass 2.
JavaClass jc = Repository.lookupClass(myOwner.getClassName());
Method[] methods = jc.getMethods();
if (method_no >= methods.length){
throw new InvalidMethodException("METHOD DOES NOT EXIST!");
}
Method method = methods[method_no];
code = method.getCode();
// No Code? Nothing to verify!
if ( method.isAbstract() || method.isNative() ){ // IF mg HAS NO CODE (static constraint of Pass 2)
return VerificationResult.VR_OK;
}
// TODO:
// We want a very sophisticated code examination here with good explanations
// on where to look for an illegal instruction or such.
// Only after that we should try to build an InstructionList and throw an
// AssertionViolatedException if after our examination InstructionList building
// still fails.
// That examination should be implemented in a byte-oriented way, i.e. look for
// an instruction, make sure its validity, count its length, find the next
// instruction and so on.
try{
instructionList = new InstructionList(method.getCode().getCode());
}
catch(RuntimeException re){
return new VerificationResult(VerificationResult.VERIFIED_REJECTED, "Bad bytecode in the code array of the Code attribute of method '"+method+"'.");
}
instructionList.setPositions(true);
// Start verification.
VerificationResult vr = VerificationResult.VR_OK; //default
try{
delayedPass2Checks();
}
catch(ClassConstraintException cce){
vr = new VerificationResult(VerificationResult.VERIFIED_REJECTED, cce.getMessage());
return vr;
}
try{
pass3StaticInstructionChecks();
pass3StaticInstructionOperandsChecks();
}
catch(StaticCodeConstraintException scce){
vr = new VerificationResult(VerificationResult.VERIFIED_REJECTED, scce.getMessage());
}
return vr;
}
else{ //did not pass Pass 2.
return VerificationResult.VR_NOTYET;
}
}
/**
* These are the checks that could be done in pass 2 but are delayed to pass 3
* for performance reasons. Also, these checks need access to the code array
* of the Code attribute of a Method so it's okay to perform them here.
* Also see the description of the do_verify() method.
*
* @throws ClassConstraintException if the verification fails.
* @see #do_verify()
*/
private void delayedPass2Checks(){
int[] instructionPositions = instructionList.getInstructionPositions();
int codeLength = code.getCode().length;
/////////////////////
// LineNumberTable //
/////////////////////
LineNumberTable lnt = code.getLineNumberTable();
if (lnt != null){
LineNumber[] lineNumbers = lnt.getLineNumberTable();
IntList offsets = new IntList();
lineNumber_loop: for (int i=0; i < lineNumbers.length; i++){ // may appear in any order.
for (int j=0; j < instructionPositions.length; j++){
// TODO: Make this a binary search! The instructionPositions array is naturally ordered!
int offset = lineNumbers[i].getStartPC();
if (instructionPositions[j] == 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 lineNumber_loop;
}
}
throw new ClassConstraintException("Code attribute '"+code+"' has a LineNumberTable attribute '"+code.getLineNumberTable()+"' referring to a code offset ('"+lineNumbers[i].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. */
Attribute[] atts = code.getAttributes();
for (int a=0; a= endpc){
throw new ClassConstraintException("Code attribute '"+code+"' has an exception_table entry '"+exceptionTable[i]+"' that has its start_pc ('"+startpc+"') not smaller than its end_pc ('"+endpc+"').");
}
if (!contains(instructionPositions, startpc)){
throw new ClassConstraintException("Code attribute '"+code+"' has an exception_table entry '"+exceptionTable[i]+"' that has a non-existant bytecode offset as its start_pc ('"+startpc+"').");
}
if ( (!contains(instructionPositions, endpc)) && (endpc != codeLength)){
throw new ClassConstraintException("Code attribute '"+code+"' has an exception_table entry '"+exceptionTable[i]+"' 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 '"+code+"' has an exception_table entry '"+exceptionTable[i]+"' that has a non-existant bytecode offset as its handler_pc ('"+handlerpc+"').");
}
}
}
/**
* These are the checks if constraints are satisfied which are described in the
* Java Virtual Machine Specification, Second Edition as Static Constraints on
* the instructions of Java Virtual Machine Code (chapter 4.8.1).
*
* @throws StaticCodeConstraintException if the verification fails.
*/
private void pass3StaticInstructionChecks(){
// Code array must not be empty:
// 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.");
}
/**
* These are the checks for the satisfaction of constraints which are described in the
* Java Virtual Machine Specification, Second Edition as Static Constraints on
* the operands of instructions of Java Virtual Machine Code (chapter 4.8.1).
* BCEL parses the code array to create an InstructionList and therefore has to check
* some of these constraints. Additional checks are also implemented here.
*
* @throws StaticCodeConstraintException if the verification fails.
*/
private void pass3StaticInstructionOperandsChecks(){
// When building up the InstructionList, BCEL has already done all those checks
// mentioned in The Java Virtual Machine Specification, Second Edition, as
// "static constraints on the operands of instructions in the code array".
// TODO: see the do_verify() comments. Maybe we should really work on the
// byte array first to give more comprehensive messages.
// TODO: Review Exception API, possibly build in some "offending instruction" thing
// when we're ready to insulate the offending instruction by doing the
// above thing.
// TODO: Implement as much as possible here. BCEL does _not_ check everything.
ConstantPoolGen cpg = new ConstantPoolGen(Repository.lookupClass(myOwner.getClassName()).getConstantPool());
InstOperandConstraintVisitor v = new InstOperandConstraintVisitor(cpg);
// Checks for the things BCEL does _not_ handle itself.
InstructionHandle ih = instructionList.getStart();
while (ih != null){
Instruction i = ih.getInstruction();
// An "own" constraint, due to JustIce's new definition of what "subroutine" means.
if (i instanceof JsrInstruction){
InstructionHandle target = ((JsrInstruction) i).getTarget();
if (target == instructionList.getStart()){
throw new StaticCodeInstructionOperandConstraintException("Due to JustIce's clear definition of subroutines, no JSR or JSR_W may have a top-level instruction (such as the very first instruction, which is targeted by instruction '"+ih+"' as its target.");
}
if (!(target.getInstruction() instanceof ASTORE)){
throw new StaticCodeInstructionOperandConstraintException("Due to JustIce's clear definition of subroutines, no JSR or JSR_W may target anything else than an ASTORE instruction. Instruction '"+ih+"' targets '"+target+"'.");
}
}
// vmspec2, page 134-137
ih.accept(v);
ih = ih.getNext();
}
}
/** A small utility method returning if a given int i is in the given int[] ints. */
private static boolean contains(int[] ints, int i){
for (int j=0; j= cpg.getSize()){
constraintViolated(i, "Illegal constant pool index '"+idx+"'.");
}
}
///////////////////////////////////////////////////////////
// The Java Virtual Machine Specification, pages 134-137 //
///////////////////////////////////////////////////////////
/**
* Assures the generic preconditions of a LoadClass instance.
* The referenced class is loaded and pass2-verified.
*/
public void visitLoadClass(LoadClass o){
ObjectType t = o.getLoadClassType(cpg);
if (t != null){// null means "no class is loaded"
Verifier v = VerifierFactory.getVerifier(t.getClassName());
VerificationResult vr = v.doPass1();
if (vr.getStatus() != VerificationResult.VERIFIED_OK){
constraintViolated((Instruction) o, "Class '"+o.getLoadClassType(cpg).getClassName()+"' is referenced, but cannot be loaded: '"+vr+"'.");
}
}
}
// The target of each jump and branch instruction [...] must be the opcode [...]
// BCEL _DOES_ handle this.
// tableswitch: BCEL will do it, supposedly.
// lookupswitch: BCEL will do it, supposedly.
/** Checks if the constraints of operands of the said instruction(s) are satisfied. */
// LDC and LDC_W (LDC_W is a subclass of LDC in BCEL's model)
public void visitLDC(LDC o){
indexValid(o, o.getIndex());
Constant c = cpg.getConstant(o.getIndex());
if (! ( (c instanceof ConstantInteger) ||
(c instanceof ConstantFloat) ||
(c instanceof ConstantString) ) ){
constraintViolated(o, "Operand of LDC or LDC_W must be one of CONSTANT_Integer, CONSTANT_Float or CONSTANT_String, but is '"+c+"'.");
}
}
/** Checks if the constraints of operands of the said instruction(s) are satisfied. */
// LDC2_W
public void visitLDC2_W(LDC2_W o){
indexValid(o, o.getIndex());
Constant c = cpg.getConstant(o.getIndex());
if (! ( (c instanceof ConstantLong) ||
(c instanceof ConstantDouble) ) ){
constraintViolated(o, "Operand of LDC2_W must be CONSTANT_Long or CONSTANT_Double, but is '"+c+"'.");
}
try{
indexValid(o, o.getIndex()+1);
}
catch(StaticCodeInstructionOperandConstraintException e){
throw new AssertionViolatedException("OOPS: Does not BCEL handle that? LDC2_W operand has a problem.");
}
}
/** Checks if the constraints of operands of the said instruction(s) are satisfied. */
//getfield, putfield, getstatic, putstatic
public void visitFieldInstruction(FieldInstruction o){
indexValid(o, o.getIndex());
Constant c = cpg.getConstant(o.getIndex());
if (! (c instanceof ConstantFieldref)){
constraintViolated(o, "Indexing a constant that's not a CONSTANT_Fieldref but a '"+c+"'.");
}
String field_name = o.getFieldName(cpg);
JavaClass jc = Repository.lookupClass(o.getClassType(cpg).getClassName());
Field[] fields = jc.getFields();
Field f = null;
for (int i=0; i or
ConstantNameAndType cnat = (ConstantNameAndType) (cpg.getConstant(((ConstantInterfaceMethodref)c).getNameAndTypeIndex()));
String name = ((ConstantUtf8) (cpg.getConstant(cnat.getNameIndex()))).getBytes();
if (name.equals(Constants.CONSTRUCTOR_NAME)){
constraintViolated(o, "Method to invoke must not be '"+Constants.CONSTRUCTOR_NAME+"'.");
}
if (name.equals(Constants.STATIC_INITIALIZER_NAME)){
constraintViolated(o, "Method to invoke must not be '"+Constants.STATIC_INITIALIZER_NAME+"'.");
}
}
// The LoadClassType is the method-declaring class, so we have to check the other types.
Type t = o.getReturnType(cpg);
if (t instanceof ArrayType){
t = ((ArrayType) t).getBasicType();
}
if (t instanceof ObjectType){
Verifier v = VerifierFactory.getVerifier(((ObjectType) t).getClassName());
VerificationResult vr = v.doPass2();
if (vr.getStatus() != VerificationResult.VERIFIED_OK){
constraintViolated(o, "Return type class/interface could not be verified successfully: '"+vr.getMessage()+"'.");
}
}
Type[] ts = o.getArgumentTypes(cpg);
for (int i=0; i= 255){
constraintViolated(o, "Not allowed to create an array with more than 255 dimensions.");
}
}
}
/** Checks if the constraints of operands of the said instruction(s) are satisfied. */
public void visitNEWARRAY(NEWARRAY o){
byte t = o.getTypecode();
if (! ( (t == Constants.T_BOOLEAN) ||
(t == Constants.T_CHAR) ||
(t == Constants.T_FLOAT) ||
(t == Constants.T_DOUBLE) ||
(t == Constants.T_BYTE) ||
(t == Constants.T_SHORT) ||
(t == Constants.T_INT) ||
(t == Constants.T_LONG) ) ){
constraintViolated(o, "Illegal type code '+t+' for 'atype' operand.");
}
}
/** Checks if the constraints of operands of the said instruction(s) are satisfied. */
public void visitILOAD(ILOAD o){
int idx = o.getIndex();
if (idx < 0){
constraintViolated(o, "Index '"+idx+"' must be non-negative.");
}
else{
int maxminus1 = max_locals()-1;
if (idx > maxminus1){
constraintViolated(o, "Index '"+idx+"' must not be greater than max_locals-1 '"+maxminus1+"'.");
}
}
}
/** Checks if the constraints of operands of the said instruction(s) are satisfied. */
public void visitFLOAD(FLOAD o){
int idx = o.getIndex();
if (idx < 0){
constraintViolated(o, "Index '"+idx+"' must be non-negative.");
}
else{
int maxminus1 = max_locals()-1;
if (idx > maxminus1){
constraintViolated(o, "Index '"+idx+"' must not be greater than max_locals-1 '"+maxminus1+"'.");
}
}
}
/** Checks if the constraints of operands of the said instruction(s) are satisfied. */
public void visitALOAD(ALOAD o){
int idx = o.getIndex();
if (idx < 0){
constraintViolated(o, "Index '"+idx+"' must be non-negative.");
}
else{
int maxminus1 = max_locals()-1;
if (idx > maxminus1){
constraintViolated(o, "Index '"+idx+"' must not be greater than max_locals-1 '"+maxminus1+"'.");
}
}
}
/** Checks if the constraints of operands of the said instruction(s) are satisfied. */
public void visitISTORE(ISTORE o){
int idx = o.getIndex();
if (idx < 0){
constraintViolated(o, "Index '"+idx+"' must be non-negative.");
}
else{
int maxminus1 = max_locals()-1;
if (idx > maxminus1){
constraintViolated(o, "Index '"+idx+"' must not be greater than max_locals-1 '"+maxminus1+"'.");
}
}
}
/** Checks if the constraints of operands of the said instruction(s) are satisfied. */
public void visitFSTORE(FSTORE o){
int idx = o.getIndex();
if (idx < 0){
constraintViolated(o, "Index '"+idx+"' must be non-negative.");
}
else{
int maxminus1 = max_locals()-1;
if (idx > maxminus1){
constraintViolated(o, "Index '"+idx+"' must not be greater than max_locals-1 '"+maxminus1+"'.");
}
}
}
/** Checks if the constraints of operands of the said instruction(s) are satisfied. */
public void visitASTORE(ASTORE o){
int idx = o.getIndex();
if (idx < 0){
constraintViolated(o, "Index '"+idx+"' must be non-negative.");
}
else{
int maxminus1 = max_locals()-1;
if (idx > maxminus1){
constraintViolated(o, "Index '"+idx+"' must not be greater than max_locals-1 '"+maxminus1+"'.");
}
}
}
/** Checks if the constraints of operands of the said instruction(s) are satisfied. */
public void visitIINC(IINC o){
int idx = o.getIndex();
if (idx < 0){
constraintViolated(o, "Index '"+idx+"' must be non-negative.");
}
else{
int maxminus1 = max_locals()-1;
if (idx > maxminus1){
constraintViolated(o, "Index '"+idx+"' must not be greater than max_locals-1 '"+maxminus1+"'.");
}
}
}
/** Checks if the constraints of operands of the said instruction(s) are satisfied. */
public void visitRET(RET o){
int idx = o.getIndex();
if (idx < 0){
constraintViolated(o, "Index '"+idx+"' must be non-negative.");
}
else{
int maxminus1 = max_locals()-1;
if (idx > maxminus1){
constraintViolated(o, "Index '"+idx+"' must not be greater than max_locals-1 '"+maxminus1+"'.");
}
}
}
/** Checks if the constraints of operands of the said instruction(s) are satisfied. */
public void visitLLOAD(LLOAD o){
int idx = o.getIndex();
if (idx < 0){
constraintViolated(o, "Index '"+idx+"' must be non-negative. [Constraint by JustIce as an analogon to the single-slot xLOAD/xSTORE instructions; may not happen anyway.]");
}
else{
int maxminus2 = max_locals()-2;
if (idx > maxminus2){
constraintViolated(o, "Index '"+idx+"' must not be greater than max_locals-2 '"+maxminus2+"'.");
}
}
}
/** Checks if the constraints of operands of the said instruction(s) are satisfied. */
public void visitDLOAD(DLOAD o){
int idx = o.getIndex();
if (idx < 0){
constraintViolated(o, "Index '"+idx+"' must be non-negative. [Constraint by JustIce as an analogon to the single-slot xLOAD/xSTORE instructions; may not happen anyway.]");
}
else{
int maxminus2 = max_locals()-2;
if (idx > maxminus2){
constraintViolated(o, "Index '"+idx+"' must not be greater than max_locals-2 '"+maxminus2+"'.");
}
}
}
/** Checks if the constraints of operands of the said instruction(s) are satisfied. */
public void visitLSTORE(LSTORE o){
int idx = o.getIndex();
if (idx < 0){
constraintViolated(o, "Index '"+idx+"' must be non-negative. [Constraint by JustIce as an analogon to the single-slot xLOAD/xSTORE instructions; may not happen anyway.]");
}
else{
int maxminus2 = max_locals()-2;
if (idx > maxminus2){
constraintViolated(o, "Index '"+idx+"' must not be greater than max_locals-2 '"+maxminus2+"'.");
}
}
}
/** Checks if the constraints of operands of the said instruction(s) are satisfied. */
public void visitDSTORE(DSTORE o){
int idx = o.getIndex();
if (idx < 0){
constraintViolated(o, "Index '"+idx+"' must be non-negative. [Constraint by JustIce as an analogon to the single-slot xLOAD/xSTORE instructions; may not happen anyway.]");
}
else{
int maxminus2 = max_locals()-2;
if (idx > maxminus2){
constraintViolated(o, "Index '"+idx+"' must not be greater than max_locals-2 '"+maxminus2+"'.");
}
}
}
/** Checks if the constraints of operands of the said instruction(s) are satisfied. */
public void visitLOOKUPSWITCH(LOOKUPSWITCH o){
int[] matchs = o.getMatchs();
int max = Integer.MIN_VALUE;
for (int i=0; i= "low". We cannot check this, as BCEL hides
// it from us.
}
/** Checks if the constraints of operands of the said instruction(s) are satisfied. */
public void visitPUTSTATIC(PUTSTATIC o){
String field_name = o.getFieldName(cpg);
JavaClass jc = Repository.lookupClass(o.getClassType(cpg).getClassName());
Field[] fields = jc.getFields();
Field f = null;
for (int i=0; i.
if ((!(jc.isClass())) && (!(meth_name.equals(Constants.STATIC_INITIALIZER_NAME)))){
constraintViolated(o, "Interface field '"+f+"' must be set in a '"+Constants.STATIC_INITIALIZER_NAME+"' method.");
}
}
/** Checks if the constraints of operands of the said instruction(s) are satisfied. */
public void visitGETSTATIC(GETSTATIC o){
String field_name = o.getFieldName(cpg);
JavaClass jc = Repository.lookupClass(o.getClassType(cpg).getClassName());
Field[] fields = jc.getFields();
Field f = null;
for (int i=0; i