📄 instconstraintvisitor.java
字号:
package org.apache.bcel.verifier.structurals;
/* ====================================================================
* 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
* <http://www.apache.org/>.
*/
import org.apache.bcel.Constants;
import org.apache.bcel.Repository;
import org.apache.bcel.classfile.Constant;
import org.apache.bcel.classfile.ConstantClass;
import org.apache.bcel.classfile.ConstantDouble;
import org.apache.bcel.classfile.ConstantInteger;
import org.apache.bcel.classfile.ConstantFieldref;
import org.apache.bcel.classfile.ConstantFloat;
import org.apache.bcel.classfile.ConstantLong;
import org.apache.bcel.classfile.ConstantString;
import org.apache.bcel.classfile.Field;
import org.apache.bcel.classfile.JavaClass;
import org.apache.bcel.generic.*;
import org.apache.bcel.verifier.*;
import org.apache.bcel.verifier.exc.*;
/**
* A Visitor class testing for valid preconditions of JVM instructions.
* The instance of this class will throw a StructuralCodeConstraintException
* instance if an instruction is visitXXX()ed which has preconditions that are
* not satisfied.
* TODO: Currently, the JVM's behaviour concerning monitors (MONITORENTER,
* MONITOREXIT) is not modeled in JustIce.
*
* @version $Id: InstConstraintVisitor.java,v 1.2 2006/09/18 14:51:46 andos Exp $
* @author <A HREF="http://www.inf.fu-berlin.de/~ehaase"/>Enver Haase</A>
* @see org.apache.bcel.verifier.exc.StructuralCodeConstraintException
* @see org.apache.bcel.verifier.exc.LinkingConstraintException
*/
public class InstConstraintVisitor extends EmptyVisitor implements org.apache.bcel.generic.Visitor{
private static ObjectType GENERIC_ARRAY = new ObjectType("org.apache.bcel.verifier.structurals.GenericArray");
/**
* The constructor. Constructs a new instance of this class.
*/
public InstConstraintVisitor(){}
/**
* The Execution Frame we're working on.
*
* @see #setFrame(Frame f)
* @see #locals()
* @see #stack()
*/
private Frame frame = null;
/**
* The ConstantPoolGen we're working on.
*
* @see #setConstantPoolGen(ConstantPoolGen cpg)
*/
private ConstantPoolGen cpg = null;
/**
* The MethodGen we're working on.
*
* @see #setMethodGen(MethodGen mg)
*/
private MethodGen mg = null;
/**
* The OperandStack we're working on.
*
* @see #setFrame(Frame f)
*/
private OperandStack stack(){
return frame.getStack();
}
/**
* The LocalVariables we're working on.
*
* @see #setFrame(Frame f)
*/
private LocalVariables locals(){
return frame.getLocals();
}
/**
* This method is called by the visitXXX() to notify the acceptor of this InstConstraintVisitor
* that a constraint violation has occured. This is done by throwing an instance of a
* StructuralCodeConstraintException.
* @throws org.apache.bcel.verifier.exc.StructuralCodeConstraintException always.
*/
private void constraintViolated(Instruction violator, String description){
String fq_classname = violator.getClass().getName();
throw new StructuralCodeConstraintException("Instruction "+ fq_classname.substring(fq_classname.lastIndexOf('.')+1) +" constraint violated: " + description);
}
/**
* This returns the single instance of the InstConstraintVisitor class.
* To operate correctly, other values must have been set before actually
* using the instance.
* Use this method for performance reasons.
*
* @see #setConstantPoolGen(ConstantPoolGen cpg)
* @see #setMethodGen(MethodGen mg)
*/
public void setFrame(Frame f){
this.frame = f;
//if (singleInstance.mg == null || singleInstance.cpg == null) throw new AssertionViolatedException("Forgot to set important values first.");
}
/**
* Sets the ConstantPoolGen instance needed for constraint
* checking prior to execution.
*/
public void setConstantPoolGen(ConstantPoolGen cpg){
this.cpg = cpg;
}
/**
* Sets the MethodGen instance needed for constraint
* checking prior to execution.
*/
public void setMethodGen(MethodGen mg){
this.mg = mg;
}
/**
* Assures index is of type INT.
* @throws org.apache.bcel.verifier.exc.StructuralCodeConstraintException if the above constraint is not satisfied.
*/
private void indexOfInt(Instruction o, Type index){
if (! index.equals(Type.INT))
constraintViolated(o, "The 'index' is not of type int but of type "+index+".");
}
/**
* Assures the ReferenceType r is initialized (or Type.NULL).
* Formally, this means (!(r instanceof UninitializedObjectType)), because
* there are no uninitialized array types.
* @throws org.apache.bcel.verifier.exc.StructuralCodeConstraintException if the above constraint is not satisfied.
*/
private void referenceTypeIsInitialized(Instruction o, ReferenceType r){
if (r instanceof UninitializedObjectType){
constraintViolated(o, "Working on an uninitialized object '"+r+"'.");
}
}
/** Assures value is of type INT. */
private void valueOfInt(Instruction o, Type value){
if (! value.equals(Type.INT))
constraintViolated(o, "The 'value' is not of type int but of type "+value+".");
}
/**
* Assures arrayref is of ArrayType or NULL;
* returns true if and only if arrayref is non-NULL.
* @throws org.apache.bcel.verifier.exc.StructuralCodeConstraintException if the above constraint is violated.
*/
private boolean arrayrefOfArrayType(Instruction o, Type arrayref){
if (! ((arrayref instanceof ArrayType) || arrayref.equals(Type.NULL)) )
constraintViolated(o, "The 'arrayref' does not refer to an array but is of type "+arrayref+".");
return (arrayref instanceof ArrayType);
}
/***************************************************************/
/* MISC */
/***************************************************************/
/**
* Ensures the general preconditions of an instruction that accesses the stack.
* This method is here because BCEL has no such superinterface for the stack
* accessing instructions; and there are funny unexpected exceptions in the
* semantices of the superinterfaces and superclasses provided.
* E.g. SWAP is a StackConsumer, but DUP_X1 is not a StackProducer.
* Therefore, this method is called by all StackProducer, StackConsumer,
* and StackInstruction instances via their visitXXX() method.
* Unfortunately, as the superclasses and superinterfaces overlap, some instructions
* cause this method to be called two or three times. [TODO: Fix this.]
*
* @see #visitStackConsumer(StackConsumer o)
* @see #visitStackProducer(StackProducer o)
* @see #visitStackInstruction(StackInstruction o)
*/
private void _visitStackAccessor(Instruction o){
int consume = o.consumeStack(cpg); // Stack values are always consumed first; then produced.
if (consume > stack().slotsUsed()){
constraintViolated((Instruction) o, "Cannot consume "+consume+" stack slots: only "+stack().slotsUsed()+" slot(s) left on stack!\nStack:\n"+stack());
}
int produce = o.produceStack(cpg) - ((Instruction) o).consumeStack(cpg); // Stack values are always consumed first; then produced.
if ( produce + stack().slotsUsed() > stack().maxStack() ){
constraintViolated((Instruction) o, "Cannot produce "+produce+" stack slots: only "+(stack().maxStack()-stack().slotsUsed())+" free stack slot(s) left.\nStack:\n"+stack());
}
}
/***************************************************************/
/* "generic"visitXXXX methods where XXXX is an interface */
/* therefore, we don't know the order of visiting; but we know */
/* these methods are called before the visitYYYY methods below */
/***************************************************************/
/**
* 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.doPass2();
if (vr.getStatus() != VerificationResult.VERIFIED_OK){
constraintViolated((Instruction) o, "Class '"+o.getLoadClassType(cpg).getClassName()+"' is referenced, but cannot be loaded and resolved: '"+vr+"'.");
}
}
}
/**
* Ensures the general preconditions of a StackConsumer instance.
*/
public void visitStackConsumer(StackConsumer o){
_visitStackAccessor((Instruction) o);
}
/**
* Ensures the general preconditions of a StackProducer instance.
*/
public void visitStackProducer(StackProducer o){
_visitStackAccessor((Instruction) o);
}
/***************************************************************/
/* "generic" visitYYYY methods where YYYY is a superclass. */
/* therefore, we know the order of visiting; we know */
/* these methods are called after the visitXXXX methods above. */
/***************************************************************/
/**
* Ensures the general preconditions of a CPInstruction instance.
*/
public void visitCPInstruction(CPInstruction o){
int idx = o.getIndex();
if ((idx < 0) || (idx >= cpg.getSize())){
throw new AssertionViolatedException("Huh?! Constant pool index of instruction '"+o+"' illegal? Pass 3a should have checked this!");
}
}
/**
* Ensures the general preconditions of a FieldInstruction instance.
*/
public void visitFieldInstruction(FieldInstruction o){
// visitLoadClass(o) has been called before: Every FieldOrMethod
// implements LoadClass.
// visitCPInstruction(o) has been called before.
// A FieldInstruction may be: GETFIELD, GETSTATIC, PUTFIELD, PUTSTATIC
Constant c = cpg.getConstant(o.getIndex());
if (!(c instanceof ConstantFieldref)){
constraintViolated(o, "Index '"+o.getIndex()+"' should refer to a CONSTANT_Fieldref_info structure, but refers to '"+c+"'.");
}
// the o.getClassType(cpg) type has passed pass 2; see visitLoadClass(o).
Type t = o.getType(cpg);
if (t instanceof ObjectType){
String name = ((ObjectType)t).getClassName();
Verifier v = VerifierFactory.getVerifier( name );
VerificationResult vr = v.doPass2();
if (vr.getStatus() != VerificationResult.VERIFIED_OK){
constraintViolated((Instruction) o, "Class '"+name+"' is referenced, but cannot be loaded and resolved: '"+vr+"'.");
}
}
}
/**
* Ensures the general preconditions of an InvokeInstruction instance.
*/
public void visitInvokeInstruction(InvokeInstruction o){
// visitLoadClass(o) has been called before: Every FieldOrMethod
// implements LoadClass.
// visitCPInstruction(o) has been called before.
//TODO
}
/**
* Ensures the general preconditions of a StackInstruction instance.
*/
public void visitStackInstruction(StackInstruction o){
_visitStackAccessor(o);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -