1 // Tests that __msan_unpoison_param() works as specified.  To prevent MSan
2 // instrumentation from modifying parameter shadow before each call to foo(), we
3 // compile main() without MSan.
4 
5 // RUN: %clangxx_msan -fno-sanitize=memory -c %s -o %t-main.o
6 // RUN: %clangxx_msan %t-main.o %s -o %t
7 // RUN: %run %t
8 
9 #include <assert.h>
10 #include <sanitizer/msan_interface.h>
11 
12 #if __has_feature(memory_sanitizer)
13 
bar(int a,int b)14 __attribute__((noinline)) int bar(int a, int b) {
15   volatile int zero = 0;
16   return zero;
17 }
18 
foo(int a,int b,int unpoisoned_params)19 int foo(int a, int b, int unpoisoned_params) {
20   if (unpoisoned_params == 0) {
21     assert(__msan_test_shadow(&a, sizeof(a)) == 0);
22     assert(__msan_test_shadow(&b, sizeof(b)) == 0);
23   } else if (unpoisoned_params == 1) {
24     assert(__msan_test_shadow(&a, sizeof(a)) == -1);
25     assert(__msan_test_shadow(&b, sizeof(b)) == 0);
26   } else if (unpoisoned_params == 2) {
27     assert(__msan_test_shadow(&a, sizeof(a)) == -1);
28     assert(__msan_test_shadow(&b, sizeof(b)) == -1);
29   }
30 
31   // Poisons parameter shadow in TLS so that the next call from uninstrumented
32   // main has params 1 and 2 poisoned no matter what.
33   int x, y;
34   return bar(x, y);
35 }
36 
37 #else
38 
39 int foo(int, int, int);
40 
main()41 int main() {
42   foo(0, 0, 2); // Poison parameters for next call.
43   foo(0, 0, 0); // Check that both params are poisoned.
44   __msan_unpoison_param(1);
45   foo(0, 0, 1); // Check that only first param is unpoisoned.
46   __msan_unpoison_param(2);
47   foo(0, 0, 2); // Check that first and second params are unpoisoned.
48   return 0;
49 }
50 
51 #endif
52