The test case winsup/testsuites/winsup.api/pthread/cancel2 fails
on Windows 11 and Windows Server 2025, while it works on Windows 10
and Windows Server 2022. PTHREAD_CANCEL_ASYNCHRONOUS is implemented
using [GS]etThreadContext() on the target thread and forcibly
overrides instruction pointer to pthread::static_cancel_self().
Previously, the stack pointer was not trimmed to 16-byte alignment,
even though this is required by 64-bit Windows ABI. This appears to
have been overlooked when cygwin first added x86_64 support.

This patch fixes this issue by aligning the stack pointer as well as
the instruction pointer in the PTHREAD_CANCEL_ASYNCHRONOUS handling.

Addresses: https://cygwin.com/pipermail/cygwin/2025-December/259117.html
Fixes: 61522196c715 ("* Merge in cygwin-64bit-branch.")
Reported-by: Takashi Yano <[email protected]>
Reviewed-by:
Signed-off-by: Takashi Yano <[email protected]>
---
 winsup/cygwin/thread.cc | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc
index 86a00e76e..2270a248b 100644
--- a/winsup/cygwin/thread.cc
+++ b/winsup/cygwin/thread.cc
@@ -630,6 +630,25 @@ pthread::cancel ()
       threadlist_t *tl_entry = cygheap->find_tls (cygtls);
       if (!cygtls->inside_kernel (&context))
        {
+#if defined(__x86_64__)
+         /* Need to trim alignment of stack pointer.
+            
https://learn.microsoft.com/en-us/cpp/build/stack-usage?view=msvc-170
+            states,
+              "The stack will always be maintained 16-byte aligned,
+               except within the prolog (for example, after the return
+               address is pushed),",
+            that is, we need 16n + 8 byte alignment here. */
+         context._CX_stackPtr &= 0xfffffffffffffff8UL;
+         if ((context._CX_stackPtr & 8) == 0)
+           context._CX_stackPtr -= 8;
+#elif defined(__aarch64__)
+         /* 16 bytes alignment required. Trim stack pointer just in case.
+         
https://learn.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions?view=msvc-170
+         */
+         context._CX_stackPtr &= 0xfffffffffffffff0UL;
+#else
+#error unimplemented for this target
+#endif
          context._CX_instPtr = (ULONG_PTR) pthread::static_cancel_self;
          SetThreadContext (win32_obj_id, &context);
        }
-- 
2.51.0

Reply via email to