You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 06:45:02