From a6da369a97eb28e89a1727c82c5ea66c00d832ca Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Fri, 10 Apr 2026 01:24:53 +0200 Subject: [PATCH 1/2] Unpoison fiber stack after context switch on AArch64 On AArch64, LLVM loses MSan shadow for struct-padding bytes in return values (llvm/llvm-project#54476). On heap-allocated fiber stacks the dirty shadow accumulates across context switches and propagates via stack-slot reuse, triggering false positives in unrelated code. Unpoison the entire fiber stack after each __msan_finish_switch_fiber to clear accumulated dirty padding shadow. Co-Authored-By: Claude Opus 4.6 (1M context) --- boost/context/fiber_ucontext.hpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/boost/context/fiber_ucontext.hpp b/boost/context/fiber_ucontext.hpp index bc4a9515e..6af9f5e66 100644 --- a/boost/context/fiber_ucontext.hpp +++ b/boost/context/fiber_ucontext.hpp @@ -172,6 +172,15 @@ struct BOOST_CONTEXT_DECL fiber_activation_record { #if defined(BOOST_USE_MSAN) __msan_finish_switch_fiber( (const void **) & current()->from->stack_bottom, & current()->from->stack_size); + // On AArch64, LLVM loses MSan shadow for struct-padding bytes in return values + // (llvm/llvm-project#54476). On heap-allocated fiber stacks the dirty shadow + // accumulates across context switches and propagates via stack-slot reuse. + // Unpoison the whole fiber stack to prevent these false positives. +#if defined(__aarch64__) + if ( ! current()->main_ctx) { + __msan_unpoison( current()->stack_bottom, current()->stack_size); + } +#endif #endif #if defined(BOOST_NO_CXX14_STD_EXCHANGE) return exchange( current()->from, nullptr); @@ -241,6 +250,11 @@ struct BOOST_CONTEXT_DECL fiber_activation_record { #if defined(BOOST_USE_MSAN) __msan_finish_switch_fiber( (const void **) & current()->from->stack_bottom, & current()->from->stack_size); +#if defined(__aarch64__) + if ( ! current()->main_ctx) { + __msan_unpoison( current()->stack_bottom, current()->stack_size); + } +#endif #endif #if defined(BOOST_NO_CXX14_STD_EXCHANGE) return exchange( current()->from, nullptr); @@ -302,6 +316,9 @@ class fiber_capture_record : public fiber_activation_record { #if defined(BOOST_USE_MSAN) __msan_finish_switch_fiber( (const void **) & from->stack_bottom, & from->stack_size); +#if defined(__aarch64__) + __msan_unpoison( stack_bottom, stack_size); +#endif #endif Ctx c{ from }; try { From 24df31b3e5c13c007efc533ef9f6ccd2e0c1f85d Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Fri, 10 Apr 2026 08:19:23 +0000 Subject: [PATCH 2/2] Add missing `__msan_unpoison` declaration to externc.hpp The AArch64 fiber stack unpoison code uses `__msan_unpoison` but it was not declared in the extern "C" block alongside the other MSan functions. This caused a build failure on arm_msan. Co-Authored-By: Claude Opus 4.6 (1M context) --- boost/context/detail/externc.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/boost/context/detail/externc.hpp b/boost/context/detail/externc.hpp index b8766fe28..c5c863fd3 100644 --- a/boost/context/detail/externc.hpp +++ b/boost/context/detail/externc.hpp @@ -19,6 +19,7 @@ void __sanitizer_finish_switch_fiber( void *, const void **, size_t *); extern "C" { void __msan_start_switch_fiber( const void *, size_t); void __msan_finish_switch_fiber( const void **, size_t *); +void __msan_unpoison( const volatile void *, size_t); } #endif