我正在尝试使用容器注释包装器强制 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;
}
为什么消毒剂没有检测到内存违规?
首先,你似乎错误地使用了
__sanitizer_annotate_contiguous_container
。它的签名是:
void __sanitizer_annotate_contiguous_container(const void *beg_p,
const void *end_p,
const void *old_mid_p,
const void *new_mid_p)
因此,当您发布
a
时,您希望将其标记为
__sanitizer_annotate_contiguous_container(buf, buf + sizeof(A), buf + sizeof(A), buf);
其次,ASAN 不报告堆栈溢出的原因似乎是 ASAN 仅将超出帧边界的 3 个影子字节(24 个实际字节)标记为不可寻址,这可以通过查看轻松找到错误时的影子字节:
https://godbolt.org/z/Mxz7qxhfo
在这里,您在帧开始之后的
(sizeof(A) + 64) * sizeof(A)
= 272 字节或帧结束之后的 264 字节处对堆栈进行寻址,因此不会引发错误。如果您在堆上分配 buf
,因为 ASAN 在堆分配上标记了更宽的红区,您会发现正确报告了内存违规,但原因是“堆溢出”,而不是“容器溢出”。