📄 pass2verifier.java
字号:
if ( ( (t==Type.LONG || t==Type.DOUBLE)? localindex+1:localindex) >= code.getMaxLocals()){ throw new ClassConstraintException("LocalVariableTable attribute '"+tostring(lvt)+"' references a LocalVariable '"+tostring(localvariables[i])+"' with an index that exceeds the surrounding Code attribute's max_locals value of '"+code.getMaxLocals()+"'."); } try{ localVariablesInfos[method_number].add(localindex, localname, localvariables[i].getStartPC(), localvariables[i].getLength(), t); } catch(LocalVariableInfoInconsistentException lviie){ throw new ClassConstraintException("Conflicting information in LocalVariableTable '"+tostring(lvt)+"' found in Code attribute '"+tostring(obj)+"' (method '"+tostring(m)+"'). "+lviie.getMessage()); } }// for all local variables localvariables[i] in the LocalVariableTable attribute atts[a] END num_of_lvt_attribs++; if (num_of_lvt_attribs > obj.getMaxLocals()){ throw new ClassConstraintException("Number of LocalVariableTable attributes of Code attribute '"+tostring(obj)+"' (method '"+tostring(m)+"') exceeds number of local variable slots '"+obj.getMaxLocals()+"' ('There may be no more than one LocalVariableTable attribute per local variable in the Code attribute.')."); } }// if atts[a] instanceof LocalVariableTable END }// for all attributes atts[a] END }// visitCode(Code) END public void visitExceptionTable(ExceptionTable obj){//vmspec2 4.7.4 // incorrectly named, it's the Exceptions attribute (vmspec2 4.7.4) checkIndex(obj, obj.getNameIndex(), CONST_Utf8); String name = ((ConstantUtf8) cp.getConstant(obj.getNameIndex())).getBytes(); if (! name.equals("Exceptions")){ throw new ClassConstraintException("The Exceptions attribute '"+tostring(obj)+"' is not correctly named 'Exceptions' but '"+name+"'."); } int[] exc_indices = obj.getExceptionIndexTable(); for (int i=0; i<exc_indices.length; i++){ checkIndex(obj, exc_indices[i], CONST_Class); ConstantClass cc = (ConstantClass) (cp.getConstant(exc_indices[i])); checkIndex(cc, cc.getNameIndex(), CONST_Utf8); // cannot be sure this ConstantClass has already been visited (checked)! String cname = ((ConstantUtf8) cp.getConstant(cc.getNameIndex())).getBytes().replace('/','.'); //convert internal notation on-the-fly to external notation Verifier v = VerifierFactory.getVerifier(cname); VerificationResult vr = v.doPass1(); if (vr != VerificationResult.VR_OK){ throw new ClassConstraintException("Exceptions attribute '"+tostring(obj)+"' references '"+cname+"' as an Exception but it does not pass verification pass 1: "+vr); } else{ // We cannot safely trust any other "instanceof" mechanism. We need to transitively verify // the ancestor hierarchy. JavaClass e = Repository.lookupClass(cname); JavaClass t = Repository.lookupClass(Type.THROWABLE.getClassName()); JavaClass o = Repository.lookupClass(Type.OBJECT.getClassName()); while (e != o){ if (e == t) break; // It's a subclass of Throwable, OKAY, leave. v = VerifierFactory.getVerifier(e.getSuperclassName()); vr = v.doPass1(); if (vr != VerificationResult.VR_OK){ throw new ClassConstraintException("Exceptions attribute '"+tostring(obj)+"' references '"+cname+"' as an Exception but '"+e.getSuperclassName()+"' in the ancestor hierachy does not pass verification pass 1: "+vr); } else{ e = Repository.lookupClass(e.getSuperclassName()); } } if (e != t) throw new ClassConstraintException("Exceptions attribute '"+tostring(obj)+"' references '"+cname+"' as an Exception but it is not a subclass of '"+t.getClassName()+"'."); } } } // SYNTHETIC: see above // DEPRECATED: see above ////////////////////////////////////////////////////////////// // code_attribute-structure-ATTRIBUTES (vmspec2 4.7.3, 4.7) // ////////////////////////////////////////////////////////////// public void visitLineNumberTable(LineNumberTable obj){//vmspec2 4.7.8 checkIndex(obj, obj.getNameIndex(), CONST_Utf8); String name = ((ConstantUtf8) cp.getConstant(obj.getNameIndex())).getBytes(); if (! name.equals("LineNumberTable")){ throw new ClassConstraintException("The LineNumberTable attribute '"+tostring(obj)+"' is not correctly named 'LineNumberTable' but '"+name+"'."); } //In JustIce,this check is delayed to Pass 3a. //LineNumber[] linenumbers = obj.getLineNumberTable(); // ...validity check... } public void visitLocalVariableTable(LocalVariableTable obj){//vmspec2 4.7.9 //In JustIce,this check is partially delayed to Pass 3a. //The other part can be found in the visitCode(Code) method. } //////////////////////////////////////////////////// // MISC-structure-ATTRIBUTES (vmspec2 4.7.1, 4.7) // //////////////////////////////////////////////////// public void visitUnknown(Unknown obj){//vmspec2 4.7.1 // Represents an unknown attribute. checkIndex(obj, obj.getNameIndex(), CONST_Utf8); // Maybe only misnamed? Give a (warning) message. addMessage("Unknown attribute '"+tostring(obj)+"'. This attribute is not known in any context!"); } ////////// // BCEL // ////////// public void visitLocalVariable(LocalVariable obj){ // This does not represent an Attribute but is only // related to internal BCEL data representation. // see visitLocalVariableTable(LocalVariableTable) } public void visitCodeException(CodeException obj){ // Code constraints are checked in Pass3 (3a and 3b). // This does not represent an Attribute but is only // related to internal BCEL data representation. // see visitCode(Code) } public void visitConstantPool(ConstantPool obj){ // No need to. We're piggybacked by the DescendingVisitor. // This does not represent an Attribute but is only // related to internal BCEL data representation. } public void visitInnerClass(InnerClass obj){ // This does not represent an Attribute but is only // related to internal BCEL data representation. } public void visitLineNumber(LineNumber obj){ // This does not represent an Attribute but is only // related to internal BCEL data representation. // see visitLineNumberTable(LineNumberTable) } } /** * Ensures that the ConstantCP-subclassed entries of the constant * pool are valid. According to "Yellin: Low Level Security in Java", * this method does not verify the existence of referenced entities * (such as classes) but only the formal correctness (such as well-formed * signatures). * The visitXXX() methods throw ClassConstraintException instances otherwise. * <B>Precondition: index-style cross referencing in the constant * pool must be valid. Simply invoke constant_pool_entries_satisfy_static_constraints() * before.</B> * * @throws ClassConstraintException otherwise. * @see #constant_pool_entries_satisfy_static_constraints() */ private void field_and_method_refs_are_valid(){ JavaClass jc = Repository.lookupClass(myOwner.getClassName()); DescendingVisitor v = new DescendingVisitor(jc, new FAMRAV_Visitor(jc)); v.visit(); } /** * A Visitor class that ensures the ConstantCP-subclassed entries * of the constant pool are valid. * <B>Precondition: index-style cross referencing in the constant * pool must be valid.</B> * * @see #constant_pool_entries_satisfy_static_constraints() * @see org.apache.bcel.classfile.ConstantCP */ private class FAMRAV_Visitor extends EmptyVisitor implements Visitor{ private final JavaClass jc; private final ConstantPool cp; // ==jc.getConstantPool() -- only here to save typing work. private FAMRAV_Visitor(JavaClass _jc){ jc = _jc; cp = _jc.getConstantPool(); } public void visitConstantFieldref(ConstantFieldref obj){ if (obj.getTag() != Constants.CONSTANT_Fieldref){ throw new ClassConstraintException("ConstantFieldref '"+tostring(obj)+"' has wrong tag!"); } int name_and_type_index = obj.getNameAndTypeIndex(); ConstantNameAndType cnat = (ConstantNameAndType) (cp.getConstant(name_and_type_index)); String name = ((ConstantUtf8) (cp.getConstant(cnat.getNameIndex()))).getBytes(); // Field or Method name if (!validFieldName(name)){ throw new ClassConstraintException("Invalid field name '"+name+"' referenced by '"+tostring(obj)+"'."); } int class_index = obj.getClassIndex(); ConstantClass cc = (ConstantClass) (cp.getConstant(class_index)); String className = ((ConstantUtf8) (cp.getConstant(cc.getNameIndex()))).getBytes(); // Class Name in internal form if (! validClassName(className)){ throw new ClassConstraintException("Illegal class name '"+className+"' used by '"+tostring(obj)+"'."); } String sig = ((ConstantUtf8) (cp.getConstant(cnat.getSignatureIndex()))).getBytes(); // Field or Method signature(=descriptor) try{ Type t = Type.getType(sig); } catch (ClassFormatError cfe){ // Well, BCEL sometimes is a little harsh describing exceptional situations. throw new ClassConstraintException("Illegal descriptor (==signature) '"+sig+"' used by '"+tostring(obj)+"'."); } } public void visitConstantMethodref(ConstantMethodref obj){ if (obj.getTag() != Constants.CONSTANT_Methodref){ throw new ClassConstraintException("ConstantMethodref '"+tostring(obj)+"' has wrong tag!"); } int name_and_type_index = obj.getNameAndTypeIndex(); ConstantNameAndType cnat = (ConstantNameAndType) (cp.getConstant(name_and_type_index)); String name = ((ConstantUtf8) (cp.getConstant(cnat.getNameIndex()))).getBytes(); // Field or Method name if (!validClassMethodName(name)){ throw new ClassConstraintException("Invalid (non-interface) method name '"+name+"' referenced by '"+tostring(obj)+"'."); } int class_index = obj.getClassIndex(); ConstantClass cc = (ConstantClass) (cp.getConstant(class_index)); String className = ((ConstantUtf8) (cp.getConstant(cc.getNameIndex()))).getBytes(); // Class Name in internal form if (! validClassName(className)){ throw new ClassConstraintException("Illegal class name '"+className+"' used by '"+tostring(obj)+"'."); } String sig = ((ConstantUtf8) (cp.getConstant(cnat.getSignatureIndex()))).getBytes(); // Field or Method signature(=descriptor) try{ Type t = Type.getReturnType(sig); Type[] ts = Type.getArgumentTypes(sig); if ( name.equals(CONSTRUCTOR_NAME) && (t != Type.VOID) ){ throw new ClassConstraintException("Instance initialization method must have VOID return type."); } } catch (ClassFormatError cfe){ // Well, BCEL sometimes is a little harsh describing exceptional situations. throw new ClassConstraintException("Illegal descriptor (==signature) '"+sig+"' used by '"+tostring(obj)+"'."); } } public void visitConstantInterfaceMethodref(ConstantInterfaceMethodref obj){ if (obj.getTag() != Constants.CONSTANT_InterfaceMethodref){ throw new ClassConstraintException("ConstantInterfaceMethodref '"+tostring(obj)+"' has wrong tag!"); } int name_and_type_index = obj.getNameAndTypeIndex(); ConstantNameAndType cnat = (ConstantNameAndType) (cp.getConstant(name_and_type_index)); String name = ((ConstantUtf8) (cp.getConstant(cnat.getNameIndex()))).getBytes(); // Field or Method name if (!validInterfaceMethodName(name)){ throw new ClassConstraintException("Invalid (interface) method name '"+name+"' referenced by '"+tostring(obj)+"'."); } int class_index = obj.getClassIndex(); ConstantClass cc = (ConstantClass) (cp.getConstant(class_index)); String className = ((ConstantUtf8) (cp.getConstant(cc.getNameIndex()))).getBytes(); // Class Name in internal form if (! validClassName(className)){ throw new ClassConstraintException("Illegal class name '"+className+"' used by '"+tostring(obj)+"'."); } String sig = ((ConstantUtf8) (cp.getConstant(cnat.getSignatureIndex()))).getBytes(); // Field or Method signature(=descriptor) try{ Type t = Type.getReturnType(sig); Type[] ts = Type.getArgumentTypes(sig); if ( name.equals(STATIC_INITIALIZER_NAME) && (t != Type.VOID) ){ addMessage("Class or interface initialization method '"+STATIC_INITIALIZER_NAME+"' usually has VOID return type instead of '"+t+"'. Note this is really not a requirement of The Java Virtual Machine Specification, Second Edition."); } } catch (ClassFormatError cfe){ // Well, BCEL sometimes is a little harsh describing exceptional situations. throw new ClassConstraintException("Illegal descriptor (==signature) '"+sig+"' used by '"+tostring(obj)+"'."); } } } /** * This method returns true if and only if the supplied String * represents a valid Java class name. */ private static final boolean validClassName(String name){ // Are there restrictions? return true; } /** * This method returns true if and only if the supplied String * represents a valid method name. * This is basically the same as a valid identifier name in the * Java programming language, but the special name for * the instance initialization method is allowed and the special name * for the class/interface initialization method may be allowed. */ private static boolean validMethodName(String name, boolean allowStaticInit){ if (validJavaLangMethodName(name)) return true; if (allowStaticInit){ return (name.equals(CONSTRUCTOR_NAME) || name.equals(STATIC_INITIALIZER_NAME)); } else{ return name.equals(CONSTRUCTOR_NAME); } } /** * This method returns true if and only if the supplied String * represents a valid method name that may be referenced by * ConstantMethodref objects. */ private static boolean validClassMethodName(String name){ return validMethodName(name, false); } /** * This method returns true if and only if the supplied String * represents a valid Java programming language method name stored as a simple * (non-qualified) name. * Conforming to: The Java Virtual Machine Specification, Second Edition,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -