Subject: bug#29040: emacs-26 crash due to misaligned longjmp buffer in 64-bit MSYS2/MinGW-W64 build

From: Richard Copley <[email-masked]>
Date: Sat, 28 Oct 2017 14:40:41 +0100

When I build from the current emacs-26 branch with the current 64-bit
mingw-w64 toolchain from MSYS2, with optimization, Emacs sometimes
crashes with a segfault on typing C-g.

As far as I can tell, the current 64-bit pretest is not affected.

The attached file "servicelistpage.txt" helps to reproduce the crash.
It was created by the OP in this thread on help-gnu-emacs:

<http://lists.gnu.org/archive/html/help-gnu-emacs/2017-10/msg00089.html>

To reproduce the build with the 64-bit MinGW-W64 toolchain from MSYS2,

 * Save a backup of your MSYS2 installation, if it is in working order.
 * Update MSYS2.
 * In MSYS2 MINGW64 shell in the emacs repo:

git reset --hard 68182a47
git clean -xfd
./autogen.sh
./configure --with-modules --without-pop 'CFLAGS=-O1 -ggdb3'
make -j8 -O

Then, to reproduce the crash from "src/emacs -Q servicelistpage.txt":

 * Wait for the buffer to be displayed.
 * Type [C-g].

Partial GDB backtrace (full backtrace attached):

Thread 1 (Thread 5480.0x1e9c):
#0  0x00007ffaa1b693a0 in ntdll!RtlCaptureContext ()
   from C:\WINDOWS\SYSTEM32\ntdll.dll
No symbol table info available.
#1  0x00007ffaa1ad8f27 in ntdll!RtlUnwindEx ()
   from C:\WINDOWS\SYSTEM32\ntdll.dll
No symbol table info available.
#2  0x00007ffaa0671f4a in msvcrt!_setjmpex ()
   from C:\WINDOWS\System32\msvcrt.dll
No symbol table info available.
#3  0x00000004000b1a9a in quit_throw_to_read_char (
    from_signal=from_signal@entry=false) at keyboard.c:10548
No locals.

The faulting instruction in ntdll!RtlCaptureContext (frame #0) is

0x00007ffaa1b693a0 <+384>:   movaps 0x60(%rax),%xmm0

The memory operand should be 16-byte aligned but it is not. That is
the cause of the segfault. I think the following extract from the GDB
session shows the problem. The value in %rax is 0x4005CDAE8 (not
16-byte aligned).

(gdb) p $rax
$1 = 17185954536
(gdb) up
#1  0x00007ffaa1ad8f27 in ntdll!RtlUnwindEx ()
   from C:\WINDOWS\SYSTEM32\ntdll.dll
(gdb) up
#2  0x00007ffaa0671f4a in msvcrt!_setjmpex ()
   from C:\WINDOWS\System32\msvcrt.dll
(gdb) up
#3  0x00000004000b1a9a in quit_throw_to_read_char (
    from_signal=from_signal@entry=false) at keyboard.c:10548
10548     sys_longjmp (getcjmp, 1);
(gdb) p &getcjmp
$2 = (sys_jmp_buf *) 0x4005cdae8 <main_thread+224>

In the help-gnu-emacs thread, Eli said:

  [...] we should ask the MinGW64 developers for advice about using
  longjmp. Most probably, something in that area has changed in recent
  releases of their runtime [...]

Eli, my apologies, but I don't think I understand the issues well
enough to have a productive discussion with the MinGW-W64 developers
myself.