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

📄 verify.c

📁 kaffe Java 解释器语言,源码,Java的子集系统,开放源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * verify.c * Perform stages 2 & 3 of class verification.  Stage 1 is performed *  when the class is being loaded (so isn't here) and stage 4 is performed *  as the method is being executed. * * verify2() was originally created by someone in Transvirtual Technologies.  however, * it did almost nothing (only a shrivel of the stuff needed by pass 2... * specifically part 3 of of pass 2, which has been modified), * so questions regarding pass 2 should be sent to: *     Rob Gonzalez <rob@kaffe.org> * * verify3() was also originally created by someone in Transvirtual, but it only * returned true :)  Questions regarding this one can be sent to Rob as well. * * All other code in this file was added to assist the full versions of verify2() and * verify3(). */#include "config.h"#include "config-std.h"#include "constants.h"#include "classMethod.h"#include "baseClasses.h"#include "lookup.h"#include "exception.h"#include "errors.h"#include "jni.h"#include "debug.h"#include "utf8const.h"/* needed for pass 3 */#include "bytecode.h"#include "itypes.h"#include "soft.h"#include "verify.h"/* * Returns whether the given class is "trusted" (i.e. does not require verification). */staticboolisTrustedClass(Hjava_lang_Class* class) {        /* recall (from main.c): -verifyremote (default) ==> verifyMode = 2	 *                       -verify                 ==> verifyMode = 3	 *                       -noverify               ==> verifyMode = 0	 */	return ((class->loader == 0 && (Kaffe_JavaVMArgs[0].verifyMode & 1) == 0) ||		(class->loader != 0 && (Kaffe_JavaVMArgs[0].verifyMode & 2) == 0));}/********************************************************************************* * Type Descriptor Parsing Methods *********************************************************************************/static const char* parseBaseTypeDescriptor(const char* sig);static const char* parseObjectTypeDescriptor(const char* sig);static const char* parseArrayTypeDescriptor(const char* sig);static const char* parseFieldTypeDescriptor(const char* sig);static bool        parseMethodTypeDescriptor(const char* sig);/* * parses a BaseType descriptor (p.100 JVML Spec 2) *  *   BaseType: B | C | D | F | I | J | S | Z * * returns the sig pointing right after the BaseType * or NULL if an error occurred. */staticconst char*parseBaseTypeDescriptor(const char* sig){	switch(*sig) {	case 'B': case 'C': case 'D': case 'F': case 'I': case 'J': case 'S': case 'Z':		return sig + 1;	default:		break;	}		return NULL;}/* * parses an ObjectType descriptor (p.101 JVML Spec 2) * *   ObjectType: L<classname>; *   <classname> is a string made from unicode characters * * precondition: *sig == 'L' * * returns the sig pointing right after the ObjectType * or NULL if an error occurred. */staticconst char*parseObjectTypeDescriptor(const char* sig){	for (sig++; sig != '\0' && *sig != ';'; sig++);		if (sig == '\0') return NULL;	else             return sig + 1;}/* parses an ArrayType descriptor (p.101 JVML Spec 2) * *   ArrayType    : [ComponentType *   ComponentType: FieldType * * precondition: *sig == '[' * * returns the sig pointing right after the ArrayType * or NULL if an error occurred. */staticconst char*parseArrayTypeDescriptor(const char* sig){	while (*sig != '\0' && *sig == '[') sig++;		if (*sig == '\0') return NULL;	else              return parseFieldTypeDescriptor(sig);}/* * parses a field type descriptor (i.e. its type signature). * *   FieldType: *     BaseType | ObjectType | ArrayType * * returns the signatures position immediately after the field's * type signature, or NULL if any error has occurred. */staticconst char*parseFieldTypeDescriptor(const char* sig){	if (sig == NULL)      return NULL;	else if (*sig == '[') return parseArrayTypeDescriptor(sig);	else if (*sig == 'L') return parseObjectTypeDescriptor(sig);	else                  return parseBaseTypeDescriptor(sig);}/* * parses a method type descriptor (i.e. its signature).  (p.103 JVML Spec 2) * *   MethodDescriptor: *     ( ParameterDescriptor* ) ReturnDescriptor *   ParameterDescriptor: *     FieldType *   ReturnDescriptor: *     FieldType | V * * returns whether the descriptor is legal */staticboolparseMethodTypeDescriptor(const char* sig){	if (sig == NULL || *sig != '(') return false;		DBG(VERIFY2, dprintf("        parsing method type descriptor: %s\n", sig); );		/* parse the type parameters */	for (sig++; sig && *sig != ')' && *sig != '\0'; sig = parseFieldTypeDescriptor(sig)) {		DBG(VERIFY2, dprintf("            parameter sig: %s\n", sig); );	}		if (sig == NULL || *sig == '\0') {		DBG(VERIFY2, dprintf("            error: no ReturnDescriptor\n"); );		return false;	}	sig++;		DBG(VERIFY2, dprintf("            ReturnDescriptor: %s\n", sig); );		if (*sig == 'V') {		sig++;		return *sig == '\0';	}		if (parseFieldTypeDescriptor(sig) != NULL) return true;		return false;}/********************************************************************************* * Pass 2 Verification *********************************************************************************/static bool checkField(Field*, errorInfo*);static bool checkConstructor(Method*, errorInfo*);static bool checkMethodStaticConstraints(Method*, errorInfo*);static bool checkAbstractMethod(Method*, errorInfo*);/* perhaps this should go in classMethod.[ch]... */static bool isMethodVoid(Method* method){	char* sig = (char*)method->parsed_sig->signature->data;	int i = strlen(sig);		return (i > 2) && (sig[i-2] == ')' && sig[i-1] == 'V');}/* * For debugging purposes.  Prints out the value of the specified constant pool entry. */#if !(defined(NDEBUG) || !defined(KAFFE_VMDEBUG))const char* indent  = "                ";const char* indent2 = "                        ";staticuint32printConstantPoolEntry(const Hjava_lang_Class* class, uint32 idx){	const constants* pool = CLASS_CONSTANTS(class);		switch (pool->tags[idx]) {	case CONSTANT_Utf8:		DBG(VERIFY2, dprintf("   UTF8: %s", CONST_UTF2CHAR(idx, pool)) );		break;							case CONSTANT_Long:	case CONSTANT_Double:		idx++;	case CONSTANT_Integer:	case CONSTANT_Float:		DBG(VERIFY2, dprintf("   NUMERICAL"); );		break;							case CONSTANT_ResolvedString:	case CONSTANT_ResolvedClass:		DBG(VERIFY2, dprintf("   RESOLVED: %s",				     ((Hjava_lang_Class*)pool->data[idx])->name->data); );		break;										case CONSTANT_Class:		DBG(VERIFY2, dprintf("   UNRESOLVED CLASS: %s", CLASS_NAMED(idx, pool)); );		break;				case CONSTANT_String:		DBG(VERIFY2, dprintf("   STRING: %s", CONST_STRING_NAMED(idx, pool)); );		break;										case CONSTANT_Fieldref:		DBG(VERIFY2, dprintf("   FIELDREF: %s  --type--  %s",				     FIELDREF_NAMED(idx, pool), FIELDREF_SIGD(idx, pool)); );		break;				case CONSTANT_Methodref:		DBG(VERIFY2, dprintf("   METHODREF: %s  --type--  %s",				     METHODREF_NAMED(idx, pool), METHODREF_SIGD(idx, pool)); );		break;							case CONSTANT_InterfaceMethodref:		DBG(VERIFY2, dprintf("   INTERFACEMETHODREF: %s  --type--  %s",				     INTERFACEMETHODREF_NAMED(idx, pool), INTERFACEMETHODREF_SIGD(idx, pool)); );		break;							case CONSTANT_NameAndType:		DBG(VERIFY2, dprintf("   NAMEANDTYPE: %s  --and--  %s",				     NAMEANDTYPE_NAMED(idx, pool), NAMEANDTYPE_SIGD(idx, pool)); );		break;				default:		DBG(VERIFY2, dprintf("   *** UNRECOGNIZED CONSTANT POOL ENTRY in class %s *** ",				     CLASS_CNAME(class)); );	}		return idx;}staticvoidprintConstantPool(const Hjava_lang_Class* class){	uint32 idx;	const constants *pool = CLASS_CONSTANTS(class);		DBG(VERIFY2, dprintf("    CONSTANT POOL FOR %s\n", class->name->data); );		for (idx = 1; idx < pool->size; idx++) {		DBG(VERIFY2, dprintf("      %d", idx); );				idx = printConstantPoolEntry(class, idx);				DBG(VERIFY2, dprintf("\n"); );	}}#endif /* !(defined(NDEBUG) || !defined(KAFFE_VMDEBUG)) *//* * Verify pass 2:  Check the internal consistency of the class file *  but do not check the bytecode.  If at any point we find an error in the *  class file format, we abort and throw a ClassFormatError or VerifyError *  (depending on what the Sun Java VM would throw given the specific error). * * According to the JVML spec for Java 2, this should do the following: *  1. ensure that every class (except java/lang/Object) has a direct superclass * *  2. a.  ensure that final classes are not subclassed  *     b.  ensure that final methods are not overriden * *  3. ensure that constant pool satisfies the documented static constraints *     - i.e. each CONSTANT_Class_info structure in constant pool contains in its *       name_index item a valid constant pool index for a CONSTANT_Utf8_info structure, *       etc. * *  4. ensure that all field references and method references in the constant pool have *     (this is basically parsing type signatures for validity): *     - valid names *     - valid classes *     - a valid type desriptor * * However, the JVML spec also specifies a bunch of other rules that make sense to be * checked here (i.e. interfaces must be abstract) */boolverify2(Hjava_lang_Class* class, errorInfo *einfo){	constants* pool;	int idx;	int tag;			if (isTrustedClass(class))		return(true);			DBG(VERIFY2, dprintf("\nPass 2 Verifying class %s\n", CLASS_CNAME(class)); );	#ifdef UNENFORCED_INTERFACE_RESTRICTIONS	/* this is commented out because Sun's Java runtime environment doesn't enforce the restrictions	 * placed upon interfaces by the specification.	 * GJC also doesn't follow this!	 */	if (CLASS_IS_INTERFACE(class)) {	        /* JVML spec p. 96: if a class has ACC_INTERFACE flag set, it must also have		 * ( ACC_ABSTRACT set and may have ACC_PUBLIC set.  it may not have any other flags		 * (in the given table) set.		 */		if (!CLASS_IS_ABSTRACT(class)) {			postExceptionMessage(einfo, JAVA_LANG(ClassFormatError),					     "interfaces must have their abstract flag set (in interface \"%s\")",					     CLASS_CNAME(class));			return(false);		} else if (CLASS_IS_FINAL(class)) {			postExceptionMessage(einfo, JAVA_LANG(ClassFormatError),					     "interfaces cannot be final (in interface \"%s\")",					     CLASS_CNAME(class));			return(false);		}	}#endif /* UNENFORCED_INTERFACE_RESTRICTIONS */	{		Field *fld;		int lpc;				fld = CLASS_FIELDS(class);		for( lpc = 0; lpc < CLASS_NFIELDS(class); lpc++ )		{			if( !checkField(&fld[lpc], einfo) )				return(false);		}	}	        /* java/lang/Object does not have a superclass, is not final, and is not an interface,	 * so we skip all of those checks	 */	if(strcmp(OBJECTCLASS, CLASS_CNAME(class))) {		if (class->superclass == NULL) {			/***********************************************************			 * 1 - every class except java/lang/Object has a superclass			 ***********************************************************/			postExceptionMessage(einfo, JAVA_LANG(ClassFormatError),					     "class \"%s\" does not have a superclass",					     CLASS_CNAME(class));			return(false);		} else if (CLASS_IS_FINAL(class->superclass)) {			/*********************************************************			 * 2a: check that final classes are not inherited from			 *********************************************************/					postExceptionMessage(einfo, JAVA_LANG(VerifyError),					     "class \"%s\" cannot inherit from final class \"%s\"",					     CLASS_CNAME(class),					     CLASS_CNAME(class->superclass));			return(false);		} else if (CLASS_IS_INTERFACE(class)) {		        /* we separate this from the rest of the method checking because the only requirement			 * of methods in an interface is that they be public, abstract, and nothing else.			 */			Method* method;			int n;					for (n = CLASS_NMETHODS(class), method = CLASS_METHODS(class);			     n > 0;			     --n, ++method) {							        /* if it's <clinit> (init_name) then it doesn't have to be public.				 * compilers often insert a <clinit> function to initialize an				 * interfaces public static fields, if there are any.				 */				if (strcmp(init_name->data, METHOD_NAMED(method))) {					if (!METHOD_IS_PUBLIC(method)) {						postExceptionMessage(einfo, JAVA_LANG(ClassFormatError),								     "interface methods must be declared public (method \"%s\" in interface \"%s\")",								     METHOD_NAMED(method),								     CLASS_CNAME(class));						return(false);					} else if (!METHOD_IS_ABSTRACT(method)) {						postExceptionMessage(einfo, JAVA_LANG(ClassFormatError),								     "interface methods must be declared abstract (method \"%s\" in interface \"%s\")",								     METHOD_NAMED(method),								     CLASS_CNAME(class));						return(false);					}				}				

⌨️ 快捷键说明

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