xref: /llvm-project/compiler-rt/test/msan/Linux/swapcontext_annotation_reset.cpp (revision 15805c030f31b8d112ee4a4706ff4f5725c794df)
1*15805c03SVitaly Buka // RUN: %clangxx_msan -fno-sanitize-memory-param-retval -fno-sanitize=memory -c %s -o %t-main.o
2*15805c03SVitaly Buka // RUN: %clangxx_msan -fno-sanitize-memory-param-retval %t-main.o %s -o %t
31d3ef5f1SJustin Cady // RUN: %run %t
41d3ef5f1SJustin Cady 
51d3ef5f1SJustin Cady #include <assert.h>
61d3ef5f1SJustin Cady #include <stdio.h>
71d3ef5f1SJustin Cady #include <stdlib.h>
81d3ef5f1SJustin Cady #include <ucontext.h>
91d3ef5f1SJustin Cady #include <unistd.h>
101d3ef5f1SJustin Cady 
111d3ef5f1SJustin Cady #include <sanitizer/msan_interface.h>
121d3ef5f1SJustin Cady 
131d3ef5f1SJustin Cady #if __has_feature(memory_sanitizer)
141d3ef5f1SJustin Cady 
bar(int a,int b)151d3ef5f1SJustin Cady __attribute__((noinline)) int bar(int a, int b) {
161d3ef5f1SJustin Cady   volatile int zero = 0;
171d3ef5f1SJustin Cady   return zero;
181d3ef5f1SJustin Cady }
191d3ef5f1SJustin Cady 
foo(int x,int y,int expected)201d3ef5f1SJustin Cady void foo(int x, int y, int expected) {
211d3ef5f1SJustin Cady   assert(__msan_test_shadow(&x, sizeof(x)) == expected);
221d3ef5f1SJustin Cady   assert(__msan_test_shadow(&y, sizeof(y)) == expected);
231d3ef5f1SJustin Cady 
241d3ef5f1SJustin Cady   // Poisons parameter shadow in TLS so that the next call (to foo) from
251d3ef5f1SJustin Cady   // uninstrumented main has params 1 and 2 poisoned no matter what.
261d3ef5f1SJustin Cady   int a, b;
271d3ef5f1SJustin Cady   (void)bar(a, b);
281d3ef5f1SJustin Cady }
291d3ef5f1SJustin Cady 
301d3ef5f1SJustin Cady #else
311d3ef5f1SJustin Cady 
321d3ef5f1SJustin Cady // This code is not instrumented by MemorySanitizer to prevent it from modifying
331d3ef5f1SJustin Cady // MSAN TLS data for this test.
341d3ef5f1SJustin Cady 
351d3ef5f1SJustin Cady int foo(int, int, int);
361d3ef5f1SJustin Cady 
main(int argc,char ** argv)371d3ef5f1SJustin Cady int main(int argc, char **argv) {
381d3ef5f1SJustin Cady   int x, y;
391d3ef5f1SJustin Cady   // The parameters should _not_ be poisoned; this is the first call to foo.
401d3ef5f1SJustin Cady   foo(x, y, -1);
411d3ef5f1SJustin Cady   // The parameters should be poisoned; the prior call to foo left them so.
421d3ef5f1SJustin Cady   foo(x, y, 0);
431d3ef5f1SJustin Cady 
441d3ef5f1SJustin Cady   ucontext_t ctx;
451d3ef5f1SJustin Cady   if (getcontext(&ctx) == -1) {
461d3ef5f1SJustin Cady     perror("getcontext");
471d3ef5f1SJustin Cady     _exit(1);
481d3ef5f1SJustin Cady   }
491d3ef5f1SJustin Cady 
501d3ef5f1SJustin Cady   // Simulate a fiber switch occurring from MSAN's perspective (though no switch
511d3ef5f1SJustin Cady   // actually occurs).
521d3ef5f1SJustin Cady   const void *previous_stack_bottom = nullptr;
531d3ef5f1SJustin Cady   size_t previous_stack_size = 0;
541d3ef5f1SJustin Cady   __msan_start_switch_fiber(ctx.uc_stack.ss_sp, ctx.uc_stack.ss_size);
551d3ef5f1SJustin Cady   __msan_finish_switch_fiber(&previous_stack_bottom, &previous_stack_size);
561d3ef5f1SJustin Cady 
571d3ef5f1SJustin Cady   // The simulated fiber switch will reset the TLS parameter shadow. So even
581d3ef5f1SJustin Cady   // though the most recent call to foo left the parameter shadow poisoned, the
591d3ef5f1SJustin Cady   // parameters are _not_ expected to be poisoned now.
601d3ef5f1SJustin Cady   foo(x, y, -1);
611d3ef5f1SJustin Cady 
621d3ef5f1SJustin Cady   return 0;
631d3ef5f1SJustin Cady }
641d3ef5f1SJustin Cady 
651d3ef5f1SJustin Cady #endif
66