xref: /llvm-project/compiler-rt/test/msan/Linux/swapcontext_annotation_reset.cpp (revision 15805c030f31b8d112ee4a4706ff4f5725c794df)
1 // RUN: %clangxx_msan -fno-sanitize-memory-param-retval -fno-sanitize=memory -c %s -o %t-main.o
2 // RUN: %clangxx_msan -fno-sanitize-memory-param-retval %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 
bar(int a,int b)15 __attribute__((noinline)) int bar(int a, int b) {
16   volatile int zero = 0;
17   return zero;
18 }
19 
foo(int x,int y,int expected)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 
main(int argc,char ** argv)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