📄 check_code.c
字号:
verify_opcode_operands(context_type *context, int inumber, int offset){ instruction_data_type *idata = context->instruction_data; instruction_data_type *this_idata = &idata[inumber]; short *code_data = context->code_data; struct methodblock *mb = context->mb; unsigned char *code = context->code; opcode_type opcode = this_idata->opcode; int var; this_idata->operand.i = 0; this_idata->operand2.i = 0; switch (opcode) { case opc_jsr: /* instruction of ret statement */ this_idata->operand2.i = UNKNOWN_RET_INSTRUCTION; /* FALLTHROUGH */ case opc_ifeq: case opc_ifne: case opc_iflt: case opc_ifge: case opc_ifgt: case opc_ifle: case opc_ifnull: case opc_ifnonnull: case opc_if_icmpeq: case opc_if_icmpne: case opc_if_icmplt: case opc_if_icmpge: case opc_if_icmpgt: case opc_if_icmple: case opc_if_acmpeq: case opc_if_acmpne: case opc_goto: { /* Set the ->operand to be the instruction number of the target. */ int jump = (((signed char)(code[offset+1])) << 8) + code[offset+2]; int target = offset + jump; if (!isLegalTarget(context, target)) CCerror(context, "Illegal target of jump or branch"); this_idata->operand.i = code_data[target]; break; } case opc_jsr_w: /* instruction of ret statement */ this_idata->operand2.i = UNKNOWN_RET_INSTRUCTION; /* FALLTHROUGH */ case opc_goto_w: { /* Set the ->operand to be the instruction number of the target. */ int jump = (((signed char)(code[offset+1])) << 24) + (code[offset+2] << 16) + (code[offset+3] << 8) + (code[offset + 4]); int target = offset + jump; if (!isLegalTarget(context, target)) CCerror(context, "Illegal target of jump or branch"); this_idata->operand.i = code_data[target]; break; } case opc_tableswitch: case opc_lookupswitch: { /* Set the ->operand to be a table of possible instruction targets. */ long *lpc = (long *) UCALIGN(code + offset + 1); long *lptr; int *saved_operand; int keys; int k, delta; if (opcode == opc_tableswitch) { keys = ntohl(lpc[2]) - ntohl(lpc[1]) + 1; delta = 1; } else { keys = ntohl(lpc[1]); /* number of pairs */ delta = 2; /* Make sure that the tableswitch items are sorted */ for (k = keys - 1, lptr = &lpc[2]; --k >= 0; lptr += 2) { long this_key = ntohl(lptr[0]); /* NB: ntohl may be unsigned */ long next_key = ntohl(lptr[2]); if (this_key >= next_key) { CCerror(context, "Unsorted lookup switch"); } } } /* This code has been changed for inlining. We know have the keys * in the same order that they occur in the code, with the default * key being the first one. */ saved_operand = NEW(int, keys + 2); if (!isLegalTarget(context, offset + ntohl(lpc[0]))) CCerror(context, "Illegal default target in switch"); saved_operand[0] = keys + 1; /* number of successors */ saved_operand[1] = code_data[offset + ntohl(lpc[0])]; /* default */ for (k = 0, lptr = &lpc[3]; k < keys; lptr += delta, k++) { int target = offset + ntohl(lptr[0]); if (!isLegalTarget(context, target)) CCerror(context, "Illegal branch in opc_tableswitch"); saved_operand[k + 2] = code_data[target]; } this_idata->operand.ip = saved_operand; break; } case opc_ldc: { /* Make sure the constant pool item is the right type. */ int key = code[offset + 1]; int types = (1 << CONSTANT_Integer) | (1 << CONSTANT_Float) | (1 << CONSTANT_String); this_idata->operand.i = key; verify_constant_pool_type(context, key, types); break; } case opc_ldc_w: { /* Make sure the constant pool item is the right type. */ int key = (code[offset + 1] << 8) + code[offset + 2]; int types = (1 << CONSTANT_Integer) | (1 << CONSTANT_Float) | (1 << CONSTANT_String); this_idata->operand.i = key; verify_constant_pool_type(context, key, types); break; } case opc_ldc2_w: { /* Make sure the constant pool item is the right type. */ int key = (code[offset + 1] << 8) + code[offset + 2]; int types = (1 << CONSTANT_Double) | (1 << CONSTANT_Long); this_idata->operand.i = key; verify_constant_pool_type(context, key, types); break; } case opc_getfield: case opc_putfield: case opc_getstatic: case opc_putstatic: { /* Make sure the constant pool item is the right type. */ int key = (code[offset + 1] << 8) + code[offset + 2]; this_idata->operand.i = key; verify_constant_pool_type(context, key, 1 << CONSTANT_Fieldref); if (opcode == opc_getfield || opcode == opc_putfield) set_protected(context, inumber, key, opcode); break; } case opc_invokevirtual: case opc_invokespecial: case opc_invokestatic: case opc_invokeinterface: { /* Make sure the constant pool item is the right type. */ int key = (code[offset + 1] << 8) + code[offset + 2]; char *methodname; fullinfo_type clazz_info; int kind = (opcode == opc_invokeinterface ? 1 << CONSTANT_InterfaceMethodref : 1 << CONSTANT_Methodref); /* Make sure the constant pool item is the right type. */ verify_constant_pool_type(context, key, kind); methodname = cp_index_to_fieldname(context, key); clazz_info = cp_index_to_class_fullinfo(context, key, TRUE); this_idata->operand.i = key; this_idata->operand2.fi = clazz_info; if (strcmp(methodname, "<init>") == 0) { if (opcode != opc_invokespecial) CCerror(context, "Must call initializers using invokespecial"); this_idata->opcode = opc_invokeinit; } else { if (methodname[0] == '<') CCerror(context, "Illegal call to internal method"); if (opcode == opc_invokespecial && clazz_info != context->currentclass_info && clazz_info != context->superclass_info) { ClassClass *cb = context->class; for (; ; cb = cbSuperclass(cb)) { if (clazz_info == MAKE_CLASSNAME_INFO_WITH_COPY(context, cbName(cb), 0)) break; /* The optimizer make cause this to happen on local code */ if (cbSuperclass(cb) == 0) { /* optimizer make cause this to happen on local code */ if (cbLoader(cb) != 0) CCerror(context, "Illegal use of nonvirtual function call"); break; } } } } if (opcode == opc_invokeinterface) { char *signature = cp_index_to_signature(context, key); unsigned int args1 = Signature2ArgsSize(signature) + 1; unsigned int args2 = code[offset + 3]; if (args1 != args2) { CCerror(context, "Inconsistent args_size for opc_invokeinterface"); } if (code[offset + 4] != 0) { CCerror(context, "Fourth operand byte of invokeinterface must be zero"); } } else if (opcode == opc_invokevirtual || opcode == opc_invokespecial) set_protected(context, inumber, key, opcode); break; } case opc_instanceof: case opc_checkcast: case opc_new: case opc_anewarray: case opc_multianewarray: { /* Make sure the constant pool item is a class */ int key = (code[offset + 1] << 8) + code[offset + 2]; fullinfo_type target; verify_constant_pool_type(context, key, 1 << CONSTANT_Class); target = cp_index_to_class_fullinfo(context, key, FALSE); if (GET_ITEM_TYPE(target) == ITEM_Bogus) CCerror(context, "Illegal type"); switch(opcode) { case opc_anewarray: if ((GET_INDIRECTION(target)) >= MAX_ARRAY_DIMENSIONS) CCerror(context, "Array with too many dimensions"); this_idata->operand.fi = MAKE_FULLINFO(GET_ITEM_TYPE(target), GET_INDIRECTION(target) + 1, GET_EXTRA_INFO(target)); break; case opc_new: if (WITH_ZERO_EXTRA_INFO(target) != MAKE_FULLINFO(ITEM_Object, 0, 0)) CCerror(context, "Illegal creation of multi-dimensional array"); /* operand gets set to the "unitialized object". operand2 gets * set to what the value will be after it's initialized. */ this_idata->operand.fi = MAKE_FULLINFO(ITEM_NewObject, 0, inumber); this_idata->operand2.fi = target; break; case opc_multianewarray: this_idata->operand.fi = target; this_idata->operand2.i = code[offset + 3]; if ( (this_idata->operand2.i > (int)GET_INDIRECTION(target)) || (this_idata->operand2.i == 0)) CCerror(context, "Illegal dimension argument"); break; default: this_idata->operand.fi = target; } break; } case opc_newarray: { /* Cache the result of the opc_newarray into the operand slot */ fullinfo_type full_info; switch (code[offset + 1]) { case T_INT: full_info = MAKE_FULLINFO(ITEM_Integer, 1, 0); break; case T_LONG: full_info = MAKE_FULLINFO(ITEM_Long, 1, 0); break; case T_FLOAT: full_info = MAKE_FULLINFO(ITEM_Float, 1, 0); break; case T_DOUBLE: full_info = MAKE_FULLINFO(ITEM_Double, 1, 0); break; case T_BYTE: full_info = MAKE_FULLINFO(ITEM_Byte, 1, 0); break; case T_BOOLEAN: full_info = MAKE_FULLINFO(ITEM_Boolean, 1, 0); break; case T_CHAR: full_info = MAKE_FULLINFO(ITEM_Char, 1, 0); break; case T_SHORT: full_info = MAKE_FULLINFO(ITEM_Short, 1, 0); break; default: full_info = 0; /* make GCC happy */ CCerror(context, "Bad type passed to opc_newarray"); } this_idata->operand.fi = full_info; break; } /* Fudge iload_x, aload_x, etc to look like their generic cousin. */ case opc_iload_0: case opc_iload_1: case opc_iload_2: case opc_iload_3: this_idata->opcode = opc_iload; var = opcode - opc_iload_0; goto check_local_variable; case opc_fload_0: case opc_fload_1: case opc_fload_2: case opc_fload_3: this_idata->opcode = opc_fload; var = opcode - opc_fload_0; goto check_local_variable; case opc_aload_0: case opc_aload_1: case opc_aload_2: case opc_aload_3: this_idata->opcode = opc_aload; var = opcode - opc_aload_0; goto check_local_variable; case opc_lload_0: case opc_lload_1: case opc_lload_2: case opc_lload_3: this_idata->opcode = opc_lload; var = opcode - opc_lload_0; goto check_local_variable2; case opc_dload_0: case opc_dload_1: case opc_dload_2: case opc_dload_3: this_idata->opcode = opc_dload; var = opcode - opc_dload_0; goto check_local_variable2; case opc_istore_0: case opc_istore_1: case opc_istore_2: case opc_istore_3: this_idata->opcode = opc_istore; var = opcode - opc_istore_0; goto check_local_variable; case opc_fstore_0: case opc_fstore_1: case opc_fstore_2: case opc_fstore_3: this_idata->opcode = opc_fstore; var = opcode - opc_fstore_0; goto check_local_variable; case opc_astore_0: case opc_astore_1: case opc_astore_2: case opc_astore_3: this_idata->opcode = opc_astore; var = opcode - opc_astore_0; goto check_local_variable; case opc_lstore_0: case opc_lstore_1: case opc_lstore_2: case opc_lstore_3: this_idata->opcode = opc_lstore; var = opcode - opc_lstore_0; goto check_local_variable2; case opc_dstore_0: case opc_dstore_1: case opc_dstore_2: case opc_dstore_3: this_idata->opcode = opc_dstore; var = opcode - opc_dstore_0; goto check_local_variable2; case opc_wide: this_idata->opcode = code[offset + 1]; var = (code[offset + 2] << 8) + code[offset + 3]; switch(this_idata->opcode) { case opc_lload: case opc_dload: case opc_lstore: case opc_dstore: goto check_local_variable2; default: goto check_local_variable; } case opc_iinc: /* the increment amount doesn't matter */ case opc_ret: case opc_aload: case opc_iload: case opc_fload: case opc_astore: case opc_istore: case opc_fstore: var = code[offset + 1]; check_local_variable: /* Make sure that the variable number isn't illegal. */ this_idata->operand.i = var; if (var >= (int)mb->nlocals) CCerror(context, "Illegal local variable number"); break; case opc_lload: case opc_dload: case opc_lstore: case opc_dstore: var = code[offset + 1]; check_local_variable2: /* Make sure that the variable number isn't illegal. */ this_idata->operand.i = var; if ((var + 1) >= (int)mb->nlocals) CCerror(context, "Illegal local variable number"); break; default: if (opcode >= opc_breakpoint) CCerror(context, "Quick instructions shouldn't appear yet."); break; } /* of switch */}/*========================================================================= * FUNCTION: set_protected * OVERVIEW: Checks the field access to see if the instruction is * protected, is private and is in the same class package, * then the protected bit for the given instruction is set. * Invoked by verify_operands_opcodes() to set protected bit * for instructions of the following opcode types:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -