在写JNI程序时,出现了stack corruption detected,刚开始我以为是我分配的内存不够导致越界了,加大内存后依然如此。出现问题的程序如下:
extern "C"
JNIEXPORT jbyteArray JNICALL
Java_net_yiim_yicrypto_NativeSupport__1cipherFinal(JNIEnv *env, jclass type, jlong ptr) {
unsigned char * buf = (unsigned char *)malloc(sizeof(unsigned char) * 33);
int outlen = 0;
if(buf == NULL) {
YiLog::getInstance().d("cipherFinal alloc memory.");
}
int retCode = cipherFinal((void *)ptr, buf + 1, (size_t *)&outlen);
if(retCode != 0 || outlen < 0) {
outlen = 1;
}
buf[0] = (unsigned char)(retCode & 0x0FF);
jbyteArray array = env->NewByteArray(outlen + 1);
env->SetByteArrayRegion(array, 0, outlen + 1, (const jbyte *) buf);
free(buf);
return array;
}
异常如下:
--------- beginning of crash
10-11 17:37:56.972 30451 30467 F libc : stack corruption detected
10-11 17:37:56.973 30451 30467 F libc : Fatal signal 6 (SIGABRT), code -6 in tid 30467 (roidJUnitRunner)
10-11 17:37:56.974 3019 3019 W : debuggerd: handling request: pid=30451 uid=10204 gid=10204 tid=30467
10-11 17:37:57.087 30469 30469 F DEBUG : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
10-11 17:37:57.088 30469 30469 F DEBUG : Build fingerprint: 'samsung/zeroltezc/zeroltechn:7.0/NRD90M/G9250ZCU2ERI1:user/release-keys'
10-11 17:37:57.088 30469 30469 F DEBUG : Revision: '10'
10-11 17:37:57.088 30469 30469 F DEBUG : ABI: 'arm64'
10-11 17:37:57.089 30469 30469 F DEBUG : pid: 30451, tid: 30467, name: roidJUnitRunner >>> net.yiim.yicrypto.android <<<
10-11 17:37:57.089 30469 30469 F DEBUG : signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
10-11 17:37:57.107 30469 30469 F DEBUG : Abort message: 'stack corruption detected'
10-11 17:37:57.107 30469 30469 F DEBUG : x0 0000000000000000 x1 0000000000007703 x2 0000000000000006 x3 0000000000000008
10-11 17:37:57.107 30469 30469 F DEBUG : x4 000000759fa888d0 x5 0080808080808080 x6 0000000000000000 x7 0000000000000010
10-11 17:37:57.107 30469 30469 F DEBUG : x8 0000000000000083 x9 ffffffffffffffdf x10 0000000000000000 x11 0000000000000001
10-11 17:37:57.107 30469 30469 F DEBUG : x12 ffffffffffffffff x13 0000000000000000 x14 0000000000000000 x15 0039fd8c3ba91dfe
10-11 17:37:57.107 30469 30469 F DEBUG : x16 00000075b50e3ee0 x17 00000075b508d5ac x18 00000000ffffffff x19 00000075a61ff4f8
10-11 17:37:57.108 30469 30469 F DEBUG : x20 0000000000000006 x21 00000075a61ff450 x22 0000000000000058 x23 00000075a65e0cad
10-11 17:37:57.108 30469 30469 F DEBUG : x24 0000000000000008 x25 63d4f7c6fab6449e x26 00000075a0940698 x27 63d4f7c6fab6449e
10-11 17:37:57.108 30469 30469 F DEBUG : x28 0000000000000002 x29 00000075a61f7740 x30 00000075b508aa54
10-11 17:37:57.108 30469 30469 F DEBUG : sp 00000075a61f7720 pc 00000075b508d5b4 pstate 0000000060000000
10-11 17:37:57.114 30469 30469 F DEBUG :
10-11 17:37:57.114 30469 30469 F DEBUG : backtrace:
10-11 17:37:57.114 30469 30469 F DEBUG : #00 pc 000000000006b5b4 /system/lib64/libc.so (tgkill+8)
10-11 17:37:57.114 30469 30469 F DEBUG : #01 pc 0000000000068a50 /system/lib64/libc.so (pthread_kill+64)
10-11 17:37:57.114 30469 30469 F DEBUG : #02 pc 0000000000023f68 /system/lib64/libc.so (raise+24)
10-11 17:37:57.114 30469 30469 F DEBUG : #03 pc 000000000001c9ec /system/lib64/libc.so (abort+52)
10-11 17:37:57.114 30469 30469 F DEBUG : #04 pc 0000000000020f74 /system/lib64/libc.so (__libc_fatal+104)
10-11 17:37:57.114 30469 30469 F DEBUG : #05 pc 000000000006a498 /system/lib64/libc.so (__stack_chk_fail+16)
10-11 17:37:57.114 30469 30469 F DEBUG : #06 pc 0000000000011210 /data/app/net.yiim.yicrypto.android-2/lib/arm64/libyicrypto.so (Java_net_yiim_yicrypto_NativeSupport__1cipherFinal+380)
10-11 17:37:57.115 30469 30469 F DEBUG : #07 pc 0000000000236b20 /data/app/net.yiim.yicrypto.android-2/oat/arm64/base.odex (offset 0x219000)
于是在网上各种搜索,百思未得其解,后来不断的打log之后,程序又突然好了,去掉log之后又崩溃。
将JNI编译指定为armeabi-v7a架构,程序运行正常,于是开始怀疑哪里的指针操作有问题,搜索到这篇文章:
stack corruption detected (-fstack-protector)
里面有一个回复是这样的:
4 posts
I've found the problem:
There was a bug like that:
void a(unsigned long* ptr) { *ptr = 0; }
void b() {
int x;
a(&x);
}
便想到会不会是size_t在32位及64位环境中,大小不一样导致的,于是把outlen直接定义为size_t后,程序运行正常。
后发现,size_t的定义正是unsigned long,跟上述回复现象一致。
特此,记一坑。