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

字符数组栈溢出检测疑问:为何写入7字节未触发告警?

栈溢出检测为何未在写入7字节时触发?

我尝试使用string.h中的strcat拼接字符串str1和str2。目标字符串str1在栈上占用6字节,按预期写入超过6字节的内容应触发“stack smashing detected”告警,但实际写入7字节(12345,6,NUL)时未触发该告警,仅在写入8字节(12345,67,NUL)时触发。已知strcat在目标空间不足时属于未定义行为,但想了解为何这会影响栈溢出检测。

编译环境:gcc (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0

#include <stdio.h>
#include <string.h>

int main() {
    char str1[6] = "12345";
    char* str2 = "6"; // 运行正常,但原因是什么?
    //char* str2 = "67"; // 触发“*** stack smashing detected ***: terminated”
    strcat(str1, str2);
    return 0;
}

原因解析

GCC默认启用的栈溢出检测依赖金丝雀(Canary)机制:编译器会在栈帧的返回地址附近插入一个随机生成的特殊标记值。函数返回前会校验该值,若被篡改则触发栈溢出告警。

具体到你的代码:

  • 拼接"6"时,strcat需要写入6和新的终止符\0,合计2字节。str1原本的终止符\0会被覆盖,随后越界写入1字节(新的\0)。这1字节的越界刚好落在金丝雀值之前的栈空白区域(比如编译器为变量分配的对齐空间、未被使用的相邻栈内存),没有触及金丝雀值,因此检测机制不会触发。
  • 拼接"67"时,strcat需要写入6、7和\0,合计3字节,越界写入2字节。这会直接覆盖到金丝雀值的位置,导致返回前的校验失败,触发告警。

需要注意的是,栈布局由编译器的优化、对齐规则等决定,未定义行为的表现本身不可预测——换个编译环境或选项,7字节写入也可能触发告警,这正是未定义行为的典型特征。

内容的提问来源于stack exchange,提问作者Electrix

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 23:50:20