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

📄 pass2verifier.java

📁 Java Bytecode Editor 是一个 JAVA 的字节码反汇编和修改器。它可以很方便的修改已经编译成 Class 文件的 JAVA 文件。
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
						throw new ClassConstraintException("Interface method '"+tostring(obj)+"' must not have any of the ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL, ACC_SYNCHRONIZED, ACC_NATIVE, ACC_ABSTRACT, ACC_STRICT modifiers set.");
					}
				}
			}

			// A specific instance initialization method... (vmspec2,Page 116).
			if (name.equals(CONSTRUCTOR_NAME)){
				//..may have at most one of ACC_PRIVATE, ACC_PROTECTED, ACC_PUBLIC set: is checked above.
				//..may also have ACC_STRICT set, but none of the other flags in table 4.5 (vmspec2, page 115)
				if (	obj.isStatic() ||
							obj.isFinal() ||
							obj.isSynchronized() ||
							obj.isNative() ||
							obj.isAbstract() ){
					throw new ClassConstraintException("Instance initialization method '"+tostring(obj)+"' must not have any of the ACC_STATIC, ACC_FINAL, ACC_SYNCHRONIZED, ACC_NATIVE, ACC_ABSTRACT modifiers set.");
				}
			}

			// Class and interface initialization methods...
			if (name.equals(STATIC_INITIALIZER_NAME)){
				if ((obj.getAccessFlags() & (~ACC_STRICT)) > 0){
					addMessage("Class or interface initialization method '"+tostring(obj)+"' has superfluous access modifier(s) set: everything but ACC_STRICT is ignored.");
				}
				if (obj.isAbstract()){
					throw new ClassConstraintException("Class or interface initialization method '"+tostring(obj)+"' must not be abstract. This contradicts the Java Language Specification, Second Edition (which omits this constraint) but is common practice of existing verifiers.");
				}
			}

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

			String nameanddesc = (name+sig);
			if (method_names_and_desc.contains(nameanddesc)){
				throw new ClassConstraintException("No two methods (like '"+tostring(obj)+"') are allowed have same names and desciptors!");
			}
			method_names_and_desc.add(nameanddesc);

			Attribute[] atts = obj.getAttributes();
			int num_code_atts = 0;
			for (int i=0; i<atts.length; i++){
				if ((! (atts[i] instanceof Code)) &&
				    (! (atts[i] instanceof ExceptionTable))     &&
				    (! (atts[i] instanceof Synthetic)) &&
				    (! (atts[i] instanceof Deprecated))){
					addMessage("Attribute '"+tostring(atts[i])+"' as an attribute of Method '"+tostring(obj)+"' is unknown and will therefore be ignored.");
				}
				if ((! (atts[i] instanceof Code)) &&
						(! (atts[i] instanceof ExceptionTable))){
					addMessage("Attribute '"+tostring(atts[i])+"' as an attribute of Method '"+tostring(obj)+"' is neither Code nor Exceptions and is therefore only of use for debuggers and such.");
				}
				if ((atts[i] instanceof Code) && (obj.isNative() || obj.isAbstract())){
					throw new ClassConstraintException("Native or abstract methods like '"+tostring(obj)+"' must not have a Code attribute like '"+tostring(atts[i])+"'."); //vmspec2 page120, 4.7.3
				}
				if (atts[i] instanceof Code) num_code_atts++;
			}
			if ( !obj.isNative() && !obj.isAbstract() && num_code_atts != 1){
				throw new ClassConstraintException("Non-native, non-abstract methods like '"+tostring(obj)+"' must have exactly one Code attribute (found: "+num_code_atts+").");
			}
		}
		///////////////////////////////////////////////////////
		// ClassFile-structure-ATTRIBUTES (vmspec2 4.1, 4.7) //
		///////////////////////////////////////////////////////
		public void visitSourceFile(SourceFile obj){//vmspec2 4.7.7

			// zero or one SourceFile attr per ClassFile: see visitJavaClass()

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

			String name = ((ConstantUtf8) cp.getConstant(obj.getNameIndex())).getBytes();
			if (! name.equals("SourceFile")){
				throw new ClassConstraintException("The SourceFile attribute '"+tostring(obj)+"' is not correctly named 'SourceFile' but '"+name+"'.");
			}

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

			String sourcefilename = ((ConstantUtf8) cp.getConstant(obj.getSourceFileIndex())).getBytes(); //==obj.getSourceFileName() ?
			String sourcefilenamelc = sourcefilename.toLowerCase();

			if (	(sourcefilename.indexOf('/') != -1) ||
						(sourcefilename.indexOf('\\') != -1) ||
						(sourcefilename.indexOf(':') != -1) ||
						(sourcefilenamelc.lastIndexOf(".java") == -1)	){
				addMessage("SourceFile attribute '"+tostring(obj)+"' has a funny name: remember not to confuse certain parsers working on javap's output. Also, this name ('"+sourcefilename+"') is considered an unqualified (simple) file name only.");
			}
		}
		public void visitDeprecated(Deprecated obj){//vmspec2 4.7.10
			checkIndex(obj, obj.getNameIndex(), CONST_Utf8);

			String name = ((ConstantUtf8) cp.getConstant(obj.getNameIndex())).getBytes();
			if (! name.equals("Deprecated")){
				throw new ClassConstraintException("The Deprecated attribute '"+tostring(obj)+"' is not correctly named 'Deprecated' but '"+name+"'.");
			}
		}
		public void visitSynthetic(Synthetic obj){//vmspec2 4.7.6
			checkIndex(obj, obj.getNameIndex(), CONST_Utf8);
			String name = ((ConstantUtf8) cp.getConstant(obj.getNameIndex())).getBytes();
			if (! name.equals("Synthetic")){
				throw new ClassConstraintException("The Synthetic attribute '"+tostring(obj)+"' is not correctly named 'Synthetic' but '"+name+"'.");
			}
		}
		public void visitInnerClasses(InnerClasses obj){//vmspec2 4.7.5

			// exactly one InnerClasses attr per ClassFile if some inner class is refernced: see visitJavaClass()

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

			String name = ((ConstantUtf8) cp.getConstant(obj.getNameIndex())).getBytes();
			if (! name.equals("InnerClasses")){
				throw new ClassConstraintException("The InnerClasses attribute '"+tostring(obj)+"' is not correctly named 'InnerClasses' but '"+name+"'.");
			}

			InnerClass[] ics = obj.getInnerClasses();

			for (int i=0; i<ics.length; i++){
				checkIndex(obj, ics[i].getInnerClassIndex(), CONST_Class);
				int outer_idx = ics[i].getOuterClassIndex();
				if (outer_idx != 0){
					checkIndex(obj, outer_idx, CONST_Class);
				}
				int innername_idx = ics[i].getInnerNameIndex();
				if (innername_idx != 0){
					checkIndex(obj, innername_idx, CONST_Utf8);
				}
				int acc = ics[i].getInnerAccessFlags();
				acc = acc & (~ (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED | ACC_STATIC | ACC_FINAL | ACC_INTERFACE | ACC_ABSTRACT));
				if (acc != 0){
					addMessage("Unknown access flag for inner class '"+tostring(ics[i])+"' set (InnerClasses attribute '"+tostring(obj)+"').");
				}
			}
			// Semantical consistency is not yet checked by Sun, see vmspec2 4.7.5.
			// [marked TODO in JustIce]
		}
		////////////////////////////////////////////////////////
		// field_info-structure-ATTRIBUTES (vmspec2 4.5, 4.7) //
		////////////////////////////////////////////////////////
		public void visitConstantValue(ConstantValue obj){//vmspec2 4.7.2
			// Despite its name, this really is an Attribute,
			// not a constant!
			checkIndex(obj, obj.getNameIndex(), CONST_Utf8);

			String name = ((ConstantUtf8) cp.getConstant(obj.getNameIndex())).getBytes();
			if (! name.equals("ConstantValue")){
				throw new ClassConstraintException("The ConstantValue attribute '"+tostring(obj)+"' is not correctly named 'ConstantValue' but '"+name+"'.");
			}

			Object pred = carrier.predecessor();
			if (pred instanceof Field){ //ConstantValue attributes are quite senseless if the predecessor is not a field.
				Field f = (Field) pred;
				// Field constraints have been checked before -- so we are safe using their type information.
				Type field_type = Type.getType(((ConstantUtf8) (cp.getConstant(f.getSignatureIndex()))).getBytes());

				int index = obj.getConstantValueIndex();
				if ((index < 0) || (index >= cplen)){
					throw new ClassConstraintException("Invalid index '"+index+"' used by '"+tostring(obj)+"'.");
				}
				Constant c = cp.getConstant(index);

				if (CONST_Long.isInstance(c) && field_type.equals(Type.LONG)){
					return;
				}
				if (CONST_Float.isInstance(c) && field_type.equals(Type.FLOAT)){
					return;
				}
				if (CONST_Double.isInstance(c) && field_type.equals(Type.DOUBLE)){
					return;
				}
				if (CONST_Integer.isInstance(c) && (field_type.equals(Type.INT) || field_type.equals(Type.SHORT) || field_type.equals(Type.CHAR) || field_type.equals(Type.BYTE) || field_type.equals(Type.BOOLEAN))){
					return;
				}
				if (CONST_String.isInstance(c) && field_type.equals(Type.STRING)){
					return;
				}

				throw new ClassConstraintException("Illegal type of ConstantValue '"+obj+"' embedding Constant '"+c+"'. It is referenced by field '"+tostring(f)+"' expecting a different type: '"+field_type+"'.");
			}
		}
		// SYNTHETIC: see above
		// DEPRECATED: see above
		/////////////////////////////////////////////////////////
		// method_info-structure-ATTRIBUTES (vmspec2 4.6, 4.7) //
		/////////////////////////////////////////////////////////
		public void visitCode(Code obj){//vmspec2 4.7.3
			// No code attribute allowed for native or abstract methods: see visitMethod(Method).
			// Code array constraints are checked in Pass3 (3a and 3b).

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

			String name = ((ConstantUtf8) cp.getConstant(obj.getNameIndex())).getBytes();
			if (! name.equals("Code")){
				throw new ClassConstraintException("The Code attribute '"+tostring(obj)+"' is not correctly named 'Code' but '"+name+"'.");
			}

			Method m = null; // satisfy compiler
			if (!(carrier.predecessor() instanceof Method)){
				addMessage("Code attribute '"+tostring(obj)+"' is not declared in a method_info structure but in '"+carrier.predecessor()+"'. Ignored.");
				return;
			}
			else{
				m = (Method) carrier.predecessor();	// we can assume this method was visited before;
																						// i.e. the data consistency was verified.
			}

			if (obj.getCode().length == 0){
				throw new ClassConstraintException("Code array of Code attribute '"+tostring(obj)+"' (method '"+m+"') must not be empty.");
			}

			//In JustIce, the check for correct offsets into the code array is delayed to Pass 3a.
			CodeException[] exc_table = obj.getExceptionTable();
			for (int i=0; i<exc_table.length; i++){
				int exc_index = exc_table[i].getCatchType();
				if (exc_index != 0){ // if 0, it catches all Throwables
					checkIndex(obj, exc_index, CONST_Class);
					ConstantClass cc = (ConstantClass) (cp.getConstant(exc_index));
					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('/','.');

					Verifier v = VerifierFactory.getVerifier(cname);
					VerificationResult vr = v.doPass1();

					if (vr != VerificationResult.VR_OK){
						throw new ClassConstraintException("Code attribute '"+tostring(obj)+"' (method '"+m+"') has an exception_table entry '"+tostring(exc_table[i])+"' that 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("Code attribute '"+tostring(obj)+"' (method '"+m+"') has an exception_table entry '"+tostring(exc_table[i])+"' that 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("Code attribute '"+tostring(obj)+"' (method '"+m+"') has an exception_table entry '"+tostring(exc_table[i])+"' that references '"+cname+"' as an Exception but it is not a subclass of '"+t.getClassName()+"'.");
					}
				}
			}

			// Create object for local variables information
			// This is highly unelegant due to usage of the Visitor pattern.
			// TODO: rework it.
			int method_number = -1;
			Method[] ms = Repository.lookupClass(myOwner.getClassName()).getMethods();
			for (int mn=0; mn<ms.length; mn++){
				if (m == ms[mn]){
					method_number = mn;
					break;
				}
			}
			if (method_number < 0){ // Mmmmh. Can we be sure BCEL does not sometimes instantiate new objects?
				throw new AssertionViolatedException("Could not find a known BCEL Method object in the corresponding BCEL JavaClass object.");
			}
			localVariablesInfos[method_number] = new LocalVariablesInfo(obj.getMaxLocals());

			int num_of_lvt_attribs = 0;
			// Now iterate through the attributes the Code attribute has.
			Attribute[] atts = obj.getAttributes();
			for (int a=0; a<atts.length; a++){
				if ((! (atts[a] instanceof LineNumberTable)) &&
				    (! (atts[a] instanceof LocalVariableTable))){
					addMessage("Attribute '"+tostring(atts[a])+"' as an attribute of Code attribute '"+tostring(obj)+"' (method '"+m+"') is unknown and will therefore be ignored.");
				}
				else{// LineNumberTable or LocalVariableTable
					addMessage("Attribute '"+tostring(atts[a])+"' as an attribute of Code attribute '"+tostring(obj)+"' (method '"+m+"') will effectively be ignored and is only useful for debuggers and such.");
				}

				//LocalVariableTable check (partially delayed to Pass3a).
				//Here because its easier to collect the information of the
				//(possibly more than one) LocalVariableTables belonging to
				//one certain Code attribute.
				if (atts[a] instanceof LocalVariableTable){ // checks conforming to vmspec2 4.7.9

					LocalVariableTable lvt = (LocalVariableTable) atts[a];

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

					String lvtname = ((ConstantUtf8) cp.getConstant(lvt.getNameIndex())).getBytes();
					if (! lvtname.equals("LocalVariableTable")){
						throw new ClassConstraintException("The LocalVariableTable attribute '"+tostring(lvt)+"' is not correctly named 'LocalVariableTable' but '"+lvtname+"'.");
					}

					Code code = obj;

					//In JustIce, the check for correct offsets into the code array is delayed to Pass 3a.
					LocalVariable[] localvariables = lvt.getLocalVariableTable();

					for (int i=0; i<localvariables.length; i++){
						checkIndex(lvt, localvariables[i].getNameIndex(), CONST_Utf8);
						String localname = ((ConstantUtf8) cp.getConstant(localvariables[i].getNameIndex())).getBytes();
						if (!validJavaIdentifier(localname)){
							throw new ClassConstraintException("LocalVariableTable '"+tostring(lvt)+"' references a local variable by the name '"+localname+"' which is not a legal Java simple name.");
						}

						checkIndex(lvt, localvariables[i].getSignatureIndex(), CONST_Utf8);
						String localsig  = ((ConstantUtf8) (cp.getConstant(localvariables[i].getSignatureIndex()))).getBytes(); // Local signature(=descriptor)
						Type t;
						try{
							t = Type.getType(localsig);
						}
						catch (ClassFormatError cfe){ // sometimes BCEL is a little harsh describing exceptional situations.
							throw new ClassConstraintException("Illegal descriptor (==signature) '"+localsig+"' used by LocalVariable '"+tostring(localvariables[i])+"' referenced by '"+tostring(lvt)+"'.");

⌨️ 快捷键说明

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