Android JNI调用C++ XTTEA加密函数触发memset栈损坏问题求助
问题根因分析
- 核心原因是栈缓冲区越界写入:你在JNI层定义的
input数组仅分配了8字节栈内存,而加密函数内部计算得到的block_size大于8,直接向input数组边界外写入数据触发了Android NDK默认开启的栈保护机制,抛出栈损坏错误。
具体计算验证:你传入的data_size为8,按照代码里的块大小计算逻辑:block_size = ((8 + 2) / 4 + 1) * 4 = (2 + 1) *4 =12,比实际传入的缓冲区大小大4字节。执行memset(&data[data_size], 0, block_size - data_size)时,会从input数组的第8位(数组下标最大为7)开始向后写4个字节的0,直接越界覆盖了栈上的其他数据,包括栈保护金丝雀值,所以触发了-fstack-protector的检测报错。
- 额外越界风险:后续的for循环
for (i = data_size + 1; i >= 2; i--)也会访问data[8]、data[9],同样属于越界操作,即使memset没报错,这里也会触发崩溃。 - 为什么线上C编译器没报错:不同编译环境的栈保护开关、栈内存布局不同,多数线上运行的C环境默认没有开启栈保护参数,越界写入如果没有覆盖到程序运行依赖的关键栈数据,不会立刻触发崩溃,属于隐性BUG,在Android NDK环境下因为默认开启栈保护才显性暴露。
修复方案
- 方案1:扩大输入缓冲区大小,调用加密函数前先计算所需的块大小,分配足够的内存空间,示例修改如下:
extern "C" JNIEXPORT jint JNICALLJava_com_example_ndkdemo_MainActivity_encryptDataInt(JNIEnv *env, jobject thiz /* this */){ int data_size = 8; // 预先计算需要的块大小,分配足够的缓冲区 int block_size = ((data_size + 2) / 4 + 1) * 4; unsigned char *input = (unsigned char*)malloc(block_size); // 初始化原始数据 memset(input, 0x11, data_size); sg_xxtea_encrypt (input, data_size); // 处理加密后的数据逻辑 // 最后释放内存 free(input); return 1; }
- 方案2:修改加密函数逻辑,将填充、移位操作放到内部临时缓冲区完成,不要直接修改传入的输入缓冲区的越界部分,加密完成后再将结果输出到用户提供的足够大的输出缓冲区中,避免外部调用方需要额外计算缓冲区大小的问题。
- 补充检查:确认全局变量
sg_data_buff的大小不小于block_size/4,避免后续向sg_data_buff写入数据时也出现越界问题。
内容的提问来源于stack exchange,提问作者bluepixel technologies
相关产品推荐
相关产品推荐

