📄 pass3averifier.java
字号:
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<ints.length; j++){ if (ints[j]==i) return true; } return false; } /** Returns the method number as supplied when instantiating. */ public int getMethodNo(){ return method_no; } /** * This visitor class does the actual checking for the instruction * operand's constraints. */ private class InstOperandConstraintVisitor extends org.apache.bcel.generic.EmptyVisitor{ /** The ConstantPoolGen instance this Visitor operates on. */ private ConstantPoolGen cpg; /** The only Constructor. */ InstOperandConstraintVisitor(ConstantPoolGen cpg){ this.cpg = cpg; } /** * Utility method to return the max_locals value of the method verified * by the surrounding Pass3aVerifier instance. */ private int max_locals(){ return Repository.lookupClass(myOwner.getClassName()).getMethods()[method_no].getCode().getMaxLocals(); } /** * A utility method to always raise an exeption. */ private void constraintViolated(Instruction i, String message) { throw new StaticCodeInstructionOperandConstraintException("Instruction "+i+" constraint violated: "+message); } /** * A utility method to raise an exception if the index is not * a valid constant pool index. */ private void indexValid(Instruction i, int idx){ if (idx < 0 || idx >= 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+"'."); } } /** Checks if the constraints of operands of the said instruction(s) are satisfied. */ public void visitInvokeInstruction(InvokeInstruction o){ indexValid(o, o.getIndex()); if ( (o instanceof INVOKEVIRTUAL) || (o instanceof INVOKESPECIAL) || (o instanceof INVOKESTATIC) ){ Constant c = cpg.getConstant(o.getIndex()); if (! (c instanceof ConstantMethodref)){ constraintViolated(o, "Indexing a constant that's not a CONSTANT_Methodref but a '"+c+"'."); } else{ // Constants are okay due to pass2. ConstantNameAndType cnat = (ConstantNameAndType) (cpg.getConstant(((ConstantMethodref) c).getNameAndTypeIndex())); ConstantUtf8 cutf8 = (ConstantUtf8) (cpg.getConstant(cnat.getNameIndex())); if (cutf8.getBytes().equals(Constants.CONSTRUCTOR_NAME) && (!(o instanceof INVOKESPECIAL)) ){ constraintViolated(o, "Only INVOKESPECIAL is allowed to invoke instance initialization methods."); } if ( (! (cutf8.getBytes().equals(Constants.CONSTRUCTOR_NAME)) ) && (cutf8.getBytes().startsWith("<")) ){ constraintViolated(o, "No method with a name beginning with '<' other than the instance initialization methods may be called by the method invocation instructions."); } } } else{ //if (o instanceof INVOKEINTERFACE){ Constant c = cpg.getConstant(o.getIndex()); if (! (c instanceof ConstantInterfaceMethodref)){ constraintViolated(o, "Indexing a constant that's not a CONSTANT_InterfaceMethodref but a '"+c+"'."); } // TODO: From time to time check if BCEL allows to detect if the // 'count' operand is consistent with the information in the // CONSTANT_InterfaceMethodref and if the last operand is zero. // By now, BCEL hides those two operands because they're superfluous. // Invoked method must not be <init> or <clinit> 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<ts.length; i++){ t = ts[i]; 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, "Argument type class/interface could not be verified successfully: '"+vr.getMessage()+"'."); } } } } /** Checks if the constraints of operands of the said instruction(s) are satisfied. */ public void visitINSTANCEOF(INSTANCEOF o){ indexValid(o, o.getIndex()); Constant c = cpg.getConstant(o.getIndex()); if (! (c instanceof ConstantClass)){ constraintViolated(o, "Expecting a CONSTANT_Class operand, but found a '"+c+"'."); } } /** Checks if the constraints of operands of the said instruction(s) are satisfied. */ public void visitCHECKCAST(CHECKCAST o){ indexValid(o, o.getIndex()); Constant c = cpg.getConstant(o.getIndex()); if (! (c instanceof ConstantClass)){ constraintViolated(o, "Expecting a CONSTANT_Class operand, but found a '"+c+"'."); } } /** Checks if the constraints of operands of the said instruction(s) are satisfied. */ public void visitNEW(NEW o){ indexValid(o, o.getIndex()); Constant c = cpg.getConstant(o.getIndex()); if (! (c instanceof ConstantClass)){ constraintViolated(o, "Expecting a CONSTANT_Class operand, but found a '"+c+"'."); } else{ ConstantUtf8 cutf8 = (ConstantUtf8) (cpg.getConstant( ((ConstantClass) c).getNameIndex() )); Type t = Type.getType("L"+cutf8.getBytes()+";"); if (t instanceof ArrayType){ constraintViolated(o, "NEW must not be used to create an array."); } } } /** Checks if the constraints of operands of the said instruction(s) are satisfied. */ public void visitMULTIANEWARRAY(MULTIANEWARRAY o){ indexValid(o, o.getIndex()); Constant c = cpg.getConstant(o.getIndex()); if (! (c instanceof ConstantClass)){ constraintViolated(o, "Expecting a CONSTANT_Class operand, but found a '"+c+"'."); } int dimensions2create = o.getDimensions(); if (dimensions2create < 1){ constraintViolated(o, "Number of dimensions to create must be greater than zero."); } Type t = o.getType(cpg); if (t instanceof ArrayType){ int dimensions = ((ArrayType) t).getDimensions(); if (dimensions < dimensions2create){ constraintViolated(o, "Not allowed to create array with more dimensions ('+dimensions2create+') than the one referenced by the CONSTANT_Class '"+t+"'."); } } else{ constraintViolated(o, "Expecting a CONSTANT_Class referencing an array type. [Constraint not found in The Java Virtual Machine Specification, Second Edition, 4.8.1]"); } } /** Checks if the constraints of operands of the said instruction(s) are satisfied. */ public void visitANEWARRAY(ANEWARRAY o){ indexValid(o, o.getIndex()); Constant c = cpg.getConstant(o.getIndex()); if (! (c instanceof ConstantClass)){ constraintViolated(o, "Expecting a CONSTANT_Class operand, but found a '"+c+"'."); } Type t = o.getType(cpg); if (t instanceof ArrayType){ int dimensions = ((ArrayType) t).getDimensions(); if (dimensions >= 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -