verifyformat.c

来自「This is a resource based on j2me embedde」· C语言 代码 · 共 2,149 行 · 第 1/5 页

C
2,149
字号
    return constant_pool[value].s;}static void skip2bytes(CFcontext *context){    if (context->end_ptr - context->ptr < 2) {	CFerror(context, "Truncated class file");    }    (context)->ptr += 2;}static void skipNbytes(CFcontext *context, size_t n){    if (context->end_ptr - context->ptr < n) {	CFerror(context, "Truncated class file");    }    context->ptr += n;}static utf_str * getUTF8String(CFcontext* context){    utf_str *result = (utf_str *)context->ptr;    skip2bytes(context);    skipNbytes(context, UTF_LEN(result));    verify_legal_utf8(context, result);    return result;}static voidverify_constant_pool(CFcontext *context, 		     cp_type *cp, 		     unsigned char *type_table,		     unsigned int cp_count){    unsigned int i, type;        if (MEASURE_ONLY)        return;    /* Let's make two quick passes over the constant pool. The first one      * checks that everything is of the right type.      */    for (i = 1; i < cp_count; i++) {        switch(type = type_table[i]) {	case JVM_CONSTANT_String:	case JVM_CONSTANT_Class: {	    unsigned int index = cp[i].i;	    if ((index <= 0) ||		(index >= cp_count) ||		(type_table[index] != JVM_CONSTANT_Utf8)) {	        CFerror(context, "Bad index in constant pool #%d", i);	    }	    break;	}		case JVM_CONSTANT_Fieldref:	case JVM_CONSTANT_Methodref:	case JVM_CONSTANT_InterfaceMethodref: 	case JVM_CONSTANT_NameAndType: {	    unsigned long index = (unsigned)(cp[i].i);	    unsigned int key1 = index >> 16;	    unsigned int key2 = index & 0xFFFF;	    if (key1 <= 0 || key1 >= cp_count 		|| key2 <= 0 || key2 >= cp_count) {	        CFerror(context, "Bad index in constant pool #%d", i);	    }	    if (type == JVM_CONSTANT_NameAndType) {	        if ((type_table[key1] != JVM_CONSTANT_Utf8) ||		    (type_table[key2] != JVM_CONSTANT_Utf8)) {		    CFerror(context, "Bad index in constant pool.");		}	    } else {	        if ((type_table[key1] != JVM_CONSTANT_Class) ||		    (type_table[key2] != JVM_CONSTANT_NameAndType)) {		    CFerror(context, "Bad index in constant pool #%d", i);		}	    }	    break;	}	case JVM_CONSTANT_Utf8:	case JVM_CONSTANT_Integer:	case JVM_CONSTANT_Float:	    break;	    	case JVM_CONSTANT_Long:	case JVM_CONSTANT_Double:	    if ((i + 1 >= cp_count) || 		(type_table[i + 1] != 0)) {	        CFerror(context, 			"Improper constant pool long/double #%d", i);	    } else {	        i++;			break;	    	    }	    	default:	    CFerror(context, "Illegal constant pool type at #%d", i);	}    }    /* The second pass checks the strings are of the right format */    for (i = 1; i < cp_count; i++) {	switch(type = type_table[i]) {	case JVM_CONSTANT_Class: {	    unsigned int index = cp[i].i;	    verify_legal_name(context, cp[index].s, LegalClass); 	    break;	}	      	case JVM_CONSTANT_Fieldref:	case JVM_CONSTANT_Methodref:	case JVM_CONSTANT_InterfaceMethodref: {	    unsigned long index = (unsigned)(cp[i].i);	    unsigned int name_type_index = index & 0xFFFF;	    unsigned int name_type_key = cp[name_type_index].i;	    unsigned int name_index = name_type_key >> 16;	    unsigned int signature_index = name_type_key & 0xFFFF;	    utf_str *name = cp[name_index].s;	    utf_str *signature = cp[signature_index].s;	    if (type == JVM_CONSTANT_Fieldref) {	        verify_legal_name(context, name, LegalField);		verify_legal_field_signature(context, name, signature);	    } else {		int methodOrInterfaceref;		/* the rule about what is allowed here are odd */		methodOrInterfaceref = (type == JVM_CONSTANT_Methodref)?					LegalMethodref : LegalMethod;	        verify_legal_name(context, name, methodOrInterfaceref);		verify_legal_method_signature(context, name, signature);	    }	    break;	}	}    }}static void verify_legal_class_modifiers(CFcontext *context, unsigned int access){    if (MEASURE_ONLY)        return;    /* Need the following version number check in order to pass the following       tests in the CDC TCK:       1. vm/classfmt/atr/atrinc211/atrinc21101m1/atrinc21101m1.html          classfile version: 45.3, class access flags: 0xfe90       2. vm/classfmt/clf/clfacc006/clfacc00601m1/clfacc00601m1.html          classfile version: 45.3, class access flags: 0x7001       3. vm/classfmt/clf/clfacc006/clfacc00603m1/clfacc00603m1.html:          classfile version: 45.3, class access flags: 0x7031       In all these cases, the class access flags have illegal bits set for       classfile version 45.3.  The VM spec says that unused bits should be       set to zero for future use.  If these bits have values set, a VM which       is capable of digesting a later classfile version should be able to       throw a ClassFormatError if these bits are malformed.  In the case of       the above TCK tests, the access flag bits are malformed.  However,       the tests are erroneously expecting the VM to ignore these bits       instead.       This check has been added here to work around these bug that have been       filed against in the CDC TCK (CR 6574335, 6574338).  This check may       be eliminated later depending on how the TCK bugs are resolved.     */    if (context->major_version < 49) {	access &= ~(JVM_ACC_SYNTHETIC | JVM_ACC_ANNOTATION | JVM_ACC_ENUM);    }#ifdef CVM_DUAL_STACK    if (!context->isCLDCClass) {#endif        /* This is a workaround for a javac bug. Interfaces are not         * marked as ABSTRACT.         */        if (access & JVM_ACC_INTERFACE) {            access |= JVM_ACC_ABSTRACT;        }#ifdef CVM_DUAL_STACK    }#endif    if (access & JVM_ACC_ANNOTATION) {	if (!(access & JVM_ACC_INTERFACE)) {	    goto failed;	}    }    if (access & JVM_ACC_INTERFACE) {        if (!(access & JVM_ACC_ABSTRACT))	    goto failed;	if (access & JVM_ACC_FINAL)	    goto failed;    } else {        if ((access & JVM_ACC_FINAL) && (access & JVM_ACC_ABSTRACT))	    goto failed;    }    return; failed:    CFerror(context, "Illegal class modifiers: 0x%X", access);}static void verify_legal_field_modifiers(CFcontext *context, unsigned int access,			     jboolean isIntf){    if (MEASURE_ONLY)        return;    if (!isIntf) {        /* class fields */        if ((access & JVM_ACC_PUBLIC) && 	    ((access & JVM_ACC_PROTECTED) || (access & JVM_ACC_PRIVATE)))	    goto failed;	if ((access & JVM_ACC_PROTECTED) && 	    ((access & JVM_ACC_PUBLIC) || (access & JVM_ACC_PRIVATE)))	    goto failed;	if ((access & JVM_ACC_PRIVATE) && 	    ((access & JVM_ACC_PROTECTED) || (access & JVM_ACC_PUBLIC)))	    goto failed;	if ((access & JVM_ACC_FINAL) && (access & JVM_ACC_VOLATILE))	    goto failed;    } else {        /* interface fields */        if (access & ~(JVM_ACC_STATIC | JVM_ACC_FINAL | JVM_ACC_PUBLIC |		       JVM_ACC_SYNTHETIC))	    goto failed;        if (!(access & JVM_ACC_STATIC) ||	    !(access & JVM_ACC_FINAL) ||	    !(access & JVM_ACC_PUBLIC))	    goto failed;    }    return; failed:    CFerror(context, "Illegal field modifiers: 0x%X", access);}static void verify_legal_method_modifiers(CFcontext *context, unsigned int access, 			      jboolean isIntf, utf_str *name){    if (MEASURE_ONLY)        return;    /* Abstract methods cannot have these other flags set. */    if ((access & JVM_ACC_ABSTRACT) &&        (access & (JVM_ACC_FINAL | JVM_ACC_NATIVE | JVM_ACC_PRIVATE |		   JVM_ACC_STATIC | JVM_ACC_STRICT | JVM_ACC_SYNCHRONIZED))) {        goto failed;    }    if (!isIntf) {        /* class or instance methods */        if (utfcmp(name, "<init>") == 0) {            /* The STRICT bit is new as of 1.2. */            if (access & ~(JVM_ACC_PUBLIC | JVM_ACC_PROTECTED |			   JVM_ACC_PRIVATE | JVM_ACC_STRICT |			   JVM_ACC_VARARGS | JVM_ACC_SYNTHETIC))	        goto failed;        }    } else {        /* interface methods */        if (!(access & JVM_ACC_ABSTRACT) ||	    !(access & JVM_ACC_PUBLIC))	    goto failed;	            }    if ((access & JVM_ACC_PUBLIC) && 	((access & JVM_ACC_PROTECTED) || (access & JVM_ACC_PRIVATE)))        goto failed;    if ((access & JVM_ACC_PROTECTED) && 	((access & JVM_ACC_PUBLIC) || (access & JVM_ACC_PRIVATE)))        goto failed;    if ((access & JVM_ACC_PRIVATE) && 	((access & JVM_ACC_PROTECTED) || (access & JVM_ACC_PUBLIC)))        goto failed;    return; failed:    CFerror(context, "Illegal method modifiers: 0x%X", access);}static voidverify_legal_utf8(CFcontext *context, utf_str *str){    unsigned int i;    unsigned int length;    unsigned char *bytes;    if (MEASURE_ONLY)        return;    length = UTF_LEN(str);    bytes = (unsigned char*)str->bytes;    for (i=0; i<length; i++) {        unsigned int c = (unsigned int)bytes[i];        if (c == 0) /* no embedded zeros */	    goto failed;	if (c < 128)	    continue;        switch (c >> 4) { /* makes sure shift is unsigned */        default:	    break;	case 0x8: case 0x9: case 0xA: case 0xB: case 0xF:	    goto failed;	case 0xC: case 0xD:		    /* 110xxxxx  10xxxxxx */	    i++;	    if (i >= length)	        goto failed;	    if ((bytes[i] & 0xC0) == 0x80)	        break;	    goto failed;	case 0xE:	    /* 1110xxxx 10xxxxxx 10xxxxxx */	    i += 2;	    if (i >= length)	        goto failed;	    if (((bytes[i-1] & 0xC0) == 0x80) &&		((bytes[i] & 0xC0) == 0x80))	        break;	    goto failed;	} /* end of switch */    }    return; failed:    CFerror(context, "Illegal UTF8 string in constant pool");}/* Check if the entire second argument consists of a legal fieldname  * (or classname, if the third argument is LegalClass).  */static voidverify_legal_name(CFcontext *context, utf_str *name, int type){    jboolean result;    unsigned int length;    char *bytes;    if (MEASURE_ONLY || CHECK_RELAXED)        return;    length = UTF_LEN(name);    bytes = name->bytes;    if (length > 0) {        if (bytes[0] == '<') {	    if (type == LegalMethod) {		result = (utfcmp(name, "<init>") == 0) || 			 (utfcmp(name, "<clinit>") == 0);	    } else if (type == LegalMethodref) {		result = (utfcmp(name, "<init>") == 0);	    } else {		result = JNI_FALSE;	    }	} else {	    char *p;	    if (type == LegalClass && bytes[0] == JVM_SIGNATURE_ARRAY) {	        p = skip_over_field_signature(bytes, JNI_FALSE, length);	    } else {	        p = skip_over_fieldname(bytes, 		    (jboolean)(type == LegalClass ? JNI_TRUE : JNI_FALSE), 					length);	    }	    result = (p != NULL) && (p - bytes == length);	}    } else {        result = JNI_FALSE;    }    if (!result) {        char buf[100];	char *thing = (type == LegalField) ? "Field" 	            : (type == LegalVariable) ? "Variable" 	            : (type == LegalClass) ? "Class"	            : "Method" ;	utfncpy(buf, sizeof(buf), name);	CFerror(context, "Illegal %s name \"%s\"", thing, buf);    } }/* Check if the entire string consists of a legal field signature */static voidverify_legal_field_signature(CFcontext *context, utf_str *fieldname, 			     utf_str *signature) {    char *bytes;    unsigned int length;    char *p;    if (MEASURE_ONLY)        return;    bytes = signature->bytes;    length = UTF_LEN(signature);    p = skip_over_field_signature(bytes, JNI_FALSE, length);    if (p == NULL || p - bytes != length) {        char buf1[100], buf2[100];	utfncpy(buf1, sizeof(buf1), fieldname);	utfncpy(buf2, sizeof(buf2), signature);	CFerror(context, "Field \"%s\" has illegal signature \"%s\"", 		buf1, buf2);    }}static unsigned intverify_legal_method_signature(CFcontext *context, utf_str *methodname, 			      utf_str *signature){    unsigned int args_size;    char *p;    unsigned length;    char *next_p;    if (MEASURE_ONLY)        return 0;  /* We return 0 as the args_size when no checking		    * is necessary. 		    */    args_size = 0;    p = signature->bytes;    length = UTF_LEN(signature);    /* The first character must be a '(' */

⌨️ 快捷键说明

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