Index: compiler-rt/trunk/lib/asan/asan_flags.inc =================================================================== --- compiler-rt/trunk/lib/asan/asan_flags.inc +++ compiler-rt/trunk/lib/asan/asan_flags.inc @@ -46,6 +46,8 @@ "If set, uses custom wrappers for memset/memcpy/memmove intrinsics.") ASAN_FLAG(bool, detect_stack_use_after_return, false, "Enables stack-use-after-return checking at run-time.") +ASAN_FLAG(bool, detect_stack_use_after_scope, true, + "Enables stack-use-after-scope checking at run-time.") ASAN_FLAG(int, min_uar_stack_size_log, 16, // We can't do smaller anyway. "Minimum fake stack size log.") ASAN_FLAG(int, max_uar_stack_size_log, Index: compiler-rt/trunk/lib/asan/asan_interface_internal.h =================================================================== --- compiler-rt/trunk/lib/asan/asan_interface_internal.h +++ compiler-rt/trunk/lib/asan/asan_interface_internal.h @@ -160,6 +160,10 @@ SANITIZER_INTERFACE_ATTRIBUTE extern int __asan_option_detect_stack_use_after_return; +// Global flag, copy of ASAN_OPTIONS=detect_stack_use_after_scope + SANITIZER_INTERFACE_ATTRIBUTE + extern int __asan_option_detect_stack_use_after_scope; + SANITIZER_INTERFACE_ATTRIBUTE extern uptr *__asan_test_only_reported_buggy_pointer; Index: compiler-rt/trunk/lib/asan/asan_poisoning.cc =================================================================== --- compiler-rt/trunk/lib/asan/asan_poisoning.cc +++ compiler-rt/trunk/lib/asan/asan_poisoning.cc @@ -315,11 +315,13 @@ } void __asan_poison_stack_memory(uptr addr, uptr size) { + if (!__asan_option_detect_stack_use_after_scope) return; VReport(1, "poisoning: %p %zx\n", (void *)addr, size); PoisonAlignedStackMemory(addr, size, true); } void __asan_unpoison_stack_memory(uptr addr, uptr size) { + if (!__asan_option_detect_stack_use_after_scope) return; VReport(1, "unpoisoning: %p %zx\n", (void *)addr, size); PoisonAlignedStackMemory(addr, size, false); } Index: compiler-rt/trunk/lib/asan/asan_rtl.cc =================================================================== --- compiler-rt/trunk/lib/asan/asan_rtl.cc +++ compiler-rt/trunk/lib/asan/asan_rtl.cc @@ -33,6 +33,7 @@ #include "ubsan/ubsan_platform.h" int __asan_option_detect_stack_use_after_return; // Global interface symbol. +int __asan_option_detect_stack_use_after_scope; // Global interface symbol. uptr *__asan_test_only_reported_buggy_pointer; // Used only for testing asan. namespace __asan { @@ -434,10 +435,12 @@ __sanitizer_set_report_path(common_flags()->log_path); - // Enable UAR detection, if required. __asan_option_detect_stack_use_after_return = flags()->detect_stack_use_after_return; + __asan_option_detect_stack_use_after_scope = + flags()->detect_stack_use_after_scope; + // Re-exec ourselves if we need to set additional env or command line args. MaybeReexec(); Index: compiler-rt/trunk/lib/asan/asan_win.cc =================================================================== --- compiler-rt/trunk/lib/asan/asan_win.cc +++ compiler-rt/trunk/lib/asan/asan_win.cc @@ -37,6 +37,12 @@ return __asan_option_detect_stack_use_after_return; } +SANITIZER_INTERFACE_ATTRIBUTE +int __asan_should_detect_stack_use_after_scope() { + __asan_init(); + return __asan_option_detect_stack_use_after_scope; +} + // -------------------- A workaround for the abscence of weak symbols ----- {{{ // We don't have a direct equivalent of weak symbols when using MSVC, but we can // use the /alternatename directive to tell the linker to default a specific Index: compiler-rt/trunk/lib/asan/asan_win_dll_thunk.cc =================================================================== --- compiler-rt/trunk/lib/asan/asan_win_dll_thunk.cc +++ compiler-rt/trunk/lib/asan/asan_win_dll_thunk.cc @@ -198,9 +198,11 @@ // Don't use the INTERFACE_FUNCTION machinery for this function as we actually // want to call it in the __asan_init interceptor. WRAP_W_V(__asan_should_detect_stack_use_after_return) +WRAP_W_V(__asan_should_detect_stack_use_after_scope) extern "C" { int __asan_option_detect_stack_use_after_return; + int __asan_option_detect_stack_use_after_scope; // Manually wrap __asan_init as we need to initialize // __asan_option_detect_stack_use_after_return afterwards. @@ -214,6 +216,8 @@ fn(); __asan_option_detect_stack_use_after_return = (__asan_should_detect_stack_use_after_return() != 0); + __asan_option_detect_stack_use_after_scope = + (__asan_should_detect_stack_use_after_scope() != 0); InterceptHooks(); } Index: compiler-rt/trunk/lib/asan/asan_win_dynamic_runtime_thunk.cc =================================================================== --- compiler-rt/trunk/lib/asan/asan_win_dynamic_runtime_thunk.cc +++ compiler-rt/trunk/lib/asan/asan_win_dynamic_runtime_thunk.cc @@ -15,6 +15,7 @@ // // This includes: // - forwarding the detect_stack_use_after_return runtime option +// - forwarding the detect_stack_use_after_scope runtime option // - working around deficiencies of the MD runtime // - installing a custom SEH handlerx // @@ -51,6 +52,23 @@ } //////////////////////////////////////////////////////////////////////////////// +// Define a copy of __asan_option_detect_stack_use_after_scope that should be +// used when linking an MD runtime with a set of object files on Windows. +// +// The ASan MD runtime dllexports '__asan_option_detect_stack_use_after_scope', +// so normally we would just dllimport it. Unfortunately, the dllimport +// attribute adds __imp_ prefix to the symbol name of a variable. +// Since in general we don't know if a given TU is going to be used +// with a MT or MD runtime and we don't want to use ugly __imp_ names on Windows +// just to work around this issue, let's clone the a variable that is +// constant after initialization anyways. +extern "C" { +__declspec(dllimport) int __asan_should_detect_stack_use_after_scope(); +int __asan_option_detect_stack_use_after_scope = + __asan_should_detect_stack_use_after_scope(); +} + +//////////////////////////////////////////////////////////////////////////////// // For some reason, the MD CRT doesn't call the C/C++ terminators during on DLL // unload or on exit. ASan relies on LLVM global_dtors to call // __asan_unregister_globals on these events, which unfortunately doesn't work Index: compiler-rt/trunk/test/asan/TestCases/use-after-scope.cc =================================================================== --- compiler-rt/trunk/test/asan/TestCases/use-after-scope.cc +++ compiler-rt/trunk/test/asan/TestCases/use-after-scope.cc @@ -1,16 +1,19 @@ // RUN: %clangxx_asan -O1 -fsanitize-address-use-after-scope %s -o %t && \ -// RUN: not %run %t 2>&1 | FileCheck %s +// RUN: %env_asan_opts=detect_stack_use_after_scope=1 not %run %t 2>&1 | FileCheck %s -int *p = 0; +// RUN: %env_asan_opts=detect_stack_use_after_scope=0 %run %t + +volatile int *p = 0; int main() { { int x = 0; p = &x; } - return *p; // BOOM + *p = 5; // BOOM // CHECK: ERROR: AddressSanitizer: stack-use-after-scope // CHECK: #0 0x{{.*}} in main {{.*}}use-after-scope.cc:[[@LINE-2]] // CHECK: Address 0x{{.*}} is located in stack of thread T{{.*}} at offset [[OFFSET:[^ ]+]] in frame // {{\[}}[[OFFSET]], {{[0-9]+}}) 'x' + return 0; }