GNU Compiler Collection: Sanitizer¶
- Compiler adds run-time instrumentation
- Analysis during runtime
- Problems that can be detected
- out of bounds memory access
- use of memory after free
- use of uninitialized values
- thread data race conditions
- undefined behavior
- ...
- GCC Program Instrumentation Options
-
Basic usage
gcc -fsanitize=${SANITIZER_TYPE} ${SOURCE}
Example: Sanitizer - Use after free¶
-
Source code
use_after_free.c++#include <iostream> int main(int argc, char *argv[]) { char *charArray = new char[10]; delete [] charArray; std::cout << charArray[0] << std::endl; } -
Set up compiler environment
module add compiler/gnu -
Compile
c++ -fsanitize=address -ggdb \ use_after_free.c++ -o use_after_free -
Execute
./use_after_free================================================================= ==131470==ERROR: AddressSanitizer: heap-use-after-free on address 0x602000000010 at pc 0x55811bc3625d bp 0x7ffc66be8b50 sp 0x7ffc66be8b40 READ of size 1 at 0x602000000010 thread T0 #0 0x55811bc3625c in main .../use_after_free.c++:6 #1 0x7ff728c3c78f (/usr/lib/libc.so.6+0x2378f) #2 0x7ff728c3c849 in __libc_start_main (/usr/lib/libc.so.6+0x23849) #3 0x55811bc36124 in _start (.../use_after_free+0x1124) 0x602000000010 is located 0 bytes inside of 10-byte region [0x602000000010,0x60200000001a) freed by thread T0 here: #0 0x7ff7292c135a in operator delete[](void*) /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_new_delete.cpp:155 #1 0x55811bc36228 in main .../use_after_free.c++:5 #2 0x7ff728c3c78f (/usr/lib/libc.so.6+0x2378f) previously allocated by thread T0 here: #0 0x7ff7292c07f2 in operator new[](unsigned long) /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_new_delete.cpp:98 #1 0x55811bc36211 in main .../use_after_free.c++:4 #2 0x7ff728c3c78f (/usr/lib/libc.so.6+0x2378f) ...
Example: Sanitizer - Out of Bound Access (C++)¶
-
Source code
out_of_bound_access.c++#include <iostream> int main(int argc, char *argv[]) { auto charArray = new char[10]; charArray[10] = 10; delete []charArray; } -
Set up compiler environment
module add compiler/gnu -
Compile
c++ -fsanitize=address -ggdb \ out_of_bound_access.c++ -o out_of_bound_access -
Execute
./out_of_bound_access================================================================= ==10275==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60200000001a at pc 0x55b37de5b1f2 bp 0x7fff95a015a0 sp 0x7fff95a01590 WRITE of size 1 at 0x60200000001a thread T0 #0 0x55b37de5b1f1 in main /.../out_of_bound_access.c++:5 #1 0x7f39d1a3984f (/usr/lib/libc.so.6+0x2384f) (BuildId: 2f005a79cd1a8e385972f5a102f16adba414d75e) #2 0x7f39d1a39909 in __libc_start_main (/usr/lib/libc.so.6+0x23909) (BuildId: 2f005a79cd1a8e385972f5a102f16adba414d75e) #3 0x55b37de5b0c4 in _start (/.../out_of_bound_access+0x10c4) (BuildId: f2cc6cfa9b75f99d03d406b9aa96c3cbadfc81dd) 0x60200000001a is located 0 bytes after 10-byte region [0x602000000010,0x60200000001a) allocated by thread T0 here: #0 0x7f39d20e2192 in operator new[](unsigned long) /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_new_delete.cpp:98 #1 0x55b37de5b1b1 in main /.../out_of_bound_access.c++:4 #2 0x7f39d1a3984f (/usr/lib/libc.so.6+0x2384f) (BuildId: 2f005a79cd1a8e385972f5a102f16adba414d75e) SUMMARY: AddressSanitizer: heap-buffer-overflow /.../out_of_bound_access.c++:5 in main ...
Example: Sanitizer - Out of Bound Access (Fortran)¶
-
Source code
out_of_bound_access.f90program out_of_bound_access implicit none character, allocatable :: charArray(:) allocate(charArray(10)) charArray(11) = 'a' deallocate(charArray) end program out_of_bound_access -
Set up compiler environment
module add compiler/gnu -
Compile
gfortran -fsanitize=address -ggdb \ out_of_bound_access.f90 -o out_of_bound_access -
Execute
./out_of_bound_access================================================================= ==9417==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60200000007a at pc 0x559e238c83fa bp 0x7ffffadf5860 sp 0x7ffffadf5850 WRITE of size 1 at 0x60200000007a thread T0 #0 0x559e238c83f9 in out_of_bound_access /.../out_of_bound_access.f90:5 #1 0x559e238c84e2 in main /.../out_of_bound_access.f90:7 #2 0x7f18b7e3984f (/usr/lib/libc.so.6+0x2384f) (BuildId: 2f005a79cd1a8e385972f5a102f16adba414d75e) #3 0x7f18b7e39909 in __libc_start_main (/usr/lib/libc.so.6+0x23909) (BuildId: 2f005a79cd1a8e385972f5a102f16adba414d75e) #4 0x559e238c8144 in _start (/.../out_of_bound_access+0x1144) (BuildId: e3946b37d4f72e5bac953feeb97c3b529178c196) 0x60200000007a is located 0 bytes after 10-byte region [0x602000000070,0x60200000007a) allocated by thread T0 here: #0 0x7f18b84e1369 in __interceptor_malloc /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_malloc_linux.cpp:69 #1 0x559e238c8357 in out_of_bound_access /.../out_of_bound_access.f90:4 #2 0x559e238c84e2 in main /.../out_of_bound_access.f90:7 #3 0x7f18b7e3984f (/usr/lib/libc.so.6+0x2384f) (BuildId: 2f005a79cd1a8e385972f5a102f16adba414d75e) SUMMARY: AddressSanitizer: heap-buffer-overflow /.../out_of_bound_access.f90:5 in out_of_bound_access ...
Example: Sanitizer - Division by zero¶
-
Source code
division_by_zero.c++#include <iostream> int main(int argc, char *argv[]) { int a=1, b=0; std::cout << a/b << std::endl; } -
Set up compiler environment
module add compiler/gnu -
Compile
c++ -fsanitize=undefined -ggdb \ division_by_zero.c++ -o division_by_zero -
Execute
./division_by_zerodivision_by_zero.c++:5:19: runtime error: division by zero Floating point exception (core dumped) -
Execute without sanitizer
./division_by_zeroFloating point exception (core dumped)
Example: Sanitizer - Datatype Overflow¶
-
Source code
overflow.c++#include <climits> #include <iostream> int main(int argc, char *argv[]) { int i = INT_MAX; i++; std::cout << i << std::endl; } -
Set up compiler environment
module add compiler/gnu -
Compile
c++ -fsanitize=undefined -ggdb \ overflow.c++ -o overflow -
Execute
./overflowoverflow.c++:6:6: runtime error: signed integer overflow: 2147483647 + 1 cannot be represented in type 'int' -2147483648 -
Execute without sanitizer
./overflow-2147483648
Example: Sanitizer - Datatype Overflow (Fortran)¶
-
Source code
datatype_overflow.f90program datatype_overflow use iso_fortran_env integer:: i i = huge(i) i = i + 1 print *, i end program datatype_overflow -
Set up compiler environment
module add compiler/gnu -
Compile
gfortran -fsanitize=undefined -ggdb \ datatype_overflow.f90 -o datatype_overflow -
Execute
./datatype_overflowdatatype_overflow.f90:5:12: runtime error: signed integer overflow: 2147483647 + 1 cannot be represented in type 'integer(kind=4)' -2147483648 -
Execute without sanitizer
./datatype_overflow-2147483648