📄 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.ConstantInterfaceMethodref;import org.apache.bcel.classfile.ConstantLong;import org.apache.bcel.classfile.ConstantNameAndType;import org.apache.bcel.classfile.ConstantString;import org.apache.bcel.classfile.ConstantUtf8;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.*;import java.util.ArrayList;import java.util.HashMap;import java.util.Hashtable;/** * 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.1.1.1 2001/10/29 20:00:41 jvanzyl 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.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -