📄 verify-block.c
字号:
type->data.class = CLASS_CLASS(idx, pool); } else { const char* namestr; namestr = CLASS_NAMED(idx, pool); if (*namestr == '[') { type->tinfo = TINFO_SIG; type->data.sig = namestr; } else { type->tinfo = TINFO_NAME; type->data.sig = namestr; } } DBG(VERIFY3, dprintf("%s", indent); printType(getOpstackTop(block)); dprintf("\n"); ); break; case NEW: GET_WIDX; CHECK_STACK_OVERFLOW(1); block->stacksz++; type = getOpstackTop(block); if (pool->tags[idx] == CONSTANT_ResolvedClass) { type->tinfo = TINFO_CLASS; type->data.class = CLASS_CLASS(idx, pool); } else { const char* namestr = CLASS_NAMED(idx, pool); if (*namestr == '[') { return verifyError(v, "new: used to create an array"); } type->tinfo = TINFO_NAME; type->data.name = namestr; } v->uninits = pushUninit(v->uninits, type); type->tinfo = TINFO_UNINIT; type->data.uninit = v->uninits; DBG(VERIFY3, dprintf("%s", indent); printType(getOpstackTop(block)); dprintf("\n"); ); break; case ANEWARRAY: GET_WIDX; OPSTACK_PEEK_T(getTINT()); type = getOpstackTop(block); if (pool->tags[idx] == CONSTANT_ResolvedClass) { class = CLASS_CLASS(idx, pool); type->tinfo = TINFO_CLASS; type->data.class = lookupArray(class, v->einfo); if (type->data.class == NULL) { return verifyError(v, "anewarray: error creating array type"); } } else { char* namestr; sig = CLASS_NAMED(idx, pool); if (*sig == '[') { namestr = checkPtr(gc_malloc(sizeof(char) * (strlen(sig) + 2), KGC_ALLOC_VERIFIER)); v->sigs = pushSig(v->sigs, namestr); sprintf(namestr, "[%s", sig); } else { namestr = checkPtr(gc_malloc(sizeof(char) * (strlen(sig) + 4), KGC_ALLOC_VERIFIER)); v->sigs = pushSig(v->sigs, namestr); sprintf(namestr, "[L%s;", sig); } type->tinfo = TINFO_SIG; type->data.sig = namestr; } DBG(VERIFY3, dprintf("%s", indent); printType(getOpstackTop(block)); dprintf("\n"); ); break; case GETFIELD: ENSURE_OPSTACK_SIZE(1); if (!checkUninit(v->class, getOpstackTop(block))) { return verifyError(v, "getfield: uninitialized type on top of operand stack"); } GET_WIDX; n = FIELDREF_CLASS(idx, pool); if (pool->tags[n] == CONSTANT_ResolvedClass) { t->tinfo = TINFO_CLASS; t->data.class = CLASS_CLASS(n, pool); } else { t->tinfo = TINFO_NAME; t->data.name = CLASS_NAMED(n, pool); } OPSTACK_POP_T_BLIND(t); goto GET_COMMON; case GETSTATIC: GET_WIDX; CHECK_STACK_OVERFLOW(1); GET_COMMON: sig = FIELDREF_SIGD(idx, pool); DBG(VERIFY3, dprintf("%sfield type: %s\n", indent, sig); ); /* TODO: we should just have a function that returns a type based on a signature */ switch (*sig) { case 'I': case 'Z': case 'S': case 'B': case 'C': opstackPushBlind(block, getTINT()); break; case 'F': opstackPushBlind(block, getTFLOAT()); break; case 'J': OPSTACK_WPUSH(getTLONG()); break; case 'D': OPSTACK_WPUSH(getTDOUBLE()); break; case '[': case 'L': CHECK_STACK_OVERFLOW(1); block->stacksz++; type = getOpstackTop(block); type->tinfo = TINFO_SIG; type->data.name = sig; break; default: DBG(VERIFY3, dprintf("%sweird type signature: %s", indent, sig); ); return verifyError(v, "get{field/static}: unrecognized type signature"); break; } break; case PUTFIELD: if (isWide(getOpstackTop(block))) n = 3; else n = 2; ENSURE_OPSTACK_SIZE(n); if (!checkUninit(v->class, getOpstackTop(block))) { return verifyError(v, "putfield: uninitialized type on top of operand stack"); } GET_WIDX; sig = FIELDREF_SIGD(idx, pool); DBG(VERIFY3, dprintf(" field name::type: %s::%s\n", FIELDREF_NAMED(idx, pool), sig); ); switch (*sig) { case 'I': case 'Z': case 'S': case 'B': case 'C': OPSTACK_POP_T_BLIND(getTINT()); break; case 'F': OPSTACK_POP_T_BLIND(getTFLOAT()); break; case 'J': OPSTACK_WPOP_T_BLIND(getTLONG()); break; case 'D': OPSTACK_WPOP_T_BLIND(getTDOUBLE()); break; case '[': case 'L': t->tinfo = TINFO_SIG; t->data.sig = sig; OPSTACK_POP_T_BLIND(t); break; default: DBG(VERIFY3, dprintf("%sweird type signature: %s", indent, sig); ); return verifyError(v, "put{field/static}: unrecognized type signature"); break; } n = FIELDREF_CLASS(idx, pool); if (pool->tags[n] == CONSTANT_ResolvedClass) { t->tinfo = TINFO_CLASS; t->data.class = CLASS_CLASS(n, pool); } else { t->tinfo = TINFO_NAME; t->data.name = CLASS_NAMED(n, pool); } OPSTACK_POP_T_BLIND(t); break; case PUTSTATIC: if (getOpstackTop(block) == getTWIDE()) n = 2; else n = 1; ENSURE_OPSTACK_SIZE(n); GET_WIDX; sig = FIELDREF_SIGD(idx, pool); DBG(VERIFY3, dprintf(" field name::type: %s::%s\n", FIELDREF_NAMED(idx, pool), sig); ); switch (*sig) { case 'I': case 'Z': case 'S': case 'B': case 'C': OPSTACK_POP_T_BLIND(getTINT()); break; case 'F': OPSTACK_POP_T_BLIND(getTFLOAT()); break; case 'J': OPSTACK_WPOP_T_BLIND(getTLONG()); break; case 'D': OPSTACK_WPOP_T_BLIND(getTDOUBLE()); break; case '[': case 'L': t->tinfo = TINFO_SIG; t->data.sig = sig; OPSTACK_POP_T_BLIND(t); break; default: DBG(VERIFY3, dprintf("%sweird type signature: %s", indent, sig); ); return verifyError(v, "put{field/static}: unrecognized type signature"); break; } break; /************************************************************** * BRANCHING INSTRUCTIONS...END OF BASIC BLOCKS **************************************************************/ case GOTO: case GOTO_W: break; case JSR_W: case JSR: CHECK_STACK_OVERFLOW(1); block->stacksz++; type = getOpstackTop(block); type->tinfo = TINFO_ADDR; type->data.addr = getNextPC(code, pc); break; case RET: /* type checking done during merging stuff... */ break; case IF_ACMPEQ: case IF_ACMPNE: ENSURE_OPSTACK_SIZE(2); if (!isReference(getOpstackTop(block)) || !isReference(getOpstackWTop(block))) { return verifyError(v, "if_acmp* when item on top of stack is not a reference type"); } opstackPopBlind(block); opstackPopBlind(block); break; case IF_ICMPEQ: case IF_ICMPNE: case IF_ICMPGT: case IF_ICMPGE: case IF_ICMPLT: case IF_ICMPLE: OPSTACK_POP_T(getTINT()); case IFEQ: case IFNE: case IFGT: case IFGE: case IFLT: case IFLE: OPSTACK_POP_T(getTINT()); break; case IFNONNULL: case IFNULL: ENSURE_OPSTACK_SIZE(1); if (!isReference(getOpstackItem(block, 1))) { return verifyError(v, "if[non]null: thing on top of stack is not a reference"); } opstackPopBlind(block); break; case LOOKUPSWITCH: case TABLESWITCH: OPSTACK_POP_T(getTINT()); return(true); /************************************************************** * METHOD CALLING/RETURNING **************************************************************/ case INVOKEVIRTUAL: case INVOKESPECIAL: case INVOKEINTERFACE: case INVOKESTATIC: if (!checkMethodCall(v, block, pc)) { DBG(VERIFY3, dprintf("\n some problem with a method call...here's the block:\n"); printBlock(v->method, block, " "); ); /* propagate error */ return verifyError(v, "invoke* error"); } break; case IRETURN: OPSTACK_PEEK_T(getTINT()); sig = getMethodReturnSig(v->method); if (strlen(sig) != 1 || (*sig != 'I' && *sig != 'Z' && *sig != 'S' && *sig != 'B' && *sig != 'C')) { return verifyError(v, "ireturn: method doesn't return an integer"); } break; case FRETURN: OPSTACK_PEEK_T(getTFLOAT()); sig = getMethodReturnSig(v->method); if (strcmp(sig, "F")) { return verifyError(v, "freturn: method doesn't return an float"); } break; case LRETURN: OPSTACK_WPEEK_T(getTLONG()); sig = getMethodReturnSig(v->method); if (strcmp(sig, "J")) { return verifyError(v, "lreturn: method doesn't return a long"); } break; case DRETURN: OPSTACK_WPEEK_T(getTDOUBLE()); sig = getMethodReturnSig(v->method); if (strcmp(sig, "D")) { return verifyError(v, "dreturn: method doesn't return a double"); } break; case RETURN: sig = getMethodReturnSig(v->method); if (strcmp(sig, "V")) { return verifyError(v, "return: must return something in a non-void function"); } break; case ARETURN: ENSURE_OPSTACK_SIZE(1); t->tinfo = TINFO_SIG; t->data.sig = getMethodReturnSig(v->method); if (!typecheck(v, t, getOpstackTop(block))) { return verifyError(v, "areturn: top of stack is not type compatible with method return type"); } break; case ATHROW: ENSURE_OPSTACK_SIZE(1); if (!javaLangThrowable) { /* TODO: this is here for now, but perhaps we should have a TTHROWABLE that initialized as * a signature, like we do for String and Object */ loadStaticClass(&javaLangThrowable, "java/lang/Throwable"); } t->tinfo = TINFO_CLASS; t->data.class = javaLangThrowable; if (!typecheck(v, t, getOpstackTop(block))) { DBG(VERIFY3, dprintf("%sATHROW error: ", indent); printType(getOpstackTop(block)); dprintf ("\n"); ); return verifyError(v, "athrow: object on top of stack is not a subclass of throwable"); } for (n = 0; n < v->method->localsz; n++) { if (block->locals[n].tinfo & TINFO_UNINIT) { return verifyError(v, "athrow: uninitialized class instance in a local variable"); } } break; /************************************************************** * MISC **************************************************************/ case NOP: break; case BREAKPOINT: /* for internal use only: cannot appear in a class file */ return verifyError(v, "breakpoint instruction cannot appear in classfile"); break; case MONITORENTER: case MONITOREXIT: ENSURE_OPSTACK_SIZE(1); if(!isReference(getOpstackTop(block))) { return verifyError(v, "monitor*: top of stack is not an object reference"); } opstackPopBlind(block); break; case DUP: ENSURE_OPSTACK_SIZE(1); if (isWide(getOpstackTop(block))) { return verifyError(v, "dup: on a long or double"); } OPSTACK_PUSH(getOpstackTop(block)); break; case DUP_X1: ENSURE_OPSTACK_SIZE(2); if (isWide(getOpstackTop(block)) || isWide(getOpstackWTop(block))) { return verifyError(v, "dup_x1: splits up a double or long"); } OPSTACK_PUSH(getOpstackTop(block)); *getOpstackItem(block, 2) = *getOpstackItem(block, 3); *getOpstackItem(block, 3) = *getOpstackItem(block, 1); break; case DUP_X2: ENSURE_OPSTACK_SIZE(3); if (isWide(getOpstackTop(block))) { return verifyError(v, "cannot dup_x2 when top item on operand stack is a two byte item"); } OPSTACK_PUSH(getOpstackTop(block)); *getOpstackItem(block, 2) = *getOpstackItem(block, 3); *getOpstackItem(block, 3) = *getOpstackItem(block, 4); *getOpstackItem(block, 4) = *getOpstackItem(block, 1); break; case DUP2: ENSURE_OPSTACK_SIZE(2); OPSTACK_PUSH(getOpstackWTop(block)); OPSTACK_PUSH(getOpstackWTop(block)); break; case DUP2_X1: ENSURE_OPSTACK_SIZE(2); if (isWide(getOpstackItem(block, 2))) { return verifyError(v, "dup_x1 requires top 2 bytes on operand stack to be single bytes items"); } CHECK_STACK_OVERFLOW(2); opstackPushBlind(block, getOpstackItem(block, 2)); opstackPushBlind(block, getOpstackItem(block, 2)); *getOpstackItem(block, 3) = *getOpstackItem(block, 5); *getOpstackItem(block, 4) = *getOpstackItem(block, 1); *getOpstackItem(block, 5) = *getOpstackItem(block, 2); break; case DUP2_X2: ENSURE_OPSTACK_SIZE(4); if (isWide(getOpstackItem(block, 2)) || isWide(getOpstackItem(block, 4))) { return verifyError(v, "dup2_x2 where either 2nd or 4th byte is 2nd half of a 2 byte item"); } CHECK_STACK_OVERFLOW(2); opstackPushBlind(block, getOpstackItem(block, 2)); opstackPushBlind(block, getOpstackItem(block, 2)); *getOpstackItem(block, 3) = *getOpstackItem(block, 5); *getOpstackItem(block, 4) = *getOpstackItem(block, 6); *getOpstackItem(block, 5) = *getOpstackItem(block, 1); *getOpstackItem(block, 6) = *getOpstackItem(block, 2); break; case SWAP: ENSURE_OPSTACK_SIZE(2); if (isWide(getOpstackTop(block)) || isWide(getOpstackWTop(block))) { return verifyError(v, "cannot swap 2 bytes of a long or double"); } tt = *getOpstackWTop(block); *getOpstackWTop(block) = *getOpstackTop(block); *getOpstackTop(block) = tt; break; case WIDE: wide = true; pc = getNextPC(code, pc); continue; default: /* should never get here because of preprocessing in defineBasicBlocks() */ return verifyError(v, "unknown opcode encountered"); } pc = getNextPC(code, pc); if (wide == true) { wide = false; pc++; } } /* SUCCESS! */ return(true); /* take care of the namespace */#undef OPSTACK_POP_N#undef OPSTACK_POP_N_BLIND#undef OPSTACK_WPOP_T#undef OPSTACK_WPOP_T_BLIND#undef OPSTACK_WPOP#undef OPSTACK_POP_T#undef OPSTACK_POP_T_BLIND#undef OPSTACK_POP#undef OPSTACK_WPEEK_T#undef OPSTACK_WPEEK_T_BLIND#undef OPSTACK_PEEK_T#undef OPSTACK_PEEK_T_BLIND#undef OPSTACK_WPUSH#undef OPSTACK_WPUSH_BLIND#undef OPSTACK_PUSH#undef OPSTACK_PUSH_BLIND#undef CHECK_STACK_OVERFLOW#undef ENSURE_OPSTACK_SIZE#undef ENSURE_LOCAL_WTYPE#undef ENSURE_LOCAL_TYPE#undef GET_WIDX#undef GET_IDX}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -