[compiler-rt] [asan][test] Distinguish real and fake stack shadow in Windows SEH (PR #226343)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 24 19:51:53 PDT 2026
https://github.com/kingakasa created https://github.com/llvm/llvm-project/pull/226343
The Windows SEH tests currently expect a local buffer's redzone to be unpoisoned after exception handling. That describes the existing real-stack cleanup behavior, but is incorrect when use-after-return detection places the still-live local buffer on the fake stack: its redzone should remain poisoned.
Query whether the buffer belongs to the current fake stack and check the corresponding shadow state. Apply the same distinction to seh.cpp and dll_seh.cpp. This preserves coverage of the existing real-stack behavior and checks that live fake-stack redzones survive the transfer.
Validation:
- Before this change, both tests fail with detect_stack_use_after_return=true and pass with it false in the dynamic CRT control.
- After the change, both tests pass under default settings and with detect_stack_use_after_return explicitly true and false, for dynamic and static CRT configurations: 12/12 lit executions.
- These are test-only changes, exercised against the unmodified baseline compiler and runtime.
Tested independently on Windows x64 using a fresh Release LLVM/Clang build with assertions enabled and a matching Release ASan runtime, based on `6dc4a4ba2850369afd537001377fb9d404653d26`.
Changed-line clang-format and git diff --check pass.
Assisted-by: OpenAI Codex
>From 4a407c8a0b1a82f96e67b70d401b9bb5e59b686f Mon Sep 17 00:00:00 2001
From: Kinga Kasa <kasakinga14 at gmail.com>
Date: Thu, 24 Sep 2026 22:50:03 -0400
Subject: [PATCH 1/2] [asan][test] Distinguish real and fake stack shadow in
Windows SEH
The Windows SEH tests currently expect a local buffer's redzone to be unpoisoned after exception handling. That describes the existing real-stack cleanup behavior, but is incorrect when use-after-return detection places the still-live local buffer on the fake stack: its redzone should remain poisoned.
Query whether the buffer belongs to the current fake stack and check the corresponding shadow state. Apply the same distinction to seh.cpp and dll_seh.cpp. This preserves coverage of the existing real-stack behavior and checks that live fake-stack redzones survive the transfer.
Validation:
- Before this change, both tests fail with detect_stack_use_after_return=true and pass with it false in the dynamic CRT control.
- After the change, both tests pass under default settings and with detect_stack_use_after_return explicitly true and false, for dynamic and static CRT configurations: 12/12 lit executions.
- These are test-only changes, exercised against the unmodified baseline compiler and runtime.
Tested independently on Windows x64 using a fresh Release LLVM/Clang build with assertions enabled and a matching Release ASan runtime, based on `6dc4a4ba2850369afd537001377fb9d404653d26`.
Changed-line clang-format and git diff --check pass.
Assisted-by: OpenAI Codex
---
.../test/asan/TestCases/Windows/msvc/dll_seh.cpp | 10 +++++++---
compiler-rt/test/asan/TestCases/Windows/msvc/seh.cpp | 10 +++++++---
2 files changed, 14 insertions(+), 6 deletions(-)
diff --git a/compiler-rt/test/asan/TestCases/Windows/msvc/dll_seh.cpp b/compiler-rt/test/asan/TestCases/Windows/msvc/dll_seh.cpp
index 9a29bee75c1b57..85c01f8b575179 100644
--- a/compiler-rt/test/asan/TestCases/Windows/msvc/dll_seh.cpp
+++ b/compiler-rt/test/asan/TestCases/Windows/msvc/dll_seh.cpp
@@ -14,6 +14,8 @@
// Should just "#include <sanitizer/asan_interface.h>" when C++ exceptions are
// supported and we don't need to use CL.
extern "C" bool __asan_address_is_poisoned(void *p);
+extern "C" void *__asan_get_current_fake_stack();
+extern "C" void *__asan_addr_is_in_fake_stack(void *, void *, void **, void **);
void ThrowAndCatch();
@@ -43,8 +45,10 @@ int test_function() {
ThrowAndCatch();
fprintf(stderr, "After: %p poisoned: %d\n", &x,
__asan_address_is_poisoned(x + 32));
- // FIXME: Invert this assertion once we fix
- // https://code.google.com/p/address-sanitizer/issues/detail?id=258
- assert(!__asan_address_is_poisoned(x + 32));
+ // Exception handling currently clears real-stack redzones (issue 258).
+ // A live fake-stack allocation must retain its redzones.
+ bool on_fake_stack = __asan_addr_is_in_fake_stack(
+ __asan_get_current_fake_stack(), x, nullptr, nullptr) != nullptr;
+ assert(__asan_address_is_poisoned(x + 32) == on_fake_stack);
return 0;
}
diff --git a/compiler-rt/test/asan/TestCases/Windows/msvc/seh.cpp b/compiler-rt/test/asan/TestCases/Windows/msvc/seh.cpp
index f3c7e1a33a568f..83d91e94337b4b 100644
--- a/compiler-rt/test/asan/TestCases/Windows/msvc/seh.cpp
+++ b/compiler-rt/test/asan/TestCases/Windows/msvc/seh.cpp
@@ -20,6 +20,8 @@
// Should just "#include <sanitizer/asan_interface.h>" when C++ exceptions are
// supported and we don't need to use CL.
extern "C" bool __asan_address_is_poisoned(void *p);
+extern "C" void *__asan_get_current_fake_stack();
+extern "C" void *__asan_addr_is_in_fake_stack(void *, void *, void **, void **);
void ThrowAndCatch();
@@ -51,8 +53,10 @@ int main() {
ThrowAndCatch();
fprintf(stderr, "After: %p poisoned: %d\n", &x,
__asan_address_is_poisoned(x + 32));
- // FIXME: Invert this assertion once we fix
- // https://code.google.com/p/address-sanitizer/issues/detail?id=258
- assert(!__asan_address_is_poisoned(x + 32));
+ // Exception handling currently clears real-stack redzones (issue 258).
+ // A live fake-stack allocation must retain its redzones.
+ bool on_fake_stack = __asan_addr_is_in_fake_stack(
+ __asan_get_current_fake_stack(), x, nullptr, nullptr) != nullptr;
+ assert(__asan_address_is_poisoned(x + 32) == on_fake_stack);
}
#endif
>From 19ef8d660a1c42b6dc0eaae031b632e2429295a8 Mon Sep 17 00:00:00 2001
From: Kinga Kasa <kasakinga14 at gmail.com>
Date: Thu, 24 Sep 2026 22:50:03 -0400
Subject: [PATCH 2/2] [style] Format seh-shadow-tests changes
Apply the upstream changed-line clang-format configuration.
No functional changes.
Assisted-by: OpenAI Codex
---
compiler-rt/test/asan/TestCases/Windows/msvc/dll_seh.cpp | 5 +++--
compiler-rt/test/asan/TestCases/Windows/msvc/seh.cpp | 5 +++--
2 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/compiler-rt/test/asan/TestCases/Windows/msvc/dll_seh.cpp b/compiler-rt/test/asan/TestCases/Windows/msvc/dll_seh.cpp
index 85c01f8b575179..99481f54afc1c3 100644
--- a/compiler-rt/test/asan/TestCases/Windows/msvc/dll_seh.cpp
+++ b/compiler-rt/test/asan/TestCases/Windows/msvc/dll_seh.cpp
@@ -47,8 +47,9 @@ int test_function() {
__asan_address_is_poisoned(x + 32));
// Exception handling currently clears real-stack redzones (issue 258).
// A live fake-stack allocation must retain its redzones.
- bool on_fake_stack = __asan_addr_is_in_fake_stack(
- __asan_get_current_fake_stack(), x, nullptr, nullptr) != nullptr;
+ bool on_fake_stack =
+ __asan_addr_is_in_fake_stack(__asan_get_current_fake_stack(), x, nullptr,
+ nullptr) != nullptr;
assert(__asan_address_is_poisoned(x + 32) == on_fake_stack);
return 0;
}
diff --git a/compiler-rt/test/asan/TestCases/Windows/msvc/seh.cpp b/compiler-rt/test/asan/TestCases/Windows/msvc/seh.cpp
index 83d91e94337b4b..d9bbd4337c28af 100644
--- a/compiler-rt/test/asan/TestCases/Windows/msvc/seh.cpp
+++ b/compiler-rt/test/asan/TestCases/Windows/msvc/seh.cpp
@@ -55,8 +55,9 @@ int main() {
__asan_address_is_poisoned(x + 32));
// Exception handling currently clears real-stack redzones (issue 258).
// A live fake-stack allocation must retain its redzones.
- bool on_fake_stack = __asan_addr_is_in_fake_stack(
- __asan_get_current_fake_stack(), x, nullptr, nullptr) != nullptr;
+ bool on_fake_stack =
+ __asan_addr_is_in_fake_stack(__asan_get_current_fake_stack(), x, nullptr,
+ nullptr) != nullptr;
assert(__asan_address_is_poisoned(x + 32) == on_fake_stack);
}
#endif
More information about the llvm-commits
mailing list