All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.org.apache.bcel.internal.verifier.statics.Pass3aVerifier Maven / Gradle / Ivy

The newest version!
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 * 
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
 * 
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License. You can obtain
 * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
 * or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 * 
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
 * Sun designates this particular file as subject to the "Classpath" exception
 * as provided by Sun in the GPL Version 2 section of the License file that
 * accompanied this code.  If applicable, add the following below the License
 * Header, with the fields enclosed by brackets [] replaced by your own
 * identifying information: "Portions Copyrighted [year]
 * [name of copyright owner]"
 * 
 * Contributor(s):
 * 
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */

package com.sun.org.apache.bcel.internal.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 [email protected].
 *
 * 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 com.sun.org.apache.bcel.internal.*;
import com.sun.org.apache.bcel.internal.generic.*;
import com.sun.org.apache.bcel.internal.classfile.*;
import com.sun.org.apache.bcel.internal.verifier.*;
import com.sun.org.apache.bcel.internal.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 2007-07-19 04:35:00 ofung 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




© 2015 - 2024 Weber Informatics LLC | Privacy Policy