verifyformat.c
来自「This is a resource based on j2me embedde」· C语言 代码 · 共 2,149 行 · 第 1/5 页
C
2,149 行
/* * @(#)verifyformat.c 1.64 06/10/10 * * Copyright 1990-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details (a copy is * included at /legal/license.txt). * * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. * */#include "javavm/include/porting/ansi/setjmp.h"#include "javavm/include/clib.h"#include "jni.h"#include "jni_util.h"#include "jvm.h"#include "javavm/include/verify.h"typedef unsigned short unicode;#if CVM_CLASSLOADING#define JAVA_CLASSFILE_MAGIC 0xCafeBabe#define JAVA_MIN_SUPPORTED_VERSION 45#define JAVA_MAX_SUPPORTED_VERSION 49#define JAVA_MAX_SUPPORTED_MINOR_VERSION 0/* align byte code */#undef ALIGN_UP#define ALIGN_UP(n,align_grain) (((n) + ((align_grain) - 1)) & ~((align_grain)-1))/* represent a UTF-8 string as appeared in class files. */typedef struct { unsigned char len_h; /* unaligned */ unsigned char len_l; char bytes[1];} utf_str;typedef struct { unsigned length; char * bytes;}UtfString;typedef struct { UtfString name; UtfString sig;}NameAndSig;typedef struct { unsigned short inner_index; unsigned short outer_index;}InnerClassPair;#define UTF_LEN(utf) \ ((((unsigned int)(utf)->len_h) << 8) + (unsigned int)((utf)->len_l))#define UTF_ASSIGN(stringStruct, utf) \ ( ((stringStruct).length = UTF_LEN(utf)) , \ ((stringStruct).bytes = (utf)->bytes) )typedef union { jint i; utf_str *s;} cp_type;typedef struct { const unsigned char *ptr; const unsigned char *end_ptr; class_size_info *size; jmp_buf jump_buffer; cp_type *constant_pool; unsigned char *type_table; int nconstants; char *cp_buffer; jint err_code; const char *class_name; char *msg; unsigned int msg_len; jboolean in_clinit;#ifdef CVM_DUAL_STACK jboolean isCLDCClass;#endif InnerClassPair* class_pairs; int major_version; int minor_version;#undef MEASURE_ONLY#undef CHECK_RELAXED#ifdef CVM_TRUSTED_CLASSLOADERS#define MEASURE_ONLY (CVM_TRUE)#define CHECK_RELAXED (CVM_TRUE)#else jboolean measure_only; jboolean check_relaxed;#define MEASURE_ONLY (context->measure_only)#define CHECK_RELAXED (context->check_relaxed)#endif} CFcontext;static int utfcmp(utf_str *ustr, char *cstr);static char * utfncpy(char *buf, int buf_len, utf_str *ustr);/* * The following routine is used to find duplicate name/signature of * interfaces, fields, and methods. */static CVMBool FindDup(NameAndSig array[], int length);static utf_str *getAsciz(CFcontext *);static utf_str *getAscizFromCP(CFcontext *, unsigned int i);static unsigned long get1byte(CFcontext *);static unsigned long get2bytes(CFcontext *);static unsigned long get4bytes(CFcontext *);static void skip2bytes(CFcontext *);static void skipNbytes(CFcontext *, size_t n);static utf_str *getUTF8String(CFcontext *);static void ParseConstantPool(CFcontext *);static void ParseCode(CFcontext *, utf_str *mb_name, unsigned long args_size);static void ParseLineTable(CFcontext *, unsigned long code_length);static void ParseExceptions(CFcontext *);static void ParseLocalVars(CFcontext *, unsigned long code_length);#ifdef CVM_SPLIT_VERIFYstatic void ParseStackMap(CFcontext *, CVMUint32 codeLength, CVMUint32 maxLocals, CVMUint32 maxStack);static void ParseStackMapTable(CFcontext *, CVMUint32 codeLength, CVMUint32 maxLocals, CVMUint32 maxStack);#endifstatic void CFerror(CFcontext *context, char *fmt, ...);static void CNerror(CFcontext *context, char *name);static void UVerror(CFcontext *context);static void CFnomem(CFcontext *context);/* JAVA SE reports different error on bytecode verification */#ifndef JAVASE#define CVerror CFerror#elsestatic void CVerror(CFcontext *context, char *fmt, ...);#endifstatic void verify_static_constant(CFcontext *context, utf_str *sig, unsigned int index);static voidverify_constant_pool(CFcontext *context, cp_type* constant_pool, unsigned char * type_table, unsigned int nconstants);static void verify_legal_class_modifiers(CFcontext *context, unsigned int access);static void verify_legal_field_modifiers(CFcontext *context, unsigned int access, jboolean isIntf);static voidverify_legal_method_modifiers(CFcontext *context, unsigned int access, jboolean isIntf, utf_str *name);static void verify_legal_utf8(CFcontext *context, utf_str *str);/* Argument for verify_legal_name */enum { LegalClass, LegalField, LegalMethod, LegalMethodref, LegalVariable };static void verify_legal_name(CFcontext *context, utf_str *name, int type);static unsigned intverify_legal_method_signature(CFcontext *context, utf_str *name, utf_str *signature);static voidverify_legal_field_signature(CFcontext *context, utf_str *name, utf_str *signature);static voidverify_constant_entry(CFcontext *context, unsigned int index, int type, char *msg);static unsigned intverify_innerclasses_attribute(CFcontext *context);static char *skip_over_fieldname(char *name, jboolean slash_okay, unsigned int len);static char *skip_over_field_signature(char *name, jboolean void_okay, unsigned int len);/* RETURNS * 0: on success * -1: out of memory * -2: class format error * -3: unsupported version error * -4: bad class name error * -5: generic verification errors * * Also fills in the class_size_info structure which contains size * information of verious class components. */#define CF_OK 0#define CF_NOMEM (-1)#define CF_ERR (-2)#define CF_UVERR (-3)#define CF_BADNAME (-4)#define CF_VERR (-5)#define LOCAL_BUFFER_SIZE 75jintCVMverifyClassFormat(const char *class_name, const unsigned char *data, unsigned int data_size, class_size_info *size, char *message_buffer, jint buffer_length, jboolean measure_only,#ifdef CVM_DUAL_STACK jboolean isCLDCClass,#endif jboolean check_relaxed){ CFcontext context_buf; CFcontext *context = &context_buf; unsigned int cb_access; unsigned int i; utf_str *cb_name; unsigned int attribute_count; unsigned int total; NameAndSig name_buffer[LOCAL_BUFFER_SIZE]; NameAndSig * volatile utf_names = name_buffer; memset(context, 0, sizeof(CFcontext)); memset(size, 0, sizeof(class_size_info)); /* Set up the context */ context->ptr = data; context->end_ptr = data + data_size; context->class_name = class_name; context->size = size; context->msg = message_buffer; context->msg_len = buffer_length; context->msg[0] = 0;#ifndef CVM_TRUSTED_CLASSLOADERS context->measure_only = measure_only; context->check_relaxed = check_relaxed;#endif#ifdef CVM_DUAL_STACK context->isCLDCClass = isCLDCClass;#endif if (setjmp(context->jump_buffer)) { if (context->cp_buffer != NULL) { free(context->cp_buffer); } if ((utf_names != name_buffer) && (utf_names != NULL)) { free(utf_names); } if (context->class_pairs != NULL){ free(context->class_pairs); } return context->err_code; } if (get4bytes(context) != JAVA_CLASSFILE_MAGIC) CFerror(context, "Bad magic number"); context->minor_version = get2bytes(context); context->major_version = get2bytes(context); if ((context->major_version < JAVA_MIN_SUPPORTED_VERSION) || (context->major_version > JAVA_MAX_SUPPORTED_VERSION) || ((context->major_version == JAVA_MAX_SUPPORTED_VERSION) && (context->minor_version > JAVA_MAX_SUPPORTED_MINOR_VERSION))) { UVerror(context); } ParseConstantPool(context); cb_access = get2bytes(context) & JVM_RECOGNIZED_CLASS_MODIFIERS; verify_legal_class_modifiers(context, cb_access); /* Get the name of the class */ i = get2bytes(context); /* index in constant pool of class */ cb_name = getAscizFromCP(context, i); verify_legal_name(context, cb_name, LegalClass); if (cb_name->bytes[0] == JVM_SIGNATURE_ARRAY) { CFerror(context, "Bad name"); } if (context->class_name != NULL && utfcmp(cb_name, (char *)(context->class_name)) != 0) { char buf[256]; utfncpy(buf, sizeof(buf), cb_name); CNerror(context, buf); } /* Get the super class name. */ i = get2bytes(context); /* index in constant pool of class */ if (i > 0) { utf_str *super_name; verify_constant_entry(context, i, JVM_CONSTANT_Class, "Superclass name"); super_name = getAscizFromCP(context, i); verify_legal_name(context, super_name, LegalClass); if (super_name->bytes[0] == JVM_SIGNATURE_ARRAY) { CFerror(context, "Bad superclass name"); } if (cb_access & JVM_ACC_INTERFACE) { if (utfcmp(super_name, "java/lang/Object") != 0) { CFerror(context, "Interfaces must have java.lang.Object as superclass"); } } } else { if (utfcmp(cb_name, "java/lang/Object") != 0) CFerror(context, "Bad superclass index"); } total = context->size->interfaces = 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 ++) { utf_str *intf_name; int intf_index = get2bytes(context); verify_constant_entry(context, intf_index, JVM_CONSTANT_Class, "Interface name"); intf_name = getAscizFromCP(context, intf_index); verify_legal_name(context, intf_name, LegalClass); if (intf_name->bytes[0] == JVM_SIGNATURE_ARRAY) { CFerror(context, "Bad interface name"); } UTF_ASSIGN(utf_names[i].name, intf_name); utf_names[i].sig.length = 0; } if ( total > 0 ){ if (FindDup( utf_names, total) ){ CFerror(context, "Repetitive interface name"); } } if (utf_names != name_buffer) { free(utf_names); utf_names = name_buffer; } total = context->size->fields = 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; jboolean hasSeenConstantValue = JNI_FALSE; unsigned int fb_access = get2bytes(context) & JVM_RECOGNIZED_FIELD_MODIFIERS; utf_str *fb_name = getAsciz(context); utf_str *fb_signature = getAsciz(context); verify_legal_field_modifiers(context, fb_access, (jboolean)((cb_access & JVM_ACC_INTERFACE) ? JNI_TRUE : JNI_FALSE)); verify_legal_name(context, fb_name, LegalField); verify_legal_field_signature(context, fb_name, fb_signature); attribute_count = get2bytes(context); for (j = 0; j < attribute_count; j++) { utf_str *attr_name = getAsciz(context); unsigned long length = get4bytes(context); if ((fb_access & JVM_ACC_STATIC) && utfcmp(attr_name, "ConstantValue") == 0) { if (length != 2) CFerror(context, "Wrong size for VALUE attribute"); if (hasSeenConstantValue) CFerror(context, "Multiple ConstantValue attributes"); else hasSeenConstantValue = JNI_TRUE; if (fb_access & JVM_ACC_STATIC) { verify_static_constant(context, fb_signature, get2bytes(context)); } } else { skipNbytes(context, length); } } if (fb_access & JVM_ACC_STATIC) { if (fb_signature->bytes[0] == 'D' || fb_signature->bytes[0] == 'J') { context->size->staticFields += 2; } else { context->size->staticFields += 1; if (fb_signature->bytes[0] == 'L' || fb_signature->bytes[0] == '[') { context->size->staticRefFields += 1; } } } UTF_ASSIGN(utf_names[i].name, fb_name); UTF_ASSIGN(utf_names[i].sig, fb_signature); } if (FindDup(utf_names, total)) { CFerror(context, "Repetitive field name/signature"); }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?