介绍
ASan,即Address Sanitizer,是一个适用于C/C++程序的动态内存错误检测器
编译选项
1. 常用选项
ASAN_CFLAGS += -static-libasan -fsanitize=address -fno-omit-frame-pointer -fsanitize-recover=all -g
- 链接库
- 动态库方式:
-lasan
- 静态库方式:
-static-libasan
- 动态库方式:
-
-fsanitize=address
核心的选项,内存检测(包括内存泄漏)
-
-fno-omit-frame-pointer
保留栈帧指针,便于asan生成更完整的调用栈信息
-
-fsanitize-recover=address/all
一般后台程序为保证稳定性,不能遇到错误就简单退出,而是继续运行,采用该选项支持内存出错之后程序继续运行,需要叠加设置
ASAN_OPTIONS=halt_on_error=0
才会生效;若未设置此选项,则内存出错即报错退出
-
-g1
表示最小调试信息,通常debug版本用-g即
-g2
-
-O1
或更高优化级别如果想要在使用asan的时候获取更好的性能,可以加上O1或者更高的编译优化选项;
-
-fno-stack-protector
去使能栈溢出保护
2.其他选项
除了 -fsanitize=address
外,还有其他 AddressSanitizer 相关的编译选项可供选择。以下是一些常用的 AddressSanitizer 编译选项及其作用:
-fsanitize=memory
:用于检测对未初始化内存或使用已释放内存的操作。这个选项可以帮助发现一些难以察觉的内存错误。fsanitize=undefined
:用于检测未定义行为,例如整数溢出、空指针解引用等问题。这有助于发现代码中的潜在 bug。-fsanitize=thread
:用于检测多线程程序中的数据竞争和死锁问题。这个选项可以帮助识别并修复多线程程序中的并发 bug。-fsanitize=leak
:启用 AddressSanitizer 的同时,也检测内存泄漏问题。这个选项有助于发现代码中的内存泄漏 bug。-fsanitize=coverage
:用于生成代码覆盖率报告,检测程序中哪些部分被执行过。这个选项通常用于代码覆盖率测试和分析。-fsanitize=kernel-address
:针对 Linux 内核模块开发,用于检测内核中的内存错误。
运行选项
export ASAN_OPTIONS="halt_on_error=0:log_path=/root/asan.log"
-
halt_on_error=0
检测内存错误后继续运行
-
detect_leaks=1
使能内存泄露检测
-
malloc_context_size=15
内存错误发生时,显示的调用栈层数为15
-
log_path=/home/xos/asan.log
内存检查问题日志存放文件路径
更多选项
ASAN_OPTIONS=help=1 ./asan_app
示例
1.源代码
#include<stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
void leak_memory()
{
int* p = malloc(sizeof(int)*10);
}
void while_print()
{
int cnt = 0;
while(1)
{
printf("cnt = %d\n", cnt++);
sleep(10);
}
}
int g_arr[10] = {0};
int main()
{
printf("main begin\n");
g_arr[12] = 12;
int *heap_arr = malloc(sizeof(int) * 5);
heap_arr[5] = 10;
free(heap_arr);
int stack_arr[10];
stack_arr[11] = 11;
int* p = malloc(sizeof(int));
free(p);
*p = 9;
leak_memory();
//while_print();
printf("main end\n");
return 0;
}
2.编译选项
gcc -o app main.c -static-libasan -fsanitize=address -g -fno-omit-frame-pointer -fsanitize-recover=all
3.运行选项
export ASAN_OPTIONS="halt_on_error=0:log_path=asan_log"
./app
4.asan_log内容
=================================================================
==2753==ERROR: AddressSanitizer: global-buffer-overflow on address 0x005a3cf0 at pc 0x0011b6bc bp 0xaeeea6bc sp 0xaeeea6b4
WRITE of size 4 at 0x005a3cf0 thread T0
#0 0x11b6bb in main /home/ypd/samba_top/mycode/asan/main.c:27
#1 0xa6d214e3 in __libc_start_main (/lib/libc.so.6+0x174e3)
0x005a3cf0 is located 8 bytes to the right of global variable 'g_arr' defined in 'main.c:22:5' (0x5a3cc0) of size 40
SUMMARY: AddressSanitizer: global-buffer-overflow /home/ypd/samba_top/mycode/asan/main.c:27 in main
Shadow bytes around the buggy address:
0x200b4740: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x200b4750: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x200b4760: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x200b4770: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x200b4780: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x200b4790: 00 00 00 00 00 00 00 00 00 00 00 00 00 f9[f9]f9
0x200b47a0: f9 f9 f9 f9 00 00 00 00 00 00 00 00 00 00 00 00
0x200b47b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x200b47c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x200b47d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x200b47e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
=================================================================
==2753==ERROR: AddressSanitizer: heap-buffer-overflow on address 0xa4400b94 at pc 0x0011b73c bp 0xaeeea6bc sp 0xaeeea6b4
WRITE of size 4 at 0xa4400b94 thread T0
#0 0x11b73b in main /home/ypd/samba_top/mycode/asan/main.c:30
#1 0xa6d214e3 in __libc_start_main (/lib/libc.so.6+0x174e3)
0xa4400b94 is located 0 bytes to the right of 20-byte region [0xa4400b80,0xa4400b94)
allocated by thread T0 here:
#0 0xda8f3 in __interceptor_malloc /tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/src/gcc/libsanitizer/asan/asan_malloc_linux.cc:86
#1 0x11b6d3 in main /home/ypd/samba_top/mycode/asan/main.c:29
#2 0xa6d214e3 in __libc_start_main (/lib/libc.so.6+0x174e3)
SUMMARY: AddressSanitizer: heap-buffer-overflow /home/ypd/samba_top/mycode/asan/main.c:30 in main
Shadow bytes around the buggy address:
0x34880120: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x34880130: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x34880140: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x34880150: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x34880160: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x34880170: 00 00[04]fa fa fa fa fa fa fa fa fa fa fa fa fa
0x34880180: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x34880190: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x348801a0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x348801b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x348801c0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
=================================================================
==2753==ERROR: AddressSanitizer: stack-buffer-overflow on address 0xaeeea72c at pc 0x0011b7a8 bp 0xaeeea6bc sp 0xaeeea6b4
WRITE of size 4 at 0xaeeea72c thread T0
#0 0x11b7a7 in main /home/ypd/samba_top/mycode/asan/main.c:34
#1 0xa6d214e3 in __libc_start_main (/lib/libc.so.6+0x174e3)
Address 0xaeeea72c is located in stack of thread T0 at offset 76 in frame
#0 0x11b5d3 in main /home/ypd/samba_top/mycode/asan/main.c:24
This frame has 1 object(s):
[32, 72) 'stack_arr' <== Memory access at offset 76 overflows this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism or swapcontext
(longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow /home/ypd/samba_top/mycode/asan/main.c:34 in main
Shadow bytes around the buggy address:
0x35ddd490: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x35ddd4a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x35ddd4b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x35ddd4c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x35ddd4d0: 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1
=>0x35ddd4e0: 00 00 00 00 00[f2]f2 f2 f3 f3 f3 f3 00 00 00 00
0x35ddd4f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x35ddd500: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x35ddd510: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x35ddd520: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x35ddd530: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
=================================================================
==2753==ERROR: AddressSanitizer: heap-use-after-free on address 0xa3e007b0 at pc 0x0011b820 bp 0xaeeea6bc sp 0xaeeea6b4
WRITE of size 4 at 0xa3e007b0 thread T0
#0 0x11b81f in main /home/ypd/samba_top/mycode/asan/main.c:38
#1 0xa6d214e3 in __libc_start_main (/lib/libc.so.6+0x174e3)
0xa3e007b0 is located 0 bytes inside of 4-byte region [0xa3e007b0,0xa3e007b4)
freed by thread T0 here:
#0 0xda5bf in __interceptor_free /tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/src/gcc/libsanitizer/asan/asan_malloc_linux.cc:66
#1 0x11b7c7 in main /home/ypd/samba_top/mycode/asan/main.c:37
#2 0xa6d214e3 in __libc_start_main (/lib/libc.so.6+0x174e3)
previously allocated by thread T0 here:
#0 0xda8f3 in __interceptor_malloc /tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/src/gcc/libsanitizer/asan/asan_malloc_linux.cc:86
#1 0x11b7b7 in main /home/ypd/samba_top/mycode/asan/main.c:36
#2 0xa6d214e3 in __libc_start_main (/lib/libc.so.6+0x174e3)
SUMMARY: AddressSanitizer: heap-use-after-free /home/ypd/samba_top/mycode/asan/main.c:38 in main
Shadow bytes around the buggy address:
0x347c00a0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x347c00b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x347c00c0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x347c00d0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x347c00e0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x347c00f0: fa fa fa fa fa fa[fd]fa fa fa fa fa fa fa fa fa
0x347c0100: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x347c0110: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x347c0120: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x347c0130: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x347c0140: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
=================================================================
==2753==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 40 byte(s) in 1 object(s) allocated from:
#0 0xda8f3 in __interceptor_malloc /tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/src/gcc/libsanitizer/asan/asan_malloc_linux.cc:86
#1 0x11b573 in leak_memory /home/ypd/samba_top/mycode/asan/main.c:9
#2 0x11b82f in main /home/ypd/samba_top/mycode/asan/main.c:40
#3 0xa6d214e3 in __libc_start_main (/lib/libc.so.6+0x174e3)
SUMMARY: AddressSanitizer: 40 byte(s) leaked in 1 allocation(s).