Address Sanitizer with Visual C++:忽略读取缓冲区溢出,同时仍然捕获写入缓冲区溢出

Address Sanitizer with Visual C++: ignore read buffer overflows while still catching write buffer overflows

考虑以下示例:

int main()
{
    char* p = new char[10];
    
    srand(p[11]); // heap buffer overflow - read

    p[11] = rand(); // heap buffer overflow - write
}

我希望 ASan 暂时不要标记 heap buffer overflow - read,同时仍然标记 heap buffer overflow - write

我想要这个的原因是现在专注于更危险的错误。读取溢出要么立即崩溃,要么没有后果,而写入溢出可能会导致损坏,稍后会在其他地方触发。对于一些小的溢出,甚至立即崩溃也被排除在外。所以我肯定也会研究读取溢出,但稍后。

有没有办法做到这一点?

实现这一目标有两个方向。

1。触发错误后继续

要在出错后继续,应使用 -fsanitize-recover=address 选项。来自 FAQ:

Q: Can AddressSanitizer continue running after reporting first error?

A: Yes it can, AddressSanitizer has recently got continue-after-error mode. This is somewhat experimental so may not yet be as reliable as default setting (and not as timely supported). Also keep in mind that errors after the first one may actually be spurious. To enable continue-after-error, compile with -fsanitize-recover=address and then run your code with ASAN_OPTIONS=halt_on_error=0.

MSVC 编译器尚不支持此选项。有一个issue可以加

如果可行,可以安装一个自定义处理程序来检查它是读错误还是写错误,忽略读错误并报告写错误。

2。不要检测读取错误

正如@yugr 所指出的,有 -mllvm -asan-instrument-reads=false 选项可以实现这一点。但是MSVC编译器也不支持这个选项。

但是在某些地方仍然有办法避免编译器检测。是__declspec(no_sanitize_address)。因此,可以通过隔离已知的读取错误来实现目标,如下所示:

__declspec(no_sanitize_address)
void isolate_read_heap_buffer_overflow(char* p)
{
    srand(p[11]); // heap buffer overflow - read
}

int main()
{
    char* p = new char[10];
    
    isolate_read_heap_buffer_overflow(p);

    p[11] = rand(); // heap buffer overflow - write

    return 0;
}

其他更好的选择

还有clang-cl编译器,其实是支持Visual C++语义的Clang。 Visual Studio 安装程序安装它。因此,如果一个项目可以重新定位为使用 Clang,这将打开所有可在 Clang 中使用的 Address Sanitizer 功能。不幸的是,重新定位一些遗留代码库可能是一项长期的任务。

理论上,向 CL 包装器提供 -mllvm -asan-instrument-reads=false 应该会禁用读取检测。