/*
 * 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;
    }
    }
}
Beispiel #2
0
/* (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);
}
Beispiel #3
0
/*
 * 比较名称。以较特定的方法,参数、内容和返回值,如果他们相等或者不等于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);
    }
}