diff options
Diffstat (limited to 'compiler-rt/test/msan/unpoison_param.cc')
-rw-r--r-- | compiler-rt/test/msan/unpoison_param.cc | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/compiler-rt/test/msan/unpoison_param.cc b/compiler-rt/test/msan/unpoison_param.cc new file mode 100644 index 00000000000..f59d2cbe231 --- /dev/null +++ b/compiler-rt/test/msan/unpoison_param.cc @@ -0,0 +1,51 @@ +// Tests that __msan_unpoison_param() works as specified. To prevent MSan +// instrumentation from modifying parameter shadow before each call to foo(), we +// compile main() without MSan. + +// RUN: %clangxx_msan -fno-sanitize=memory -c %s -o %t-main.o +// RUN: %clangxx_msan %t-main.o %s -o %t +// RUN: %run %t + +#include <assert.h> +#include <sanitizer/msan_interface.h> + +#if __has_feature(memory_sanitizer) + +__attribute__((noinline)) int bar(int a, int b) { + volatile int zero = 0; + return zero; +} + +int foo(int a, int b, int unpoisoned_params) { + if (unpoisoned_params == 0) { + assert(__msan_test_shadow(&a, sizeof(a)) == 0); + assert(__msan_test_shadow(&b, sizeof(b)) == 0); + } else if (unpoisoned_params == 1) { + assert(__msan_test_shadow(&a, sizeof(a)) == -1); + assert(__msan_test_shadow(&b, sizeof(b)) == 0); + } else if (unpoisoned_params == 2) { + assert(__msan_test_shadow(&a, sizeof(a)) == -1); + assert(__msan_test_shadow(&b, sizeof(b)) == -1); + } + + // Poisons parameter shadow in TLS so that the next call from uninstrumented + // main has params 1 and 2 poisoned no matter what. + int x, y; + return bar(x, y); +} + +#else + +int foo(int, int, int); + +int main() { + foo(0, 0, 2); // Poison parameters for next call. + foo(0, 0, 0); // Check that both params are poisoned. + __msan_unpoison_param(1); + foo(0, 0, 1); // Check that only first param is unpoisoned. + __msan_unpoison_param(2); + foo(0, 0, 2); // Check that first and second params are unpoisoned. + return 0; +} + +#endif |