Adjust 'suppress_fake_stack.cpp' and 'suppress_fake_stack_force_disabled.cpp' to work with MSVC's ASan#172707
Adjust 'suppress_fake_stack.cpp' and 'suppress_fake_stack_force_disabled.cpp' to work with MSVC's ASan#172707davidmrdavid wants to merge 1 commit intollvm:mainfrom
Conversation
…led.cpp' to work with MSVC's ASan
|
@llvm/pr-subscribers-compiler-rt-sanitizer Author: David Justo (davidmrdavid) ChangesFollow-up to: #160135 Context: The aforementioned PR introduced the ability to suppress ASan's 'fake stack' on demand, and tests this via 2 new tests: (1) The tests invoke This PR addresses these issues by: (A) Using Full diff: https://github.com/llvm/llvm-project/pull/172707.diff 2 Files Affected:
diff --git a/compiler-rt/test/asan/TestCases/suppress_fake_stack.cpp b/compiler-rt/test/asan/TestCases/suppress_fake_stack.cpp
index f072c6ad3b034..bd35df99ab705 100644
--- a/compiler-rt/test/asan/TestCases/suppress_fake_stack.cpp
+++ b/compiler-rt/test/asan/TestCases/suppress_fake_stack.cpp
@@ -1,6 +1,14 @@
-// RUN: %clangxx_asan %s -o %t && env ASAN_OPTIONS=detect_stack_use_after_return=1 %run %t
-// RUN: %clangxx_asan %s -mllvm -asan-use-after-return=runtime -o %t && env ASAN_OPTIONS=detect_stack_use_after_return=1 %run %t
-// RUN: %clangxx_asan %s -mllvm -asan-use-after-return=always -o %t && %run %t
+// This file tests the suppression of fake stack frames in ASan.
+
+// We need to separate the MSVC and non-MSVC tests because MSVC because the MSVC enablement of 'stack-use-after-return' detection is different.
+
+// MSVC tests
+// RUN: %if target={{.*-windows-msvc.*}} %{ %clangxx_asan -fsanitize-address-use-after-return %s -o %t && env ASAN_OPTIONS=detect_stack_use_after_return=1 %run %t %}
+
+// Non-MSVC tests
+// RUN: %if !target={{.*-windows-msvc.*}} %{ %clangxx_asan %s -o %t && env ASAN_OPTIONS=detect_stack_use_after_return=1 %run %t %}
+// RUN: %if !target={{.*-windows-msvc.*}} %{ %clangxx_asan %s -mllvm -asan-use-after-return=runtime -o %t && env ASAN_OPTIONS=detect_stack_use_after_return=1 %run %t %}
+// RUN: %if !target={{.*-windows-msvc.*}} %{ %clangxx_asan %s -mllvm -asan-use-after-return=always -o %t && %run %t %}
#include "defines.h"
@@ -9,10 +17,18 @@
volatile uintptr_t saved;
+// Use FRAME_ADDRESS macro to get the current frame address
+#ifdef _MSC_VER
+// MSVC does not have a 'builtin_frame_address' equivalent.
+// However, for the purposes of this test, its `_AddressOfReturnAddress` built-in suffices
+# define FRAME_ADDRESS reinterpret_cast<uintptr_t>(_AddressOfReturnAddress())
+#else
+# define FRAME_ADDRESS reinterpret_cast<uintptr_t>(__builtin_frame_address(0))
+#endif
+
ATTRIBUTE_NOINLINE bool IsOnRealStack(uintptr_t parent_frame,
uintptr_t var_addr) {
- uintptr_t this_frame =
- reinterpret_cast<uintptr_t>(__builtin_frame_address(0));
+ uintptr_t this_frame = FRAME_ADDRESS;
return this_frame <= var_addr && var_addr <= parent_frame;
}
@@ -22,9 +38,7 @@ ATTRIBUTE_NOINLINE bool IsOnRealStack(uintptr_t parent_frame) {
return IsOnRealStack(parent_frame, saved);
}
-ATTRIBUTE_NOINLINE bool IsOnRealStack() {
- return IsOnRealStack(reinterpret_cast<uintptr_t>(__builtin_frame_address(0)));
-}
+ATTRIBUTE_NOINLINE bool IsOnRealStack() { return IsOnRealStack(FRAME_ADDRESS); }
int main(int argc, char *argv[]) {
assert(!IsOnRealStack());
diff --git a/compiler-rt/test/asan/TestCases/suppress_fake_stack_force_disabled.cpp b/compiler-rt/test/asan/TestCases/suppress_fake_stack_force_disabled.cpp
index c549f08a7f0a8..f92a42381e0a3 100644
--- a/compiler-rt/test/asan/TestCases/suppress_fake_stack_force_disabled.cpp
+++ b/compiler-rt/test/asan/TestCases/suppress_fake_stack_force_disabled.cpp
@@ -1,7 +1,11 @@
// Check unsuppressing fake stack does not reenable it if disabled via compile or runtime options.
-//
-// RUN: %clangxx_asan %s -mllvm -asan-use-after-return=never -o %t && %run %t
-// RUN: %clangxx_asan %s -mllvm -asan-use-after-return=runtime -o %t && env ASAN_OPTIONS=detect_stack_use_after_return=0 %run %t
+
+// MSVC tests, where disablement is only at runtime.
+// RUN: %if target={{.*-windows-msvc.*}} %{ %clangxx_asan -fsanitize-address-use-after-return %s -o %t && env ASAN_OPTIONS=detect_stack_use_after_return=0 %run %t %}
+
+// Non-MSVC tests
+// RUN: %if !target={{.*-windows-msvc.*}} %{ %clangxx_asan %s -mllvm -asan-use-after-return=never -o %t && %run %t %}
+// RUN: %if !target={{.*-windows-msvc.*}} %{ %clangxx_asan %s -mllvm -asan-use-after-return=runtime -o %t && env ASAN_OPTIONS=detect_stack_use_after_return=0 %run %t %}
#include "defines.h"
@@ -10,10 +14,18 @@
volatile uintptr_t saved;
+// Use FRAME_ADDRESS macro to get the current frame address
+#ifdef _MSC_VER
+// MSVC does not have a 'builtin_frame_address' equivalent.
+// However, for the purposes of this test, its `_AddressOfReturnAddress` built-in suffices
+# define FRAME_ADDRESS reinterpret_cast<uintptr_t>(_AddressOfReturnAddress())
+#else
+# define FRAME_ADDRESS reinterpret_cast<uintptr_t>(__builtin_frame_address(0))
+#endif
+
ATTRIBUTE_NOINLINE bool IsOnRealStack(uintptr_t parent_frame,
uintptr_t var_addr) {
- uintptr_t this_frame =
- reinterpret_cast<uintptr_t>(__builtin_frame_address(0));
+ uintptr_t this_frame = FRAME_ADDRESS;
return this_frame <= var_addr && var_addr <= parent_frame;
}
@@ -23,9 +35,7 @@ ATTRIBUTE_NOINLINE bool IsOnRealStack(uintptr_t parent_frame) {
return IsOnRealStack(parent_frame, saved);
}
-ATTRIBUTE_NOINLINE bool IsOnRealStack() {
- return IsOnRealStack(reinterpret_cast<uintptr_t>(__builtin_frame_address(0)));
-}
+ATTRIBUTE_NOINLINE bool IsOnRealStack() { return IsOnRealStack(FRAME_ADDRESS); }
int main(int argc, char *argv[]) {
assert(IsOnRealStack());
|
🪟 Windows x64 Test Results
Failed Tests(click on a test name to see its output) AddressSanitizer-x86_64-windowsAddressSanitizer-x86_64-windows.TestCases/suppress_fake_stack.cppAddressSanitizer-x86_64-windows.TestCases/suppress_fake_stack_force_disabled.cppAddressSanitizer-x86_64-windows-dynamicAddressSanitizer-x86_64-windows-dynamic.TestCases/suppress_fake_stack.cppAddressSanitizer-x86_64-windows-dynamic.TestCases/suppress_fake_stack_force_disabled.cppIf these failures are unrelated to your changes (for example tests are broken or flaky at HEAD), please open an issue at https://github.com/llvm/llvm-project/issues and add the |
|
I don't feel very strongly about this, but I wonder if you should just mark this test unsupported in your configuration and make a separate test in |
|
Thanks @ndrewh - yeah I think that's valid, and in our fork that's pretty much what we've done to pull in the latest changes. That said, I'm interested in paving the way for MSVC to work directly upstream, some I'd love to use this PR to learn how to properly exclude tests from running in MSVC (while still allowing them to run w/ clang) when they're incompatible. The failing tests here reveal that the conditional I'm going to be away for ~2 weeks due to the holidays, so I'll mark this as draft in the meantime. If you have any suggestions on how to exclude tests from running under the clang driver, I'm all ears. Thanks! |
|
Actually, this PR gives the tools I need to be able to discern between clang and MSVC. I'll make a follow up commit in early 2026 incorporating some tricks from there. Thanks! |
Follow-up to: #160135
Context: The aforementioned PR introduced the ability to suppress ASan's 'fake stack' on demand, and tests this via 2 new tests:
suppress_fake_stack.cppandsuppress_fake_stack_force_disabled.cpp. These tests fail to run in MSVC's ASan (a fork of LLVM's ASan) for 2 reasons:(1) The tests invoke
__builtin_frame_address, a built-in that does not exist in MSVC.(2) MSVC has slightly different 'stack-use-after-return' enablement flags, as per this documentation. The short story is that MSVC's 'stack-use-after-return' behavior is a more constrained.
This PR addresses these issues by:
(A) Using
_AddressOfReturnAddressinstead of__builtin_frame_addresswhen MSVC is detected (i.e._MSC_VERis defined)(B) Using conditionals to split the
// RUN:commands into MSVC specific commands, and everything else.