Skip to content

Commit 283b3dc

Browse files
committed
Fix invalid MXCSR restore on Linux i386 after SIGFPE
Floating-point exception handling calls restoreControlRegs() from the SIGFPE handler before throwing a C++ MathExc. On Linux i386, when the kernel _fpstate magic field was non-zero, the code passed 0 to LDMXCSR. An all-zero MXCSR is not a valid control register value on x86 and leaves SSE in a corrupt state, which showed up as crashes inside libstdc++ (for example std::ostream::sentry) on i686 CI runs. Read MXCSR from the live CPU when the saved frame does not use the expected layout (magic != 0), and never load zero: substitute the usual hardware default 0x1f80 before setMxcsr applies the clearExceptions mask. Made-with: Cursor Signed-off-by: Cary Phillips <cary@ilm.com>
1 parent d68fcb6 commit 283b3dc

1 file changed

Lines changed: 11 additions & 1 deletion

File tree

src/lib/Iex/IexMathFpu.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,17 @@ restoreControlRegs (const ucontext_t& ucon, bool clearExceptions)
252252

253253
_fpstate* kfp = reinterpret_cast<_fpstate*> (ucon.uc_mcontext.fpregs);
254254
# if defined(__linux__) && defined(__i386__)
255-
setMxcsr (kfp->magic == 0 ? kfp->mxcsr : 0, clearExceptions);
255+
//
256+
// Choose MXCSR from the signal-frame _fpstate when magic == 0 (kernel
257+
// layout matches this struct); otherwise read it from the CPU because
258+
// the saved mxcsr offset may not apply. LDMXCSR must not be given 0,
259+
// which is not a valid control value on x86—substitute 0x1f80 (typical
260+
// default) before setMxcsr clears sticky exception bits per
261+
// clearExceptions.
262+
//
263+
uint32_t mxcsr = (kfp->magic == 0) ? kfp->mxcsr : getMxcsr ();
264+
if (mxcsr == 0) mxcsr = 0x1f80;
265+
setMxcsr (mxcsr, clearExceptions);
256266
# else
257267
setMxcsr (kfp->mxcsr, clearExceptions);
258268
# endif

0 commit comments

Comments
 (0)