1673dc3d4SNico Weber // Regression test for 2673dc3d4SNico Weber // https://bugs.llvm.org/show_bug.cgi?id=32434 3673dc3d4SNico Weber 4ac191bccSLeonard Chan // REQUIRES: shared_cxxabi 5ac191bccSLeonard Chan 6673dc3d4SNico Weber // RUN: %clangxx_asan -fexceptions -O0 %s -o %t 7*4b4437c0SVitaly Buka // RUN: %env_asan_opts=detect_stack_use_after_return=0 %run %t 8673dc3d4SNico Weber 9673dc3d4SNico Weber // The current implementation of this functionality requires special 10673dc3d4SNico Weber // combination of libraries that are not used by default on NetBSD 11673dc3d4SNico Weber // XFAIL: netbsd 12673dc3d4SNico Weber // FIXME: Bug 42703 13673dc3d4SNico Weber // XFAIL: solaris 14673dc3d4SNico Weber 1591f0a6adSVitaly Buka // https://reviews.llvm.org/D111703 made compiler incompatible with released NDK. 1691f0a6adSVitaly Buka // UNSUPPORTED: android && arm-target-arch 1791f0a6adSVitaly Buka 18673dc3d4SNico Weber #include <assert.h> 19673dc3d4SNico Weber #include <exception> 20673dc3d4SNico Weber #include <sanitizer/asan_interface.h> 21673dc3d4SNico Weber 22673dc3d4SNico Weber namespace { 23673dc3d4SNico Weber 24673dc3d4SNico Weber // Not instrumented because std::rethrow_exception is a [[noreturn]] function, 25673dc3d4SNico Weber // for which the compiler would emit a call to __asan_handle_no_return which 26673dc3d4SNico Weber // unpoisons the stack. 27673dc3d4SNico Weber // We emulate here some code not compiled with asan. This function is not 28673dc3d4SNico Weber // [[noreturn]] because the scenario we're emulating doesn't always throw. If it 29673dc3d4SNico Weber // were [[noreturn]], the calling code would emit a call to 30673dc3d4SNico Weber // __asan_handle_no_return. 31673dc3d4SNico Weber void __attribute__((no_sanitize("address"))) uninstrumented_rethrow_exception(std::exception_ptr const & exc_ptr)32673dc3d4SNico Weberuninstrumented_rethrow_exception(std::exception_ptr const &exc_ptr) { 33673dc3d4SNico Weber std::rethrow_exception(exc_ptr); 34673dc3d4SNico Weber } 35673dc3d4SNico Weber 36673dc3d4SNico Weber char *poisoned1; 37673dc3d4SNico Weber char *poisoned2; 38673dc3d4SNico Weber 39673dc3d4SNico Weber // Create redzones for stack variables in shadow memory and call 40673dc3d4SNico Weber // std::rethrow_exception which should unpoison the entire stack. create_redzones_and_throw(std::exception_ptr const & exc_ptr)41673dc3d4SNico Webervoid create_redzones_and_throw(std::exception_ptr const &exc_ptr) { 42673dc3d4SNico Weber char a[100]; 43673dc3d4SNico Weber poisoned1 = a - 1; 44673dc3d4SNico Weber poisoned2 = a + sizeof(a); 45673dc3d4SNico Weber assert(__asan_address_is_poisoned(poisoned1)); 46673dc3d4SNico Weber assert(__asan_address_is_poisoned(poisoned2)); 47673dc3d4SNico Weber uninstrumented_rethrow_exception(exc_ptr); 48673dc3d4SNico Weber } 49673dc3d4SNico Weber 50673dc3d4SNico Weber } // namespace 51673dc3d4SNico Weber 52673dc3d4SNico Weber // Check that std::rethrow_exception is intercepted by asan and the interception 53673dc3d4SNico Weber // unpoisons the stack. 54673dc3d4SNico Weber // If std::rethrow_exception is NOT intercepted, then calls to this function 55673dc3d4SNico Weber // from instrumented code will still unpoison the stack because 56673dc3d4SNico Weber // std::rethrow_exception is a [[noreturn]] function and any [[noreturn]] 57673dc3d4SNico Weber // function call will be instrumented with __asan_handle_no_return. 58673dc3d4SNico Weber // However, calls to std::rethrow_exception from UNinstrumented code will not 59673dc3d4SNico Weber // unpoison the stack, so we need to intercept std::rethrow_exception to 60673dc3d4SNico Weber // unpoison the stack. main()61673dc3d4SNico Weberint main() { 62673dc3d4SNico Weber // In some implementations of std::make_exception_ptr, e.g. libstdc++ prior to 63673dc3d4SNico Weber // gcc 7, this function calls __cxa_throw. The __cxa_throw is intercepted by 64673dc3d4SNico Weber // asan to unpoison the entire stack; since this test essentially tests that 65673dc3d4SNico Weber // the stack is unpoisoned by a call to std::rethrow_exception, we need to 66673dc3d4SNico Weber // generate the exception_ptr BEFORE we have the local variables poison the 67673dc3d4SNico Weber // stack. 68673dc3d4SNico Weber std::exception_ptr my_exception_ptr = std::make_exception_ptr("up"); 69673dc3d4SNico Weber 70673dc3d4SNico Weber try { 71673dc3d4SNico Weber create_redzones_and_throw(my_exception_ptr); 72673dc3d4SNico Weber } catch(char const *) { 73673dc3d4SNico Weber assert(!__asan_region_is_poisoned(poisoned1, poisoned2 - poisoned1 + 1)); 74673dc3d4SNico Weber } 75673dc3d4SNico Weber } 76