1 // Regression test for 2 // https://bugs.llvm.org/show_bug.cgi?id=32434 3 4 // RUN: %clangxx_asan -fexceptions -O0 %s -o %t 5 // RUN: %run %t 6 7 // The current implementation of this functionality requires special 8 // combination of libraries that are not used by default on NetBSD 9 // XFAIL: netbsd 10 // FIXME: Bug 42703 11 // XFAIL: solaris 12 13 #include <assert.h> 14 #include <exception> 15 #include <sanitizer/asan_interface.h> 16 17 namespace { 18 19 // Not instrumented because std::rethrow_exception is a [[noreturn]] function, 20 // for which the compiler would emit a call to __asan_handle_no_return which 21 // unpoisons the stack. 22 // We emulate here some code not compiled with asan. This function is not 23 // [[noreturn]] because the scenario we're emulating doesn't always throw. If it 24 // were [[noreturn]], the calling code would emit a call to 25 // __asan_handle_no_return. 26 void __attribute__((no_sanitize("address"))) uninstrumented_rethrow_exception(std::exception_ptr const & exc_ptr)27uninstrumented_rethrow_exception(std::exception_ptr const &exc_ptr) { 28 std::rethrow_exception(exc_ptr); 29 } 30 31 char *poisoned1; 32 char *poisoned2; 33 34 // Create redzones for stack variables in shadow memory and call 35 // std::rethrow_exception which should unpoison the entire stack. create_redzones_and_throw(std::exception_ptr const & exc_ptr)36void create_redzones_and_throw(std::exception_ptr const &exc_ptr) { 37 char a[100]; 38 poisoned1 = a - 1; 39 poisoned2 = a + sizeof(a); 40 assert(__asan_address_is_poisoned(poisoned1)); 41 assert(__asan_address_is_poisoned(poisoned2)); 42 uninstrumented_rethrow_exception(exc_ptr); 43 } 44 45 } // namespace 46 47 // Check that std::rethrow_exception is intercepted by asan and the interception 48 // unpoisons the stack. 49 // If std::rethrow_exception is NOT intercepted, then calls to this function 50 // from instrumented code will still unpoison the stack because 51 // std::rethrow_exception is a [[noreturn]] function and any [[noreturn]] 52 // function call will be instrumented with __asan_handle_no_return. 53 // However, calls to std::rethrow_exception from UNinstrumented code will not 54 // unpoison the stack, so we need to intercept std::rethrow_exception to 55 // unpoison the stack. main()56int main() { 57 // In some implementations of std::make_exception_ptr, e.g. libstdc++ prior to 58 // gcc 7, this function calls __cxa_throw. The __cxa_throw is intercepted by 59 // asan to unpoison the entire stack; since this test essentially tests that 60 // the stack is unpoisoned by a call to std::rethrow_exception, we need to 61 // generate the exception_ptr BEFORE we have the local variables poison the 62 // stack. 63 std::exception_ptr my_exception_ptr = std::make_exception_ptr("up"); 64 65 try { 66 create_redzones_and_throw(my_exception_ptr); 67 } catch(char const *) { 68 assert(!__asan_region_is_poisoned(poisoned1, poisoned2 - poisoned1 + 1)); 69 } 70 } 71