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

使用Container注解包装器让ASan检测栈内存缓冲区溢出失效问题

为何ASan未检测到栈内存的缓冲区溢出?

你的测试代码如下:

#include <sanitizer/asan_interface.h>
#include <iostream>
#include <array>

constexpr size_t N = 32;

class A {
public:
    int x;
};

int main() {
    char buf [sizeof(A)];
    A *a = new (buf) A;
    __sanitizer_annotate_contiguous_container(buf, buf + sizeof(A), buf, buf + sizeof(A));
    a->~A();
    a[sizeof(A) + 64].x = 4;
    std::cout << a[sizeof(A) + 64].x << std::endl;
}

ASan未触发检测的原因主要有三点:

  • __sanitizer_annotate_contiguous_container不适用于栈内存
    这个注解函数是专门为**堆上的动态容器(比如std::vector)**设计的,用于标记容器的有效元素范围,辅助ASan检测容器内部的越界访问。但栈上的数组由ASan在编译阶段通过栈帧红区机制监控,这个注解不会改变栈内存的检测规则,对栈内存完全无效。

  • 指针算术的实际偏移超出栈红区监控范围
    你使用a[sizeof(A)+64]访问内存时,由于a是A*类型,下标会自动乘以sizeof(A)。假设sizeof(A)=4,实际偏移量是(4+64)*4=272字节——这个地址可能没有落在当前栈帧的红区(ASan为栈帧分配的保护区域),而是落在栈的其他合法区域甚至进程的可访问内存中,ASan自然不会触发错误。

  • 对象析构后栈内存未被标记为不可访问
    调用a->~A()仅完成对象的析构,但栈上的buf内存依然属于当前栈帧的一部分,ASan不会自动将其标记为不可访问的Poisoned区域。如果要检测对已析构对象内存的非法访问,需要手动调用__asan_poison_memory_region(buf, sizeof(A))。

修复示例

如果要让ASan检测到内存违规,可以修改代码手动标记栈内存为不可访问:

#include <sanitizer/asan_interface.h>
#include <iostream>

class A {
public:
    int x;
};

int main() {
    char buf [sizeof(A)];
    A *a = new (buf) A;
    // 手动标记buf内存为不可访问
    __asan_poison_memory_region(buf, sizeof(A));
    // 访问a[1]会触发ASan越界检测
    a[1].x = 4;
    std::cout << a[1].x << std::endl;
}

或者用堆内存测试注解的效果:

#include <sanitizer/asan_interface.h>
#include <iostream>
#include <malloc.h>

class A {
public:
    int x;
};

int main() {
    size_t buf_size = sizeof(A) * 2;
    char *buf = (char*)malloc(buf_size);
    A *a = new (buf) A;
    // 标注容器的有效范围为buf到buf+sizeof(A)
    __sanitizer_annotate_contiguous_container(buf, buf + buf_size, buf, buf + sizeof(A));
    a->~A();
    // 访问a[1]超出有效范围,触发ASan错误
    a[1].x = 4;
    std::cout << a[1].x << std::endl;
    free(buf);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 20:32:34