verifyformat.c

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

C
2,149
字号
    if (utf_names != name_buffer) {	free(utf_names);	utf_names = name_buffer;    }    total = context->size->methods = get2bytes(context);    if (total > LOCAL_BUFFER_SIZE) {	utf_names = (NameAndSig *)malloc(total * sizeof(NameAndSig));        if (!utf_names) {	    CFnomem(context);        }    }    for (i = 0; i < total; i ++ ) {        unsigned int j;        unsigned int args_size;        jboolean hasSeenCodeAttribute = JNI_FALSE;	jboolean hasSeenExceptionsAttribute = JNI_FALSE;	unsigned int mb_access = 	    get2bytes(context) & JVM_RECOGNIZED_METHOD_MODIFIERS;	utf_str *mb_name = getAsciz(context);	utf_str *mb_signature = getAsciz(context);	if (utfcmp(mb_name, "<clinit>") == 0 &&	    utfcmp(mb_signature, "()V") == 0) {	    /* The VM ignores the access flags of <clinit>. We reset the	     * access flags to avoid future errors in the VM */	    mb_access = JVM_ACC_STATIC;	    context->in_clinit = JNI_TRUE;	} else {	    verify_legal_method_modifiers(context, 					  mb_access,	    (jboolean)((cb_access & JVM_ACC_INTERFACE) ? JNI_TRUE : JNI_FALSE),					  mb_name);	}	verify_legal_name(context, mb_name, LegalMethod);	args_size = ((mb_access & JVM_ACC_STATIC) ? 0 : 1) + 	    verify_legal_method_signature(context, mb_name, mb_signature);	if (args_size > 255) {	    CFerror(context, "Too many arguments in signature");	}        UTF_ASSIGN(utf_names[i].name, mb_name);        UTF_ASSIGN(utf_names[i].sig,  mb_signature);	attribute_count = get2bytes(context);	for (j = 0; j < attribute_count; j++) {	    utf_str *attr_name = getAsciz(context);	    if (!utfcmp(attr_name, "Code")) {		context->size->javamethods++;	        if (mb_access & (JVM_ACC_NATIVE | JVM_ACC_ABSTRACT)) {		    CFerror(context,			    "Code attribute in native or abstract methods");		}		if (hasSeenCodeAttribute)		    CFerror(context, "Multiple Code attributes");		else		    hasSeenCodeAttribute = JNI_TRUE;		ParseCode(context, mb_name, args_size);	    } else if (utfcmp(attr_name, "Exceptions") == 0) {		if (hasSeenExceptionsAttribute)		    CFerror(context, "Multiple Exceptions attributes");		else		    hasSeenExceptionsAttribute = JNI_TRUE;	        ParseExceptions(context);	    } else {		unsigned long length = get4bytes(context);		skipNbytes(context, length);	    }	}	if ((hasSeenCodeAttribute == 0) && 		(mb_access & (JVM_ACC_NATIVE | JVM_ACC_ABSTRACT)) == 0){	    /* no code, not abstract, not native. This is wrong. */	    CFerror(context, "Non-native non-abstract method missing code");	}	context->in_clinit = JNI_FALSE;    }    if (FindDup(utf_names, total)) {        CFerror(context, "Repetitive method name/signature");    }    if (utf_names != name_buffer) {	free(utf_names);	utf_names = name_buffer;    }    /* See if there are class attributes */    attribute_count = get2bytes(context);     {	jboolean seenSourceAttribute = JNI_FALSE;	jboolean seenInnerClassesAttribute = JNI_FALSE;	for (i = 0; i < attribute_count; i++) {	    utf_str *attr_name = getAsciz(context);	    unsigned long length = get4bytes(context);	    if (utfcmp(attr_name, "SourceFile") == 0) {	        utf_str *source_name;		if (length != 2) {		    CFerror(context, "Wrong size for VALUE attribute");		}		if (seenSourceAttribute)		    CFerror(context, "Multiple SourceFile attributes");		source_name = getAsciz(context);		seenSourceAttribute = JNI_TRUE;	    } else if (utfcmp(attr_name, "InnerClasses") == 0) {		if (seenInnerClassesAttribute) {		    CFerror(context, "Multiple InnerClasses attributes");		}		seenInnerClassesAttribute = JNI_TRUE;		context->size->innerclasses = 		    verify_innerclasses_attribute(context);	    } else {	        skipNbytes(context, length);	    }	}    }    if (context->ptr != context->end_ptr && !CHECK_RELAXED)        CFerror(context, "Extra bytes at the end of the class file");    free(context->cp_buffer);    return CF_OK;}/* * Verify that the "InnerClasses" attribute is well formed, and return * the number of inner class records. */static unsigned intverify_innerclasses_attribute(CFcontext *context) {    unsigned number_of_classes = get2bytes(context);    unsigned int i = 0;    unsigned int j;    InnerClassPair  localbuf[LOCAL_BUFFER_SIZE];    InnerClassPair* class_pairs;    if (MEASURE_ONLY) {	skipNbytes(context, number_of_classes * 8);	return number_of_classes;    }    if  (number_of_classes <= LOCAL_BUFFER_SIZE){	class_pairs = localbuf;	context->class_pairs = NULL;    }else{	class_pairs = (InnerClassPair*)			malloc(number_of_classes*sizeof(InnerClassPair));        if (!class_pairs) {	    CFnomem(context);	}	context->class_pairs = class_pairs;    }    for (; i < number_of_classes; i++) {	unsigned short ioff  = (unsigned short)get2bytes(context); /* inner_class_info_index */	unsigned short ooff  = (unsigned short)get2bytes(context); /* outer_class_info_index */	unsigned short inoff = (unsigned short)get2bytes(context); /* inner_name_index       */	unsigned short iacc  = (unsigned short)get2bytes(context); /* inner_class_access_flg */	verify_constant_entry(context, ioff, JVM_CONSTANT_Class,			      "inner_class_info_index");		/* Can be zero for non-members. */	if (ooff)	    verify_constant_entry(context, ooff, JVM_CONSTANT_Class,				  "outer_class_info_index");		/* Can be zero for anonymous. */	if (inoff)	    verify_constant_entry(context, inoff, JVM_CONSTANT_Utf8,				  "inner_name_index");		if (ooff == ioff) 	    CFerror(context, "Class is both outer and inner class");		verify_legal_class_modifiers(context, iacc);	/* verify that this one is different than all others */	for (j=0; j<i; j++){	    if ((ioff == class_pairs[j].inner_index)		&& (ooff == class_pairs[j].outer_index)){		CFerror(context, "Class has duplicate Inner Class entries");	    }	}	/* remember this entry to compare to future entries */	class_pairs[i].inner_index = ioff;	class_pairs[i].outer_index = ooff;    }    if (class_pairs != localbuf){	free(class_pairs);	context->class_pairs = NULL;    }    return number_of_classes;}/* Initialize the static variables in a class structure */static voidverify_static_constant(CFcontext *context, utf_str *sig, unsigned int index){    unsigned char *type_table;    if (MEASURE_ONLY)        return;    type_table = context->type_table;    if (index <= 0 || index >= context->size->constants) {        CFerror(context, "Bad initial value");    }    switch (sig->bytes[0]) {     case JVM_SIGNATURE_DOUBLE:         if (type_table[index] != JVM_CONSTANT_Double) 	    CFerror(context, "Bad index into constant pool");	break;    case JVM_SIGNATURE_LONG:         if (type_table[index] != JVM_CONSTANT_Long)	    CFerror(context, "Bad index into constant pool");	break;    case JVM_SIGNATURE_CLASS:        if (utfcmp(sig, "Ljava/lang/String;") != 0 ||	    type_table[index] != JVM_CONSTANT_String) {	    CFerror(context, "Bad string initial value");	}	break;    case JVM_SIGNATURE_BYTE:     case JVM_SIGNATURE_CHAR:    case JVM_SIGNATURE_SHORT:    case JVM_SIGNATURE_BOOLEAN:    case JVM_SIGNATURE_INT:          if (type_table[index] != JVM_CONSTANT_Integer)	    CFerror(context, "Bad index into constant pool");	break;    case JVM_SIGNATURE_FLOAT:        if (type_table[index] != JVM_CONSTANT_Float)	    CFerror(context, "Bad index into constant pool");	break;			    default:         CFerror(context, "Unable to set initial value");    }}static void ParseConstantPool(CFcontext *context) {    unsigned int nconstants = get2bytes(context);    unsigned long cp_request;    unsigned char *type_table;    cp_type *constant_pool;    unsigned int i;    unsigned int lastNonUtf8Constant = 0;    if (nconstants < 1) {	CFerror(context, "Illegal constant pool size");    }    /*     * Measure how much space we need for the constant pool     * in memory: both the type table and the items.     */    cp_request = nconstants * (sizeof(char) + sizeof(cp_type));    /* Allocate the space */    context->cp_buffer = (char *)malloc(cp_request);    if (context->cp_buffer == NULL) {	CFnomem(context);    }    memset(context->cp_buffer, 0, cp_request);    /* Divide up the space. */    constant_pool = (cp_type *) context->cp_buffer;    type_table = (unsigned char *)        (context->cp_buffer + (nconstants * sizeof(cp_type)));    context->constant_pool = constant_pool;    context->type_table = type_table;    context->size->constants = nconstants;    /* Read in the constant pool */    for (i = 1; i < nconstants; i++) {	int type = get1byte(context);	type_table[i] = type;	if (type != JVM_CONSTANT_Utf8) {	    lastNonUtf8Constant = i;	}	switch (type) {	  case JVM_CONSTANT_Utf8: {	      constant_pool[i].s = getUTF8String(context);	      break;	  }		  case JVM_CONSTANT_Class:	  case JVM_CONSTANT_String:	      constant_pool[i].i = get2bytes(context);	      break;	  case JVM_CONSTANT_Fieldref:	  case JVM_CONSTANT_Methodref:	  case JVM_CONSTANT_InterfaceMethodref:	  case JVM_CONSTANT_NameAndType:	      constant_pool[i].i = get4bytes(context);	      break;	    	  case JVM_CONSTANT_Integer:	  case JVM_CONSTANT_Float:	      get4bytes(context);	      break;	  case JVM_CONSTANT_Long:	  case JVM_CONSTANT_Double: {	      get4bytes(context);	      get4bytes(context);	      i++;		/* increment i for loop, too */	      lastNonUtf8Constant++;	      /* A mangled type might cause you to overrun allocated memory */	      if (i >= nconstants) {		  CFerror(context, "Invalid constant pool entry");	      }	      break;	  }	  default:	      CFerror(context, "Illegal constant pool type");	}    }    context->size->reducedConstants = lastNonUtf8Constant + 1;    verify_constant_pool(context, constant_pool, type_table, nconstants);}static void ParseCode(CFcontext *context, utf_str *mb_name, 		      unsigned long args_size){    unsigned long attribute_length = get4bytes(context);    const unsigned char *end_ptr = context->ptr + attribute_length;    unsigned long attribute_count;    unsigned long code_length;    unsigned int i;    unsigned int maxstack;    unsigned int nlocals;#ifdef CVM_SPLIT_VERIFY    jboolean hasSeenStackMapTableAttribute = JNI_FALSE;#endif    if (context->major_version == 45 && context->minor_version <= 2) { 	maxstack = get1byte(context);	nlocals = get1byte(context);	code_length = get2bytes(context);    } else { 	maxstack = get2bytes(context);	nlocals = get2bytes(context);	code_length = get4bytes(context);    }    if (context->in_clinit) {        context->size->clinit.code += ALIGN_UP(code_length,sizeof(int));    } else {        context->size->main.code += ALIGN_UP(code_length,sizeof(int));    }    if (code_length == 0) {        CFerror(context, "Method with zero code length");    }    if (code_length > 65535) {        CFerror(context, "Code of a method longer than 65535 bytes");    }    if (nlocals < args_size)        CFerror(context, "Arguments can't fit into locals");    skipNbytes(context, code_length);    i = get2bytes(context);    if (context->in_clinit) {        context->size->clinit.etab += i;    } else {        context->size->main.etab += i;    }    for (; i > 0; i--) {	unsigned int start_pc;	unsigned int end_pc;	unsigned int handler_pc;	unsigned int catch_type_entry;        start_pc = get2bytes(context);	end_pc = get2bytes(context);	handler_pc = get2bytes(context);	catch_type_entry = get2bytes(context);	/* We do not check that start_pc indeed points to the 	 * beginning of an instruction. That would require changes in the byte 	 * code verifier.	 */	if (start_pc >= code_length || end_pc > code_length ||            end_pc <= start_pc || handler_pc >= code_length)	    CVerror(context, "Invalid start_pc/length in exception table");	if (catch_type_entry != 0){	    verify_constant_entry(context, catch_type_entry, JVM_CONSTANT_Class,				  "Caught type in exception table");	}    }    attribute_count = get2bytes(context);    for (i = 0; i < attribute_count; i++) {        utf_str *attr_name = getAsciz(context);	if (utfcmp(attr_name, "LineNumberTable") == 0) {	    ParseLineTable(context, code_length);	} else if (utfcmp(attr_name, "LocalVariableTable") == 0) {	    ParseLocalVars(context, code_length);#ifdef CVM_SPLIT_VERIFY	} else if (utfcmp(attr_name, "StackMapTable") == 0 &&	    context->major_version >= 50)	{	    if (hasSeenStackMapTableAttribute) {		CFerror(context, "Multiple StackMapTable attributes");	    }	    hasSeenStackMapTableAttribute = JNI_TRUE;	    ParseStackMapTable(context, code_length, nlocals, maxstack);	} else if (utfcmp(attr_name, "StackMap") == 0) {	    ParseStackMap(context, code_length, nlocals, maxstack);#endif	} else {	    unsigned long length = get4bytes(context);	    skipNbytes(context, length);	}    }    if (context->ptr != end_ptr) 	CVerror(context, "Code segment has wrong length");}#ifdef CVM_SPLIT_VERIFYstatic intParseMapElements(    CFcontext* context,

⌨️ 快捷键说明

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