On Alpine Linux 3.18 (32-bit x86), the generated 'gzip' binary fails
at every invocation:

$ ./gzip < ../gzip.doc > gzip.doc.gz-t
Segmentation fault

$ ./gzip --help
Segmentation fault

The stack trace in gdb shows 5 frames in /lib/ld-musl-i386.so.1.

Configuring with
  DEFS=-DNO_ASM
provides a workaround. This proves that the problem is with lib/match.c.

Find attached the output of "objdump -d -r lib.match.o". This object code
looks harmless to me, but apparently it trips some verification failure
inside musl libc.

The attached patch fixes it. Tested on Alpine Linux 3.18 (32-bit x86).

lib/match.o:     file format elf32-i386


Disassembly of section .text:

00000000 <match_init>:
   0:   c3                      ret

00000001 <longest_match>:
   1:   55                      push   %ebp
   2:   57                      push   %edi
   3:   56                      push   %esi
   4:   53                      push   %ebx
   5:   8b 74 24 14             mov    0x14(%esp),%esi
   9:   8b 2d 00 00 00 00       mov    0x0,%ebp
                        b: R_386_32     max_chain_length
   f:   8b 3d 00 00 00 00       mov    0x0,%edi
                        11: R_386_32    strstart
  15:   89 fa                   mov    %edi,%edx
  17:   81 ea fa 7e 00 00       sub    $0x7efa,%edx
  1d:   73 02                   jae    21 <limit_ok>
  1f:   29 d2                   sub    %edx,%edx

00000021 <limit_ok>:
  21:   81 c7 02 00 00 00       add    $0x2,%edi
                        23: R_386_32    window
  27:   8b 1d 00 00 00 00       mov    0x0,%ebx
                        29: R_386_32    prev_length
  2d:   66 8b 44 3b fd          mov    -0x3(%ebx,%edi,1),%ax
  32:   66 8b 4f fe             mov    -0x2(%edi),%cx
  36:   3b 1d 00 00 00 00       cmp    0x0,%ebx
                        38: R_386_32    good_match
  3c:   72 24                   jb     62 <do_scan>
  3e:   c1 ed 02                shr    $0x2,%ebp
  41:   eb 1f                   jmp    62 <do_scan>
  43:   90                      nop

00000044 <long_loop>:
  44:   66 8b 44 3b fd          mov    -0x3(%ebx,%edi,1),%ax
  49:   66 8b 4f fe             mov    -0x2(%edi),%cx

0000004d <short_loop>:
  4d:   81 e6 ff 7f 00 00       and    $0x7fff,%esi
  53:   66 8b b4 36 00 00 00    mov    0x0(%esi,%esi,1),%si
  5a:   00 
                        57: R_386_32    prev
  5b:   39 d6                   cmp    %edx,%esi
  5d:   76 53                   jbe    b2 <the_end>
  5f:   4d                      dec    %ebp
  60:   74 50                   je     b2 <the_end>

00000062 <do_scan>:
  62:   66 3b 84 33 ff ff ff    cmp    -0x1(%ebx,%esi,1),%ax
  69:   ff 
                        66: R_386_32    window
  6a:   75 e1                   jne    4d <short_loop>
  6c:   66 3b 8e 00 00 00 00    cmp    0x0(%esi),%cx
                        6f: R_386_32    window
  73:   75 d8                   jne    4d <short_loop>
  75:   8d b6 02 00 00 00       lea    0x2(%esi),%esi
                        77: R_386_32    window
  7b:   89 f8                   mov    %edi,%eax
  7d:   b9 80 00 00 00          mov    $0x80,%ecx
  82:   f3 66 a7                repz cmpsw %es:(%edi),%ds:(%esi)
  85:   74 32                   je     b9 <maxmatch>

00000087 <mismatch>:
  87:   8a 4f fe                mov    -0x2(%edi),%cl
  8a:   2a 4e fe                sub    -0x2(%esi),%cl
  8d:   97                      xchg   %eax,%edi
  8e:   29 f8                   sub    %edi,%eax
  90:   29 c6                   sub    %eax,%esi
  92:   81 ee 02 00 00 00       sub    $0x2,%esi
                        94: R_386_32    window
  98:   80 e9 01                sub    $0x1,%cl
  9b:   83 d0 00                adc    $0x0,%eax
  9e:   39 d8                   cmp    %ebx,%eax
  a0:   7e a2                   jle    44 <long_loop>
  a2:   89 35 00 00 00 00       mov    %esi,0x0
                        a4: R_386_32    match_start
  a8:   89 c3                   mov    %eax,%ebx
  aa:   3b 05 00 00 00 00       cmp    0x0,%eax
                        ac: R_386_32    nice_match
  b0:   7c 92                   jl     44 <long_loop>

000000b2 <the_end>:
  b2:   89 d8                   mov    %ebx,%eax
  b4:   5b                      pop    %ebx
  b5:   5e                      pop    %esi
  b6:   5f                      pop    %edi
  b7:   5d                      pop    %ebp
  b8:   c3                      ret

000000b9 <maxmatch>:
  b9:   a6                      cmpsb  %es:(%edi),%ds:(%esi)
  ba:   eb cb                   jmp    87 <mismatch>
>From c0c8dacb5b84b0d58f5432b58feda8d0ff1391f6 Mon Sep 17 00:00:00 2001
From: Bruno Haible <[email protected]>
Date: Sat, 18 Apr 2026 15:53:55 +0200
Subject: [PATCH] build: Fix broken executable on 32-bit x86 systems with musl
 libc

* configure.ac (gzip_cv_assembler): Set to no on musl libc.
---
 configure.ac | 50 +++++++++++++++++++++++++++++---------------------
 1 file changed, 29 insertions(+), 21 deletions(-)

diff --git a/configure.ac b/configure.ac
index f319346..f54042b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -249,27 +249,35 @@ AC_CACHE_CHECK([for an assembler syntax supported by this package],
   [gzip_cv_assembler],
   [gzip_cv_assembler=no
    case $DEFS in
-   *NO_ASM*) ;;
-   *)
-     if cp $srcdir/lib/match.c _match.S &&
-        eval "$CPP $CPPFLAGS $ASCPPFLAGS _match.S > _match.i" &&
-        eval "$ASCPPPOST < _match.i > match_.s"; then
-       if test ! -s match_.s || grep error < match_.s > /dev/null; then
-         :
-       elif eval "$CC $CPPFLAGS $CFLAGS -c match_.s >/dev/null" &&
-            test -f match_.$OBJEXT; then
-         rm -f match_.$OBJEXT
-         gzip_cv_assembler=yes
-         if echo 'void foo (void) {}' > conftest.c &&
-            eval "$CC $CPPFLAGS $CFLAGS -S conftest.c >/dev/null" &&
-            grep '\.note\.GNU-stack' conftest.s >/dev/null &&
-            eval "$CC $CPPFLAGS $CFLAGS -c -Wa,--noexecstack match_.s >/dev/null" &&
-            test -f match_.$OBJEXT; then
-           gzip_cv_assembler='yes, with -Wa,--noexecstack'
-         fi
-       fi
-     fi
-     rm -f conftest* _match.i _match.S match_.s match_.$OBJEXT;;
+     *NO_ASM*) ;;
+     *)
+       # Avoid a crash in musl libc's startup code.
+       AC_REQUIRE([AC_CANONICAL_HOST])
+       case "$host_os" in
+         *-musl* | midipix*) ;;
+         *)
+           if cp $srcdir/lib/match.c _match.S &&
+              eval "$CPP $CPPFLAGS $ASCPPFLAGS _match.S > _match.i" &&
+              eval "$ASCPPPOST < _match.i > match_.s"; then
+             if test ! -s match_.s || grep error < match_.s > /dev/null; then
+               :
+             elif eval "$CC $CPPFLAGS $CFLAGS -c match_.s >/dev/null" &&
+                  test -f match_.$OBJEXT; then
+               rm -f match_.$OBJEXT
+               gzip_cv_assembler=yes
+               if echo 'void foo (void) {}' > conftest.c &&
+                  eval "$CC $CPPFLAGS $CFLAGS -S conftest.c >/dev/null" &&
+                  grep '\.note\.GNU-stack' conftest.s >/dev/null &&
+                  eval "$CC $CPPFLAGS $CFLAGS -c -Wa,--noexecstack match_.s >/dev/null" &&
+                  test -f match_.$OBJEXT; then
+                 gzip_cv_assembler='yes, with -Wa,--noexecstack'
+               fi
+             fi
+           fi
+           rm -f conftest* _match.i _match.S match_.s match_.$OBJEXT
+           ;;
+       esac
+       ;;
    esac])
 if test "$gzip_cv_assembler" != no; then
   AC_DEFINE([ASMV], ,
-- 
2.52.0

Reply via email to