1 // RUN: %clangxx_msan -fno-sanitize=memory -c %s -o %t-main.o 2 // RUN: %clangxx_msan %t-main.o %s -o %t 3 // RUN: %run %t 4 5 #include <assert.h> 6 #include <stdio.h> 7 #include <stdlib.h> 8 #include <ucontext.h> 9 #include <unistd.h> 10 11 #include <sanitizer/msan_interface.h> 12 13 #if __has_feature(memory_sanitizer) 14 15 __attribute__((noinline)) int bar(int a, int b) { 16 volatile int zero = 0; 17 return zero; 18 } 19 20 void foo(int x, int y, int expected) { 21 assert(__msan_test_shadow(&x, sizeof(x)) == expected); 22 assert(__msan_test_shadow(&y, sizeof(y)) == expected); 23 24 // Poisons parameter shadow in TLS so that the next call (to foo) from 25 // uninstrumented main has params 1 and 2 poisoned no matter what. 26 int a, b; 27 (void)bar(a, b); 28 } 29 30 #else 31 32 // This code is not instrumented by MemorySanitizer to prevent it from modifying 33 // MSAN TLS data for this test. 34 35 int foo(int, int, int); 36 37 int main(int argc, char **argv) { 38 int x, y; 39 // The parameters should _not_ be poisoned; this is the first call to foo. 40 foo(x, y, -1); 41 // The parameters should be poisoned; the prior call to foo left them so. 42 foo(x, y, 0); 43 44 ucontext_t ctx; 45 if (getcontext(&ctx) == -1) { 46 perror("getcontext"); 47 _exit(1); 48 } 49 50 // Simulate a fiber switch occurring from MSAN's perspective (though no switch 51 // actually occurs). 52 const void *previous_stack_bottom = nullptr; 53 size_t previous_stack_size = 0; 54 __msan_start_switch_fiber(ctx.uc_stack.ss_sp, ctx.uc_stack.ss_size); 55 __msan_finish_switch_fiber(&previous_stack_bottom, &previous_stack_size); 56 57 // The simulated fiber switch will reset the TLS parameter shadow. So even 58 // though the most recent call to foo left the parameter shadow poisoned, the 59 // parameters are _not_ expected to be poisoned now. 60 foo(x, y, -1); 61 62 return 0; 63 } 64 65 #endif 66