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 -fno-sanitize-memory-param-retval %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
14__attribute__((noinline)) int bar(int a, int b) {
15 volatile int zero = 0;
16 return zero;
17}
18
19int 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
39int foo(int, int, int);
40
41int 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(n: 1);
45 foo(0, 0, 1); // Check that only first param is unpoisoned.
46 __msan_unpoison_param(n: 2);
47 foo(0, 0, 2); // Check that first and second params are unpoisoned.
48 return 0;
49}
50
51#endif
52

source code of compiler-rt/test/msan/unpoison_param.cpp