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

📄 pass2verifier.java

📁 Java Bytecode Editor 是一个 JAVA 的字节码反汇编和修改器。它可以很方便的修改已经编译成 Class 文件的 JAVA 文件。
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
			CONST_InterfaceMethodref = org.apache.bcel.classfile.ConstantInterfaceMethodref.class;
            */
			CONST_String = org.apache.bcel.classfile.ConstantString.class;
			CONST_Integer = org.apache.bcel.classfile.ConstantInteger.class;
			CONST_Float = org.apache.bcel.classfile.ConstantFloat.class;
			CONST_Long = org.apache.bcel.classfile.ConstantLong.class;
			CONST_Double = org.apache.bcel.classfile.ConstantDouble.class;
			CONST_NameAndType = org.apache.bcel.classfile.ConstantNameAndType.class;
			CONST_Utf8 = org.apache.bcel.classfile.ConstantUtf8.class;

			carrier = new DescendingVisitor(_jc, this);
			carrier.visit();
		}

		private void checkIndex(Node referrer, int index, Class shouldbe){
			if ((index < 0) || (index >= cplen)){
				throw new ClassConstraintException("Invalid index '"+index+"' used by '"+tostring(referrer)+"'.");
			}
			Constant c = cp.getConstant(index);
			if (! shouldbe.isInstance(c)){
				/* String isnot = shouldbe.toString().substring(shouldbe.toString().lastIndexOf(".")+1); //Cut all before last "." */
				throw new ClassCastException("Illegal constant '"+tostring(c)+"' at index '"+index+"'. '"+tostring(referrer)+"' expects a '"+shouldbe+"'.");
			}
		}
		///////////////////////////////////////
		// ClassFile structure (vmspec2 4.1) //
		///////////////////////////////////////
		public void visitJavaClass(JavaClass obj){
			Attribute[] atts = obj.getAttributes();
			boolean foundSourceFile = false;
			boolean foundInnerClasses = false;

			// Is there an InnerClass referenced?
			// This is a costly check; existing verifiers don't do it!
			boolean hasInnerClass = new InnerClassDetector(jc).innerClassReferenced();

			for (int i=0; i<atts.length; i++){
				if ((! (atts[i] instanceof SourceFile)) &&
				    (! (atts[i] instanceof Deprecated))     &&
				    (! (atts[i] instanceof InnerClasses)) &&
				    (! (atts[i] instanceof Synthetic))){
					addMessage("Attribute '"+tostring(atts[i])+"' as an attribute of the ClassFile structure '"+tostring(obj)+"' is unknown and will therefore be ignored.");
				}

				if (atts[i] instanceof SourceFile){
					if (foundSourceFile == false) foundSourceFile = true;
					else throw new ClassConstraintException("A ClassFile structure (like '"+tostring(obj)+"') may have no more than one SourceFile attribute."); //vmspec2 4.7.7
				}

				if (atts[i] instanceof InnerClasses){
					if (foundInnerClasses == false) foundInnerClasses = true;
					else{
						if (hasInnerClass){
							throw new ClassConstraintException("A Classfile structure (like '"+tostring(obj)+"') must have exactly one InnerClasses attribute if at least one Inner Class is referenced (which is the case). More than one InnerClasses attribute was found.");
						}
					}
					if (!hasInnerClass){
						addMessage("No referenced Inner Class found, but InnerClasses attribute '"+tostring(atts[i])+"' found. Strongly suggest removal of that attribute.");
					}
				}

			}
			if (hasInnerClass && !foundInnerClasses){
				//throw new ClassConstraintException("A Classfile structure (like '"+tostring(obj)+"') must have exactly one InnerClasses attribute if at least one Inner Class is referenced (which is the case). No InnerClasses attribute was found.");
				//vmspec2, page 125 says it would be a constraint: but existing verifiers
				//don't check it and javac doesn't satisfy it when it comes to anonymous
				//inner classes
				addMessage("A Classfile structure (like '"+tostring(obj)+"') must have exactly one InnerClasses attribute if at least one Inner Class is referenced (which is the case). No InnerClasses attribute was found.");
			}
		}
		/////////////////////////////
		// CONSTANTS (vmspec2 4.4) //
		/////////////////////////////
		public void visitConstantClass(ConstantClass obj){
			if (obj.getTag() != Constants.CONSTANT_Class){
				throw new ClassConstraintException("Wrong constant tag in '"+tostring(obj)+"'.");
			}
			checkIndex(obj, obj.getNameIndex(), CONST_Utf8);

		}
		public void visitConstantFieldref(ConstantFieldref obj){
			if (obj.getTag() != Constants.CONSTANT_Fieldref){
				throw new ClassConstraintException("Wrong constant tag in '"+tostring(obj)+"'.");
			}
			checkIndex(obj, obj.getClassIndex(), CONST_Class);
			checkIndex(obj, obj.getNameAndTypeIndex(), CONST_NameAndType);
		}
		public void visitConstantMethodref(ConstantMethodref obj){
			if (obj.getTag() != Constants.CONSTANT_Methodref){
				throw new ClassConstraintException("Wrong constant tag in '"+tostring(obj)+"'.");
			}
			checkIndex(obj, obj.getClassIndex(), CONST_Class);
			checkIndex(obj, obj.getNameAndTypeIndex(), CONST_NameAndType);
		}
		public void visitConstantInterfaceMethodref(ConstantInterfaceMethodref obj){
			if (obj.getTag() != Constants.CONSTANT_InterfaceMethodref){
				throw new ClassConstraintException("Wrong constant tag in '"+tostring(obj)+"'.");
			}
			checkIndex(obj, obj.getClassIndex(), CONST_Class);
			checkIndex(obj, obj.getNameAndTypeIndex(), CONST_NameAndType);
		}
		public void visitConstantString(ConstantString obj){
			if (obj.getTag() != Constants.CONSTANT_String){
				throw new ClassConstraintException("Wrong constant tag in '"+tostring(obj)+"'.");
			}
			checkIndex(obj, obj.getStringIndex(), CONST_Utf8);
		}
		public void visitConstantInteger(ConstantInteger obj){
			if (obj.getTag() != Constants.CONSTANT_Integer){
				throw new ClassConstraintException("Wrong constant tag in '"+tostring(obj)+"'.");
			}
			// no indices to check
		}
		public void visitConstantFloat(ConstantFloat obj){
			if (obj.getTag() != Constants.CONSTANT_Float){
				throw new ClassConstraintException("Wrong constant tag in '"+tostring(obj)+"'.");
			}
			//no indices to check
		}
		public void visitConstantLong(ConstantLong obj){
			if (obj.getTag() != Constants.CONSTANT_Long){
				throw new ClassConstraintException("Wrong constant tag in '"+tostring(obj)+"'.");
			}
			//no indices to check
		}
		public void visitConstantDouble(ConstantDouble obj){
			if (obj.getTag() != Constants.CONSTANT_Double){
				throw new ClassConstraintException("Wrong constant tag in '"+tostring(obj)+"'.");
			}
			//no indices to check
		}
		public void visitConstantNameAndType(ConstantNameAndType obj){
			if (obj.getTag() != Constants.CONSTANT_NameAndType){
				throw new ClassConstraintException("Wrong constant tag in '"+tostring(obj)+"'.");
			}
			checkIndex(obj, obj.getNameIndex(), CONST_Utf8);
			//checkIndex(obj, obj.getDescriptorIndex(), CONST_Utf8); //inconsistently named in BCEL, see below.
			checkIndex(obj, obj.getSignatureIndex(), CONST_Utf8);
		}
		public void visitConstantUtf8(ConstantUtf8 obj){
			if (obj.getTag() != Constants.CONSTANT_Utf8){
				throw new ClassConstraintException("Wrong constant tag in '"+tostring(obj)+"'.");
			}
			//no indices to check
		}
		//////////////////////////
		// FIELDS (vmspec2 4.5) //
		//////////////////////////
		public void visitField(Field obj){

			if (jc.isClass()){
				int maxone=0;
				if (obj.isPrivate()) maxone++;
				if (obj.isProtected()) maxone++;
				if (obj.isPublic()) maxone++;
				if (maxone > 1){
					throw new ClassConstraintException("Field '"+tostring(obj)+"' must only have at most one of its ACC_PRIVATE, ACC_PROTECTED, ACC_PUBLIC modifiers set.");
				}

				if (obj.isFinal() && obj.isVolatile()){
					throw new ClassConstraintException("Field '"+tostring(obj)+"' must only have at most one of its ACC_FINAL, ACC_VOLATILE modifiers set.");
				}
			}
			else{ // isInterface!
				if (!obj.isPublic()){
					throw new ClassConstraintException("Interface field '"+tostring(obj)+"' must have the ACC_PUBLIC modifier set but hasn't!");
				}
				if (!obj.isStatic()){
					throw new ClassConstraintException("Interface field '"+tostring(obj)+"' must have the ACC_STATIC modifier set but hasn't!");
				}
				if (!obj.isFinal()){
					throw new ClassConstraintException("Interface field '"+tostring(obj)+"' must have the ACC_FINAL modifier set but hasn't!");
				}
			}

			if ((obj.getAccessFlags() & ~(ACC_PUBLIC|ACC_PRIVATE|ACC_PROTECTED|ACC_STATIC|ACC_FINAL|ACC_VOLATILE|ACC_TRANSIENT)) > 0){
				addMessage("Field '"+tostring(obj)+"' has access flag(s) other than ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL, ACC_VOLATILE, ACC_TRANSIENT set (ignored).");
			}

			checkIndex(obj, obj.getNameIndex(), CONST_Utf8);

			String name = obj.getName();
			if (! validFieldName(name)){
				throw new ClassConstraintException("Field '"+tostring(obj)+"' has illegal name '"+obj.getName()+"'.");
			}

			// A descriptor is often named signature in BCEL
			checkIndex(obj, obj.getSignatureIndex(), CONST_Utf8);

			String sig  = ((ConstantUtf8) (cp.getConstant(obj.getSignatureIndex()))).getBytes(); // Field or Method signature(=descriptor)

			try{
				Type.getType(sig);  /* Don't need the return value */
			}
			catch (ClassFormatError cfe){ // sometimes BCEL is a little harsh describing exceptional situations.
				throw new ClassConstraintException("Illegal descriptor (==signature) '"+sig+"' used by '"+tostring(obj)+"'.");
			}

			String nameanddesc = (name+sig);
			if (field_names_and_desc.contains(nameanddesc)){
				throw new ClassConstraintException("No two fields (like '"+tostring(obj)+"') are allowed have same names and descriptors!");
			}
			if (field_names.contains(name)){
				addMessage("More than one field of name '"+name+"' detected (but with different type descriptors). This is very unusual.");
			}
			field_names_and_desc.add(nameanddesc);
			field_names.add(name);

			Attribute[] atts = obj.getAttributes();
			for (int i=0; i<atts.length; i++){
				if ((! (atts[i] instanceof ConstantValue)) &&
				    (! (atts[i] instanceof Synthetic))     &&
				    (! (atts[i] instanceof Deprecated))){
					addMessage("Attribute '"+tostring(atts[i])+"' as an attribute of Field '"+tostring(obj)+"' is unknown and will therefore be ignored.");
				}
				if  (! (atts[i] instanceof ConstantValue)){
					addMessage("Attribute '"+tostring(atts[i])+"' as an attribute of Field '"+tostring(obj)+"' is not a ConstantValue and is therefore only of use for debuggers and such.");
				}
			}
		}
		///////////////////////////
		// METHODS (vmspec2 4.6) //
		///////////////////////////
		public void visitMethod(Method obj){

			checkIndex(obj, obj.getNameIndex(), CONST_Utf8);

			String name = obj.getName();
			if (! validMethodName(name, true)){
				throw new ClassConstraintException("Method '"+tostring(obj)+"' has illegal name '"+name+"'.");
			}

			// A descriptor is often named signature in BCEL
			checkIndex(obj, obj.getSignatureIndex(), CONST_Utf8);

			String sig  = ((ConstantUtf8) (cp.getConstant(obj.getSignatureIndex()))).getBytes(); // Method's signature(=descriptor)

			Type t;
			Type[] ts; // needed below the try block.
			try{
				t  = Type.getReturnType(sig);
				ts = Type.getArgumentTypes(sig);
			}
			catch (ClassFormatError cfe){
				// Well, BCEL sometimes is a little harsh describing exceptional situations.
				throw new ClassConstraintException("Illegal descriptor (==signature) '"+sig+"' used by Method '"+tostring(obj)+"'.");
			}

			// Check if referenced objects exist.
			Type act = t;
			if (act instanceof ArrayType) act = ((ArrayType) act).getBasicType();
			if (act instanceof ObjectType){
				Verifier v = VerifierFactory.getVerifier( ((ObjectType) act).getClassName() );
				VerificationResult vr = v.doPass1();
				if (vr != VerificationResult.VR_OK) {
					throw new ClassConstraintException("Method '"+tostring(obj)+"' has a return type that does not pass verification pass 1: '"+vr+"'.");
				}
			}

			for (int i=0; i<ts.length; i++){
				act = ts[i];
				if (act instanceof ArrayType) act = ((ArrayType) act).getBasicType();
				if (act instanceof ObjectType){
					Verifier v = VerifierFactory.getVerifier( ((ObjectType) act).getClassName() );
					VerificationResult vr = v.doPass1();
					if (vr != VerificationResult.VR_OK) {
						throw new ClassConstraintException("Method '"+tostring(obj)+"' has an argument type that does not pass verification pass 1: '"+vr+"'.");
					}
				}
			}

			// Nearly forgot this! Funny return values are allowed, but a non-empty arguments list makes a different method out of it!
			if (name.equals(STATIC_INITIALIZER_NAME) && (ts.length != 0)){
				throw new ClassConstraintException("Method '"+tostring(obj)+"' has illegal name '"+name+"'. It's name resembles the class or interface initialization method which it isn't because of its arguments (==descriptor).");
			}

			if (jc.isClass()){
				int maxone=0;
				if (obj.isPrivate()) maxone++;
				if (obj.isProtected()) maxone++;
				if (obj.isPublic()) maxone++;
				if (maxone > 1){
					throw new ClassConstraintException("Method '"+tostring(obj)+"' must only have at most one of its ACC_PRIVATE, ACC_PROTECTED, ACC_PUBLIC modifiers set.");
				}

				if (obj.isAbstract()){
					if (obj.isFinal()) throw new ClassConstraintException("Abstract method '"+tostring(obj)+"' must not have the ACC_FINAL modifier set.");
					if (obj.isNative()) throw new ClassConstraintException("Abstract method '"+tostring(obj)+"' must not have the ACC_NATIVE modifier set.");
					if (obj.isPrivate()) throw new ClassConstraintException("Abstract method '"+tostring(obj)+"' must not have the ACC_PRIVATE modifier set.");
					if (obj.isStatic()) throw new ClassConstraintException("Abstract method '"+tostring(obj)+"' must not have the ACC_STATIC modifier set.");
					if (obj.isStrictfp()) throw new ClassConstraintException("Abstract method '"+tostring(obj)+"' must not have the ACC_STRICT modifier set.");
					if (obj.isSynchronized()) throw new ClassConstraintException("Abstract method '"+tostring(obj)+"' must not have the ACC_SYNCHRONIZED modifier set.");
				}
			}
			else{ // isInterface!
				if (!name.equals(STATIC_INITIALIZER_NAME)){//vmspec2, p.116, 2nd paragraph
					if (!obj.isPublic()){
						throw new ClassConstraintException("Interface method '"+tostring(obj)+"' must have the ACC_PUBLIC modifier set but hasn't!");
					}
					if (!obj.isAbstract()){
						throw new ClassConstraintException("Interface method '"+tostring(obj)+"' must have the ACC_STATIC modifier set but hasn't!");
					}
					if (	obj.isPrivate() ||
								obj.isProtected() ||
								obj.isStatic() ||
								obj.isFinal() ||
								obj.isSynchronized() ||
								obj.isNative() ||
								obj.isStrictfp() ){

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -