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 + -
显示快捷键?