0. 功能:
Use after free (dangling pointer dereference)
Heap buffer overflow
Stack buffer overflow
Global buffer overflow
Use after return
Use after scope
Initialization order bugs
Memory leaks
原文链接:https://blog.csdn.net/weixin_41644391/article/details/103450401
1、Use after free (dangling pointer dereference)
// RUN: clang -O -g -fsanitize=address %t && ./a.out
int main(int argc, char **argv) {
int *array = new int[100];
delete [] array;
return array[argc]; // BOOM
}
=================================================================
==6254== ERROR: AddressSanitizer: heap-use-after-free on address 0x603e0001fc64 at pc 0x417f6a bp 0x7fff626b3250 sp 0x7fff626b3248
READ of size 4 at 0x603e0001fc64 thread T0
#0 0x417f69 in main example_UseAfterFree.cc:5
#1 0x7fae62b5076c (/lib/x86_64-linux-gnu/libc.so.6+0x2176c)
#2 0x417e54 (a.out+0x417e54)
0x603e0001fc64 is located 4 bytes inside of 400-byte region [0x603e0001fc60,0x603e0001fdf0)
freed by thread T0 here:
#0 0x40d4d2 in operator delete[](void*) /home/kcc/llvm/projects/compiler-rt/lib/asan/asan_new_delete.cc:61
#1 0x417f2e in main example_UseAfterFree.cc:4
previously allocated by thread T0 here:
#0 0x40d312 in operator new[](unsigned long) /home/kcc/llvm/projects/compiler-rt/lib/asan/asan_new_delete.cc:46
#1 0x417f1e in main example_UseAfterFree.cc:3
Shadow bytes around the buggy address:
0x1c07c0003f30: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x1c07c0003f40: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x1c07c0003f50: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x1c07c0003f60: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x1c07c0003f70: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x1c07c0003f80: fa fa fa fa fa fa fa fa fa fa fa fa[fd]fd fd fd
0x1c07c0003f90: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x1c07c0003fa0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x1c07c0003fb0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fa fa
0x1c07c0003fc0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x1c07c0003fd0: 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
Heap righ redzone: fb
Freed Heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack partial redzone: f4
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
ASan internal: fe
==6254== ABORTING
2、Heap buffer overflow
// RUN: clang -O -g -fsanitize=address %t && ./a.out
int main(int argc, char **argv) {
int *array = new int[100];
array[0] = 0;
int res = array[argc + 100]; // BOOM
delete [] array;
return res;
}
=================================================================
==6226== ERROR: AddressSanitizer: heap-buffer-overflow on address 0x603e0001fdf4 at pc 0x417f8c bp 0x7fff64c0c010 sp 0x7fff64c0c008
READ of size 4 at 0x603e0001fdf4 thread T0
#0 0x417f8b in main example_HeapOutOfBounds.cc:5
#1 0x7fa97c09376c (/lib/x86_64-linux-gnu/libc.so.6+0x2176c)
#2 0x417e54 (a.out+0x417e54)
0x603e0001fdf4 is located 4 bytes to the right of 400-byte region [0x603e0001fc60,0x603e0001fdf0)
allocated by thread T0 here:
#0 0x40d312 in operator new[](unsigned long) /home/kcc/llvm/projects/compiler-rt/lib/asan/asan_new_delete.cc:46
#1 0x417f1c in main example_HeapOutOfBounds.cc:3
Shadow bytes around the buggy address:
0x1c07c0003f60: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x1c07c0003f70: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x1c07c0003f80: fa fa fa fa fa fa fa fa fa fa fa fa 00 00 00 00
0x1c07c0003f90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1c07c0003fa0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x1c07c0003fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00[fa]fa
0x1c07c0003fc0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x1c07c0003fd0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x1c07c0003fe0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x1c07c0003ff0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x1c07c0004000: 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
Heap righ redzone: fb
Freed Heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack partial redzone: f4
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
ASan internal: fe
==6226== ABORTING
3、Stack buffer overflow
// RUN: clang -O -g -fsanitize=address %t && ./a.out
int main(int argc, char **argv) {
int stack_array[100];
stack_array[1] = 0;
return stack_array[argc + 100]; // BOOM
}
=================================================================
==6240== ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7fff8098b2b4 at pc 0x417fe1 bp 0x7fff8098b0f0 sp 0x7fff8098b0e8
READ of size 4 at 0x7fff8098b2b4 thread T0
#0 0x417fe0 in main example_StackOutOfBounds.cc:5
#1 0x7fa3667c976c (/lib/x86_64-linux-gnu/libc.so.6+0x2176c)
#2 0x417e54 (a.out+0x417e54)
Address 0x7fff8098b2b4 is located at offset 436 in frame <main> of T0's stack:
This frame has 1 object(s):
[32, 432) 'stack_array'
HINT: this may be a false positive if your program uses some custom stack unwind mechanism or swapcontext
(longjmp and C++ exceptions *are* supported)
Shadow bytes around the buggy address:
0x1ffff0131600: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1ffff0131610: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1ffff0131620: f1 f1 f1 f1 00 00 00 00 00 00 00 00 00 00 00 00
0x1ffff0131630: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1ffff0131640: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x1ffff0131650: 00 00 00 00 00 00[f4]f4 f3 f3 f3 f3 00 00 00 00
0x1ffff0131660: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1ffff0131670: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1ffff0131680: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1ffff0131690: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1ffff01316a0: 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
Heap righ redzone: fb
Freed Heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack partial redzone: f4
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
ASan internal: fe
==6240== ABORTING
4、Global buffer overflow
// RUN: clang -O -g -fsanitize=address %t && ./a.out
int global_array[100] = {-1};
int main(int argc, char **argv) {
return global_array[argc + 100]; // BOOM
}
=================================================================
==6211== ERROR: AddressSanitizer: global-buffer-overflow on address 0x000000622314 at pc 0x417fee bp 0x7fff2e146300 sp 0x7fff2e1462f8
READ of size 4 at 0x000000622314 thread T0
#0 0x417fed in main example_GlobalOutOfBounds.cc:4
#1 0x7f1c10d2a76c (/lib/x86_64-linux-gnu/libc.so.6+0x2176c)
#2 0x417ef4 (a.out+0x417ef4)
0x000000622314 is located 4 bytes to the right of global variable 'global_array (example_GlobalOutOfBounds.cc)' (0x622180) of size 400
Shadow bytes around the buggy address:
0x1000000c4410: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1000000c4420: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1000000c4430: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1000000c4440: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1000000c4450: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x1000000c4460: 00 00[f9]f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9
0x1000000c4470: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1000000c4480: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1000000c4490: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1000000c44a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1000000c44b0: 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
Heap righ redzone: fb
Freed Heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack partial redzone: f4
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
ASan internal: fe
==6211== ABORTING
5、Use after return
// RUN: clang -O -g -fsanitize=address %t && ./a.out
// By default, AddressSanitizer does not try to detect
// stack-use-after-return bugs.
// It may still find such bugs occasionally
// and report them as a hard-to-explain stack-buffer-overflow.
// You need to run the test with ASAN_OPTIONS=detect_stack_use_after_return=1
int *ptr;
__attribute__((noinline))
void FunctionThatEscapesLocalObject() {
int local[100];
ptr = &local[0];
}
int main(int argc, char **argv) {
FunctionThatEscapesLocalObject();
return ptr[argc];
}
=================================================================
==6268== ERROR: AddressSanitizer: stack-use-after-return on address 0x7fa19a8fc024 at pc 0x4180d5 bp 0x7fff73c3fc50 sp 0x7fff73c3fc48
READ of size 4 at 0x7fa19a8fc024 thread T0
#0 0x4180d4 in main example_UseAfterReturn.cc:17
#1 0x7fa19b11d76c (/lib/x86_64-linux-gnu/libc.so.6+0x2176c)
#2 0x417f34 (a.out+0x417f34)
Address 0x7fa19a8fc024 is located at offset 36 in frame <_Z30FunctionThatEscapesLocalObjectv> of T0's stack:
This frame has 1 object(s):
[32, 432) 'local'
HINT: this may be a false positive if your program uses some custom stack unwind mechanism or swapcontext
(longjmp and C++ exceptions *are* supported)
Shadow bytes around the buggy address:
0x1ff43351f7b0: fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe
0x1ff43351f7c0: fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe
0x1ff43351f7d0: fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe
0x1ff43351f7e0: fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe
0x1ff43351f7f0: fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe
=>0x1ff43351f800: f5 f5 f5 f5[f5]f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
0x1ff43351f810: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
0x1ff43351f820: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
0x1ff43351f830: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 00 00 00 00
0x1ff43351f840: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1ff43351f850: 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
Heap righ redzone: fb
Freed Heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack partial redzone: f4
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
ASan internal: fe
==6268== ABORTING
6、Use after scope
// RUN: clang -O -g -fsanitize=address -fsanitize-address-use-after-scope \
// use-after-scope.cpp -o /tmp/use-after-scope
// RUN: /tmp/use-after-scope
// Check can be disabled in run-time:
// RUN: ASAN_OPTIONS=detect_stack_use_after_scope=0 /tmp/use-after-scope
volatile int *p = 0;
int main() {
{
int x = 0;
p = &x;
}
*p = 5;
return 0;
}
=================================================================
==58237==ERROR: AddressSanitizer: stack-use-after-scope on address 0x7ffc4d830880 at pc 0x0000005097ed bp 0x7ffc4d830850 sp 0x7ffc4d830848
WRITE of size 4 at 0x7ffc4d830880 thread T0
#0 0x5097ec (/tmp/use-after-scope+0x5097ec)
#1 0x7ff85fa6bf44 (/lib/x86_64-linux-gnu/libc.so.6+0x21f44)
#2 0x41a005 (/tmp/use-after-scope+0x41a005)
Address 0x7ffc4d830880 is located in stack of thread T0 at offset 32 in frame
#0 0x5096ef (/tmp/use-after-scope+0x5096ef)
This frame has 1 object(s):
[32, 36) 'x' <== Memory access at offset 32 is inside 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-use-after-scope (/tmp/use-after-scope+0x5097ec)
Shadow bytes around the buggy address:
0x100009afe0c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100009afe0d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100009afe0e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100009afe0f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100009afe100: 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1
=>0x100009afe110:[f8]f3 f3 f3 00 00 00 00 00 00 00 00 00 00 00 00
0x100009afe120: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100009afe130: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100009afe140: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100009afe150: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100009afe160: 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
Heap right redzone: fb
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack partial redzone: f4
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
==58237==ABORTING
7、Initialization order bugs
静态初始化顺序失败是 C++ 程序中与构造全局对象的顺序有关的常见问题。未指定不同源文件中全局对象的构造函数的运行顺序。Parashift C++ FAQ 的第 10.14-10.18 节很好地解释了问题是什么,以及可以做些什么来纠正它。这是一个简短的例子:
$ cat tmp/init-order/example/a.cc
#include <stdio.h>
extern int extern_global;
int __attribute__((noinline)) read_extern_global() {
return extern_global;
}
int x = read_extern_global() + 1;
int main() {
printf("%d\n", x);
return 0;
}
$ cat tmp/init-order/example/b.cc
int foo() { return 42; }
int extern_global = foo();
这里的值 ifx
取决于 的值extern_global
,根据翻译单元的初始化程序运行的顺序,它可能会或可能不会被初始化为“42”:
$ clang++ tmp/init-order/example/a.cc tmp/init-order/example/b.cc && ./a.out
1
$ clang++ tmp/init-order/example/b.cc tmp/init-order/example/a.cc && ./a.out
43
这些错误很难被发现,并且可能会一直被忽视,直到代码(或编译器或链接策略)中的一些不相关的更改改变了代码行为,通常会以意想不到的方式破坏它。
AddressSanitizer 中的初始化顺序检查器
AddressSanitizer将检查插入到编译程序中,旨在检测初始化顺序问题。默认情况下它们是关闭的,您必须传递运行时标志才能启用它们。请参阅示例用法。
松散的初始化顺序检查
如果全局变量的初始化程序从另一个尚未初始化的翻译单元访问动态初始化的 global ,则此模式会报告错误。使用check_initialization_order=true
来激活它:
$ clang++ -fsanitize=address -g tmp/init-order/example/a.cc tmp/init-order/example/b.cc
$ ASAN_OPTIONS=check_initialization_order=true ./a.out
=================================================================
==26772==ERROR: AddressSanitizer: initialization-order-fiasco on address 0x000001068820 at pc 0x427e74 bp 0x7ffff8295010 sp 0x7ffff8295008
READ of size 4 at 0x000001068820 thread T0
#0 0x427e73 in read_extern_global() tmp/init-order/example/a.cc:4
#1 0x42806c in __cxx_global_var_init tmp/init-order/example/a.cc:7
#2 0x4280d5 in global constructors keyed to a tmp/init-order/example/a.cc:10
#3 0x42823c in __libc_csu_init (a.out+0x42823c)
#4 0x7f9afdbdb6ff (/lib/x86_64-linux-gnu/libc.so.6+0x216ff)
#5 0x427d64 (a.out+0x427d64)
0x000001068820 is located 0 bytes inside of global variable 'extern_global' from 'tmp/init-order/example/b.cc' (0x1068820) of size 4
SUMMARY: AddressSanitizer: initialization-order-fiasco tmp/init-order/example/a.cc:4 read_extern_global()
<...>
从某种意义上说,这种模式报告了存在的问题。如果初始化的顺序发生变化,可能不会报错:
$ clang++ -fsanitize=address -g tmp/init-order/example/b.cc tmp/init-order/example/a.cc
$ ASAN_OPTIONS=check_initialization_order=true ./a.out
43
严格的初始化顺序检查
如果全局变量的初始化程序从另一个翻译单元访问任何动态初始化的全局变量,则此模式会报告错误。使用附加变量strict_init_order=true
来激活它:
$ clang++ -fsanitize=address -g tmp/init-order/example/b.cc tmp/init-order/example/a.cc
$ ASAN_OPTIONS=check_initialization_order=true:strict_init_order=true ./a.out
=================================================================
==27853==ERROR: AddressSanitizer: initialization-order-fiasco on address 0x0000010687e0 at pc 0x427f74 bp 0x7fff3d076ba0 sp 0x7fff3d076b98
READ of size 4 at 0x0000010687e0 thread T0
#0 0x427f73 in read_extern_global() tmp/init-order/example/a.cc:4
<...>
通过这种方式,您还可能会发现潜在的初始化顺序问题。
误报
- 当期望从另一个翻译单元访问已初始化的全局变量时,或者当通过例如使用共享库强制执行特定的构造顺序时,严格的初始化顺序检查可能会报告误报。
- 松散的初始化顺序检查可能会报告动态初始化的全局变量的误报,在初始化之前仍然可以安全地访问它们(例如,如果它们的构造函数什么都不做)。
黑名单
您可以通过使用该-fsanitize-blacklist=path/to/blacklist.txt
选项来抑制某些全局变量上的 init-order 检查器的误报。相关黑名单条目有:
# Disable init-order checking for a single variable:
global:bad_variable=init
# Disable checking for all variables of a given type:
type:Namespace::ClassName=init
# Disable checking for all variables in given files:
src:path/to/bad/files/*=init
表现
Init-order 会减慢程序启动速度。它的复杂度是O(NM)
,其中N
是二进制中动态初始化的全局变量M
的总数, 是翻译单元的总数。
8、Memory leaks
介绍
LeakSanitizer 是一个内存泄漏检测器,它集成到AddressSanitizer 中。该工具在 x86_64 Linux 和 OS X 上受支持。
LeakSanitizer 在 x86_64 Linux 的 ASan 版本中默认启用,并且可以ASAN_OPTIONS=detect_leaks=1
在 x86_64 OS X 上启用。 LSan 处于休眠状态,直到过程结束,此时有一个额外的泄漏检测阶段。在性能关键的场景中,LSan 也可以在没有 ASan 检测的情况下使用。
另请参阅:设计文档,与 tcmalloc 的堆泄漏检查器的比较
使用 LeakSanitizer
要使用 LSan,只需使用AddressSanitizer构建您的程序:
$ cat memory-leak.c
#include <stdlib.h>
void *p;
int main() {
p = malloc(7);
p = 0; // The memory is leaked here.
return 0;
}
$ clang -fsanitize=address -g memory-leak.c
$ ./a.out
=================================================================
==7829==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 7 byte(s) in 1 object(s) allocated from:
#0 0x42c0c5 in __interceptor_malloc /usr/home/hacker/llvm/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:74
#1 0x43ef81 in main /usr/home/hacker/memory-leak.c:6
#2 0x7fef044b876c in __libc_start_main /build/buildd/eglibc-2.15/csu/libc-start.c:226
SUMMARY: AddressSanitizer: 7 byte(s) leaked in 1 allocation(s).
如果你想在不泄漏检测运行牙山仪表程序,你可以通过detect_leaks=0
在ASAN_OPTIONS
环境变量中。
单机模式
如果你只需要泄漏检测,并不愿意承担阿三放缓,你可以建立-fsanitize=leak
替代-fsanitize=address
。这会将您的程序链接到一个运行时库,该库只包含 LeakSanitizer 工作所需的基本必需品。不会应用任何编译时检测。
请注意,与在 ASan 之上运行 LSan 相比,独立模式的测试效果较差。
旗帜
您可以通过LSAN_OPTIONS
环境变量微调 LeakSanitizer 的行为。
旗帜 | 默认 | 描述 |
---|---|---|
退出码 | 23 | 如果非零,LSan 将调用_exit(exitcode) 检测泄漏。这可能与用于发出 ASan 错误信号的退出代码不同。 |
最大泄漏 | 0 | 如果非零,则仅报告这么多*泄漏。 |
镇压 | (没有任何) | 包含抑制规则的文件路径(见下文) |
打印抑制 | 1 | 如果为 1,则打印匹配抑制的统计信息。 |
报告对象 | 0 | 如果为 1,LSan 将报告个别泄漏对象的地址。 |
use_unaligned | 0 | 如果为 0,则 LSan 在查找指针时将仅考虑正确对齐的 8 字节模式。设置为 1 以包括未对齐的图案。这是指指针本身,而不是指向的内存。 |
泄漏检测也受某些ASan 标志的影响。如果你不愉快的堆栈跟踪你看,检查fast_unwind_on_malloc
,malloc_context_size
和strip_path_prefix
。那些标志ASAN_OPTIONS
照常进入。但是,如果您使用 构建-fsanitize=leak
,请将它们放入LSAN_OPTIONS
(并用于LSAN_SYMBOLIZER_PATH
传递符号路径)。
抑制
您可以通过传入抑制文件来指示 LeakSanitizer 忽略某些泄漏。该文件的每行必须包含一个抑制规则,每条规则的格式为leak:<pattern>
. 该模式将与泄漏的符号堆栈跟踪进行子字符串匹配。如果函数名、源文件名或二进制文件名匹配,泄漏报告将被抑制。
$ cat suppr.txt
# This is a known leak.
leak:FooBar
$ cat lsan-suppressed.cc
#include <stdlib.h>
void FooBar() {
malloc(7);
}
void Baz() {
malloc(5);
}
int main() {
FooBar();
Baz();
return 0;
}
$ clang++ lsan-suppressed.cc -fsanitize=address
$ ASAN_OPTIONS=detect_leaks=1 LSAN_OPTIONS=suppressions=suppr.txt ./a.out
=================================================================
==26475==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 5 byte(s) in 1 object(s) allocated from:
#0 0x44f2de in malloc /usr/home/hacker/llvm/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:74
#1 0x464e86 in Baz() (/usr/home/hacker/a.out+0x464e86)
#2 0x464fb4 in main (/usr/home/hacker/a.out+0x464fb4)
#3 0x7f7e760b476c in __libc_start_main /build/buildd/eglibc-2.15/csu/libc-start.c:226
-----------------------------------------------------
Suppressions used:[design document](AddressSanitizerLeakSanitizerDesignDocument)
count bytes template
1 7 FooBar
-----------------------------------------------------
SUMMARY: AddressSanitizer: 5 byte(s) leaked in 1 allocation(s).
特殊符号^
和$
匹配字符串的开头和结尾。