verifycode.c
来自「This is a resource based on j2me embedde」· C语言 代码 · 共 1,993 行 · 第 1/5 页
C
1,993 行
/* * @(#)verifycode.c 1.165 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. * */ /*- * Verify that the code within a method block doesn't exploit any * security holes. *//* Exported function: jboolean VerifyClass(CVMExecEnv*, CVMClassBlock *cb, char *message_buffer, jint buffer_length) */#ifdef CVM_CLASSLOADING#ifndef CVM_TRUSTED_CLASSLOADERS #include "javavm/include/clib.h"#include "javavm/include/porting/ansi/setjmp.h"#include "javavm/include/porting/ansi/limits.h"#include "javavm/include/indirectmem.h"#include "jni.h"#include "jvm.h"#include "javavm/include/verify_impl.h"#include "javavm/include/verify.h"#include "javavm/include/globals.h"#include "javavm/include/opcodes.h"#include "opcodes.in_out"#ifdef __cplusplus#define this XthisX#define new XnewX#define class XclassX#define protected XprotectedX#endifstatic const unsigned char *JVM_GetMethodByteCode(CVMMethodBlock* mb){ CVMJavaMethodDescriptor* jmd = CVMmbJmd(mb); if (jmd == NULL) { return NULL; } else { return CVMmbJavaCode(mb); }}static jintJVM_GetMethodByteCodeLength(CVMMethodBlock* mb){ CVMJavaMethodDescriptor* jmd = CVMmbJmd(mb); if (jmd == NULL) { return 0; } else { return CVMjmdCodeLength(jmd); }}static CVMExceptionHandler *JVM_GetMethodExceptionTableEntry(CVMMethodBlock* mb, jint entry_index){ CVMJavaMethodDescriptor* jmd = CVMmbJmd(mb); return CVMjmdExceptionTable(jmd) + entry_index;}static jintJVM_GetMethodExceptionTableLength(CVMMethodBlock* mb){ CVMJavaMethodDescriptor* jmd = CVMmbJmd(mb); if (jmd == NULL) { return 0; } else { return CVMjmdExceptionTableLength(jmd); }}static jintJVM_GetMethodLocalsCount(CVMMethodBlock* mb){ CVMJavaMethodDescriptor* jmd = CVMmbJmd(mb); if (jmd == NULL) { return 0; } else { return CVMjmdMaxLocals(jmd); }}#ifdef CVM_TRACEstatic CVMFieldTypeIDJVM_GetCPFieldName(CVMConstantPool* cp, jint cp_index){ CVMUint16 typeIDIdx = CVMcpGetMemberRefTypeIDIdx(cp, cp_index); return CVMcpGetFieldTypeID(cp, typeIDIdx);}#endifstatic CVMMethodTypeIDJVM_GetCPMethodName(CVMConstantPool* cp, jint cp_index){ CVMUint16 typeIDIdx = CVMcpGetMemberRefTypeIDIdx(cp, cp_index); return CVMcpGetMethodTypeID(cp, typeIDIdx);}static CVMClassTypeIDJVM_GetCPFieldSignature(CVMConstantPool* cp, jint cp_index){ CVMUint16 typeIDIdx = CVMcpGetMemberRefTypeIDIdx(cp, cp_index); return CVMtypeidGetType(CVMcpGetFieldTypeID(cp, typeIDIdx));}static CVMMethodTypeIDJVM_GetCPMethodSignature(CVMConstantPool* cp, jint cp_index){ CVMUint16 typeIDIdx = CVMcpGetMemberRefTypeIDIdx(cp, cp_index); return CVMcpGetMethodTypeID(cp, typeIDIdx);}static CVMClassTypeIDJVM_GetCPClassName(CVMExecEnv* ee, CVMConstantPool* cp, jint classIdx){ CVMClassTypeID classID; if (CVMcpTypeIs(cp, classIdx, ClassBlock)) { classID = CVMcbClassName(CVMcpGetCb(cp, classIdx)); } else { CVMcpLock(ee); if (CVMcpTypeIs(cp, classIdx, ClassBlock)) { classID = CVMcbClassName(CVMcpGetCb(cp, classIdx)); } else { classID = CVMcpGetClassTypeID(cp, classIdx); } CVMcpUnlock(ee); } return classID;}static CVMClassTypeIDJVM_GetCPFieldClassName(CVMExecEnv* ee, CVMConstantPool* cp, jint cp_index){ CVMUint16 classIdx = CVMcpGetMemberRefClassIdx(cp, cp_index); return JVM_GetCPClassName(ee, cp, classIdx);}static CVMClassTypeIDJVM_GetCPMethodClassName(CVMExecEnv* ee, CVMConstantPool* cp, jint cp_index){ CVMUint16 classIdx = CVMcpGetMemberRefClassIdx(cp, cp_index); return JVM_GetCPClassName(ee, cp, classIdx);}static jintJVM_GetCPFieldModifiers(CVMConstantPool* cp, int cp_index, CVMClassBlock *cbCalled){ CVMUint16 typeIDIdx = CVMcpGetMemberRefTypeIDIdx(cp, cp_index); CVMFieldTypeID typeID = CVMcpGetFieldTypeID(cp, typeIDIdx); int i; for (i = 0; i < CVMcbFieldCount(cbCalled); i++) { CVMFieldBlock* fb = CVMcbFieldSlot(cbCalled, i); if (CVMtypeidIsSame(CVMfbNameAndTypeID(fb), typeID)) { return CVMfbAccessFlags(fb); } } return -1;} static jintJVM_GetCPMethodModifiers(CVMConstantPool* cp, int cp_index, CVMClassBlock *cbCalled){ CVMUint16 typeIDIdx = CVMcpGetMemberRefTypeIDIdx(cp, cp_index); CVMMethodTypeID typeID = CVMcpGetMethodTypeID(cp, typeIDIdx); int i; for (i = 0; i < CVMcbMethodCount(cbCalled); i++) { CVMMethodBlock* mb = CVMcbMethodSlot(cbCalled, i); if (CVMtypeidIsSame(CVMmbNameAndTypeID(mb), typeID)) { return CVMmbAccessFlags(mb); } } return -1;}typedef CVMOpcode opcode_type;#define MAX_ARRAY_DIMENSIONS 255/* align byte code */#ifndef ALIGN_UP#define ALIGN_UP(n,align_grain) (((n) + ((align_grain) - 1)) & ~((align_grain)-1))#endif /* ALIGN_UP *//* * Casts from pointer types to scalar types have to * be casts to the type CVMAddr which is 4 byte on * 32 bit platforms and 8 byte on 64 bit platforms. */#define UCALIGN(n) ((unsigned char *)ALIGN_UP((CVMAddr)(n),sizeof(int)))#ifdef CVM_TRACE#define verify_verbose (CVMcheckDebugFlags(CVM_DEBUGFLAG(TRACE_VERIFIER)) != 0)#endif/* * an analyzed instruction's stack size and register count are initially unknown. */#define UNKNOWN_STACK_SIZE -1#define UNKNOWN_REGISTER_COUNT -1/* * The first time we encounter a jsr instruction, we set its operand2 field to the * following. Thereafter we use the instruction index of the ret instruction * corresponding to it. This helps us analyze flow and enforce the * correspondence between subroutines and ret instructions. */#define UNKNOWN_RET_INSTRUCTION -1#undef MAX#undef MIN #define MAX(a, b) ((a) > (b) ? (a) : (b))#define MIN(a, b) ((a) < (b) ? (a) : (b))#define BITS_PER_INT (CHAR_BIT * sizeof(int)/sizeof(char))#define SET_BIT(flags, i) (flags[(i)/BITS_PER_INT] |= \ ((unsigned)1 << ((i) % BITS_PER_INT)))#define IS_BIT_SET(flags, i) (flags[(i)/BITS_PER_INT] & \ ((unsigned)1 << ((i) % BITS_PER_INT)))typedef unsigned int *bitvector;/* opc_invokespecial calls to <init> need to be treated special */#define opc_invokeinit ((CVMOpcode)0x100)/* A hash mechanism used by the verifier. * Maps class names to unique 16 bit integers. * This is very similar to the classic VM's string intern table. * The good thing about this one is that it is part of the context * so requires less management when we're done. */#define HASH_TABLE_SIZE 503/* The buckets are managed as a 256 by 256 matrix. We allocate an entire * row (256 buckets) at a time to minimize fragmentation. Rows are * allocated on demand so that we don't waste too much space. */ #define MAX_HASH_ENTRIES 65536#define HASH_ROW_SIZE 256typedef struct hash_bucket_type { CVMClassTypeID name; /* also used as the hash */ CVMClassBlock* class; unsigned short next; unsigned loadable:1; /* from context->class loader */} hash_bucket_type;typedef struct { hash_bucket_type **buckets; unsigned short *table; int entries_used;} hash_table_type;#define GET_BUCKET(class_hash, ID)\ (class_hash->buckets[ID / HASH_ROW_SIZE] + ID % HASH_ROW_SIZE)#undef CVM_VERIFY_OPERAND_BUF_SIZE /* operand buffer size used in pop_stack */#define CVM_VERIFY_OPERAND_BUF_SIZE 257#undef CVM_VERIFY_TYPE_BUF_SIZE /* type buffer size used in pop_stack */#define CVM_VERIFY_TYPE_BUF_SIZE 256/* The context type encapsulates the current invocation of the byte * code verifier. This permits simultaneous invocation of it in multiple threads. */struct context_type { CVMExecEnv *ee; /* current CVMExecEnv */ /* buffers etc. */ char stack_operand_buffer[CVM_VERIFY_OPERAND_BUF_SIZE]; fullinfo_type stack_info_buffer[CVM_VERIFY_TYPE_BUF_SIZE]; char *message; jint message_buf_len; /* these fields are per class */ CVMClassBlock *class; /* current class */ CVMUint16 nconstants; CVMConstantPool *constant_pool; hash_table_type class_hash; fullinfo_type object_info; /* fullinfo for java/lang/Object */ fullinfo_type string_info; /* fullinfo for java/lang/String */ fullinfo_type class_info; /* fullinfo for java/lang/Class */ fullinfo_type throwable_info; /* fullinfo for java/lang/Throwable */ fullinfo_type cloneable_info; /* fullinfo for java/lang/Cloneable */ fullinfo_type serializable_info; /* fullinfo for java/io/Serializable */ fullinfo_type currentclass_info; /* fullinfo for context->class */ fullinfo_type superclass_info; /* fullinfo for superclass */ /* these fields are per method */ CVMMethodBlock *mb; /* current method */ const unsigned char *code; /* current code object */ jint code_length; int *code_data; /* offset to instruction number */ struct instruction_data_type *instruction_data; /* info about each */ struct handler_info_type *handler_info; fullinfo_type *superclasses; /* null terminated superclasses */ int instruction_count; /* number of instructions */ fullinfo_type return_type; /* function return type */ fullinfo_type swap_table[4]; /* used for passing information */ int bitmask_size; /* words needed to hold bitmap of arguments */ CVMBool method_has_jsr; CVMBool method_has_switch;#if 0 /* See comment in verify_field(). */ /* these fields are per field */ CVMFieldBlock *fb;#endif /* Used by the space allocator */ struct CCpool *CCroot, *CCcurrent; char *CCfree_ptr; int CCfree_size; /* Jump here on any error. */ jmp_buf jump_buffer; /* Class file version we are checking against */ int major_version;};/* * The state of the stack is a linked list of stack_item_type. * The first item is the stack top: lower items are found by * following the next pointer. To pop an item from the stack * is to replace the "stack" pointer by stack->next and decrement * stack_size. To push an item, use * stack_item_type *stack_item = NEW(stack_item_type, 1); * stack_item->next = s->stack; * s->stack = stack_item; * s->stack_size++; * obviously, see stack_item_type below. */struct stack_info_type { struct stack_item_type *stack; int stack_size;};/* * For each of the register_count registers we know about at this point, * a fullinfo_type gives what we know about the content. See above, * especially ITEM_ReturnAddress. * There is also an array of mask_count mask bitsets. Frequently * mask_count == 0. The sets must be at least register_count long. * The registers information, as well as the masks information, is * modified at every store into a local "register." * See mask_type. */struct register_info_type { int register_count; /* number of registers used */ fullinfo_type *registers; int mask_count; /* number of masks in the following */ struct mask_type *masks;};/* * For most instructions, there are multiple code paths from the beginning of the * method to the start of the instruction. For code paths which can be * reached by way of a jsr (and are thus part of a subroutine as defined by a jsr/ret pair), * we keep a bit mask of registers modified (by store instruction) during the subroutine. * This helps us merge state information from the ret back to the instruction after the jsr.
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?