Description
Support Google Address Sanitizer, by chen-guanghua.
Address Sanitizer
Address Sanitizer (Asan) is a fast memory error detection tool. Detailed introduction can be found at AddressSanitizer. Starting from gcc 4.8, AddressSanitizer became a part of gcc. However, for a better experience, it is recommended to use version 4.9 and above, as AddressSanitizer in gcc 4.8 is still incomplete, with the biggest drawback being the lack of symbol information.
To detect memory error issues as early as possible, the use of Asan for memory error detection has been added to SRS. The relevant submission can be found at #3212.
Usage in SRS
Considering the limited platform support of Address Sanitizer, SRS supports the x86_64 platform. Two new configuration options have been added:
- --sanitizer: Enable memory detection feature. Enabled by default.
- --sanitizer-static: On some platforms, static linking of libasan is required, such as ubuntu20-amd64. Disabled by default.
The following are common memory detection errors, recommended for use on Ubuntu 20.
heap_use_after_free
Dangling pointer issue: Using memory that has already been freed.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
char *p = NULL;
p = (char*)malloc(16);
free(p);
p[0] = 'a';
return 0;
}
Compile and execute:
gcc -g -fsanitize=address heap_use_after_free.cpp -o heap_use_after_free
./heap_use_after_free
The errors after execution are as follows:
heap_use_after_free(29694,0x111c1d600) malloc: nano zone abandoned due to inability to preallocate reserved vm space.
=================================================================
==29694==ERROR: AddressSanitizer: heap-use-after-free on address 0x602000000090 at pc 0x000103a9df27 bp 0x7ff7bc4656a0 sp 0x7ff7bc465698
WRITE of size 1 at 0x602000000090 thread T0
#0 0x103a9df26 in main heap_use_after_free.cpp:12
#1 0x111ba252d in start+0x1cd (dyld:x86_64+0x552d)
0x602000000090 is located 0 bytes inside of 16-byte region [0x602000000090,0x6020000000a0)
freed by thread T0 here:
#0 0x103f23019 in wrap_free+0xa9 (libclang_rt.asan_osx_dynamic.dylib:x86_64h+0x4b019)
#1 0x103a9dee4 in main heap_use_after_free.cpp:10
#2 0x111ba252d in start+0x1cd (dyld:x86_64+0x552d)
previously allocated by thread T0 here:
#0 0x103f22ed0 in wrap_malloc+0xa0 (libclang_rt.asan_osx_dynamic.dylib:x86_64h+0x4aed0)
#1 0x103a9ded7 in main heap_use_after_free.cpp:8
#2 0x111ba252d in start+0x1cd (dyld:x86_64+0x552d)
SUMMARY: AddressSanitizer: heap-use-after-free heap_use_after_free.cpp:12 in main
Shadow bytes around the buggy address:
0x1c03ffffffc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1c03ffffffd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1c03ffffffe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1c03fffffff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1c0400000000: fa fa fd fd fa fa 00 00 fa fa 00 02 fa fa 00 04
=>0x1c0400000010: fa fa[fd]fd fa fa fa fa fa fa fa fa fa fa fa fa
0x1c0400000020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x1c0400000030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x1c0400000040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x1c0400000050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x1c0400000060: 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
==29694==ABORTING
[1] 29694 abort ./heap_use_after_free
The program crashed at the same place where the problem initially occurred, and it is also easy to fix.
heap_buffer_overflow
Dangling pointer: Memory out of bounds, using an address beyond the memory allocated to itself.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
char* p = (char*)malloc(16);
p[17] = 'a';
free(p);
return 0;
}
Compile and execute:
gcc -g -fsanitize=address heap-buffer-overflow.cpp -o heap-buffer-overflow
./heap-buffer-overflow
After execution, the error is as follows:
heap-buffer-overflow(32783,0x10cf61600) malloc: nano zone abandoned due to inability to preallocate reserved vm space.
=================================================================
==32783==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6020000000a1 at pc 0x000100ae1f1a bp 0x7ff7bf4216a0 sp 0x7ff7bf421698
WRITE of size 1 at 0x6020000000a1 thread T0
#0 0x100ae1f19 in main heap-buffer-overflow.cpp:8
#1 0x10cee652d in start+0x1cd (dyld:x86_64+0x552d)
0x6020000000a1 is located 1 bytes to the right of 16-byte region [0x602000000090,0x6020000000a0)
allocated by thread T0 here:
#0 0x100f66ed0 in wrap_malloc+0xa0 (libclang_rt.asan_osx_dynamic.dylib:x86_64h+0x4aed0)
#1 0x100ae1ecf in main heap-buffer-overflow.cpp:6
#2 0x10cee652d in start+0x1cd (dyld:x86_64+0x552d)
SUMMARY: AddressSanitizer: heap-buffer-overflow heap-buffer-overflow.cpp:8 in main
Shadow bytes around the buggy address:
0x1c03ffffffc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1c03ffffffd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1c03ffffffe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1c03fffffff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1c0400000000: fa fa fd fd fa fa 00 00 fa fa 00 02 fa fa 00 04
=>0x1c0400000010: fa fa 00 00[fa]fa fa fa fa fa fa fa fa fa fa fa
0x1c0400000020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x1c0400000030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x1c0400000040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x1c0400000050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x1c0400000060: 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
==32783==ABORTING
[1] 32783 abort ./heap-buffer-overflow
The program crashed at the very beginning where the problem first occurred, and it is also easy to fix.
stack_buffer_overflow
Wild pointer: stack address out of bounds.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
int arr[8] = {0};
arr[0] = 10;
arr[9] = 10;
return 0;
}
Compile and execute:
gcc -g -fsanitize=address stack_buffer_overflow.cpp -o stack_buffer_overflow
./stack_buffer_overflow
After execution, the error is as follows:
stack_buffer_overflow(25634,0x112f26600) malloc: nano zone abandoned due to inability to preallocate reserved vm space.
=================================================================
==25634==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ff7aff4a624 at pc 0x00010ffb8e7c bp 0x7ff7aff4a5d0 sp 0x7ff7aff4a5c8
WRITE of size 4 at 0x7ff7aff4a624 thread T0
#0 0x10ffb8e7b in main stack_buffer_overflow.cpp:9
#1 0x112eab52d in start+0x1cd (dyld:x86_64+0x552d)
Address 0x7ff7aff4a624 is located in stack of thread T0 at offset 68 in frame
#0 0x10ffb8d0f in main stack_buffer_overflow.cpp:5
This frame has 1 object(s):
[32, 64) 'arr' (line 6) <== Memory access at offset 68 overflows this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
(longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow stack_buffer_overflow.cpp:9 in main
Shadow bytes around the buggy address:
0x1ffef5fe9470: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1ffef5fe9480: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1ffef5fe9490: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1ffef5fe94a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1ffef5fe94b0: 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1
=>0x1ffef5fe94c0: 00 00 00 00[f3]f3 f3 f3 00 00 00 00 00 00 00 00
0x1ffef5fe94d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1ffef5fe94e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1ffef5fe94f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1ffef5fe9500: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1ffef5fe9510: 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
==25634==ABORTING
[1] 25634 abort ./stack_buffer_overflow
The program crashed at the very beginning where the problem first occurred, and it is also easy to fix.
stack_use_after_scope
Dangling pointer: Using a stack object that has already been released.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
char *ptr;
{
char my_char = 'a';
ptr = &my_char;
}
*ptr = 'b';
return 0;
}
Compile and execute:
gcc -g -fsanitize=address stack_use_after_scope.cpp -o stack_use_after_scope
./stack_use_after_scope
After execution, the error is as follows:
stack_use_after_scope(40744,0x10bb35600) malloc: nano zone abandoned due to inability to preallocate reserved vm space.
=================================================================
==40744==ERROR: AddressSanitizer: stack-use-after-scope on address 0x7ff7bbbd0600 at pc 0x000104332e99 bp 0x7ff7bbbd05d0 sp 0x7ff7bbbd05c8
WRITE of size 1 at 0x7ff7bbbd0600 thread T0
#0 0x104332e98 in main stack_use_after_scope.cpp:13
#1 0x10baba52d in start+0x1cd (dyld:x86_64+0x552d)
Address 0x7ff7bbbd0600 is located in stack of thread T0 at offset 32 in frame
#0 0x104332d3f in main stack_use_after_scope.cpp:5
This frame has 1 object(s):
[32, 33) 'my_char' (line 9) <== 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, swapcontext or vfork
(longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-use-after-scope stack_use_after_scope.cpp:13 in main
Shadow bytes around the buggy address:
0x1ffef777a070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1ffef777a080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1ffef777a090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1ffef777a0a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1ffef777a0b0: 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1
=>0x1ffef777a0c0:[f8]f3 f3 f3 00 00 00 00 00 00 00 00 00 00 00 00
0x1ffef777a0d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1ffef777a0e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1ffef777a0f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1ffef777a100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1ffef777a110: 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
==40744==ABORTING
[1] 40744 abort ./stack_use_after_scope
The program crashed at the very beginning where the problem first occurred, and it is also easy to fix.
These errors will also be printed with corresponding messages in the SRS.
TRANS_BY_GPT3