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

空字符是否会触发栈溢出?栈溢出检测特殊行为咨询

栈溢出检测中空字符的特殊行为分析

测试场景与现象

测试GCC的-f-stack-protector栈溢出检测机制时发现:向字符缓冲区末尾外写入空字符'\0'不会触发栈溢出提示,但写入其他字符则会触发。

测试代码(开启-f-stack-protector编译):

#include <stdio.h>

int main(int argc, char *argv[])
{
  char buf[8];
  char c;

  printf("Enter a string: ");
  int i;
  for (i = 0; (c = getchar()) != '\n'; i++) buf[i] = c;
  buf[i] = '\0';
  printf("string = [%s]\n", buf);

  return 0;
}

测试现象:

  • 输入9个字符时,程序正常弹出*** stack smashing detected ***: terminated提示;
  • 输入8个字符时,buf[8] = '\0'会写入缓冲区外,但无任何检测提示;
  • 若将代码中的'\0'替换为其他字符(如'A'),输入8个字符时会触发检测。

原因分析

这并非异常行为,而是-f-stack-protector机制的设计特性:

  1. 栈金丝雀的原理:该机制会在栈上的缓冲区与返回地址之间插入一个随机生成的「栈金丝雀(canary)」值,程序退出前会检查金丝雀是否被篡改,若值被改变则判定为栈溢出并触发提示。
  2. 金丝雀的设计细节:GCC默认生成的栈金丝雀值低位字节固定为0,这是为了兼容C语言中字符串以'\0'结尾的特性——避免正常的字符串终止操作(如在缓冲区末尾外意外写入'\0')误触发栈溢出检测。
  3. 对应场景的解释:
    • 输入8个字符时,循环结束后i=8,buf[8] = '\0'写入的位置恰好是栈金丝雀的低位字节,而该字节原本就是0,所以金丝雀值未被篡改,检测机制不触发;
    • 输入9个字符时,循环中会向buf[8]写入输入的第9个字符(非0),直接破坏金丝雀值,后续检查时就会触发栈溢出提示;
    • 若将'\0'替换为'A'(0x41),写入金丝雀位置时会改变其值,因此触发检测。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 05:20:30