⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pass2verifier.java

📁 Java Bytecode Editor 是一个 JAVA 的字节码反汇编和修改器。它可以很方便的修改已经编译成 Class 文件的 JAVA 文件。
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
						}
						int localindex = localvariables[i].getIndex();
						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 ConstantPool cp; // ==jc.getConstantPool() -- only here to save typing work.
		private FAMRAV_Visitor(JavaClass _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.getType(sig); /* Don't need the return value */
			}
			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);
				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);
				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){
        /*
         * TODO: implement.
		 * Are there any 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 + -