📄 verifierutil.c
字号:
*=======================================================================*/int Vfy_popInvokeArguments() { unsigned char* sig = (unsigned char*)change_Key_to_Name(calleeContext, NULL); unsigned char* sig_bak; unsigned short nargs; int nwords = 0; CLASSKEY ty[2]; int j,k; unsigned short i; nargs = *sig++; sig_bak = sig; for (i = 0; i < nargs; i++) { nwords += change_Arg_to_StackType(&sig, ty); } sig = sig_bak; /* * Are there the required number of words on the stack? */ if (vSP < nwords) { Vfy_throw(VE_ARGS_NOT_ENOUGH); } vSP -= nwords; k = 0; for (i = 0; i < nargs; i++) { int n = change_Arg_to_StackType(&sig, ty); for (j = 0; j < n; j++) { VERIFIERTYPE arg = vStack[vSP + k]; if (!vIsAssignable(arg, ty[j], NULL)) { Vfy_throw(VE_ARGS_BAD_TYPE); } k++; } } sigResult = sig; return nwords;}/*========================================================================= * FUNCTION: Vfy_pushInvokeResult * TYPE: private operation on stack * OVERVIEW: Push the callee's result * * INTERFACE: * parameters: None * returns: Nothing *=======================================================================*/void Vfy_pushInvokeResult() { /* * Push the result type. */ if (*sigResult != 'V') { CLASSKEY ty[2]; int i; int n = change_Arg_to_StackType(&sigResult, ty); for (i = 0 ; i < n; i++) { Vfy_push(ty[i]); } }}bool_t Vfy_MethodNameStartsWithLeftAngleBracket(METHODNAMEKEY methodNameKey) { char *methodName = change_Key_to_Name(methodNameKey, NULL); return methodName[0] == '<';}bool_t Vfy_MethodNameIsInit(METHODNAMEKEY methodNameKey) { return methodNameKey == initNameAndType.nt.nameKey;}void Vfy_ReplaceTypeWithType(VERIFIERTYPE fromType, VERIFIERTYPE toType) { int i; for (i = 0; i < vSP; i++) { if (vStack[i] == fromType) { vStack[i] = toType; } } for (i = 0; i < Mth_frameSize(methodBeingVerified); i++) { if (vLocals[i] == fromType) { vLocals[i] = toType; } }}/* ------------------------------------------------------------------------ *\ * Method Accessor Methods *\* ------------------------------------------------------------------------ *//*========================================================================= * FUNCTION: Mth_getStackMapEntryIP * TYPE: private operation * OVERVIEW: Get the ip address of an entry in the stack map table * * INTERFACE: * parameters: vMethod: the method, stackMapIndex: the index * returns: The ip address of the indexed entry. Or 0x7FFFFFFF if * the index is off the end of the table. *=======================================================================*/int Mth_getStackMapEntryIP(METHOD vMethod, int stackMapIndex) { METHOD thisMethod = (METHOD)vMethod; POINTERLIST stackMaps = thisMethod->u.java.stackMaps.verifierMap; if (stackMaps && stackMapIndex < stackMaps->length) { return stackMaps->data[stackMapIndex + stackMaps->length].cell; } else { return 0x7FFFFFFF; }}/*========================================================================= * FUNCTION: Mth_checkStackMapOffset * TYPE: private operation * OVERVIEW: Validates the stackmap offset to ensure that it does * not exceed code size. * * INTERFACE: * parameters: vMethod: the method, stackMapIndex: the index * returns: true if ok, false otherwise. *=======================================================================*/bool_t Mth_checkStackMapOffset(METHOD vMethod, int stackMapIndex) { METHOD thisMethod = (METHOD)vMethod; POINTERLIST stackMaps = thisMethod->u.java.stackMaps.verifierMap; if (stackMaps && stackMapIndex != stackMaps->length) { return FALSE; } return TRUE;}/*========================================================================= * FUNCTION: Mth_getExceptionTableLength * TYPE: private operation * OVERVIEW: Get the number of entries in the exception table * * INTERFACE: * parameters: vMethod: the method * returns: The number of entries *=======================================================================*/int Mth_getExceptionTableLength(METHOD vMethod) { HANDLERTABLE handlers = vMethod->u.java.handlers; if (handlers != 0) { return handlers->length; } else { return 0; }}/* ------------------------------------------------------------------------ *\ * Printing *\* ------------------------------------------------------------------------ */#if INCLUDEDEBUGCODE/*========================================================================= * FUNCTION: Vfy_setErrorIp * TYPE: private operation * OVERVIEW: Set the ip address for error printing * * INTERFACE: * parameters: ip: the IP address * returns: Nothing *=======================================================================*//* * Set to ip for error messages */void Vfy_setErrorIp(int ip) { vErrorIp = ip;#if EXCESSIVE_GARBAGE_COLLECTION if (excessivegc) { garbageCollect(0); }#endif /* EXCESSIVE_GARBAGE_COLLECTION */}/*========================================================================= * FUNCTION: getByteCodeName() * TYPE: public debugging operation * OVERVIEW: Given a bytecode value, get the mnemonic name of * the bytecode. * INTERFACE: * parameters: bytecode as an integer * returns: constant string containing the name of the bytecode *=======================================================================*/#if INCLUDEDEBUGCODEstatic const char* getByteCodeName(ByteCode token) { if (token >= 0 && token <= LASTBYTECODE) return byteCodeNames[token]; else return "<INVALID>";}#else# define getByteCodeName(token) ""#endif/*========================================================================= * FUNCTION: Vfy_printVerifyStartMessage * TYPE: private operation * OVERVIEW: Print trace info * * INTERFACE: * parameters: vMethod: the method * returns: Nothing *=======================================================================*/static void Vfy_printVerifyStartMessage(METHOD vMethod) { if (traceverifier) { START_TEMPORARY_ROOTS DECLARE_TEMPORARY_ROOT(char*, className, getClassName(&(vMethod->ofClass->clazz))); unsigned short nameKey = vMethod->nameTypeKey.nt.nameKey; unsigned short typeKey = vMethod->nameTypeKey.nt.typeKey; DECLARE_TEMPORARY_ROOT(char*, signature, change_Key_to_MethodSignature(typeKey)); fprintf(stdout, "Verifying method %s.%s%s\n", className, change_Key_to_Name(nameKey, NULL), signature); END_TEMPORARY_ROOTS }}/*========================================================================= * FUNCTION: Vfy_printVerifyLoopMessage * TYPE: private operation * OVERVIEW: Print trace info * * INTERFACE: * parameters: vMethod: the method,ip: the IP address * returns: Nothing *=======================================================================*/void Vfy_printVerifyLoopMessage(METHOD vMethod, IPINDEX ip) { if (traceverifier) { unsigned char *code = Mth_getBytecodes(vMethod); ByteCode token = code[ip]; fprintf(stdout, "Display derived/recorded stackmap at %ld:\n", (long)ip); printStackMap(vMethod, ip); fprintf(stdout, "%ld %s\n", (long)ip, getByteCodeName(token)); }}/*========================================================================= * FUNCTION: Vfy_printVerifyEndMessage * TYPE: private operation * OVERVIEW: Print trace info * * INTERFACE: * parameters: vMethod: the method * returns: Nothing *=======================================================================*/static void Vfy_printVerifyEndMessage(METHOD vMethod, int result) { static const char* verifierStatusInfo[] = KVM_MSG_VERIFIER_STATUS_INFO_INITIALIZER; /* See messages.h */ if (result != 0) { const int count = sizeof(verifierStatusInfo)/sizeof(verifierStatusInfo[0]); const char *info = (result > 0 && result < count) ? verifierStatusInfo[result] : "Unknown problem"; fprintf(stderr, "Error verifying method "); printMethodName(vMethod, stderr); fprintf(stderr, "Approximate bytecode offset %ld: %s\n", (long)vErrorIp, info); }}/*========================================================================= * FUNCTION: Vfy_trace1 * TYPE: private operation * OVERVIEW: Print trace info * * INTERFACE: * parameters: msg: a printf format string, p1: a parameter * returns: Nothing *=======================================================================*/void Vfy_trace1(char *msg, long p1) { if (traceverifier) { fprintf(stdout, msg, p1); }}#endif /* INCLUDEDEBUGCODE */ /* ------------------------------------------------------------------------ *\ * Entry / Exit * \* ------------------------------------------------------------------------ */ static jmp_buf vJumpBuffer; /* * Main verity routine *//*========================================================================= * FUNCTION: Vfy_verifyMethod * TYPE: private operation * OVERVIEW: Verify a method * * INTERFACE: * parameters: vMethod: the method * returns: Nothing *=======================================================================*/ static int Vfy_verifyMethod(METHOD vMethod) { void Vfy_verifyMethodOrAbort(const METHOD vMethod); static bool_t Vfy_checkNewInstructions(METHOD vMethod); int res;#if INCLUDEDEBUGCODE Vfy_printVerifyStartMessage(vMethod);#endif START_TEMPORARY_ROOTS vMaxStack = vMethod->u.java.maxStack; vFrameSize = vMethod->frameSize; IS_TEMPORARY_ROOT(vStack, (VERIFIERTYPE*) callocObject(ByteSizeToCellSize(vMaxStack * sizeof(VERIFIERTYPE)), GCT_NOPOINTERS)); IS_TEMPORARY_ROOT(vLocals, (VERIFIERTYPE*) callocObject(ByteSizeToCellSize(vFrameSize * sizeof(VERIFIERTYPE)), GCT_NOPOINTERS)); /* * This bitmap keeps track of all the NEW instructions that we have * already seen. */ IS_TEMPORARY_ROOT(NEWInstructions, NULL); vSP = 0; /* initial stack is empty. */ /* * All errors from Vfy_verifyMethodOrAbort are longjmped here. If no error * is thrown then res will be zero from the call to setjmp */ res = setjmp(vJumpBuffer); if (res == 0) { /* * Setup the verification context and call the core function. */ methodBeingVerified = vMethod; bytecodesBeingVerified = Mth_getBytecodes(vMethod); Vfy_verifyMethodOrAbort(vMethod); if (!Vfy_checkNewInstructions(vMethod)) { Vfy_throw(VE_BAD_NEW_OFFSET); } } END_TEMPORARY_ROOTS#if INCLUDEDEBUGCODE Vfy_printVerifyEndMessage(vMethod, res);#endif return res;}/*========================================================================= * FUNCTION: Vfy_throw * TYPE: private operation * OVERVIEW: Throw a verification exception * * INTERFACE: * parameters: code: the VE_xxxx code * returns: Does a longjmp back to Vfy_verifyMethod *=======================================================================*/void Vfy_throw(int code) { longjmp(vJumpBuffer, code); }/*========================================================================= * FUNCTION: Vfy_checkNewInstructions * TYPE: private operation * OVERVIEW: ITEM_new were all used * * INTERFACE: * parameters: thisMethod: the method * returns: FALSE if there is an error *=======================================================================*/static bool_t Vfy_checkNewInstructions(METHOD thisMethod) { /* We need to double check that all of the ITEM_new's that * we stack in the stack map were legitimate. */ const int codeLength = thisMethod->u.java.codeLength; int i, j; POINTERLIST stackMaps = thisMethod->u.java.stackMaps.verifierMap; if (stackMaps != NULL) { for (i = stackMaps->length; --i >= 0;) { unsigned short *stackMap = (unsigned short*)stackMaps->data[i].cellp; for (j = 0; j < 2; j++) { /* Do this loop twice: locals and stack */ unsigned short count = *stackMap++; while (count-- > 0) { unsigned short typeKey = *stackMap++; if (typeKey & ITEM_NewObject_Flag) { int index = DECODE_NEWOBJECT(typeKey); if (index >= codeLength || NEWInstructions == NULL || !IS_NTH_BIT(NEWInstructions, index)) { return FALSE; } } } } } } return TRUE;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -