📄 check_code.c
字号:
/* * @(#)check_code.c 1.26 02/09/27 * * Copyright 1995-1999 by Sun Microsystems, Inc., * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A. * All rights reserved. * * This software is the confidential and proprietary information * of Sun Microsystems, Inc. ("Confidential Information"). You * shall not disclose such Confidential Information and shall use * it only in accordance with the terms of the license agreement * you entered into with Sun. * Use is subject to license terms. */ /*========================================================================= * SYSTEM: Verifier * SUBSYSTEM: Verifies codes within a method block. * FILE: check_code.c * OVERVIEW: Verifies that the code within a method block does not * exploit any security holes. * AUTHOR: Sheng Liang, Consumer & Embedded * Initial implementation based on the Classic VM Verifier. * Edited by Tasneem Sayeed, Java Consumer Technologies *=======================================================================*//*========================================================================= * Include files *=======================================================================*/#include <check_code.h>#include <opcodes.length>#include <opcodes.in_out>/*========================================================================= * Globals and extern declarations *=======================================================================*/#ifdef DEBUG_VERIFIER int verify_verbose = 0; static struct context_type *GlobalContext;#endifvoid rewriteCode(context_type *vcontext, struct methodblock *mb);static void verify_method(context_type *context, struct methodblock *mb);static void verify_field(context_type *context, struct fieldblock *fb);static void verify_opcode_operands (context_type *, int inumber, int offset);static void set_protected(context_type *, int inumber, int key, opcode_type);static bool_t isSuperClass(context_type *, fullinfo_type);static void initialize_exception_table(context_type *);static int instruction_length(unsigned char *iptr);static bool_t isLegalTarget(context_type *, int offset);static void verify_constant_pool_type(context_type *, int, unsigned);static void initialize_dataflow(context_type *);static void run_dataflow(context_type *context);static void check_register_values(context_type *context, int inumber);static void check_flags(context_type *context, int inumber);static void pop_stack(context_type *, int inumber, stack_info_type *);static void update_registers(context_type *, int inumber, register_info_type *);static void update_flags(context_type *, int inumber, flag_type *new_and_flags, flag_type *new_or_flags);static void push_stack(context_type *, int inumber, stack_info_type *stack);static void merge_into_successors(context_type *, int inumber, register_info_type *register_info, stack_info_type *stack_info, flag_type and_flags, flag_type or_flags);static void merge_into_one_successor(context_type *context, int from_inumber, int inumber, register_info_type *register_info, stack_info_type *stack_info, flag_type and_flags, flag_type or_flags, bool_t isException);static void merge_stack(context_type *, int inumber, int to_inumber, stack_info_type *);static void merge_registers(context_type *, int inumber, int to_inumber, register_info_type *);static void merge_flags(context_type *context, int from_inumber, int to_inumber, flag_type new_and_flags, flag_type new_or_flags);static stack_item_type *copy_stack(context_type *, stack_item_type *);static mask_type *copy_masks(context_type *, mask_type *masks, int mask_count);static mask_type *add_to_masks(context_type *, mask_type *, int , int);static fullinfo_type decrement_indirection(fullinfo_type);static fullinfo_type merge_fullinfo_types(context_type *context, fullinfo_type a, fullinfo_type b, bool_t assignment);static bool_t isAssignableTo(context_type *,fullinfo_type a, fullinfo_type b);static ClassClass *object_fullinfo_to_classclass(context_type *, fullinfo_type);#define NEW(type, count) \ ((type *)CCalloc(context, (count)*(sizeof(type)), FALSE))#define ZNEW(type, count) \ ((type *)CCalloc(context, (count)*(sizeof(type)), TRUE))static void CCinit(context_type *context);static void CCreinit(context_type *context);static void CCdestroy(context_type *context);static void *CCalloc(context_type *context, int size, bool_t zero);static char *cp_index_to_fieldname(context_type *context, int cp_index);static char *cp_index_to_signature(context_type *context, int cp_index);static fullinfo_type cp_index_to_class_fullinfo(context_type *, int, bool_t);static char signature_to_fieldtype(context_type *context, char **signature_p, fullinfo_type *info);static void CCerror (context_type *, char *format, ...);#ifdef DEBUG_VERIFIERstatic void print_stack (context_type *, stack_info_type *stack_info);static void print_registers(context_type *, register_info_type *register_info);static void print_flags(context_type *, flag_type, flag_type);static void print_formatted_fieldname(context_type *context, int index);#endif/* * Access local hash tables without locking. This extra level * of naming is intended to emphasize the fact that locks are * not held and also to do error handling. Although it is not * strictly necessary, one should always use the "_Local" * versions of these functions on the verifier's local hash * tables. */#define Str2IDFree_Local(localHashRoot) Str2IDFree(localHashRoot)/*========================================================================= * FUNCTION: Str2ID_Local * OVERVIEW: Access local hash tables without locking * This extra level of naming is intended to emphasize the * fact that locks are not held and also to do error handling. * These functions could all be macros like Str2IDFree_Local(), * except that Str2ID() and ID2Str() can run out of memory, * and the code in this file makes it inconvenient to check * for that. As an expedient, rather than throwing exceptions, * Str2ID_Local() is a function that calls CCerror() if * necessary. * Returns the index given the string which corresponds to the * hash table entry. * INTERFACE: * parameters: context_type *: context * struct StrIDhash **: hash_ptr * char *: s * void ***: param * int: Copy * * returns: unsigned short *=======================================================================*/unsigned shortStr2ID_Local(context_type *context, struct StrIDhash **hash_ptr, char *s, void ***param, int Copy) { unsigned short ret; if ((ret = Str2ID(hash_ptr, s, param, Copy)) == 0) { CCerror(context, "Out of memory"); } return ret;}/*========================================================================= * FUNCTION: ID2Str_Local * OVERVIEW: Access local hash tables without locking * This extra level of naming is intended to emphasize the * fact that locks are not held and also to do error handling. * These functions could all be macros like Str2IDFree_Local(), * except that Str2ID() and ID2Str() can run out of memory, * and the code in this file makes it inconvenient to check * for that. As an expedient, rather than throwing exceptions, * ID2Str_Local() is a function that calls CCerror() if * necessary. * Returns the string given the index which corresponds to the * hash table entry. * INTERFACE: * parameters: context_type *: context * struct StrIDhash *: h * unsigned short: ID * void ***: param * * returns: char * *=======================================================================*/char *ID2Str_Local(context_type *context, struct StrIDhash *h, unsigned short ID, void ***param) { char *ret; if ((ret = ID2Str(h, ID, param)) == 0) { CCerror(context, "Out of memory"); } return ret;}/*========================================================================= * FUNCTION: verify_class_codes * OVERVIEW: Verifies the code for each of the methods in a class. * Invoked by verify_class(). * Returns true if the class codes are ok. * INTERFACE: * parameters: pointer to the ClassClass structure. * * returns: boolean type *=======================================================================*/bool_t verify_class_codes(ClassClass *cb) { context_type context_structure; context_type *context = &context_structure; bool_t result = TRUE; void **addr; int i;#ifdef DEBUG_VERIFIER GlobalContext = context;#endif /* Initialize the class-wide fields of the context. */ context->class = cb; context->classHash = 0; /* Zero method block field of the context, in case anyone calls CCerrror */ context->mb = 0; context->superClasses = NULL; /* filled in later */ /* Don't call CCerror or anything that can call it above the setjmp! */ if (!setjmp(context->jump_buffer)) { struct methodblock *mb; struct fieldblock *fb; CCinit(context); /* initialize heap; may throw */ context->object_info = MAKE_CLASSNAME_INFO(context, JAVAPKG "Object", &addr); *addr = classJavaLangObject; context->string_info = MAKE_CLASSNAME_INFO(context, JAVAPKG "String", &addr); *addr = classJavaLangString; context->throwable_info = MAKE_CLASSNAME_INFO(context, JAVAPKG "Throwable", &addr); *addr = classJavaLangThrowable; context->currentclass_info = MAKE_CLASSNAME_INFO_WITH_COPY(context, cbName(cb), &addr); *addr = cb; if (cbSuperclass(cb) != 0) { ClassClass *super = cbSuperclass(cb); context->superclass_info = MAKE_CLASSNAME_INFO_WITH_COPY(context, cbName(super), &addr); *addr = super; } else { context->superclass_info = 0; } /* Look at each method */ for (i = cbFieldsCount(cb), fb = cbFields(cb); --i >= 0; fb++) verify_field(context, fb); unhand(context->class)->new_class_entries = (char **)malloc((cbConstantPoolCount(context->class) * 3 + 100) * sizeof(char *)); unhand(context->class)->n_new_class_entries = 0; for (i = cbMethodsCount(cb), mb = cbMethods(cb); --i >= 0; mb++) verify_method(context, mb); unhand(context->class)->new_class_entries = (char **)realloc(unhand(context->class)->new_class_entries, unhand(context->class)->n_new_class_entries * sizeof(char *)); result = TRUE; } else { result = FALSE; } /* Cleanup */ Str2IDFree_Local(&context->classHash);#ifdef DEBUG_VERIFIER GlobalContext = 0;#endif if (context->superClasses != NULL) { sysFree(context->superClasses); } CCdestroy(context); /* destroy heap */ return result;}/*========================================================================= * FUNCTION: verify_field * OVERVIEW: Verifies the field block within each method of a class * file. * Invoked by verify_class_codes(). * Returns true if the field block is ok. * INTERFACE: * parameters: pointer to the context_type structure. * pointer to the field block * * returns: boolean type *=======================================================================*/static voidverify_field(context_type *context, struct fieldblock *fb){ int access_bits = fb->access; if ( ((access_bits & ACC_PUBLIC) != 0) && ((access_bits & (ACC_PRIVATE | ACC_PROTECTED)) != 0)) { if (verbose) { jio_fprintf(stderr, "VERIFIER ERROR %s.%s:\n", cbName(fieldclass(fb)), fb->name); jio_fprintf(stderr, "Inconsistent access bits."); } longjmp(context->jump_buffer, 1); } }/*========================================================================= * FUNCTION: get_type_name * OVERVIEW: Retrieves the type name information given the item type. * Used by get_type_code() which is invoked by verify_method() * to retrieve the type code for the stack map entries. * INTERFACE: * parameters: pointer to the context_type structure. * fullinfo_type: type * char *: buf * * returns: nothing *=======================================================================*/static void get_type_name(context_type *context, fullinfo_type type, char *buf){ int i; int indirection = GET_INDIRECTION(type); for (i = indirection; i-- > 0; ) *buf++ = '['; switch (GET_ITEM_TYPE(type)) { case ITEM_Integer: *buf++ = 'I'; break; case ITEM_Float: *buf++ = 'F'; break; case ITEM_Double: *buf++ = 'D'; break; case ITEM_Long: *buf++ = 'J'; break; case ITEM_Char: *buf++ = 'C'; break; case ITEM_Short: *buf++ = 'S'; break; case ITEM_Byte: *buf++ = 'B'; break; case ITEM_Boolean: *buf++ = 'Z'; break; case ITEM_Object: { unsigned short extra = GET_EXTRA_INFO(type); if (indirection) *buf++ = 'L';
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -