/* * Find the return type in the signature, and convert it to a class * object. For primitive types we use a boxed class, for reference types * we do a name lookup. * * On failure, we return NULL with an exception raised. */ ClassObject* dvmGetBoxedReturnType(const Method* meth) { const char* sig = dexProtoGetReturnType(&meth->prototype); switch (*sig) { case 'Z': case 'C': case 'F': case 'D': case 'B': case 'S': case 'I': case 'J': case 'V': return dvmFindPrimitiveClass(*sig); case '[': case 'L': return dvmFindClass(sig, meth->clazz->classLoader); default: { /* should not have passed verification */ char* desc = dexProtoCopyMethodDescriptor(&meth->prototype); ALOGE("Bad return type in signature '%s'", desc); free(desc); dvmThrowInternalError(NULL); return NULL; } } }
/* (documented in header file) */ int dexProtoCompareToDescriptor(const DexProto* proto, const char* descriptor) { // First compare the return types. const char *returnType = methodDescriptorReturnType(descriptor); assert(returnType != NULL); int result = strcmp(dexProtoGetReturnType(proto), returnType); if (result != 0) { return result; } // The return types match, so we have to check arguments. return protoCompareToParameterDescriptors(proto, descriptor, true); }
/* * 比较名称。以较特定的方法,参数、内容和返回值,如果他们相等或者不等于0,则返回0 * */ static inline int compareMethodHelper(Method* method, const char* methodName, const char* returnType, size_t argCount, const char** argTypes) { DexParameterIterator iterator; const DexProto* proto; if (strcmp(methodName, method->name) != 0) { return 1; } proto = &method->prototype; if (strcmp(returnType, dexProtoGetReturnType(proto)) != 0) { return 1; } if (dexProtoGetParameterCount(proto) != argCount) { return 1; } dexParameterIteratorInit(&iterator, proto); for (/*argCount*/; argCount != 0; argCount--, argTypes++) { const char* argType = *argTypes; const char* paramType = dexParameterIteratorNextDescriptor(&iterator); if (paramType == NULL) { /* Param list ended early; no match */ break; } else if (strcmp(argType, paramType) != 0) { /* Types aren't the same; no match. */ break; } } if (argCount == 0) { /* We ran through all the given arguments... */ if (dexParameterIteratorNextDescriptor(&iterator) == NULL) { /* ...and through all the method's arguments; success! */ return 0; } } return 1; }
/* Used to propagate taint for JNI methods * Two types of propagation: * 1) simple conservative propagation based on parameters * 2) propagation based on function profile policies */ void dvmTaintPropJniMethod(const u4* args, JValue* pResult, const Method* method, const int nativeTaint) { const DexProto* proto = &method->prototype; DexParameterIterator pIterator; int nParams = dexProtoGetParameterCount(proto); int pStart = (dvmIsStaticMethod(method)?0:1); /* index where params start */ /* Consider 3 arguments. [x] indicates return taint index * 0 1 2 [3] 4 5 6 */ int nArgs = method->insSize; u4* rtaint = (u4*) &args[nArgs]; /* The return taint value */ int tStart = nArgs+1; /* index of args[] where taint values start */ int tEnd = nArgs*2; /* index of args[] where taint values end */ u4 tag = TAINT_CLEAR; int i; #if 0 { char *desc = dexProtoCopyMethodDescriptor(proto); ALOGW("Jni: %s.%s%s, descriptor: %s", method->clazz->descriptor, method->name, dvmIsStaticMethod(method)?"[static]":"", desc); free(desc); } #endif #ifdef TAINT_JNI_LOG /* JNI logging for debugging purposes */ if (gJniLog) { u4 hash; int len; char *inStr, *outStr; len = strlen(method->clazz->descriptor) + 1 + strlen(method->name); inStr = (char*) malloc(len+1); strcpy(inStr, method->clazz->descriptor); strcat(inStr, "."); strcat(inStr, method->name); hash = dvmComputeUtf8Hash(inStr); dvmHashTableLock(gJniLogSeen); outStr = (char*) dvmHashTableLookup(gJniLogSeen, hash, inStr, (HashCompareFunc) strcmp, false); if (outStr == NULL) { /* New method! */ /* add it */ dvmHashTableLookup(gJniLogSeen, hash, inStr, (HashCompareFunc) strcmp, true); } else { free(inStr); /* don't need this anymore */ } dvmHashTableUnlock(gJniLogSeen); } #endif /* Union the taint tags, this includes object ref tags * - we don't need to worry about static vs. not static, because getting * the taint tag on the "this" object reference is a good * - we don't need to worry about wide registers, because the stack * interleaving of taint tags makes it transparent */ /*for (i = tStart; i <= tEnd; i++) { tag |= args[i]; if (args[i]!=0 && args[i]!=TAINT_ACCELEROMETER) //found a taint, and its not the accelerometer spam either ALOGD("dvmTaintPropJNIMethod found taint %08x in method=%s:%s(%s) for arg[%d]=%08x", args[i], method->clazz->descriptor, method->name, method->shorty, i-nArgs, args[i-nArgs]); }*/ /* If not static, pull any taint from the "this" object */ /*if (!dvmIsStaticMethod(method)) { tag |= getObjectTaint((Object*)args[0], method->clazz->descriptor); }*/ /* Union taint from Objects we care about */ dexParameterIteratorInit(&pIterator, proto); for (i=pStart; ; i++) { const char* desc = dexParameterIteratorNextDescriptor(&pIterator); if (desc == NULL) { break; } if (desc[0] == '[' || desc[0] == 'L') { tag |= getObjectTaint((Object*) args[i], desc); } if (desc[0] == 'J' || desc[0] == 'D') { /* wide argument, increment index one more */ i++; } } /* Look at the taint policy profiles (may have return taint) */ //tag |= propMethodProfile(args, method); /* Update return taint according to the return type */ //Native Tainting: get taint Value from native code //if (tag) { if (nativeTaint) { const char* desc = dexProtoGetReturnType(proto); //setReturnTaint(tag, rtaint, pResult, desc); ALOGD("dvmTaintPropJniMethod: setting result taint to %x", nativeTaint); setReturnTaint(nativeTaint, rtaint, pResult, desc); } }