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