Logging control, for Address Sanitizer PLUS Undefined Behavior Sanitizer?

Several of the Sanitizers (from either GCC or Clang) cannot be combined – i.e. used simultaneously in the same build, but Asan and Ubsan are combinable – i.e. I can build with “-fsanitize=address,undefined -fsanitize-recover=all …” and have an exe that performs the checks from both sanitizers. All good so far.

The LOGGING from the resulting executable seems problematic though.

In all cases, if ‘log_path’ is not set in the options, the defects all get reported on stderr. OK so far. Try to use log_path though, and things get strange:

  • For an exe built just with Asan, and setting ASAN_OPTIONS to include “log_path=./ASAN”, the Address Saniitizer defects will go into a file named ASAN.
  • For an exe built just with Ubsan, and setting UBSAN_OPTIONS to include “log_path=./UBSAN”, the Undefined Behavior defects will go into a file named UBSAN.
  • For an exe built with both Asan and Ubsan
    o The Asan output goes to the designated log file, but the ubsan output goes only to stderr
    o The above applies even if the log_path is only set via UBSAN_OPTIONS, and ASAN_OPTIONS is unset
    o If log_path is set in both ASAN_OPTIONS and UBSAN_OPTIONS, the log_path used is the UBSAN one, yet only contains the ASAN results

Is there some hidden magic that will let both sanitizers write to the same defect log ?


To reproduce, use a simple testcase that has a defect for each sanitizer:

char *hello = "hello";

int main (int argc, char *argv[])
{
   int x = 1;
   x <<= 32; // Error: (1 << 32) can't be represented in a (32-bit) int
   char some_char = hello [argc *10];
}

build and run: (g++ 7.3.0 used here, but other GCC versions, and also clang 7.1.0 have shown the same basic behavior)

Asan only – works as expected

g++ foo.C -fsanitize=address -fsanitize-recover=all -g
setenv ASAN_OPTIONS "log_path=./ASAN:halt_on_error=0:handle_abort=1:exitcode=0"
a.out 

File ASAN. 29648 contains defect starting with

==29648==ERROR: AddressSanitizer: global-buffer-overflow on address 0x000000400aca at pc 0x0000004009a5 bp 0x7fffffffe090 sp 0x7fffffffe088

READ of size 1 at 0x000000400aca thread T0
0x4009a4 in main /tmp/foo.C:7

Ubsan only – works as expected

g++ foo.C -fsanitize=undefined -fsanitize-recover=all -g
setenv UBSAN_OPTIONS "log_path=./UBSAN:halt_on_error=0:handle_abort=1:exitcode=0”
a.out

File UBSAN.29675 contains

foo.C:6:6: runtime error: shift exponent 32 is too large for 32-bit type ‘int’

Asan PLUS Ubsan – strange logging behavior

g++ foo.C -fsanitize=address,undefined -fsanitize-recover=all -g

setenv ASAN_OPTIONS "log_path=./ASAN:halt_on_error=0:handle_abort=1:exitcode=0"
a.out 

ASAN_OPTIONS gets ignored, all defects reported on stderr. Now try setting UBSAN_OPTIONS:

setenv UBSAN_OPTIONS "log_path=./UBSAN:halt_on_error=0:handle_abort=1:exitcode=0”
a.out

File UBSAN.30352 contains ONLY the Asan defect:

==30352==ERROR: AddressSanitizer: global-buffer-overflow on address 0x000000400aca at pc 0x0000004009a5 bp 0x7fffffffe090 sp 0x7fffffffe088
READ of size 1 at 0x000000400aca thread T0
0x4009a4 in main /tmp/foo.C:7

and the Ubsan defect gets written only to stderr:

foo.C:6:6: runtime error: shift exponent 32 is too large for 32-bit type ‘int’

%d bloggers like this: