📄 check_class.c
字号:
/* * @(#)check_class.c 1.6 02/09/27 * * Copyright 1995-1998 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 ClassClass structure. * FILE: check_class.c * OVERVIEW: Code for verifying the ClassClass structure for internal * consistency. * AUTHOR: Sheng Liang, Consumer & Embedded * Initial implementation based on the Classic VM Verifier. * Edited by Tasneem Sayeed, Java Consumer Technologies *=======================================================================*//*========================================================================= * Include files *=======================================================================*/#include <ctype.h>#include <oobj.h>#include <utf.h>#include <tree.h>#include <sys_api.h>/*========================================================================= * Globals and extern declarations *=======================================================================*/extern bool_t verify_class_codes(ClassClass *cb);static bool_t verify_constant_pool(ClassClass *cb);static bool_t is_legal_fieldname(ClassClass *cb, char *name, int type);static bool_t is_legal_method_signature(ClassClass *cb, char *name, char *signature);static bool_t is_legal_field_signature(ClassClass *cb, char *name, char *signature);static char *skip_over_fieldname(char *name, bool_t slash_okay);static char *skip_over_field_signature(char *name, bool_t void_okay);static void CCerror (ClassClass *cb, char *format, ...);/* Argument for is_legal_fieldname */enum { LegalClass, LegalField, LegalMethod };/*========================================================================= * FUNCTION: VerifyClass * OVERVIEW: Verifies a class given a pointer to the ClassClass struct. * Returns true if the class is ok. * INTERFACE: * parameters: pointer to the ClassClass structure. * * returns: boolean type *=======================================================================*/bool_tVerifyClass(ClassClass *cb){ bool_t result = TRUE; struct methodblock *mb; struct fieldblock *fb; int i; if (!verify_constant_pool(cb)) return FALSE; /* Make sure all the method names and signatures are okay */ for (i = cbMethodsCount(cb), mb = cbMethods(cb); --i >= 0; mb++) { char *name = mb->fb.name; char *signature = mb->fb.signature; if (! (is_legal_fieldname(cb, name, LegalMethod) && is_legal_method_signature(cb, name, signature))) result = FALSE; } /* Make sure all the field names and signatures are okay */ for (i = cbFieldsCount(cb), fb = cbFields(cb); --i >= 0; fb++) { if (! (is_legal_fieldname(cb, fb->name, LegalField) && is_legal_field_signature(cb, fb->name, fb->signature))) result = FALSE; } /* Make sure we are not overriding any final methods or classes*/ if (cbIsInterface(cb)) { struct methodblock *mb; if ((cbSuperclass(cb) == NULL) || (cbSuperclass(cb) != classJavaLangObject)) { CCerror(cb, "Interface %s has bad superclass", cbName(cb)); result = FALSE; } for (i = cbMethodsCount(cb), mb = cbMethods(cb); --i >= 0; mb++) { if (mb->fb.access & ACC_STATIC) { if (mb->fb.name[0] != '<') { /* Only internal methods can be static */ CCerror(cb, "Illegal static method %s in interface %s", mb->fb.name, cbName(cb)); result = FALSE; } } } } else if (cbSuperclass(cb)) { ClassClass *super_cb; unsigned bitvector_size = (unsigned)(cbMethodTableSize(cb) + 31) >> 5; long *bitvector = sysCalloc(bitvector_size, sizeof(long)); for (super_cb = cbSuperclass(cb); ; super_cb = cbSuperclass(super_cb)) { if (cbAccess(super_cb) & ACC_FINAL) { CCerror(cb, "Class %s is subclass of final class %s", cbName(cb), cbName(super_cb)); result = FALSE; } mb = cbMethods(super_cb); for (i = cbMethodsCount(super_cb); --i >= 0; mb++) { if (mb->fb.access & ACC_FINAL) { unsigned offset = mb->fb.u.offset; bitvector[offset >> 5] |= (1 << (offset & 0x1F)); } } if (cbSuperclass(super_cb) == NULL) break; } for (i = cbMethodsCount(cb), mb = cbMethods(cb); --i >= 0; mb++) { unsigned offset = mb->fb.u.offset; if ((offset > 0) && bitvector[offset >> 5] & (1 << (offset & 0x1F))) { CCerror(cb, "Class %s overrides final method %s.%s", cbName(cb), mb->fb.name, mb->fb.signature); result = FALSE; } } sysFree(bitvector); } else if (cb != classJavaLangObject) { CCerror(cb, "Class %s does not have superclass", cbName(cb)); result = FALSE; } if (result) result = verify_class_codes(cb); return result;}/*========================================================================= * FUNCTION: verify_constant_pool * OVERVIEW: Verifies the constant pool given a pointer to the * ClassClass structure. * Makes two quick passes over the constant pool. The first * pass ensures that everything is of the right type. * Returns true if the constant pool is ok. * INTERFACE: * parameters: pointer to the ClassClass structure. * * returns: boolean type *=======================================================================*/static bool_tverify_constant_pool(ClassClass *cb){ union cp_item_type *cp = cbConstantPool(cb); long cp_count = cbConstantPoolCount(cb); unsigned char *type_table; int i, type; const int utf8_resolved = (CONSTANT_Utf8 | CONSTANT_POOL_ENTRY_RESOLVED); if (cp_count == 0) /* Primitive classes */ return TRUE; type_table = cp[CONSTANT_POOL_TYPE_TABLE_INDEX].type; /* Let's make two quick passes over the constant pool. The first one * checks that everything is of the right type. */ for (i = 1; i < cp_count; i++) { switch(type = type_table[i]) { case CONSTANT_String: case CONSTANT_Class: { int index = cp[i].i; if ( (index < 1) || (index >= cp_count) || (type_table[index] != utf8_resolved)) { CCerror(cb, "Bad index in constant pool #%d", i); return FALSE; } break; } case CONSTANT_String | CONSTANT_POOL_ENTRY_RESOLVED: /* This can only happen if a string is the "initial" value of * some final static String. We assume that the checking has * already been done. */ break; case CONSTANT_Fieldref: case CONSTANT_Methodref: case CONSTANT_InterfaceMethodref: case CONSTANT_NameAndType: { unsigned index = (unsigned)(cp[i].i); int key1 = index >> 16; int key2 = index & 0xFFFF; if (key1 < 1 || key1 >= cp_count || key2 < 1 || key2 >= cp_count) { CCerror(cb, "Bad index in constant pool #%d", i); return FALSE; } if (type == CONSTANT_NameAndType) { if ( (type_table[key1] != utf8_resolved) || (type_table[key2] != utf8_resolved)) { CCerror(cb, "Bad index in constant pool."); return FALSE; } } else { if ( ((type_table[key1] & CONSTANT_POOL_ENTRY_TYPEMASK) != CONSTANT_Class) || ((type_table[key2] != CONSTANT_NameAndType))) { CCerror(cb, "Bad index in constant pool #%d", i); return FALSE; } } break; } case CONSTANT_Fieldref | CONSTANT_POOL_ENTRY_RESOLVED: case CONSTANT_Methodref | CONSTANT_POOL_ENTRY_RESOLVED: case CONSTANT_InterfaceMethodref | CONSTANT_POOL_ENTRY_RESOLVED: case CONSTANT_NameAndType | CONSTANT_POOL_ENTRY_RESOLVED: CCerror(cb, "Improperly resolved constant pool #%d", i); return FALSE; case CONSTANT_Class | CONSTANT_POOL_ENTRY_RESOLVED: case CONSTANT_Utf8 | CONSTANT_POOL_ENTRY_RESOLVED: case CONSTANT_Integer | CONSTANT_POOL_ENTRY_RESOLVED: case CONSTANT_Float | CONSTANT_POOL_ENTRY_RESOLVED: break; case CONSTANT_Long | CONSTANT_POOL_ENTRY_RESOLVED: case CONSTANT_Double | CONSTANT_POOL_ENTRY_RESOLVED: if ((i + 1 >= cp_count) || (type_table[i + 1] != CONSTANT_POOL_ENTRY_RESOLVED)) { CCerror(cb, "Improper constant pool long/double #%d", i); return FALSE; } else { i++; break; } case CONSTANT_Integer: case CONSTANT_Float: case CONSTANT_Long: case CONSTANT_Double: case CONSTANT_Utf8: CCerror(cb, "Improperly unresolved constant pool #%d", i); return FALSE; default: CCerror(cb, "Illegal constant pool type at #%d", i); return FALSE; } } for (i = 1; i < cp_count; i++) { switch(type = type_table[i]) { case CONSTANT_Class: { int index = cp[i].i; if (!is_legal_fieldname(cb, cp[index].cp, LegalClass)) return FALSE; break; } case CONSTANT_Fieldref: case CONSTANT_Methodref: case CONSTANT_InterfaceMethodref: { unsigned index = (unsigned)(cp[i].i); int name_type_index = index & 0xFFFF; int name_type_key = cp[name_type_index].i; int name_index = name_type_key >> 16; int signature_index = name_type_key & 0xFFFF; char *name = cp[name_index].cp; char *signature = cp[signature_index].cp; if (type == CONSTANT_Fieldref) { if (! (is_legal_fieldname(cb, name, LegalField) && is_legal_field_signature(cb, name, signature))) return FALSE; } else { if (! (is_legal_fieldname(cb, name, LegalMethod) && is_legal_method_signature(cb, name, signature))) return FALSE; } break; } } } return TRUE;} /*========================================================================= * FUNCTION: is_legal_fieldname * OVERVIEW: Returns true if the given name within the given ClassClass * structure consists of a legal fieldname or a classname * if the third argument is LegalClass. * INTERFACE: * parameters: pointer to the ClassClass structure. * char*: legal field name or a classname * int: type of name (class or field name) * * returns: boolean type *=======================================================================*/static bool_t is_legal_fieldname(ClassClass *cb, char *name, int type){ bool_t result; if (name[0] == '<') { result = (type == LegalMethod) && ((strcmp(name, "<init>") == 0) || (strcmp(name, "<clinit>") == 0)); } else { char *p; if (type == LegalClass && name[0] == SIGNATURE_ARRAY) { p = skip_over_field_signature(name, FALSE); } else { p = skip_over_fieldname(name, type == LegalClass); } result = (p != 0 && p[0] == '\0'); } if (!result) { char *thing = (type == LegalField) ? "Field" : (type == LegalMethod) ? "Method" : "Class"; CCerror(cb, "Illegal %s name \"%s\"", thing, name); return FALSE; } else { return TRUE; }}/*========================================================================= * FUNCTION: is_legal_field_signature * OVERVIEW: Returns true if the entire given string within the given * ClassClass structure consists of a legal field signature. * INTERFACE: * parameters: pointer to the ClassClass structure. * char*: field name * char*: field signature * * returns: boolean type *=======================================================================*/static bool_t is_legal_field_signature(ClassClass *cb, char *fieldname, char *signature) { char *p = skip_over_field_signature(signature, FALSE); if (p != 0 && p[0] == '\0') { return TRUE; } else { CCerror(cb, "Field \"%s\" has illegal signature \"%s\"", fieldname, signature); return FALSE; }}/*========================================================================= * FUNCTION: is_legal_method_signature * OVERVIEW: Returns true if the entire given string within the given * ClassClass structure consists of a legal method signature. * INTERFACE: * parameters: pointer to the ClassClass structure. * char*: method name * char*: method signature * * returns: boolean type *=======================================================================*/static bool_t is_legal_method_signature(ClassClass *cb, char *methodname, char *signature){ char *p = signature; char *next_p; /* The first character must be a '(' */ if (*p++ == SIGNATURE_FUNC) { /* Skip over however many legal field signatures there are */ while ((next_p = skip_over_field_signature(p, FALSE)) != 0) p = next_p; /* The first non-signature thing better be a ')' */ if (*p++ == SIGNATURE_ENDFUNC) { if (methodname[0] == '<') { /* All internal methods must return void */ if ((p[0] == SIGNATURE_VOID) && (p[1] == '\0')) return TRUE; } else { /* Now, we better just have a return value. */ next_p = skip_over_field_signature(p, TRUE); if (next_p && next_p[0] == '\0') return TRUE; } } } CCerror(cb, "Method \"%s\" has illegal signature \"%s\"", methodname, signature); return FALSE;} /*========================================================================= * Automatic code generation tables *=======================================================================*/ /* The following tables and code generated using: */ /* java GenerateCharacter -verbose -c -identifiers -spec UnicodeData-2.1.2.txt -template check_class.c.template -o check_class.c 8 4 4 */ /* The X table has 256 entries for a total of 256 bytes. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -