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 14 __attribute__((noinline)) int bar(int a, int b) { 15 volatile int zero = 0; 16 return zero; 17 } 18 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 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