@@ -1,387 +1,387 @@ -/* javaclfl.c: Copyright (C) Codemist Ltd., 1996. */ - -#include -#include -#include "machine.h" -#include "tags.h" -#include "cslerror.h" -#include "externs.h" -#include "read.h" -#include "stream.h" -#include "arith.h" -#include "entries.h" -#include "javahost.h" -#include "javaglb.h" -/* #include "javatype.h" */ - -#define D_CLASSFILE 1 -#define D_CLASSFILEIO 2 -#define D_CLASSFILECODE 4 - -static int depth; - -static unsigned32 rd1(FILE *f) -{ unsigned32 x = getc(f); - if (debugging & D_CLASSFILEIO) jdebug("rd1 %d", x); - return x; -} - -static unsigned32 rd2(FILE *f) -{ unsigned32 x = getc(f); - x = x<<8 | getc(f); - if (debugging & D_CLASSFILEIO) jdebug("rd2 0x%.4x", x); - return x; -} - -static unsigned32 rd4(FILE *f) -{ unsigned32 x = getc(f); - x = x<<8 | getc(f); - x = x<<8 | getc(f); - x = x<<8 | getc(f); - if (debugging & D_CLASSFILEIO) jdebug("rd4 0x%.8x", x); - return x; -} - -static char *rd1string(FILE *f, unsigned32 n) -{ int i; - unsigned8 *p = (unsigned8 *)jmalloc((n+1) * sizeof(*p)); - for (i=0; iconstant_pool_count) - { Cp_Info *cpitem = &cf->constant_pool[cpx]; - if (cpitem->tag == CONSTANT_Utf8) return cpitem->u.utf8; - return ""; - } - return ""; -} - -static Attribute_Sort lookup_attribute_sort(char *utf8, unsigned32 len) -{ /* Should use 'len' not rely on rd1string() zero padding. */ - if (strcmp(utf8,"SourceFile") == 0) return ATT_SourceFile; - if (strcmp(utf8,"ConstantValue") == 0) return ATT_ConstantValue; - if (strcmp(utf8,"Code") == 0) return ATT_Code; - if (strcmp(utf8,"Exceptions") == 0) return ATT_Exceptions; - if (strcmp(utf8,"LineNumberTable") == 0) return ATT_LineNumberTable; - if (strcmp(utf8,"LocalVariableTable") == 0) return ATT_LocalVariableTable; - return ATT_unknown; -} - -static int rdAttribute_Info(FILE *f, ClassFile *cf, unsigned32 n, Attribute_Info **res); - -static int rdSourceFile_Attribute(FILE *f, ClassFile *cf, - SourceFile_Attribute **res) -{ SourceFile_Attribute *p = (SourceFile_Attribute *)jmalloc(sizeof(*p)); - depth++; - p->sourcefile_index = rd2(f); - if (debugging & D_CLASSFILE) - jdebug("%*sAttribute Sourcefile '%s'", - depth*2, "", cpname(p->sourcefile_index, cf)); - *res = p; - return (depth--, 0); -} - -static int rdConstantValue_Attribute(FILE *f, ClassFile *cf, - ConstantValue_Attribute **res) -{ ConstantValue_Attribute *p = (ConstantValue_Attribute *)jmalloc(sizeof(*p)); - depth++; - p->constantvalue_index = rd2(f); - if (debugging & D_CLASSFILE) - jdebug("%*sAttribute ConstantValue [%d]", - depth*2, "", p->constantvalue_index); - *res = p; - return (depth--, 0); -} - -static int rdCode_Attribute(FILE *f, ClassFile *cf, Code_Attribute **res) -{ Code_Attribute *p = (Code_Attribute *)jmalloc(sizeof(*p)); - unsigned32 i,n; - depth++; - p->max_stack = rd2(f); - p->max_locals = rd2(f); - p->code_length = n = rd4(f); - p->code = (unsigned8 *)jmalloc(n * sizeof(*p->code)); - for (i=0; icode[i] = rd1(f); - p->exception_table_length = n = rd2(f); - p->exception_table = (Exception_Info *)jmalloc(n * sizeof(*p->exception_table)); - for (i=0; iexception_table[i]; - q->start_pc = rd2(f); - q->end_pc = rd2(f); - q->handler_pc = rd2(f); - q->catch_type = rd2(f); - } - p->attributes_count = n = rd2(f); - if (debugging & D_CLASSFILE) - jdebug("%*sAttribute Code \ -(stack %d, locals %d, bytes %d, exceptions %d)", - depth*2, "", - p->max_stack, p->max_locals, - p->code_length, p->exception_table_length); - if (debugging & D_CLASSFILECODE) - javadecode(p->code, p->code_length, - cf->constant_pool, cf->constant_pool_count); - if (rdAttribute_Info(f, cf, n, &p[i].attributes)) return 5; - *res = p; - return (depth--, 0); -} - -static int rdExceptions_Attribute(FILE *f, ClassFile *cf, - Exceptions_Attribute **res) -{ Exceptions_Attribute *p = (Exceptions_Attribute *)jmalloc(sizeof(*p)); - unsigned32 i,n; - depth++; - p->number_of_exceptions = n = rd2(f); - p->exception_index_table = (unsigned16 *)jmalloc(n * sizeof(*p->exception_index_table)); - for (i=0; iexception_index_table[i] = rd2(f); - if (debugging & D_CLASSFILE) - jdebug("%*sAttribute Exceptions (entries %d)", - depth*2, "", p->number_of_exceptions); - *res = p; - return (depth--, 0); -} - -static int rdLineNumberTable_Attribute(FILE *f, ClassFile *cf, - LineNumberTable_Attribute **res) -{ LineNumberTable_Attribute *p = (LineNumberTable_Attribute *)jmalloc(sizeof(*p)); - unsigned32 i,n; - depth++; - p->line_number_table_length = n = rd2(f); - p->line_number_table = (LineNumber_Info *)jmalloc(n * sizeof(*p->line_number_table)); - for (i=0; iline_number_table[i]; - q->start_pc = rd2(f); - q->line_number = rd2(f); - } - if (debugging & D_CLASSFILE) - jdebug("%*sAttribute LineNumberTable (entries %d)", - depth*2, "", p->line_number_table_length); - *res = p; - return (depth--, 0); -} - -static int rdLocalVariableTable_Attribute(FILE *f, ClassFile *cf, - LocalVariableTable_Attribute **res) -{ LocalVariableTable_Attribute *p = (LocalVariableTable_Attribute *)jmalloc(sizeof(*p)); - unsigned32 i,n; - depth++; - p->local_variable_table_length = n = rd2(f); - p->local_variable_table = (LocalVariable_Info *)jmalloc(n * sizeof(*p->local_variable_table)); - for (i=0; ilocal_variable_table[i]; - q->start_pc = rd2(f); - q->length = rd2(f); - q->name_index = rd2(f); - q->signature_index = rd2(f); - q->slot = rd2(f); - } - if (debugging & D_CLASSFILE) - jdebug("%*sAttribute LocalVariableTable (entries %d)", - depth*2, "", p->local_variable_table_length); - *res = p; - return (depth--, 0); -} - -/* 'Attributes' occur more than once in a Classfile, hence they are */ -/* stored in *res (OK/NOK is return value), but reading Attributes */ -/* also requires cf to access the previously read Cp_Info. */ -static int rdAttribute_Info(FILE *f, ClassFile *cf, unsigned32 n, Attribute_Info **res) -{ Attribute_Info *p; - unsigned32 i; - if (n > 0xffff) return 1; - p = (Attribute_Info *)jmalloc(n * sizeof(*p)); - if (debugging & D_CLASSFILE) - jdebug("%*sAttributes_Info %d", depth*2, "", n); - for (i=0; iconstant_pool[cpx]; - if (cpitem->tag != CONSTANT_Utf8) return 3; - switch (p[i].sort = lookup_attribute_sort(cpitem->u.utf8, cpitem->len)) - { -case ATT_Code: - if (rdCode_Attribute(f, cf, &p[i].uattr.code)) return 6; - break; -case ATT_SourceFile: - if (rdSourceFile_Attribute(f, cf, &p[i].uattr.sourcefile)) return 6; - break; -case ATT_ConstantValue: - if (rdConstantValue_Attribute(f, cf, &p[i].uattr.constantvalue)) - return 6; - break; -case ATT_Exceptions: - if (rdExceptions_Attribute(f, cf, &p[i].uattr.exceptions)) - return 6; - break; -case ATT_LineNumberTable: - if (rdLineNumberTable_Attribute(f, cf, &p[i].uattr.linenumbertable)) - return 6; - break; -case ATT_LocalVariableTable: - if (rdLocalVariableTable_Attribute(f, cf, &p[i].uattr.localvariabletable)) - return 6; - break; -default: /* currently ignore other attributes */ - if (debugging & D_CLASSFILE) - jdebug("%*sAttribute '%s' unknown", (depth+1)*2, "", - cpitem->u.utf8); - while (len) rd1(f), len--; - } - } - *res = p; - return 0; -} - -static int rdCp_Info(FILE *f, ClassFile *cf, unsigned32 n) -{ Cp_Info *p; - unsigned32 i, nn; - depth++; - if (n > 0xffff) return 1; - if (debugging & D_CLASSFILE) jdebug("Cp_Info %d", n); - p = (Cp_Info *)jmalloc(n * sizeof(*p)); - /* Yes, the next line really is '1'! */ - for (i=1; i 0xffff) nn = 0; /* EOF */ - p[i].len = nn; p[i].u.utf8 = rd1string(f, nn); - break; -case CONSTANT_Unicode: if ((nn = rd2(f)) > 0xffff) nn = 0; /* EOF */ - p[i].len = nn; p[i].u.utf8 = rd2string(f, nn); - break; -case CONSTANT_NameAndType: - /* stuff signature_index into len */ - p[i].u.val = rd2(f); p[i].len = rd2(f); break; - } - cf->constant_pool = p; - return (depth--, 0); -} - -static int rdInterface_Info(FILE *f, ClassFile *cf, unsigned32 n) -{ unsigned16 *p; - unsigned32 i; - depth++; - if (n > 0xffff) return 1; - if (debugging & D_CLASSFILE) jdebug("Interface_Info %d", n); - p = (unsigned16 *)jmalloc(n * sizeof(*p)); - for (i=0; iinterfaces = p; - return (depth--, 0); -} - -static int rdField_Info(FILE *f, ClassFile *cf, unsigned32 n) -{ Field_Info *p; - unsigned32 i; - depth++; - if (n > 0xffff) return 1; - if (debugging & D_CLASSFILE) jdebug("Field_Info %d", n); - p = (Field_Info *)jmalloc(n * sizeof(*p)); - for (i=0; ifields = p; - return (depth--, 0); -} - -static int rdMethod_Info(FILE *f, ClassFile *cf, unsigned32 n) -{ Method_Info *p; - unsigned32 i; - depth++; - if (n > 0xffff) return 1; - if (debugging & D_CLASSFILE) jdebug("Method_Info %d", n); - p = (Method_Info *)jmalloc(n * sizeof(*p)); - for (i=0; imethods = p; - return (depth--, 0); -} - -ClassFile *rdClassFile(char *name) -{ FILE *f = fopen(name, "rb"); - ClassFile *cf = rdClassFILE1(f, name); - fclose(f); - return cf; -} - -ClassFile *rdClassFILE1(FILE *f, char *name) -{ - ClassFile *cf; - unsigned32 n; - depth = 0; - if (f == 0) - { jsyserr("cannot read '%s'", name); return 0; } - if (rd4(f) != JAVA_MAGIC) - { jsyserr("not class file '%s'", name); return 0; } - if ((n = rd2(f)) > JAVA_THIS_MIN) - jdebug("ClassFile '%s' wrong minor vsn %d", name, n); - if ((n = rd2(f)) != JAVA_THIS_MAJ) - jdebug("ClassFile '%s' wrong major vsn %d", name, n); - cf = (ClassFile *)jmalloc(sizeof(ClassFile)); - cf->constant_pool_count = n = rd2(f); - if (rdCp_Info(f, cf, n)) goto corrupt; - cf->access_flags = rd2(f); - cf->this_class = rd2(f); - cf->super_class = rd2(f); - cf->interfaces_count = n = rd2(f); - if (rdInterface_Info(f, cf, n)) goto corrupt; - cf->fields_count = n = rd2(f); - if (rdField_Info(f, cf, n)) goto corrupt; - cf->methods_count = n = rd2(f); - if (rdMethod_Info(f, cf, n)) goto corrupt; - cf->attributes_count = n = rd2(f); - if (rdAttribute_Info(f, cf, n, &cf->attributes)) goto corrupt; - if (rd1(f) != EOF) jdebug("junk at end of ClassFile '%s'", name); - return cf; -corrupt: - jsyserr("ClassFile '%s' corrupted", name); - return 0; -} +/* javaclfl.c: Copyright (C) Codemist Ltd., 1996. */ + +#include +#include +#include "machine.h" +#include "tags.h" +#include "cslerror.h" +#include "externs.h" +#include "read.h" +#include "stream.h" +#include "arith.h" +#include "entries.h" +#include "javahost.h" +#include "javaglb.h" +/* #include "javatype.h" */ + +#define D_CLASSFILE 1 +#define D_CLASSFILEIO 2 +#define D_CLASSFILECODE 4 + +static int depth; + +static unsigned32 rd1(FILE *f) +{ unsigned32 x = getc(f); + if (debugging & D_CLASSFILEIO) jdebug("rd1 %d", x); + return x; +} + +static unsigned32 rd2(FILE *f) +{ unsigned32 x = getc(f); + x = x<<8 | getc(f); + if (debugging & D_CLASSFILEIO) jdebug("rd2 0x%.4x", x); + return x; +} + +static unsigned32 rd4(FILE *f) +{ unsigned32 x = getc(f); + x = x<<8 | getc(f); + x = x<<8 | getc(f); + x = x<<8 | getc(f); + if (debugging & D_CLASSFILEIO) jdebug("rd4 0x%.8x", x); + return x; +} + +static char *rd1string(FILE *f, unsigned32 n) +{ int i; + unsigned8 *p = (unsigned8 *)jmalloc((n+1) * sizeof(*p)); + for (i=0; iconstant_pool_count) + { Cp_Info *cpitem = &cf->constant_pool[cpx]; + if (cpitem->tag == CONSTANT_Utf8) return cpitem->u.utf8; + return ""; + } + return ""; +} + +static Attribute_Sort lookup_attribute_sort(char *utf8, unsigned32 len) +{ /* Should use 'len' not rely on rd1string() zero padding. */ + if (strcmp(utf8,"SourceFile") == 0) return ATT_SourceFile; + if (strcmp(utf8,"ConstantValue") == 0) return ATT_ConstantValue; + if (strcmp(utf8,"Code") == 0) return ATT_Code; + if (strcmp(utf8,"Exceptions") == 0) return ATT_Exceptions; + if (strcmp(utf8,"LineNumberTable") == 0) return ATT_LineNumberTable; + if (strcmp(utf8,"LocalVariableTable") == 0) return ATT_LocalVariableTable; + return ATT_unknown; +} + +static int rdAttribute_Info(FILE *f, ClassFile *cf, unsigned32 n, Attribute_Info **res); + +static int rdSourceFile_Attribute(FILE *f, ClassFile *cf, + SourceFile_Attribute **res) +{ SourceFile_Attribute *p = (SourceFile_Attribute *)jmalloc(sizeof(*p)); + depth++; + p->sourcefile_index = rd2(f); + if (debugging & D_CLASSFILE) + jdebug("%*sAttribute Sourcefile '%s'", + depth*2, "", cpname(p->sourcefile_index, cf)); + *res = p; + return (depth--, 0); +} + +static int rdConstantValue_Attribute(FILE *f, ClassFile *cf, + ConstantValue_Attribute **res) +{ ConstantValue_Attribute *p = (ConstantValue_Attribute *)jmalloc(sizeof(*p)); + depth++; + p->constantvalue_index = rd2(f); + if (debugging & D_CLASSFILE) + jdebug("%*sAttribute ConstantValue [%d]", + depth*2, "", p->constantvalue_index); + *res = p; + return (depth--, 0); +} + +static int rdCode_Attribute(FILE *f, ClassFile *cf, Code_Attribute **res) +{ Code_Attribute *p = (Code_Attribute *)jmalloc(sizeof(*p)); + unsigned32 i,n; + depth++; + p->max_stack = rd2(f); + p->max_locals = rd2(f); + p->code_length = n = rd4(f); + p->code = (unsigned8 *)jmalloc(n * sizeof(*p->code)); + for (i=0; icode[i] = rd1(f); + p->exception_table_length = n = rd2(f); + p->exception_table = (Exception_Info *)jmalloc(n * sizeof(*p->exception_table)); + for (i=0; iexception_table[i]; + q->start_pc = rd2(f); + q->end_pc = rd2(f); + q->handler_pc = rd2(f); + q->catch_type = rd2(f); + } + p->attributes_count = n = rd2(f); + if (debugging & D_CLASSFILE) + jdebug("%*sAttribute Code \ +(stack %d, locals %d, bytes %d, exceptions %d)", + depth*2, "", + p->max_stack, p->max_locals, + p->code_length, p->exception_table_length); + if (debugging & D_CLASSFILECODE) + javadecode(p->code, p->code_length, + cf->constant_pool, cf->constant_pool_count); + if (rdAttribute_Info(f, cf, n, &p[i].attributes)) return 5; + *res = p; + return (depth--, 0); +} + +static int rdExceptions_Attribute(FILE *f, ClassFile *cf, + Exceptions_Attribute **res) +{ Exceptions_Attribute *p = (Exceptions_Attribute *)jmalloc(sizeof(*p)); + unsigned32 i,n; + depth++; + p->number_of_exceptions = n = rd2(f); + p->exception_index_table = (unsigned16 *)jmalloc(n * sizeof(*p->exception_index_table)); + for (i=0; iexception_index_table[i] = rd2(f); + if (debugging & D_CLASSFILE) + jdebug("%*sAttribute Exceptions (entries %d)", + depth*2, "", p->number_of_exceptions); + *res = p; + return (depth--, 0); +} + +static int rdLineNumberTable_Attribute(FILE *f, ClassFile *cf, + LineNumberTable_Attribute **res) +{ LineNumberTable_Attribute *p = (LineNumberTable_Attribute *)jmalloc(sizeof(*p)); + unsigned32 i,n; + depth++; + p->line_number_table_length = n = rd2(f); + p->line_number_table = (LineNumber_Info *)jmalloc(n * sizeof(*p->line_number_table)); + for (i=0; iline_number_table[i]; + q->start_pc = rd2(f); + q->line_number = rd2(f); + } + if (debugging & D_CLASSFILE) + jdebug("%*sAttribute LineNumberTable (entries %d)", + depth*2, "", p->line_number_table_length); + *res = p; + return (depth--, 0); +} + +static int rdLocalVariableTable_Attribute(FILE *f, ClassFile *cf, + LocalVariableTable_Attribute **res) +{ LocalVariableTable_Attribute *p = (LocalVariableTable_Attribute *)jmalloc(sizeof(*p)); + unsigned32 i,n; + depth++; + p->local_variable_table_length = n = rd2(f); + p->local_variable_table = (LocalVariable_Info *)jmalloc(n * sizeof(*p->local_variable_table)); + for (i=0; ilocal_variable_table[i]; + q->start_pc = rd2(f); + q->length = rd2(f); + q->name_index = rd2(f); + q->signature_index = rd2(f); + q->slot = rd2(f); + } + if (debugging & D_CLASSFILE) + jdebug("%*sAttribute LocalVariableTable (entries %d)", + depth*2, "", p->local_variable_table_length); + *res = p; + return (depth--, 0); +} + +/* 'Attributes' occur more than once in a Classfile, hence they are */ +/* stored in *res (OK/NOK is return value), but reading Attributes */ +/* also requires cf to access the previously read Cp_Info. */ +static int rdAttribute_Info(FILE *f, ClassFile *cf, unsigned32 n, Attribute_Info **res) +{ Attribute_Info *p; + unsigned32 i; + if (n > 0xffff) return 1; + p = (Attribute_Info *)jmalloc(n * sizeof(*p)); + if (debugging & D_CLASSFILE) + jdebug("%*sAttributes_Info %d", depth*2, "", n); + for (i=0; iconstant_pool[cpx]; + if (cpitem->tag != CONSTANT_Utf8) return 3; + switch (p[i].sort = lookup_attribute_sort(cpitem->u.utf8, cpitem->len)) + { +case ATT_Code: + if (rdCode_Attribute(f, cf, &p[i].uattr.code)) return 6; + break; +case ATT_SourceFile: + if (rdSourceFile_Attribute(f, cf, &p[i].uattr.sourcefile)) return 6; + break; +case ATT_ConstantValue: + if (rdConstantValue_Attribute(f, cf, &p[i].uattr.constantvalue)) + return 6; + break; +case ATT_Exceptions: + if (rdExceptions_Attribute(f, cf, &p[i].uattr.exceptions)) + return 6; + break; +case ATT_LineNumberTable: + if (rdLineNumberTable_Attribute(f, cf, &p[i].uattr.linenumbertable)) + return 6; + break; +case ATT_LocalVariableTable: + if (rdLocalVariableTable_Attribute(f, cf, &p[i].uattr.localvariabletable)) + return 6; + break; +default: /* currently ignore other attributes */ + if (debugging & D_CLASSFILE) + jdebug("%*sAttribute '%s' unknown", (depth+1)*2, "", + cpitem->u.utf8); + while (len) rd1(f), len--; + } + } + *res = p; + return 0; +} + +static int rdCp_Info(FILE *f, ClassFile *cf, unsigned32 n) +{ Cp_Info *p; + unsigned32 i, nn; + depth++; + if (n > 0xffff) return 1; + if (debugging & D_CLASSFILE) jdebug("Cp_Info %d", n); + p = (Cp_Info *)jmalloc(n * sizeof(*p)); + /* Yes, the next line really is '1'! */ + for (i=1; i 0xffff) nn = 0; /* EOF */ + p[i].len = nn; p[i].u.utf8 = rd1string(f, nn); + break; +case CONSTANT_Unicode: if ((nn = rd2(f)) > 0xffff) nn = 0; /* EOF */ + p[i].len = nn; p[i].u.utf8 = rd2string(f, nn); + break; +case CONSTANT_NameAndType: + /* stuff signature_index into len */ + p[i].u.val = rd2(f); p[i].len = rd2(f); break; + } + cf->constant_pool = p; + return (depth--, 0); +} + +static int rdInterface_Info(FILE *f, ClassFile *cf, unsigned32 n) +{ unsigned16 *p; + unsigned32 i; + depth++; + if (n > 0xffff) return 1; + if (debugging & D_CLASSFILE) jdebug("Interface_Info %d", n); + p = (unsigned16 *)jmalloc(n * sizeof(*p)); + for (i=0; iinterfaces = p; + return (depth--, 0); +} + +static int rdField_Info(FILE *f, ClassFile *cf, unsigned32 n) +{ Field_Info *p; + unsigned32 i; + depth++; + if (n > 0xffff) return 1; + if (debugging & D_CLASSFILE) jdebug("Field_Info %d", n); + p = (Field_Info *)jmalloc(n * sizeof(*p)); + for (i=0; ifields = p; + return (depth--, 0); +} + +static int rdMethod_Info(FILE *f, ClassFile *cf, unsigned32 n) +{ Method_Info *p; + unsigned32 i; + depth++; + if (n > 0xffff) return 1; + if (debugging & D_CLASSFILE) jdebug("Method_Info %d", n); + p = (Method_Info *)jmalloc(n * sizeof(*p)); + for (i=0; imethods = p; + return (depth--, 0); +} + +ClassFile *rdClassFile(char *name) +{ FILE *f = fopen(name, "rb"); + ClassFile *cf = rdClassFILE1(f, name); + fclose(f); + return cf; +} + +ClassFile *rdClassFILE1(FILE *f, char *name) +{ + ClassFile *cf; + unsigned32 n; + depth = 0; + if (f == 0) + { jsyserr("cannot read '%s'", name); return 0; } + if (rd4(f) != JAVA_MAGIC) + { jsyserr("not class file '%s'", name); return 0; } + if ((n = rd2(f)) > JAVA_THIS_MIN) + jdebug("ClassFile '%s' wrong minor vsn %d", name, n); + if ((n = rd2(f)) != JAVA_THIS_MAJ) + jdebug("ClassFile '%s' wrong major vsn %d", name, n); + cf = (ClassFile *)jmalloc(sizeof(ClassFile)); + cf->constant_pool_count = n = rd2(f); + if (rdCp_Info(f, cf, n)) goto corrupt; + cf->access_flags = rd2(f); + cf->this_class = rd2(f); + cf->super_class = rd2(f); + cf->interfaces_count = n = rd2(f); + if (rdInterface_Info(f, cf, n)) goto corrupt; + cf->fields_count = n = rd2(f); + if (rdField_Info(f, cf, n)) goto corrupt; + cf->methods_count = n = rd2(f); + if (rdMethod_Info(f, cf, n)) goto corrupt; + cf->attributes_count = n = rd2(f); + if (rdAttribute_Info(f, cf, n, &cf->attributes)) goto corrupt; + if (rd1(f) != EOF) jdebug("junk at end of ClassFile '%s'", name); + return cf; +corrupt: + jsyserr("ClassFile '%s' corrupted", name); + return 0; +}