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 + -
显示快捷键?