Compiling GNU Bison (HEAD~10) with the newest gnulib, and running "make check", I get 8 test failures: testsuite: 608 615 619 620 622 623 625 626 failed Seen on Ubuntu 22.04 and on Ubuntu 24.04 with gcc 13.
Same of the failures are caused by SIGSEGV, some by SIGABRT: tests/testsuite.dir/608/testsuite.log:+/media/develdata/devel/BISON/bison-older/tests/bison: line 33: 2359811 Aborted (core dumped) $PREBISON "$abs_top_builddir/src/bison" ${1+"$@"} tests/testsuite.dir/615/testsuite.log:+/media/develdata/devel/BISON/bison-older/tests/bison: line 33: 2360097 Segmentation fault (core dumped) $PREBISON "$abs_top_builddir/src/bison" ${1+"$@"} tests/testsuite.dir/619/testsuite.log:+/media/develdata/devel/BISON/bison-older/tests/bison: line 33: 2360330 Aborted (core dumped) $PREBISON "$abs_top_builddir/src/bison" ${1+"$@"} tests/testsuite.dir/620/testsuite.log:+/media/develdata/devel/BISON/bison-older/tests/bison: line 33: 2360350 Segmentation fault (core dumped) $PREBISON "$abs_top_builddir/src/bison" ${1+"$@"} tests/testsuite.dir/622/testsuite.log:+/media/develdata/devel/BISON/bison-older/tests/bison: line 33: 2360438 Aborted (core dumped) $PREBISON "$abs_top_builddir/src/bison" ${1+"$@"} tests/testsuite.dir/623/testsuite.log:+/media/develdata/devel/BISON/bison-older/tests/bison: line 33: 2360460 Segmentation fault (core dumped) $PREBISON "$abs_top_builddir/src/bison" ${1+"$@"} tests/testsuite.dir/625/testsuite.log:+/media/develdata/devel/BISON/bison-older/tests/bison: line 33: 2360610 Segmentation fault (core dumped) $PREBISON "$abs_top_builddir/src/bison" ${1+"$@"} tests/testsuite.dir/626/testsuite.log:/media/develdata/devel/BISON/bison-older/tests/bison: line 33: 2360667 Segmentation fault (core dumped) $PREBISON "$abs_top_builddir/src/bison" ${1+"$@"} I picked the first of these failures and ran it under valgrind: $ cd tests/testsuite.dir/608 $ PREBISON=valgrind ./run The first error shown by valgrind looks like this: +==2376698== Invalid write of size 1 +==2376698== at 0x4852EE3: memmove (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so) +==2376698== by 0x48DCD87: memcpy (string_fortified.h:29) +==2376698== by 0x48DCD87: __printf_buffer_write (Xprintf_buffer_write.c:39) +==2376698== by 0x48E510B: __printf_buffer (vfprintf-internal.c:653) +==2376698== by 0x490BF65: __obstack_vprintf_internal (obprintf.c:95) +==2376698== by 0x490C0AB: obstack_printf (obprintf.c:120) +==2376698== by 0x138C70: prepare_symbol_definitions (output.c:624) +==2376698== by 0x13D40F: output (output.c:923) +==2376698== by 0x12E2B5: main (main.c:231) +==2376698== Address 0x4fa1fe0 is 10 bytes after a block of size 13,094 alloc'd +==2376698== at 0x4846828: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so) +==2376698== by 0x188919: xmalloc (xmalloc.c:45) +==2376698== by 0x492B8BC: _obstack_newchunk (obstack.c:261) +==2376698== by 0x490BE7C: __printf_buffer_flush_obstack (obprintf.c:46) +==2376698== by 0x48DC78C: __printf_buffer_do_flush (printf_buffer_flush.c:77) +==2376698== by 0x48DC78C: __printf_buffer_flush (Xprintf_buffer_flush.c:65) +==2376698== by 0x48DC8D5: __printf_buffer_pad_1 (Xprintf_buffer_pad_1.c:33) +==2376698== by 0x48E693C: __printf_buffer_pad (printf_buffer.h:164) +==2376698== by 0x48E693C: __printf_buffer (vfprintf-process-arg.c:213) +==2376698== by 0x490BF65: __obstack_vprintf_internal (obprintf.c:95) +==2376698== by 0x490C0AB: obstack_printf (obprintf.c:120) +==2376698== by 0x1333FF: muscle_insert_int_table (output.c:100) +==2376698== by 0x13ADB4: prepare_actions (output.c:717) +==2376698== by 0x13D40A: output (output.c:922) The cause is that this bison build uses the 'struct obstack' from gnulib in combination with the obstack_printf function from glibc: $ nm src/bison | grep obstack 0000000000007b22 t AnnotationList__alloc_on_obstack 0000000000065261 T bitset_obstack_alloc 0000000000065412 T bitset_obstack_free 00000000000b11c0 b format_obstack 00000000000b1ea0 b lbitset_obstack 00000000000b1ef8 b lbitset_obstack_init 00000000000b1140 B muscle_obstack 00000000000b0a80 D obstack_alloc_failed_handler 00000000000784b6 t _obstack_begin_worker 0000000000017095 t obstack_escape 00000000000263d4 t obstack_escape 000000000002ad94 t obstack_escape 00000000000465f1 t obstack_escape 00000000000b0358 D obstack_for_actions 00000000000b1520 b obstack_for_string 00000000000b16c0 b obstack_for_string 00000000000b1820 b obstack_for_string 00000000000b1240 B obstack_for_unquote U obstack_printf@GLIBC_2.2.5 00000000000789ed T rpl_obstack_allocated_p 000000000007866d T rpl_obstack_begin 00000000000786c8 T rpl_obstack_begin_1 0000000000078a46 T rpl_obstack_free 0000000000078b06 T rpl_obstack_memory_used 0000000000078733 T rpl_obstack_newchunk 000000000000a5fe T Sbitset__new_on_obstack 00000000000b0cc0 b solved_conflicts_obstack 00000000000b0d20 b solved_conflicts_xml_obstack 00000000000b1da0 b tbitset_obstack 00000000000b1df8 b tbitset_obstack_init At this point it's irrelevant whether this incompatibility is caused by different layouts of 'struct obstack' or by different calling conventions of _obstack_newchunk. The incompatibility needs to be avoided. This patch does it, and it fixes all of the 8 test failures. 2025-07-12 Bruno Haible <br...@clisp.org> obstack-printf: Fix memory overrun on glibc systems. * m4/obstack.m4 (gl_FUNC_OBSTACK): Define through AC_DEFUN_ONCE. * m4/obstack-printf.m4 (gl_FUNC_OBSTACK_PRINTF): Require gl_FUNC_OBSTACK. Invoke gl_REPLACE_OBSTACK_PRINTF when using the 'obstack' replacement code. diff --git a/m4/obstack-printf.m4 b/m4/obstack-printf.m4 index 05ca0af650..eeee458484 100644 --- a/m4/obstack-printf.m4 +++ b/m4/obstack-printf.m4 @@ -1,5 +1,5 @@ # obstack-printf.m4 -# serial 4 +# serial 5 dnl Copyright (C) 2008-2025 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -12,12 +12,17 @@ AC_DEFUN([gl_FUNC_OBSTACK_PRINTF], [ + AC_REQUIRE([gl_STDIO_H_DEFAULTS]) + AC_REQUIRE([gl_FUNC_OBSTACK]) + dnl Persuade glibc <stdio.h> to declare obstack_printf(), obstack_vprintf(). AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS]) - AC_REQUIRE([gl_STDIO_H_DEFAULTS]) AC_CHECK_FUNCS_ONCE([obstack_printf]) - if test $ac_cv_func_obstack_printf = no ; then + dnl The obstack_printf function from glibc does not work with the + dnl 'struct obstack' defined in gnulib's <obstack.h>. Therefore, when + dnl overriding 'struct obstack', we must also override obstack_printf. + if test $HAVE_OBSTACK = 0 || test $REPLACE_OBSTACK = 1; then gl_REPLACE_OBSTACK_PRINTF fi diff --git a/m4/obstack.m4 b/m4/obstack.m4 index 15f667332a..161370f86e 100644 --- a/m4/obstack.m4 +++ b/m4/obstack.m4 @@ -1,5 +1,5 @@ # obstack.m4 -# serial 2 +# serial 3 dnl Copyright 1996-2025 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -11,7 +11,7 @@ dnl Autoconf's AC_FUNC_OBSTACK is marked obsolete since version 2.70. dnl We provide our own macro here. -AC_DEFUN([gl_FUNC_OBSTACK], +AC_DEFUN_ONCE([gl_FUNC_OBSTACK], [ AC_CHECK_HEADERS_ONCE([obstack.h]) if test $ac_cv_header_obstack_h = yes; then