每次调用JNI方法时附加值

时间:2016-11-10 07:08:34

标签: android c android-ndk java-native-interface

我正在使用JNI来获取apk的签名,我得到的非常好。当我第一次从java调用这个方法时,我得到的确切值。再次调用它我得到具有精确值的附加值(例如1234456123456)。 PFB我正在使用的代码

char* getSignatureMd5(JNIEnv* env, jobject obj)
{
    char* sign = loadSignature(env, obj);
    MD5_CTX context = { 0 };
    MD5Init(&context);
    MD5Update(&context, (unsigned char*)sign, strlen(sign));
    unsigned char dest[16] = { 0 };
    MD5Final(dest, &context);
    int i;
    static char destination[32]={0};
    for (i = 0; i < 16; i++) {
            sprintf(destination, "%s%02x", destination, dest[i]);
    }
    return destination;
}

getToken JNI方法

JNIEXPORT jstring JNICALL Java_com_sign_signaturecapturesbi_MyAdapter_getToken(JNIEnv *env, jobject obj)
                                                                     {
    char* signValue = getSignatureMd5(env, obj);
    __android_log_print(ANDROID_LOG_VERBOSE, "MyApp", "signValue %s", signValue);
    return (*env)->NewStringUTF(env, signValue);
    }

1 个答案:

答案 0 :(得分:2)

这些行导致未定义的行为:

for (i = 0; i < 16; i++) {
        sprintf(destination, "%s%02x", destination, dest[i]);
}

man 3 printf

  

C99和POSIX.1-2001指定在调用时结果未定义   到sprintf()snprintf()vsprintf()vsnprintf()会导致   复制发生在重叠的对象之间(例如,如果   目标字符串数组和提供的输入参数之一引用   相同的缓冲区。)

此外destinationstatic,因此它会在调用之间保留其内容。这些点一起给你带来如此奇怪的行为。

由于dest大小众所周知,您可以简单地展开循环,也不要忘记向destination添加一个额外的单元格来终止\0。如果可能,您应该使用snprintf()代替:

static char destination[33];

snprintf(destination, sizeof destination,
    "%02x%02x%02x%02x%02x%02x%02x%02x"
    "%02x%02x%02x%02x%02x%02x%02x%02x",
    dest[0], dest[1], dest[2], dest[3],
    dest[4], dest[5], dest[6], dest[7],
    dest[8], dest[9], dest[10], dest[11],
    dest[12], dest[13], dest[14], dest[15]);

在这种情况下,您可以将destination保留为static,因为您的代码不再对其内容进行中继。但请注意,getSignatureMd5()每次调用时都会返回指向同一缓冲区的指针,因此后续调用会擦除先前调用获得的结果。