verifyformat.c
来自「This is a resource based on j2me embedde」· C语言 代码 · 共 2,149 行 · 第 1/5 页
C
2,149 行
int nElements, int codeLength, int currSlot, int maxSlot){ int nSlot = 0; while (nElements-- > 0 ){ CVMUint32 tag = get1byte(context); CVMUint32 offset; switch (tag){ case JVM_STACKMAP_DOUBLE: case JVM_STACKMAP_LONG: /* these take 2 slots, so there's an extra increment of nSlot */ /* otherwise, there is not further info here */ nSlot += 1; break; case JVM_STACKMAP_TOP: case JVM_STACKMAP_INT: case JVM_STACKMAP_FLOAT: case JVM_STACKMAP_NULL: case JVM_STACKMAP_UNINIT_THIS: break; /* these have no further info */ case JVM_STACKMAP_OBJECT: /* Make sure the referenced constant pool entry * corresponds to an object type. */ offset = get2bytes(context); if (offset == 0 || offset > context->size->constants ){ CFerror(context, "Stackmap entry entry references" " outside constant pool"); } if (context->type_table[offset] != JVM_CONSTANT_Class){ CFerror(context, "Stackmap entry entry references" " wrong constant pool type"); } break; case JVM_STACKMAP_UNINIT_OBJECT: offset = get2bytes(context); if (offset >= codeLength){ CFerror(context, "Stackmap entry entry references" " beyond code length"); } break; default: CFerror(context, "illegal stackmap entry"); } nSlot += 1; } if (currSlot + nSlot > maxSlot) { CFerror(context, "Stackmap entries for too many stack slots"); } return nSlot;}static voidParseStackMapTable(CFcontext *context, CVMUint32 codeLength, CVMUint32 maxLocals, CVMUint32 maxStack){ CVMInt32 nEntries; CVMInt32 lastPC = -1; CVMUint32 length = get4bytes(context); int nLocalSlots = 0; int nStackSlots = 0; const unsigned char * endPtr = context->ptr + length; char * locals; int nLocals; /* * These asserts are here to remind us that the format of these * things changes for big methods. */ CVMassert(codeLength <= 65535); CVMassert(maxLocals <= 65535); CVMassert(maxStack <= 65535); locals = calloc(1, maxLocals); if (locals == NULL) { CFerror(context, "Out of memory"); }#if 0 /* Initialize locals from args */ /* The following code is just an example. We don't have an mb yet so we really need to parse the signature string. */{ CVMterseSigIterator sig; int typeSyllable; CVMtypeidGetTerseSignatureIterator(CVMmbNameAndTypeID(mb), &sig); nLocals = 0; if (!CVMmbIs(mb, STATIC)) { locals[nLocals++] = 1; } while ((typeSyllable=CVM_TERSE_ITER_NEXT(sig)) != CVM_TYPEID_ENDFUNC) { switch (typeSyllable) { case CVM_TYPEID_LONG: case CVM_TYPEID_DOUBLE: locals[nLocals++] = 2; break; default: locals[nLocals++] = 1; } }}#else /* We don't support code that rewrites the arguments, so start at 0 */ nLocals = 0;#endif nEntries = get2bytes(context); while (nEntries-- > 0) { int tag = get1byte(context); int frame_type = tag; int offset_delta; int thisPC; if (tag < 64) { /* 0 .. 63 SAME */ nStackSlots = 0; offset_delta = frame_type; thisPC = lastPC + offset_delta + 1; } else if (tag < 128) { /* 64 .. 127 SAME_LOCALS_1_STACK_ITEM */ offset_delta = frame_type - 64; thisPC = lastPC + offset_delta + 1; nStackSlots = ParseMapElements(context, 1, codeLength, 0, maxStack); } else if (tag == 255) { /* 255 FULL_FRAME */ int i, l, s; offset_delta = get2bytes(context); thisPC = lastPC + offset_delta + 1; l = get2bytes(context); nLocalSlots = 0; nLocals = 0; for (i = 0; i < l; ++i) { int slots = ParseMapElements(context, 1, codeLength, nLocalSlots, maxLocals); nLocalSlots += slots; locals[nLocals + i] = slots; } nLocals += l; CVMassert(nLocals <= maxLocals); s = get2bytes(context); nStackSlots = ParseMapElements(context, s, codeLength, 0, maxStack); } else if (tag >= 252) { /* 252 .. 254 APPEND */ int i; int k = frame_type - 251; offset_delta = get2bytes(context); thisPC = lastPC + offset_delta + 1; if (nLocals + k > maxLocals) { CFerror(context, "Stackmap entry too many locals "); } for (i = 0; i < k; ++i) { int slots = ParseMapElements(context, 1, codeLength, nLocalSlots, maxLocals); nLocalSlots += slots; locals[nLocals + i] = slots; } nLocals += k; nStackSlots = 0; CVMassert(nLocals <= maxLocals); } else if (tag == 251) { /* 251 SAME_FRAME_EXTENDED */ offset_delta = get2bytes(context); nStackSlots = 0; thisPC = lastPC + offset_delta + 1; } else if (tag >= 248) { /* 248 .. 250 CHOP */ int i; int k = 251 - frame_type; if (k > nLocals) { CFerror(context, "Stackmap entry args chopped!"); } for (i = 0; i < k; ++i) { nLocalSlots -= locals[--nLocals]; } offset_delta = get2bytes(context); nStackSlots = 0; thisPC = lastPC + offset_delta + 1; } else if (tag == 247) { /* 247 SAME_LOCALS_1_STACK_ITEM_EXTENDED */ offset_delta = get2bytes(context); thisPC = lastPC + offset_delta + 1; nStackSlots = ParseMapElements(context, 1, codeLength, 0, maxStack); } else { thisPC = -1; CFerror(context, "Stackmap entry unsupported tag value"); } if (thisPC >= codeLength){ CFerror(context, "Stackmap entry PC out of range"); } lastPC = thisPC; if (context->ptr > endPtr){ CFerror(context, "Stackmap info too long"); } } if (context->ptr != endPtr){ CFerror(context, "Stackmap info too short"); } free(locals);}static voidParseStackMap(CFcontext *context, CVMUint32 codeLength, CVMUint32 maxLocals, CVMUint32 maxStack){ CVMUint32 nEntries; CVMInt32 lastPC = -1; CVMUint32 length = get4bytes(context); const unsigned char * endPtr = context->ptr + length; /* * These asserts are here to remind us that the format of these * things changes for big methods. */ CVMassert(codeLength <= 65535); CVMassert(maxLocals <= 65535); CVMassert(maxStack <= 65535); nEntries = get2bytes(context); while (nEntries-- > 0){ int nLocalElements; int nStackElements; int thisPC; thisPC = get2bytes(context); if (thisPC <= lastPC){ CFerror(context, "Stackmap entry out of order"); } if (thisPC >= codeLength){ CFerror(context, "Stackmap entry PC out of range"); } lastPC = thisPC; nLocalElements = get2bytes(context); ParseMapElements(context, nLocalElements, codeLength, 0, maxLocals); nStackElements = get2bytes(context); ParseMapElements(context, nStackElements, codeLength, 0, maxStack); if (context->ptr > endPtr){ CFerror(context, "Stackmap info too long"); } } if (context->ptr != endPtr){ CFerror(context, "Stackmap info too short"); }}#endifstatic voidParseLineTable(CFcontext *context, unsigned long code_length){ unsigned long attribute_length = get4bytes(context); const unsigned char *end_ptr = context->ptr + attribute_length; unsigned long i, table_length; table_length = get2bytes(context); if (context->in_clinit) { context->size->clinit.lnum += table_length; } else { context->size->main.lnum += table_length; } for (i = 0; i < table_length; i++) { int pc = get2bytes(context); skip2bytes(context); /* skip line number */ if (pc >= code_length) CFerror(context, "Invalid pc in line number table"); } if (context->ptr != end_ptr) CFerror(context, "Line number table has wrong length"); return;} static voidParseLocalVars(CFcontext *context, unsigned long code_length){ unsigned long attribute_length = get4bytes(context); const unsigned char *end_ptr = context->ptr + attribute_length; unsigned long i, table_length; table_length = get2bytes(context); if (context->in_clinit) { context->size->clinit.lvar += table_length; } else { context->size->main.lvar += table_length; } for (i = 0; i < table_length; i++) { unsigned int pc0 = get2bytes(context); unsigned int length = get2bytes(context); unsigned int nameoff = get2bytes(context); unsigned int sigoff = get2bytes(context); unsigned long end_pc; utf_str *name, *sig; skip2bytes(context); /* skip slot */ /* Assign to a unsigned long to avoid overflow */ end_pc = (unsigned long)pc0 + (unsigned long)length; /* We do not check that pc0 indeed points to the * beginning of an instruction, or slot in fact holds * this variable. That would require changes in the byte * code verifier. */ if (pc0 >= code_length || end_pc > code_length) CFerror(context, "Invalid start_pc/length in local var table"); verify_constant_entry(context, nameoff, JVM_CONSTANT_Utf8, "Local variable name"); verify_constant_entry(context, sigoff, JVM_CONSTANT_Utf8, "Local variable signature"); name = context->constant_pool[nameoff].s; sig = context->constant_pool[sigoff].s; verify_legal_name(context, name, LegalVariable); verify_legal_field_signature(context, name, sig); } if (context->ptr != end_ptr) CFerror(context, "Local variables table has wrong length"); return;} static voidParseExceptions(CFcontext *context){ unsigned long attribute_length = get4bytes(context); const unsigned char *end_ptr = context->ptr + attribute_length; unsigned long nexceptions = get2bytes(context); int i; if (context->in_clinit) { context->size->clinit.excs += nexceptions; } else { context->size->main.excs += nexceptions; } for (i = 0; i < nexceptions; i++) { unsigned int index = get2bytes(context); verify_constant_entry(context, index, JVM_CONSTANT_Class, "Exception name"); } if (context->ptr != end_ptr) CFerror(context, "Exceptions attribute has wrong length");} static unsigned long get1byte(CFcontext *context){ const unsigned char *ptr = context->ptr; unsigned long value; if (context->end_ptr - ptr < 1) { CFerror(context, "Truncated class file"); } value = ptr[0]; (context->ptr) += 1; return value;}static unsigned long get2bytes(CFcontext *context){ const unsigned char *ptr = context->ptr; unsigned long value; if (context->end_ptr - ptr < 2) { CFerror(context, "Truncated class file"); } value = (ptr[0] << 8) + ptr[1]; /* * unsigned long is bigger than 2 byte on 64 bit platforms * therefore be sure to return only 2 significant bytes */#ifdef CVM_64 value &= 0x0ffff;#endif (context->ptr) += 2; return value;}static unsigned long get4bytes(CFcontext *context){ const unsigned char *ptr = context->ptr; unsigned long value; if (context->end_ptr - ptr < 4) { CFerror(context, "Truncated class file"); } value = (ptr[0] << 24) + (ptr[1] << 16) + (ptr[2] << 8) + ptr[3]; /* * unsigned long is bigger than 4 byte on 64 bit platforms * therefore be sure to return only 4 significant bytes */#ifdef CVM_64 value &= 0x0ffffffff;#endif (context->ptr) += 4; return value;}static utf_str *getAsciz(CFcontext *context) { cp_type *constant_pool = context->constant_pool; unsigned char *type_table = context->type_table; int nconstants = context->size->constants; int value = get2bytes(context); if ((value == 0) || (value >= nconstants) || (type_table[value] != JVM_CONSTANT_Utf8)) CFerror(context, "Illegal constant pool index"); return constant_pool[value].s;}static utf_str *getAscizFromCP(CFcontext *context, unsigned int value) { cp_type *constant_pool = context->constant_pool; unsigned char *type_table = context->type_table; int nconstants = context->size->constants; if ((value <= 0) || (value >= nconstants) || (type_table[value] != JVM_CONSTANT_Class)) CFerror(context, "Illegal constant pool index"); value = constant_pool[value].i; if ((value <= 0) || (value >= nconstants) || (type_table[value] != JVM_CONSTANT_Utf8)) CFerror(context, "Illegal constant pool index");
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?