LLVM Address Sanitizer与MALLOC_CHECK_=3:后者是否仍具必要性?
Address Sanitizer与MALLOC_CHECK_=3的检测差异验证
传闻真实性说明
关于“Address Sanitizer无法识别破坏分配器私有数据结构”的说法,需分场景看待:
- 当程序使用ASAN替换后的分配器时,ASAN会对自身的元数据做严格监控,任何篡改行为都会被即时检测到。
- 但如果程序绕过ASAN的拦截,直接调用系统原生的malloc/free(比如通过动态链接获取原生函数地址),ASAN就无法监控这类内存操作,此时对原生分配器私有结构的破坏,只有MALLOC_CHECK_=3能检测到。
满足要求的单元测试用例
以下代码可实现“ASAN下通过,MALLOC_CHECK_=3下失败”的效果:
#include <dlfcn.h> #include <cstdlib> // 定义原生内存分配/释放的函数指针 typedef void* (*RealMalloc)(size_t); typedef void (*RealFree)(void*); int main() { // 获取系统原生malloc和free的真实地址,绕过ASAN拦截 RealMalloc real_malloc = (RealMalloc)dlsym(RTLD_NEXT, "malloc"); RealFree real_free = (RealFree)dlsym(RTLD_NEXT, "free"); if (!real_malloc || !real_free) { return 1; } // 用原生malloc分配内存 void* ptr = real_malloc(1024); if (!ptr) { return 1; } // 篡改glibc malloc_chunk的size字段(破坏分配器私有结构) // 注:malloc_chunk结构依赖glibc版本,此代码适配常见x86/x86_64环境 size_t* size_field = (size_t*)((char*)ptr - sizeof(size_t)); *size_field = 0xdeadbeef; // 写入非法值破坏堆结构 // 释放内存触发检测 real_free(ptr); return 0; }
编译与运行验证
- 编译代码:
g++ -o malloc_corruption_test malloc_corruption_test.cpp -ldl - ASAN环境下运行(无报错):
ASAN_OPTIONS=detect_leaks=0 ./malloc_corruption_test - MALLOC_CHECK_=3环境下运行(触发堆结构损坏报错):
运行后会输出类似错误:MALLOC_CHECK_=3 ./malloc_corruption_test*** Error in './malloc_corruption_test': corrupted double-linked list: 0x000000000209a010 ***
结论
- 上述测试用例证实了特殊场景下MALLOC_CHECK_=3能检测到ASAN覆盖不到的内存错误。
- 常规开发中,ASAN已能覆盖绝大多数内存错误场景;但如果项目存在绕过标准分配器的底层代码、动态加载模块,保留MALLOC_CHECK_=3作为补充检测仍有必要。
内容的提问来源于stack exchange,提问作者Lajos Nagy
相关产品推荐
相关产品推荐

