简介
https://zhuanlan.zhihu.com/p/360135083
使用方式
添加编译选项
-Lasan -fsanitize=address -fsanitize-recover=address -fno-omit-frame-pointer
编写代码文件,如添加test_asan.c
#include<stdio.h>
#include<stdlib.h>
int main(){
//未释放的内存,会产生内存泄漏
int* arr = (int*)malloc(sizeof(int) * 10);
return 0;
}
1.gcc添加方式
gcc -g test_asan.c -o t1 -Lasan -fsanitize=address -fsanitize-recover=address -fno-omit-frame-pointer
2.CMakeLists添加方式
cmake_minimum_required(VERSION 2.8)
project(test C)
set(CMAKE_C_STANDARD 99)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -Lasan -fsanitize=address -fsanitize-recover=address -fno-omit-frame-pointer")
add_executable(t1 test_asan.c)
ps:一般需要添加-g,否则仅仅会输出错误,找不到对应函数与行号。
重新编译生成可执行文件
查找动态库位置
find /usr -name 'libasan.so'
#/usr里面没有也可以全局查找或自行安装
find / -name 'libasan.so'
#输出位置如下
/usr/local/lib64/libasan.so
添加动态库
export LD_PRELOAD=/usr/local/lib64/libasan.so
执行程序,可以看到内存泄漏问题并定位
./t1
=================================================================
==2154==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 40 byte(s) in 1 object(s) allocated from:
#0 0xffff852eb67b in __interceptor_malloc ../../.././libsanitizer/asan/asan_malloc_linux.cc:62
#1 0x400853 in main /home/lichangshi/ML2/my_test/test_ascan.c:5
#2 0xffff850a1723 in __libc_start_main (/lib64/libc.so.6+0x21723)
#3 0x40076b (/home/lichangshi/ML2/my_test/t1+0x40076b)
#4 0xffffe963f53c (<unknown module>)
第二次编译之前需要清除添加的动态库
unset LD_PRELOAD
注意:
一定要在编译之后添加动态库位置,如果在编译前添加libasan.so动态库,编译阶段输出以下错误,CMake无法生成可执行文件。
=================================================================
==2644==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 112 byte(s) in 1 object(s) allocated from:
#0 0xffffa2f3b82b in __interceptor_calloc ../../.././libsanitizer/asan/asan_malloc_linux.cc:70
#1 0xf2748b in xcalloc ../.././libiberty/xmalloc.c:162
#2 0xf2463b in htab_create_typed_alloc ../.././libiberty/hashtab.c:357
#3 0xef0243 in linemap_init(line_maps*, unsigned int) ../.././libcpp/line-map.c:354
#4 0x542aa3 in general_init ../.././gcc/toplev.c:1141
#5 0x542aa3 in toplev::main(int, char**) ../.././gcc/toplev.c:2092
#6 0x544823 in main ../.././gcc/main.c:39
#7 0xffffa2ab1723 in __libc_start_main (/lib64/libc.so.6+0x21723)
#8 0x544c8b (/usr/local/libexec/gcc/aarch64-unknown-linux-gnu/7.3.0/cc1+0x544c8b)
#9 0xfffff243f2e6 (<unknown module>)
...省略
上述错误显示的文件为linux中的代码文件,推测是cmake可能存在内存泄漏问题,或cmake的执行代码中的malloc被替换为Ascan中的申请方式可能无法正确执行。具体原因还请相关专业人士解答。
常见错误类型
1.内存泄漏(Memory leaks),即申请的内存未释放。
#include<stdio.h>
#include<stdlib.h>
int main(){
//未释放的内存,会产生内存泄漏
int* arr = (int*)malloc(sizeof(int) * 10);
return 0;
}
./t1
=================================================================
==2154==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 40 byte(s) in 1 object(s) allocated from:
#0 0xffff852eb67b in __interceptor_malloc ../../.././libsanitizer/asan/asan_malloc_linux.cc:62
#1 0x400853 in main /home/lichangshi/ML2/my_test/test_ascan.c:5
#2 0xffff850a1723 in __libc_start_main (/lib64/libc.so.6+0x21723)
#3 0x40076b (/home/lichangshi/ML2/my_test/t1+0x40076b)
#4 0xffffe963f53c (<unknown module>)
2.栈溢出(Stack buffer overflow),函数中的变量,参数,引用,指针,返回地址等存储在栈中,若超出栈的容量会导致栈溢出,常见情形为递归过深或申请的数组过大。
void stack_buffer_overflow(){
long long len = 1024*1024*1024;
double a[len];
for(int i = 0; i < len; i++){
a[i] = -1.0;
}
return;
}
int main(){
stack_buffer_overflow();
return 0;
}
ASAN:DEADLYSIGNAL
=================================================================
==10239==ERROR: AddressSanitizer: stack-overflow on address 0xfffde74c4500 (pc 0x000000400b0c bp 0xffffe74c4510 sp 0xfffde74c4500 T0)
#0 0x400b0b in stack_buffer_overflow /home/lichangshi/ML2/my_test/test_asan.c:13
#1 0x400b4f in main /home/lichangshi/ML2/my_test/test_asan.c:19
#2 0xffff97301723 in __libc_start_main (/lib64/libc.so.6+0x21723)
#3 0x40093b (/home/lichangshi/ML2/my_test/build/test+0x40093b)
SUMMARY: AddressSanitizer: stack-overflow /home/lichangshi/ML2/my_test/test_asan.c:13 in stack_buffer_overflow
==10239==ABORTING
SUMMARY: AddressSanitizer: stack-overflow (/home/lichangshi/ML2/my_test/build/test+0x400b0b) in stack_buffer_overflow
==10284==ABORTING
3.堆溢出(heap buffer overflow)。堆中存储动态申请内存,如malloc(), calloc(), new int[]等,常见情况为访问到申请内存之外的地址。
void heap_buffer_overflow(){
int* a = (int*)malloc(sizeof(int)*10);
a[11] = 1;
return;
}
int main(){
heap_buffer_overflow();
return 0;
}
=================================================================
==10349==ERROR: AddressSanitizer: heap-buffer-overflow on address 0xffffb4c00f7c at pc 0x000000400c44 bp 0xfffffbffb640 sp 0xfffffbffb658
WRITE of size 4 at 0xffffb4c00f7c thread T0
#0 0x400c43 in heap_buffer_overflow /home/lichangshi/ML2/my_test/test_asan.c:20
#1 0x400c67 in main /home/lichangshi/ML2/my_test/test_asan.c:25
#2 0xffffb8091723 in __libc_start_main (/lib64/libc.so.6+0x21723)
#3 0x4009cb (/home/lichangshi/ML2/my_test/build/test+0x4009cb)
0xffffb4c00f7c is located 4 bytes to the right of 40-byte region [0xffffb4c00f50,0xffffb4c00f78)
allocated by thread T0 here:
#0 0xffffb838b67b in __interceptor_malloc ../../.././libsanitizer/asan/asan_malloc_linux.cc:62
#1 0x400be7 in heap_buffer_overflow /home/lichangshi/ML2/my_test/test_asan.c:19
#2 0x400c67 in main /home/lichangshi/ML2/my_test/test_asan.c:25
#3 0xffffb8091723 in __libc_start_main (/lib64/libc.so.6+0x21723)
#4 0x4009cb (/home/lichangshi/ML2/my_test/build/test+0x4009cb)
#5 0xfffffbfff53c (<unknown module>)
SUMMARY: AddressSanitizer: heap-buffer-overflow /home/lichangshi/ML2/my_test/test_asan.c:20 in heap_buffer_overflow
Shadow bytes around the buggy address:
0x200ff6980190: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x200ff69801a0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x200ff69801b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x200ff69801c0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x200ff69801d0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x200ff69801e0: fa fa fa fa fa fa fa fa fa fa 00 00 00 00 00[fa]
0x200ff69801f0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x200ff6980200: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x200ff6980210: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x200ff6980220: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x200ff6980230: 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
==10349==ABORTING
4.全局溢出(Global buffer overflow)。
把超大静态数组/放到全局变量中或越界访问静态数组,不写了。
等等
参考链接
https://zhuanlan.zhihu.com/p/360135083
https://www.jianshu.com/p/9e85345e500b
栈溢出是什么:
https://zhuanlan.zhihu.com/p/73411916
堆溢出是什么:
https://eternalsakura13.com/2018/02/28/heap_exp1/