1 /*
2 * @(#)check_class.c 1.6 02/09/27
3 *
4 * Copyright 1995-1998 by Sun Microsystems, Inc.,
5 * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
6 * All rights reserved.
7 *
8 * This software is the confidential and proprietary information
9 * of Sun Microsystems, Inc. ("Confidential Information"). You
10 * shall not disclose such Confidential Information and shall use
11 * it only in accordance with the terms of the license agreement
12 * you entered into with Sun.
13 * Use is subject to license terms.
14 */
16 /*=========================================================================
17 * SYSTEM: Verifier
18 * SUBSYSTEM: Verifies ClassClass structure.
19 * FILE: check_class.c
20 * OVERVIEW: Code for verifying the ClassClass structure for internal
21 * consistency.
22 * AUTHOR: Sheng Liang, Consumer & Embedded
23 * Initial implementation based on the Classic VM Verifier.
24 * Edited by Tasneem Sayeed, Java Consumer Technologies
25 *=======================================================================*/
27 /*=========================================================================
28 * Include files
29 *=======================================================================*/
31 #include <ctype.h>
38 /*=========================================================================
39 * Globals and extern declarations
40 *=======================================================================*/
44 //static bool_t verify_constant_pool(ClassClass *cb);
46 //static bool_t is_legal_fieldname(ClassClass *cb, char *name, int type);
47 //static bool_t is_legal_method_signature(ClassClass *cb, char *name, char *signature);
48 //static bool_t is_legal_field_signature(ClassClass *cb, char *name, char *signature);
50 //static char *skip_over_fieldname(char *name, bool_t slash_okay);
51 //static char *skip_over_field_signature(char *name, bool_t void_okay);
53 //static void CCerror (ClassClass *cb, char *format, ...);
56 /* Argument for is_legal_fieldname */
60 /*=========================================================================
61 * FUNCTION: VerifyClass
62 * OVERVIEW: Verifies a class given a pointer to the ClassClass struct.
63 * Returns true if the class is ok.
64 * INTERFACE:
65 * parameters: pointer to the ClassClass structure.
66 *
67 * returns: boolean type
68 *=======================================================================*/
69 bool_t
71 {
74 /*
75 bool_t result = TRUE;
76 struct methodblock *mb;
77 struct fieldblock *fb;
78 int i;
79 if (!verify_constant_pool(cb))
80 return FALSE;
81 /* Make sure all the method names and signatures are okay
82 for (i = cbMethodsCount(cb), mb = cbMethods(cb); --i >= 0; mb++) {
83 char *name = mb->fb.name;
84 char *signature = mb->fb.signature;
85 if (! (is_legal_fieldname(cb, name, LegalMethod) &&
86 is_legal_method_signature(cb, name, signature)))
87 result = FALSE;
88 }
89 /* Make sure all the field names and signatures are okay
90 for (i = cbFieldsCount(cb), fb = cbFields(cb); --i >= 0; fb++) {
91 if (! (is_legal_fieldname(cb, fb->name, LegalField) &&
92 is_legal_field_signature(cb, fb->name, fb->signature)))
93 result = FALSE;
94 }
95 /* Make sure we are not overriding any final methods or classes
96 if (cbIsInterface(cb)) {
97 struct methodblock *mb;
98 if ((cbSuperclass(cb) == NULL) ||
99 (cbSuperclass(cb) != classJavaLangObject)) {
100 // CCerror(cb, "Interface %s has bad superclass", cbName(cb));
101 result = FALSE;
102 }
103 for (i = cbMethodsCount(cb), mb = cbMethods(cb); --i >= 0; mb++) {
104 if (mb->fb.access & ACC_STATIC) {
105 if (mb->fb.name[0] != '<') {
106 /* Only internal methods can be static
107 // CCerror(cb, "Illegal static method %s in interface %s",
108 // mb->fb.name, cbName(cb));
109 result = FALSE;
110 }
111 }
112 }
113 } else if (cbSuperclass(cb)) {
114 ClassClass *super_cb;
115 unsigned bitvector_size = (unsigned)(cbMethodTableSize(cb) + 31) >> 5;
116 long *bitvector = sysCalloc(bitvector_size, sizeof(long));
117 for (super_cb = cbSuperclass(cb); ; super_cb = cbSuperclass(super_cb)) {
118 if (cbAccess(super_cb) & ACC_FINAL) {
119 // CCerror(cb, "Class %s is subclass of final class %s",
120 // cbName(cb), cbName(super_cb));
121 result = FALSE;
122 }
123 mb = cbMethods(super_cb);
124 for (i = cbMethodsCount(super_cb); --i >= 0; mb++) {
125 if (mb->fb.access & ACC_FINAL) {
126 unsigned offset = mb->fb.u.offset;
127 bitvector[offset >> 5] |= (1 << (offset & 0x1F));
128 }
129 }
130 if (cbSuperclass(super_cb) == NULL) break;
131 }
132 for (i = cbMethodsCount(cb), mb = cbMethods(cb); --i >= 0; mb++) {
133 unsigned offset = mb->fb.u.offset;
134 if ((offset > 0)
135 && bitvector[offset >> 5] & (1 << (offset & 0x1F))) {
136 // CCerror(cb, "Class %s overrides final method %s.%s",
137 // cbName(cb), mb->fb.name, mb->fb.signature);
138 result = FALSE;
139 }
140 }
141 sysFree(bitvector);
142 } else if (cb != classJavaLangObject) {
143 // CCerror(cb, "Class %s does not have superclass", cbName(cb));
144 result = FALSE;
145 }
147 if (result)
148 result = verify_class_codes(cb);
149 return result;*/
150 }
153 /*=========================================================================
154 * FUNCTION: verify_constant_pool
155 * OVERVIEW: Verifies the constant pool given a pointer to the
156 * ClassClass structure.
157 * Makes two quick passes over the constant pool. The first
158 * pass ensures that everything is of the right type.
159 * Returns true if the constant pool is ok.
160 * INTERFACE:
161 * parameters: pointer to the ClassClass structure.
162 *
163 * returns: boolean type
164 *=======================================================================*/
165 /*
166 static bool_t
167 verify_constant_pool(ClassClass *cb)
168 {
169 union cp_item_type *cp = cbConstantPool(cb);
170 long cp_count = cbConstantPoolCount(cb);
171 unsigned char *type_table;
172 int i, type;
174 const int utf8_resolved = (CONSTANT_Utf8 | CONSTANT_POOL_ENTRY_RESOLVED);
176 if (cp_count == 0) /* Primitive classes
177 return TRUE;
178 type_table = cp[CONSTANT_POOL_TYPE_TABLE_INDEX].type;
179 /* Let's make two quick passes over the constant pool. The first one
180 * checks that everything is of the right type.
181 for (i = 1; i < cp_count; i++) {
182 switch(type = type_table[i]) {
183 case CONSTANT_String:
184 case CONSTANT_Class: {
185 int index = cp[i].i;
186 if ( (index < 1)
187 || (index >= cp_count)
188 || (type_table[index] != utf8_resolved)) {
189 // CCerror(cb, "Bad index in constant pool #%d", i);
190 return FALSE;
191 }
192 break;
193 }
195 case CONSTANT_String | CONSTANT_POOL_ENTRY_RESOLVED:
196 /* This can only happen if a string is the "initial" value of
197 * some final static String. We assume that the checking has
198 * already been done.
200 break;
202 case CONSTANT_Fieldref:
203 case CONSTANT_Methodref:
204 case CONSTANT_InterfaceMethodref:
205 case CONSTANT_NameAndType: {
206 unsigned index = (unsigned)(cp[i].i);
207 int key1 = index >> 16;
208 int key2 = index & 0xFFFF;
209 if (key1 < 1 || key1 >= cp_count
210 || key2 < 1 || key2 >= cp_count) {
211 // CCerror(cb, "Bad index in constant pool #%d", i);
212 return FALSE;
213 }
214 if (type == CONSTANT_NameAndType) {
215 if ( (type_table[key1] != utf8_resolved)
216 || (type_table[key2] != utf8_resolved)) {
217 // CCerror(cb, "Bad index in constant pool.");
218 return FALSE;
219 }
220 } else {
221 if ( ((type_table[key1] & CONSTANT_POOL_ENTRY_TYPEMASK)
222 != CONSTANT_Class)
223 || ((type_table[key2] != CONSTANT_NameAndType))) {
224 // CCerror(cb, "Bad index in constant pool #%d", i);
225 return FALSE;
226 }
227 }
228 break;
229 }
231 case CONSTANT_Fieldref | CONSTANT_POOL_ENTRY_RESOLVED:
232 case CONSTANT_Methodref | CONSTANT_POOL_ENTRY_RESOLVED:
233 case CONSTANT_InterfaceMethodref | CONSTANT_POOL_ENTRY_RESOLVED:
234 case CONSTANT_NameAndType | CONSTANT_POOL_ENTRY_RESOLVED:
235 // CCerror(cb, "Improperly resolved constant pool #%d", i);
236 return FALSE;
239 case CONSTANT_Class | CONSTANT_POOL_ENTRY_RESOLVED:
240 case CONSTANT_Utf8 | CONSTANT_POOL_ENTRY_RESOLVED:
241 case CONSTANT_Integer | CONSTANT_POOL_ENTRY_RESOLVED:
242 case CONSTANT_Float | CONSTANT_POOL_ENTRY_RESOLVED:
243 break;
245 case CONSTANT_Long | CONSTANT_POOL_ENTRY_RESOLVED:
246 case CONSTANT_Double | CONSTANT_POOL_ENTRY_RESOLVED:
247 if ((i + 1 >= cp_count) ||
248 (type_table[i + 1] != CONSTANT_POOL_ENTRY_RESOLVED)) {
249 // CCerror(cb, "Improper constant pool long/double #%d", i);
250 return FALSE;
251 } else {
252 i++;
253 break;
254 }
256 case CONSTANT_Integer:
257 case CONSTANT_Float:
258 case CONSTANT_Long:
259 case CONSTANT_Double:
260 case CONSTANT_Utf8:
261 // CCerror(cb, "Improperly unresolved constant pool #%d", i);
262 return FALSE;
265 default:
266 // CCerror(cb, "Illegal constant pool type at #%d", i);
267 return FALSE;
270 }
271 }
272 for (i = 1; i < cp_count; i++) {
273 switch(type = type_table[i]) {
274 case CONSTANT_Class: {
275 int index = cp[i].i;
276 if (!is_legal_fieldname(cb, cp[index].cp, LegalClass))
277 return FALSE;
278 break;
279 }
281 case CONSTANT_Fieldref:
282 case CONSTANT_Methodref:
283 case CONSTANT_InterfaceMethodref: {
284 unsigned index = (unsigned)(cp[i].i);
285 int name_type_index = index & 0xFFFF;
286 int name_type_key = cp[name_type_index].i;
287 int name_index = name_type_key >> 16;
288 int signature_index = name_type_key & 0xFFFF;
289 char *name = cp[name_index].cp;
290 char *signature = cp[signature_index].cp;
292 if (type == CONSTANT_Fieldref) {
293 if (! (is_legal_fieldname(cb, name, LegalField) &&
294 is_legal_field_signature(cb, name, signature)))
295 return FALSE;
296 } else {
297 if (! (is_legal_fieldname(cb, name, LegalMethod) &&
298 is_legal_method_signature(cb, name, signature)))
299 return FALSE;
300 }
301 break;
302 }
303 }
304 }
305 return TRUE;
306 }
307 */
309 /*=========================================================================
310 * FUNCTION: is_legal_fieldname
311 * OVERVIEW: Returns true if the given name within the given ClassClass
312 * structure consists of a legal fieldname or a classname
313 * if the third argument is LegalClass.
314 * INTERFACE:
315 * parameters: pointer to the ClassClass structure.
316 * char*: legal field name or a classname
317 * int: type of name (class or field name)
318 *
319 * returns: boolean type
320 *=======================================================================*/
321 #if 0
322 static bool_t
324 {
325 bool_t result;
336 }
338 }
343 // CCerror(cb, "Illegal %s name \"%s\"", thing, name);
348 }
349 }
352 /*=========================================================================
353 * FUNCTION: is_legal_field_signature
354 * OVERVIEW: Returns true if the entire given string within the given
355 * ClassClass structure consists of a legal field signature.
356 * INTERFACE:
357 * parameters: pointer to the ClassClass structure.
358 * char*: field name
359 * char*: field signature
360 *
361 * returns: boolean type
362 *=======================================================================*/
363 static bool_t
365 {
370 // CCerror(cb, "Field \"%s\" has illegal signature \"%s\"",
371 // fieldname, signature);
373 }
374 }
377 /*=========================================================================
378 * FUNCTION: is_legal_method_signature
379 * OVERVIEW: Returns true if the entire given string within the given
380 * ClassClass structure consists of a legal method signature.
381 * INTERFACE:
382 * parameters: pointer to the ClassClass structure.
383 * char*: method name
384 * char*: method signature
385 *
386 * returns: boolean type
387 *=======================================================================*/
388 static bool_t
390 {
393 /* The first character must be a '(' */
395 /* Skip over however many legal field signatures there are */
398 /* The first non-signature thing better be a ')' */
401 /* All internal methods must return void */
405 /* Now, we better just have a return value. */
409 }
410 }
411 }
412 // CCerror(cb, "Method \"%s\" has illegal signature \"%s\"",
413 // methodname, signature);
415 }
417 #endif
419 #if 0
421 /*=========================================================================
422 * Automatic code generation tables
423 *=======================================================================*/
424 /* The following tables and code generated using: */
425 /* java GenerateCharacter -verbose -c -identifiers -spec UnicodeData-2.1.2.txt -template check_class.c.template -o check_class.c 8 4 4 */
426 /* The X table has 256 entries for a total of 256 bytes. */
461 };
463 /* The Y table has 496 entries for a total of 496 bytes. */
528 };
530 /* The A table has 2208 entries for a total of 552 bytes. */
671 };
673 /* In all, the character property tables require 1304 bytes. */
675 /*
676 * This code mirrors Character.isJavaIdentifierStart. It determines whether
677 * the specified character is a legal start of a Java identifier as per JLS.
678 *
679 * The parameter ch is the character to be tested; return 1 if the
680 * character is a letter, 0 otherwise.
681 */
682 #define isJavaIdentifierStart(ch) (((A[Y[(X[ch>>8]<<4)|((ch>>4)&0xF)]]>>((ch&0xF)<<1))&3) & 0x2)
684 /*
685 * This code mirrors Character.isJavaIdentifierPart. It determines whether
686 * the specified character is a legal part of a Java identifier as per JLS.
687 *
688 * The parameter ch is the character to be tested; return 1 if the
689 * character is a digit, 0 otherwise.
690 */
691 #define isJavaIdentifierPart(ch) (((A[Y[(X[ch>>8]<<4)|((ch>>4)&0xF)]]>>((ch&0xF)<<1))&3) & 0x1)
694 /*=========================================================================
695 * FUNCTION: skip_over_fieldname
696 * OVERVIEW: Skips over the longest part of the string that could be
697 * taken as a fieldname given a pointer to a string.
698 * Allows '/' if slash_okay parameter is true.
699 * Returns a pointer to just past the fieldname.
700 * Returns NULL if no fieldname is found, or in the case of
701 * slash_okay being TRUE, we may see consecutive slashes
702 * (meaning that we were looking for a qualified path, but
703 * found something that was badly-formed.)
704 * INTERFACE:
705 * parameters: char*: name
706 * boolean: slash_okay
707 *
708 * returns: char* field name or NULL
709 *=======================================================================*/
712 {
713 bool_t first;
726 }
729 }
730 }
731 }
734 /*=========================================================================
735 * FUNCTION: skip_over_field_signature
736 * OVERVIEW: Skips over the longest part of the string that could be
737 * taken as a field signature given a pointer to a string.
738 * Allows "void" if void_okay parameter is true.
739 * Returns a pointer to just past the signature.
740 * Returns NULL if no legal signature is found.
741 * INTERFACE:
742 * parameters: char*: name
743 * boolean: void_okay
744 *
745 * returns: char* field signature or NULL
746 *=======================================================================*/
749 {
754 /* FALL THROUGH */
768 /* Skip over the classname, if one is there. */
770 /* The next character better be a semicolon. */
773 }
775 }
778 /* The rest of what's there better be a legal signature. */
779 name++;
785 }
786 }
787 }
790 /*=========================================================================
791 * FUNCTION: CCerror
792 * OVERVIEW: Handles formating errors found during class file
793 * verification.
794 * INTERFACE:
795 * parameters: pointer to the ClassClass structure.
796 * char *: format
797 *
798 * returns: nothing
799 *=======================================================================*/
800 static void
802 {
805 // jio_fprintf(stderr, "VERIFIER CLASS ERROR %s:\n", cbName(cb));
809 // jio_fprintf(stderr, "\n");
810 }
811 }
814 /*=========================================================================
815 * FUNCTION: IsLegalClassname
816 * OVERVIEW: Determines if the specified name is a legal UTF name for
817 * a class name.
818 * Note that this routine is intended for external use and
819 * expects the internal form of qualified classes
820 * (i.e. the dots should have been replaced by slashes.)
821 * INTERFACE:
822 * parameters: char*: name
823 * boolean: allowArrayClass
824 *
825 * returns: boolean type
826 *=======================================================================*/
828 {
834 /* Everything that's left better be a field signature */
836 }
838 /* skip over the fieldname. Slashes are okay */
840 }
842 }
844 #endif