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

📄 verify.c

📁 kaffe Java 解释器语言,源码,Java的子集系统,开放源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
				if (checkMethodStaticConstraints(method, einfo) == false) {				        /* something else is wrong...exception raised elsewhere */					return(false);				}			}		} else {			/*********************************************************			 * 2b: check that final methods are not overridden			 *********************************************************/						Hjava_lang_Class *superclass;			Method* curMethod;			Method* method;			int n, m;									for (n = CLASS_NMETHODS(class), curMethod = CLASS_METHODS(class);			     n > 0;			     --n, ++curMethod) {						        /* check static constraints on each method */							if (METHOD_IS_CONSTRUCTOR(curMethod) && checkConstructor(curMethod, einfo) == false) {					return(false);				} else if (checkMethodStaticConstraints(curMethod, einfo) == false) {					return(false);				}			}									/* cycle through superclass hiarchy and make sure final methods aren't overriden */			for (superclass = class->superclass; superclass != NULL; superclass = superclass->superclass) {							        /* cycle through methods in current super class */				for (m = CLASS_NMETHODS(superclass), method = CLASS_METHODS(superclass);				     m > 0;				     --m, ++method) {										if (METHOD_IS_FINAL(method) && !METHOD_IS_PRIVATE(method) &&					    					    /* the following exceptions come from testing against Sun's JVM behavior */					    (strcmp(init_name->data, METHOD_NAMED(method)) &&					     strcmp("this", METHOD_NAMED(method)))) {											        /* make sure the method in question was not overriden in the current class */						for (n = CLASS_NMETHODS(class), curMethod = CLASS_METHODS(class);						     n > 0;						     --n, ++curMethod) {													/* TODO: we should really put all the methods of class into a hash table							 *       that we can access through name and signature.  this would make							 *       this check more efficient (is this done in the interpretter?  if so							 *       we may think about setting up the hashes here and just keeping them							 *       around for later).							 */							if (utf8ConstEqual(curMethod->name, method->name)							    && utf8ConstEqual(METHOD_SIG(curMethod), METHOD_SIG(method)))								{									postExceptionMessage(einfo, JAVA_LANG(VerifyError),											     "final method \"%s\" declared in class \"%s\" is overriden in class \"%s\"",											     METHOD_NAMED(method),											     CLASS_CNAME(class->superclass),											     CLASS_CNAME(class));									return(false);								}						}					}				}			}		}	}			/*********************************************************	 * 3 - Check class constant pool is consistent	 *	 * This is the only section of pass 2 that was available	 * under Transvirtual, though even this has been modified.	 *********************************************************/	/* error message for step 3 */#define POOLERROR \	postExceptionMessage(einfo, JAVA_LANG(ClassFormatError), "malformed constant pool in class \"%s\"", CLASS_CNAME(class)); \	return (false)			pool = CLASS_CONSTANTS(class);	        /* Constant pool loaded - check it's integrity. */	for (idx = 1; idx < pool->size; idx++) {		switch (pool->tags[idx]) {		case CONSTANT_Fieldref:		case CONSTANT_Methodref:		case CONSTANT_InterfaceMethodref:			tag = CONST_TAG(FIELDREF_CLASS(idx, pool), pool);			if (tag != CONSTANT_Class && tag != CONSTANT_ResolvedClass) {				POOLERROR;			}			if (CONST_TAG(FIELDREF_NAMEANDTYPE(idx, pool), pool) != CONSTANT_NameAndType) {				POOLERROR;			}			break;					case CONSTANT_NameAndType:			if (CONST_TAG(NAMEANDTYPE_NAME(idx, pool), pool) != CONSTANT_Utf8) {				POOLERROR;			}			if (CONST_TAG(NAMEANDTYPE_SIGNATURE(idx, pool), pool) != CONSTANT_Utf8) {				POOLERROR;			}			break;									/* the following tags are always legal, so no furthur checks need be performed */		case CONSTANT_Long:		case CONSTANT_Double:			idx++;		case CONSTANT_Integer:		case CONSTANT_Float:					case CONSTANT_Utf8:					case CONSTANT_ResolvedString:		case CONSTANT_ResolvedClass:						/* CONSTANT_Class and CONSTANT_String			 * have already been re-written to avoid the			 * extra indirection added by Java.  This is to fit			 * with the precompiled format.  Here we will not			 * get an error.			 */		case CONSTANT_Class:		case CONSTANT_String:			break;								default:		        /* undefined tag */			POOLERROR;			break;		}	}#undef POOLERROR		DBG(VERIFY2, printConstantPool(class));		/**************************************************************	 * 4 - ensure that all field and method references in	 *     constant pool have valid names, classes, and type	 *     descriptor	 *	 * From the JVM spec pp.141-2:	 *   Note that when it looks at field and method references,	 *   this pass does not check to make sure that the given	 *   field or method actually exists in the given class, nor	 *   does it check that the type descriptors given refer to	 *   real classes.  It checks only that these items are well	 *   formed.	 **************************************************************/		/* Constant pool loaded - check the integrity of the type references */	pool = CLASS_CONSTANTS(class);	for (idx = 1; idx < pool->size; idx++) {		switch (pool->tags[idx]) {		case CONSTANT_Long:		case CONSTANT_Double:			idx++;		case CONSTANT_Integer:		case CONSTANT_Float:					case CONSTANT_Utf8:					case CONSTANT_ResolvedString:		case CONSTANT_ResolvedClass:					case CONSTANT_Class:		case CONSTANT_String:		case CONSTANT_NameAndType:			break;											case CONSTANT_Fieldref:			if (!parseFieldTypeDescriptor(FIELDREF_SIGD(idx, pool))) {				postExceptionMessage(einfo, JAVA_LANG(ClassFormatError),						     "malformed field reference type descriptor, \"%s\", in class \"%s\"",						     CONST_UTF2CHAR(FIELDREF_TYPE(idx, pool), pool),						     CLASS_CNAME(class));				return(false);			}			break;					case CONSTANT_Methodref:			if (!parseMethodTypeDescriptor(METHODREF_SIGD(idx, pool))) {				postExceptionMessage(einfo, JAVA_LANG(ClassFormatError),						     "malformed method reference type descriptor, \"%s\", in class \"%s\"",						     CONST_UTF2CHAR(METHODREF_SIGNATURE(idx, pool), pool),						     CLASS_CNAME(class));				return(false);			}			break;					case CONSTANT_InterfaceMethodref:			if (!parseMethodTypeDescriptor(INTERFACEMETHODREF_SIGD(idx, pool))) {				postExceptionMessage(einfo, JAVA_LANG(ClassFormatError),						     "malformed interface method reference type descriptor, \"%s\", in class \"%s\"",						     CONST_UTF2CHAR(INTERFACEMETHODREF_SIGNATURE(idx, pool), pool),						     CLASS_CNAME(class));				return(false);			}			break;					default:		        /* we'll never get here, because of pass 3 */			postExceptionMessage(einfo, JAVA_LANG(InternalError),					     "step 4 of pass 2 verification has screwed up while processing class \"%s\"",					     CLASS_CNAME(class));			return(false);		}	}		return (true);}staticboolcheckField(Field *field, errorInfo *einfo){	bool retval = true;	char *reason;	if( (reason = checkAccessFlags(CLASS_IS_INTERFACE(field->clazz) ?				       ACC_TYPE_INTERFACE_FIELD :				       ACC_TYPE_FIELD,				       field->accflags)) != NULL )	{		postExceptionMessage(einfo,				     JAVA_LANG(ClassFormatError),				     "(class: %s, field: %s) %s",				     CLASS_CNAME(field->clazz),				     field->name->data,				     reason);		retval = false;	}	return( retval );}/* * makes sure a constructor's flags are valid. */staticboolcheckConstructor(Method* method, errorInfo* einfo){	if (METHOD_IS_STATIC(method)) {		postExceptionMessage(einfo, JAVA_LANG(ClassFormatError),				     "class %s: constructor cannot be static",				     CLASS_CNAME(method->class));		return false;	} else if (METHOD_IS_FINAL(method)) {		postExceptionMessage(einfo, JAVA_LANG(ClassFormatError),				     "class %s: constructor cannot be final",				     CLASS_CNAME(method->class));		return false;	} else if (!isMethodVoid(method)) {		postExceptionMessage(einfo, JAVA_LANG(ClassFormatError),				     "class %s: constructor does not have void return type",				     CLASS_CNAME(method->class));		return false;	} else if (checkMethodStaticConstraints(method, einfo) == false) {		return false;	}		return(true);}/* * ensures that all access flags are legal (more specifically, that the combination * of access flags in a method is legal). * * also checks code-length constraints of the method. */staticboolcheckMethodStaticConstraints(Method* method, errorInfo* einfo){	if (METHOD_IS_PUBLIC(method)) {		if (METHOD_IS_PROTECTED(method)) {			postExceptionMessage(einfo, JAVA_LANG(ClassFormatError),					     "%s.%s: method cannot be both public and protected",					     CLASS_CNAME(method->class),					     METHOD_NAMED(method));			return(false);		} else if(METHOD_IS_PRIVATE(method)) {			postExceptionMessage(einfo, JAVA_LANG(ClassFormatError),					     "%s.%s: method cannot be both public and private",					     CLASS_CNAME(method->class),					     METHOD_NAMED(method));			return(false);		}	} else if (METHOD_IS_PROTECTED(method) && METHOD_IS_PRIVATE(method)) {		postExceptionMessage(einfo, JAVA_LANG(ClassFormatError),				     "%s.%s: method cannot be both protected and private",				     CLASS_CNAME(method->class),				     METHOD_NAMED(method));		return(false);	}			if (METHOD_IS_ABSTRACT(method)) {		if (checkAbstractMethod(method, einfo) == false) {			return(false);		}	} else if (!METHOD_IS_NATIVE(method)) {	        /* code length static constraints */				if (METHOD_BYTECODE_LEN(method) == 0) {			postExceptionMessage(einfo, JAVA_LANG(ClassFormatError),					     "%s.%s: method's code length cannot be zero",					     CLASS_CNAME(method->class),					     METHOD_NAMED(method));			return(false);		} else if (METHOD_BYTECODE_LEN(method) >= 65536) {			postExceptionMessage(einfo, JAVA_LANG(ClassFormatError),					     "%s.%s: method's code length must be less than 65536 bytes",					     CLASS_CNAME(method->class),					     METHOD_NAMED(method));			return(false);		}	}			return(true);}/* * Given a method with its ACC_ABSTRACT flag set, this checks the the rest of the access flags * are set appropriately.  that is, it cannot be final, native, private, static, strictfp, or synchronized. * * also, we check that an abstract method doesn't have a code attribute. */staticboolcheckAbstractMethod(Method* method, errorInfo* einfo){#define ABSTRACT_METHOD_ERROR(_MSG) \	postExceptionMessage(einfo, JAVA_LANG(ClassFormatError), \			     "in method \"%s.%s\": abstract methods cannot be %s", \			     CLASS_CNAME(method->class), \			     METHOD_NAMED(method), _MSG); \	return(false)	#ifdef ABSTRACT_METHOD_VS_ABSTRACT_CLASS		/* This is commented out because Sun's verifier doesn't care if an abstract method	 * is in an abstract class.	 */	 /* ensure that only abstract classes may have abstract methods */	if (!(CLASS_IS_INTERFACE(method->class) || CLASS_IS_ABSTRACT(method->class))) {		postExceptionMessage(einfo, JAVA_LANG(ClassFormatError),				     "in method \"%s.%s\": only abstract classes may have abstract methods",				     CLASS_CNAME(method->class),				     METHOD_NAMED(method));		return(false);	}#endif /* ABSTRACT_METHOD_VS_ABSTRACT_CLASS */			/* constructors cannot be abstract */	if (METHOD_IS_CONSTRUCTOR(method)) {		if (CLASS_IS_INTERFACE(method->class)) {			postExceptionMessage(einfo, JAVA_LANG(ClassFormatError),					     "in method \"%s.%s\": an interface cannot have a constructor <init>",					     CLASS_CNAME(method->class),					     METHOD_NAMED(method));			return(false);		} else {			postExceptionMessage(einfo, JAVA_LANG(ClassFormatError),					     "in method \"%s.%s\": constructors cannot be abstract",					     CLASS_CNAME(method->class),					     METHOD_NAMED(method));			return(false);		}	}			/* ensure the abstract method has no code */	if (METHOD_BYTECODE_LEN(method) > 0) {		postExceptionMessage(einfo, JAVA_LANG(ClassFormatError),				     "in method \"%s.%s\": abstract methods cannot have a Code attribute",				     CLASS_CNAME(method->class),				     METHOD_NAMED(method));		return(false);	}			/* enforce access flag rules of the JVML spec. for abstract methods */	if (METHOD_IS_PRIVATE(method))           { ABSTRACT_METHOD_ERROR("private");      }	else if (METHOD_IS_FINAL(method))        { ABSTRACT_METHOD_ERROR("final");        }	else if (METHOD_IS_NATIVE(method))       { ABSTRACT_METHOD_ERROR("native");       }	else if (METHOD_IS_STATIC(method))       { ABSTRACT_METHOD_ERROR("static");       }	else if (METHOD_IS_STRICT(method))       { ABSTRACT_METHOD_ERROR("strictfp");     }		/* not enforced by Sun's verifier	 *	else if (METHOD_IS_SYNCHRONISED(method)) { ABSTRACT_METHOD_ERROR("synchronized"); }	*/			return(true);	#undef ABSTRACT_METHOD_ERROR}/************************************************************************************ * Pass 3 Verification * * Pass 3 of verification is broken up into two distinct passes.  The first, 3a, * checks static constraints of the bytecode (detailed on p. 134 of the JVML Spec 2). * The second, 3b, performs data-flow analysis on the bytecode, which checks structural * constraints and does type checking. * * NOTE: according to p.171 of JVML Spec 2, "Performing verification at link time *       is attractive in that the checks are performed just once, substantially *       reducing the amount of work that must be done at run time.  Other *       implementation strategies are possible, provided that they comply with *       The Java Language Specification and The Java Virtual Machine Specification." * *       In other words, we can perform pass 3 verification whenever convenient, and *       not necessarily at link time.  This could provide for optimizations in the *       future, as verification generates a lot of information that is useful to *       the JIT compilers.  At the moment, this same information is generated by

⌨️ 快捷键说明

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