Index: lib/msan/msan.h =================================================================== --- lib/msan/msan.h +++ lib/msan/msan.h @@ -329,11 +329,20 @@ StackTrace::GetCurrentPc(), GET_CURRENT_FRAME(), \ common_flags()->fast_unwind_on_malloc) +// For platforms which support slow unwinder only, we restrict the store context +// size to 1, basically only storing the current pc. We do this because the slow +// unwinder which is based on libunwind is not async signal safe and causes +// random freezes in forking applications as well as in signal handlers. #define GET_STORE_STACK_TRACE_PC_BP(pc, bp) \ BufferedStackTrace stack; \ - if (__msan_get_track_origins() > 1 && msan_inited) \ - GetStackTrace(&stack, flags()->store_context_size, pc, bp, \ - common_flags()->fast_unwind_on_malloc) + if (__msan_get_track_origins() > 1 && msan_inited) { \ + if (!SANITIZER_CAN_FAST_UNWIND) \ + GetStackTrace(&stack, Min(1, flags()->store_context_size), pc, bp, \ + false); \ + else \ + GetStackTrace(&stack, flags()->store_context_size, pc, bp, \ + common_flags()->fast_unwind_on_malloc); \ + } #define GET_FATAL_STACK_TRACE_PC_BP(pc, bp) \ BufferedStackTrace stack; \ Index: test/msan/chained_origin.cc =================================================================== --- test/msan/chained_origin.cc +++ test/msan/chained_origin.cc @@ -1,15 +1,15 @@ // RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -O3 %s -o %t && \ // RUN: not %run %t >%t.out 2>&1 -// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-STACK < %t.out +// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%short-stack --check-prefix=CHECK-STACK < %t.out // RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -DHEAP=1 -O3 %s -o %t && \ // RUN: not %run %t >%t.out 2>&1 -// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-HEAP < %t.out +// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%short-stack --check-prefix=CHECK-HEAP < %t.out // RUN: %clangxx_msan -mllvm -msan-instrumentation-with-call-threshold=0 -fsanitize-memory-track-origins=2 -O3 %s -o %t && \ // RUN: not %run %t >%t.out 2>&1 -// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-STACK < %t.out +// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%short-stack --check-prefix=CHECK-STACK < %t.out // RUN: %clangxx_msan -mllvm -msan-instrumentation-with-call-threshold=0 -fsanitize-memory-track-origins=2 -DHEAP=1 -O3 %s -o %t && \ // RUN: not %run %t >%t.out 2>&1 @@ -50,16 +50,18 @@ // CHECK: {{#0 .* in main.*chained_origin.cc:}}[[@LINE-4]] // CHECK: Uninitialized value was stored to memory at -// CHECK: {{#0 .* in fn_h.*chained_origin.cc:}}[[@LINE-19]] -// CHECK: {{#1 .* in main.*chained_origin.cc:}}[[@LINE-9]] +// CHECK-FULL-STACK: {{#0 .* in fn_h.*chained_origin.cc:}}[[@LINE-19]] +// CHECK-FULL-STACK: {{#1 .* in main.*chained_origin.cc:}}[[@LINE-9]] +// CHECK-SHORT-STACK: {{#0 .* in fn_h.*chained_origin.cc:}}[[@LINE-21]] // CHECK: Uninitialized value was stored to memory at -// CHECK: {{#0 .* in fn_g.*chained_origin.cc:}}[[@LINE-33]] -// CHECK: {{#1 .* in fn_f.*chained_origin.cc:}}[[@LINE-29]] -// CHECK: {{#2 .* in main.*chained_origin.cc:}}[[@LINE-15]] +// CHECK-FULL-STACK: {{#0 .* in fn_g.*chained_origin.cc:}}[[@LINE-34]] +// CHECK-FULL-STACK: {{#1 .* in fn_f.*chained_origin.cc:}}[[@LINE-30]] +// CHECK-FULL-STACK: {{#2 .* in main.*chained_origin.cc:}}[[@LINE-16]] +// CHECK-SHORT-STACK: {{#0 .* in fn_g.*chained_origin.cc:}}[[@LINE-37]] // CHECK-STACK: Uninitialized value was created by an allocation of 'z' in the stack frame of function 'main' -// CHECK-STACK: {{#0 .* in main.*chained_origin.cc:}}[[@LINE-25]] +// CHECK-STACK: {{#0 .* in main.*chained_origin.cc:}}[[@LINE-27]] // CHECK-HEAP: Uninitialized value was created by a heap allocation -// CHECK-HEAP: {{#1 .* in main.*chained_origin.cc:}}[[@LINE-26]] +// CHECK-HEAP: {{#1 .* in main.*chained_origin.cc:}}[[@LINE-28]] Index: test/msan/chained_origin_limits.cc =================================================================== --- test/msan/chained_origin_limits.cc +++ test/msan/chained_origin_limits.cc @@ -10,7 +10,7 @@ // RUN: FileCheck %s --check-prefix=CHECK2 < %t.out // RUN: MSAN_OPTIONS=origin_history_per_stack_limit=1 not %run %t >%t.out 2>&1 -// RUN: FileCheck %s --check-prefix=CHECK-PER-STACK < %t.out +// RUN: FileCheck %s --check-prefix=CHECK-PER-STACK --check-prefix=CHECK-%short-stack < %t.out // RUN: MSAN_OPTIONS=origin_history_size=7,origin_history_per_stack_limit=0 not %run %t >%t.out 2>&1 // RUN: FileCheck %s --check-prefix=CHECK7 < %t.out @@ -25,7 +25,7 @@ // RUN: FileCheck %s --check-prefix=CHECK2 < %t.out // RUN: MSAN_OPTIONS=origin_history_per_stack_limit=1 not %run %t >%t.out 2>&1 -// RUN: FileCheck %s --check-prefix=CHECK-PER-STACK < %t.out +// RUN: FileCheck %s --check-prefix=CHECK-PER-STACK --check-prefix=CHECK-%short-stack < %t.out // RUN: MSAN_OPTIONS=origin_history_size=7,origin_history_per_stack_limit=0 not %run %t >%t.out 2>&1 // RUN: FileCheck %s --check-prefix=CHECK7 < %t.out @@ -41,7 +41,7 @@ // RUN: FileCheck %s --check-prefix=CHECK2 < %t.out // RUN: MSAN_OPTIONS=origin_history_per_stack_limit=1 not %run %t >%t.out 2>&1 -// RUN: FileCheck %s --check-prefix=CHECK-PER-STACK < %t.out +// RUN: FileCheck %s --check-prefix=CHECK-PER-STACK --check-prefix=CHECK-%short-stack < %t.out // RUN: MSAN_OPTIONS=origin_history_size=7,origin_history_per_stack_limit=0 not %run %t >%t.out 2>&1 // RUN: FileCheck %s --check-prefix=CHECK7 < %t.out @@ -57,7 +57,7 @@ // RUN: FileCheck %s --check-prefix=CHECK2 < %t.out // RUN: MSAN_OPTIONS=origin_history_per_stack_limit=1 not %run %t >%t.out 2>&1 -// RUN: FileCheck %s --check-prefix=CHECK-PER-STACK < %t.out +// RUN: FileCheck %s --check-prefix=CHECK-PER-STACK --check-prefix=CHECK-%short-stack < %t.out // RUN: MSAN_OPTIONS=origin_history_size=7,origin_history_per_stack_limit=0 not %run %t >%t.out 2>&1 // RUN: FileCheck %s --check-prefix=CHECK7 < %t.out @@ -147,13 +147,21 @@ // CHECK2-NOT: Uninitialized value was stored to memory at // CHECK2: Uninitialized value was created +// For architectures with short stack all the stacks in the chain are same +// because the stack trace does not contain frames upto the functions fn1, fn2, +// fn3 from where the uninitialized stores actually originate. Since we report +// uninitialized value store once for each stack frame +// (origin_history_per_stack_limit = 1) we expect only one instance of +// "Uninitialized value was stored to memory at". + // CHECK-PER-STACK: WARNING: MemorySanitizer: use-of-uninitialized-value // CHECK-PER-STACK: Uninitialized value was stored to memory at -// CHECK-PER-STACK: in fn3 -// CHECK-PER-STACK: Uninitialized value was stored to memory at -// CHECK-PER-STACK: in fn2 -// CHECK-PER-STACK: Uninitialized value was stored to memory at -// CHECK-PER-STACK: in fn1 +// CHECK-SHORT-STACK: in __msan_memmove +// CHECK-FULL-STACK: in fn3 +// CHECK-FULL-STACK: Uninitialized value was stored to memory at +// CHECK-FULL-STACK: in fn2 +// CHECK-FULL-STACK: Uninitialized value was stored to memory at +// CHECK-FULL-STACK: in fn1 // CHECK-PER-STACK: Uninitialized value was created // CHECK-UNLIMITED: WARNING: MemorySanitizer: use-of-uninitialized-value Index: test/msan/chained_origin_memcpy.cc =================================================================== --- test/msan/chained_origin_memcpy.cc +++ test/msan/chained_origin_memcpy.cc @@ -1,19 +1,19 @@ // RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -DOFFSET=0 -O3 %s -o %t && \ // RUN: not %run %t >%t.out 2>&1 -// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-Z1 < %t.out +// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-Z1 --check-prefix=CHECK-%short-stack < %t.out // RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -DOFFSET=10 -O3 %s -o %t && \ // RUN: not %run %t >%t.out 2>&1 -// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-Z2 < %t.out +// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-Z2 --check-prefix=CHECK-%short-stack < %t.out // RUN: %clangxx_msan -mllvm -msan-instrumentation-with-call-threshold=0 -fsanitize-memory-track-origins=2 -DOFFSET=0 -O3 %s -o %t && \ // RUN: not %run %t >%t.out 2>&1 -// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-Z1 < %t.out +// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-Z1 --check-prefix=CHECK-%short-stack < %t.out // RUN: %clangxx_msan -mllvm -msan-instrumentation-with-call-threshold=0 -fsanitize-memory-track-origins=2 -DOFFSET=10 -O3 %s -o %t && \ // RUN: not %run %t >%t.out 2>&1 -// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-Z2 < %t.out +// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-Z2 --check-prefix=CHECK-%short-stack < %t.out #include #include @@ -49,12 +49,14 @@ // CHECK: {{#0 .* in main .*chained_origin_memcpy.cc:}}[[@LINE-4]] // CHECK: Uninitialized value was stored to memory at -// CHECK: {{#1 .* in fn_h.*chained_origin_memcpy.cc:}}[[@LINE-15]] +// CHECK-FULL-STACK: {{#1 .* in fn_h.*chained_origin_memcpy.cc:}}[[@LINE-15]] +// CHECK-SHORT-STACK: {{#0 .* in __msan_memcpy .*msan_interceptors.cc:}} // CHECK: Uninitialized value was stored to memory at -// CHECK: {{#0 .* in fn_g.*chained_origin_memcpy.cc:}}[[@LINE-28]] -// CHECK: {{#1 .* in fn_f.*chained_origin_memcpy.cc:}}[[@LINE-24]] +// CHECK-FULL-STACK: {{#0 .* in fn_g.*chained_origin_memcpy.cc:}}[[@LINE-29]] +// CHECK-FULL-STACK: {{#1 .* in fn_f.*chained_origin_memcpy.cc:}}[[@LINE-25]] +// CHECK-SHORT-STACK: {{#0 .* in fn_g.*chained_origin_memcpy.cc:}}[[@LINE-31]] // CHECK-Z1: Uninitialized value was created by an allocation of 'z1' in the stack frame of function 'main' // CHECK-Z2: Uninitialized value was created by an allocation of 'z2' in the stack frame of function 'main' -// CHECK: {{#0 .* in main.*chained_origin_memcpy.cc:}}[[@LINE-20]] +// CHECK: {{#0 .* in main.*chained_origin_memcpy.cc:}}[[@LINE-22]] Index: test/msan/lit.cfg =================================================================== --- test/msan/lit.cfg +++ test/msan/lit.cfg @@ -35,3 +35,11 @@ if config.target_arch != 'aarch64': config.available_features.add('stable-runtime') + +# For mips64, mips64el we have forced store_context_size to 1 because these +# archs use slow unwinder which is not async signal safe. Therefore we only +# check the first frame since store_context size is 1. +if config.host_arch in ['mips64', 'mips64el']: + config.substitutions.append( ('CHECK-%short-stack', 'CHECK-SHORT-STACK')) +else: + config.substitutions.append( ('CHECK-%short-stack', 'CHECK-FULL-STACK')) Index: test/msan/msan_copy_shadow.cc =================================================================== --- test/msan/msan_copy_shadow.cc +++ test/msan/msan_copy_shadow.cc @@ -1,7 +1,7 @@ // Test that __msan_copy_shadow copies shadow, updates origin and does not touch // the application memory. // RUN: %clangxx_msan -fsanitize-memory-track-origins=0 -O0 %s -o %t && not %run %t 2>&1 -// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -O0 %s -o %t && not %run %t 2>&1 | FileCheck --check-prefix=CHECK --check-prefix=CHECK-%short-stack %s #include #include @@ -28,7 +28,8 @@ // CHECK: use-of-uninitialized-value // CHECK: {{in main.*msan_copy_shadow.cc:}}[[@LINE-2]] // CHECK: Uninitialized value was stored to memory at - // CHECK: {{in main.*msan_copy_shadow.cc:}}[[@LINE-8]] + // CHECK-FULL-STACK: {{in main.*msan_copy_shadow.cc:}}[[@LINE-8]] + // CHECK-SHORT-STACK: {{in __msan_copy_shadow .*msan_interceptors.cc:}} // CHECK: Uninitialized value was created by a heap allocation - // CHECK: {{in main.*msan_copy_shadow.cc:}}[[@LINE-22]] + // CHECK: {{in main.*msan_copy_shadow.cc:}}[[@LINE-23]] } Index: test/msan/realloc-large-origin.cc =================================================================== --- test/msan/realloc-large-origin.cc +++ test/msan/realloc-large-origin.cc @@ -1,7 +1,7 @@ // RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -O0 %s -o %t && not %run %t >%t.out 2>&1 -// RUN: FileCheck %s < %t.out +// RUN: FileCheck --check-prefix=CHECK --check-prefix=CHECK-%short-stack %s < %t.out // RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -O2 %s -o %t && not %run %t >%t.out 2>&1 -// RUN: FileCheck %s < %t.out +// RUN: FileCheck --check-prefix=CHECK --check-prefix=CHECK-%short-stack %s < %t.out // This is a regression test: there used to be broken "stored to memory at" // stacks with @@ -21,10 +21,11 @@ // CHECK: {{#0 0x.* in main .*realloc-large-origin.cc:}}[[@LINE-3]] // CHECK: Uninitialized value was stored to memory at -// CHECK: {{#0 0x.* in .*realloc}} -// CHECK: {{#1 0x.* in main .*realloc-large-origin.cc:}}[[@LINE-10]] +// CHECK-FULL-STACK: {{#0 0x.* in .*realloc}} +// CHECK-FULL-STACK: {{#1 0x.* in main .*realloc-large-origin.cc:}}[[@LINE-10]] +// CHECK-SHORT-STACK: {{#0 0x.* in .*realloc}} // CHECK: Uninitialized value was created by a heap allocation // CHECK: {{#0 0x.* in .*malloc}} -// CHECK: {{#1 0x.* in main .*realloc-large-origin.cc:}}[[@LINE-15]] +// CHECK: {{#1 0x.* in main .*realloc-large-origin.cc:}}[[@LINE-16]] }