Some useful address sanitizer checks are disabled by default because they are relatively expensive (or, as for the
std::vector
checking, need to be enabled for all translation units).Use after return
The address sanitizer warns when a variable is used after it has gone out of scope in a function, but it does not warn when the variable is used after the function return. That can, however, be enabled by adding
detect_stack_use_after_return=1
to the ASAN_OPTIONS
environment variable.Example
int *ptr; __attribute__((noinline)) void foo(void) { int a; ptr = &a; } int main(void) { foo(); return *ptr; // Error }Compile as
gcc -O -fsanitize=address file.cand add
detect_stack_use_after_return=1
to the ASAN_OPTIONS
environment variable before running the programenv ASAN_OPTIONS="detect_stack_use_after_return=1" ./a.out
Pointer comparison
It is not valid to compare two pointers from different objects using the relational operators
Note:
<
, <=
, >
, and >=
. This can be detected by compiling with -fsanitize=address,pointer-compare
and adding detect_invalid_pointer_pairs=1
to the ASAN_OPTIONS
environment variable.Note:
-fsanitize=pointer-compare
was added in GCC 8.Example
#include <stdlib.h> int main(void) { char *p = malloc(42); char *q = malloc(42); int tmp = p < q; // Error free(p); free(q); return tmp; }Compile as
gcc -fsanitize=address,pointer-compare file.cand add
detect_invalid_pointer_pairs=1
to the ASAN_OPTIONS
environment variable before running the programenv ASAN_OPTIONS="detect_invalid_pointer_pairs=1" ./a.out
Pointer subtraction
It is not valid to subtract pointers that point into different objects. This can be detected by compiling with
Note:
-fsanitize=address,pointer-subtract
and adding detect_invalid_pointer_pairs=1
to the ASAN_OPTIONS
environment variable.Note:
-fsanitize=pointer-subtract
was added in GCC 8.Example
#include <stdlib.h> int main(void) { char *p = malloc(42); char *q = malloc(42); int tmp = p - q; // Error free(p); free(q); return tmp; }Compile as
gcc -O -fsanitize=address,pointer-subtract file.cand add
detect_invalid_pointer_pairs=1
to the ASAN_OPTIONS
environment variable before running the programenv ASAN_OPTIONS="detect_invalid_pointer_pairs=1" ./a.out
std::vector checking
The address sanitizer does not detect out-of-bounds accesses to the unused capacity of a vector, such as
Note:
std::vector<int> v(2); int* p = v.data(); v.pop_back(); return p[1]; // Errorbecause the memory is valid, even though it is an error to use it. It is possible to make the address sanitizer warn for this by compiling with
-D_GLIBCXX_SANITIZE_VECTOR
which makes libstdc++ annotate the memory so that the validity can be tracked. The annotations must be present on all vector operations or none, so this macro must be defined to the same value for all translation units that create, destroy or modify vectors.Note:
_GLIBCXX_SANITIZE_VECTOR
was added in the GCC 8 libstdc++.Example
#include <vector> int main() { std::vector<int> v(2); int* p = v.data(); v.pop_back(); return p[1]; // Error }Compile as
g++ -O -fsanitize=address -D_GLIBCXX_SANITIZE_VECTOR file.cpp
Asan faq (https://github.com/google/sanitizers/wiki/AddressSanitizer#faq) also suggests
ReplyDeleteCFLAGS += -U_FORTIFY_SOURCE -fsanitize-address-use-after-scope
export ASAN_OPTIONS=strict_string_checks=1:detect_stack_use_after_return=1:check_initialization_order=1:strict_init_order=1
Nice article! Thank you for sharing.
ReplyDelete