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

为何AddressSanitizer对BSS段全局缓冲区溢出检测无效?

AddressSanitizer对BSS段全局缓冲区溢出无法检测的原因解析

我来帮你拆解这个问题——这本质上是AddressSanitizer(ASan)对不同内存段的全局变量采取了差异化保护策略导致的。

先把你的测试用例整理得更清晰,方便对比差异:

测试1:未初始化的全局数组(BSS段)

#include <stdio.h>

int test[16];

int main()
{
    test[17] = -1;
}

编译运行操作:

/tmp $ gcc ./main.c -o main -fsanitize=address
/tmp $ ./main
# 无任何报错输出

测试2:初始化的全局数组(数据段)

#include <stdio.h>

int test[16] = {1};

int main()
{
    test[17] = -1;
}

编译运行操作:

/tmp $ gcc ./main.c -o main -fsanitize=address
/tmp $ ./main
=================================================================
==19776==ERROR: AddressSanitizer: global-buffer-overflow on address ...
Looks like global buffer ov...

核心原因:BSS段与数据段的ASan保护机制差异

  • 内存段本质区别
    未初始化的全局变量(比如测试1里的test[16])会被分配到BSS段,这部分内存是程序启动时由操作系统批量清零的,多个未初始化全局变量会被紧凑排列;而初始化的全局变量(测试2的test[16])会进入数据段,每个变量拥有独立的内存区域。
  • ASan保护策略不同
    对于数据段的全局变量,ASan会在变量前后插入专门的红色区域(Redzone)——这是标记为不可访问的内存,一旦程序读写到该区域,ASan会立即触发缓冲区溢出报错;但对于BSS段的全局变量,ASan默认不会给每个变量单独添加红色区域(主要是为了避免内存浪费,毕竟BSS段通常存在大量小变量),当你溢出test[17]时,实际是写到了BSS段相邻的其他全局变量内存或未标记的空闲BSS内存,ASan无法识别这是非法操作,因此不会报错。

如何让ASan检测BSS段的全局缓冲区溢出?

你可以添加-fno-common编译选项,这个选项会强制编译器将BSS段的全局变量当作非公共符号处理,给每个变量分配独立内存块并添加红色区域,这样就能触发溢出检测了。

修改后的编译命令:

/tmp $ gcc ./main.c -o main -fsanitize=address -fno-common
/tmp $ ./main
# 此时会触发和测试2类似的global-buffer-overflow报错

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 07:05:56