Re: Does Gnulib replace exit(3) under any circumstances?

Paul Eggert <[email protected]> Thu, 23 Jul 2026 19:15:19 -0700
Newsgroups gmane.comp.lib.gnulib.bugs,gmane.comp.printing.groff.general
Organization UCLA Computer Science Department
Message-ID <[email protected]>
On 2026-07-23 17:25, G. Branden Robinson wrote:
> The good news is that this seems_not_ to be a release blocker for
> groff.  If the problem ain't in groff, I can't fix it in groff.

What Collin said.

For what it's worth, when I tried to debug this on Fedora 44 I found 
that I couldn't build groff head (commit 
d6675ad14d71b4b36b2274b889cd1e2594bfc79c), because groff's build 
procedure assumes that because stdckdint.h works with C it also works 
with C++, which is not true on Fedora 44. I worked around that problem 
by syncing with current Gnulib (which fixes this problem), and I assume 
you'll do something similar before a groff release.

Also for what it's worth I built with this shell command:

ASAN_OPTIONS=detect_leaks=0 make CXXFLAGS='-g3 -O2 -fsanitize=address' 
CFLAGS='-g3 -O2 -fsanitize=address'

and when that failed, with this shell command:

ASAN_OPTIONS=detect_leaks=0,alloc_dealloc_mismatch=0 make CXXFLAGS='-g3 
-O2 -fsanitize=address' CFLAGS='-g3 -O2 -fsanitize=address'

and got the following failures, the first with the first command and the 
second with the second:

...
   GROFF    doc/groff-man-pages.pdf
=================================================================
==484606==ERROR: AddressSanitizer: alloc-dealloc-mismatch (malloc vs 
operator delete []) on 0x7b6448be0560
     #0 0x7f044a0f104f in operator delete[](void*) 
(/lib64/libasan.so.8+0xf104f) (BuildId: 
5395ec74f54d9ec7bf97c06583dd39a96c230822)
     #1 0x00000043027d in block_entry::~block_entry() 
src/preproc/tbl/table.cpp:654
     #2 0x00000043027d in left_block_entry::~left_block_entry() 
src/preproc/tbl/table.cpp:324
     #3 0x00000043027d in left_block_entry::~left_block_entry() 
src/preproc/tbl/table.cpp:324
     #4 0x000000419d1b in table::~table() src/preproc/tbl/table.cpp:1293
     #5 0x00000040e249 in process_table(table_input&) 
src/preproc/tbl/main.cpp:1618
     #6 0x00000040ec10 in process_input_file(_IO_FILE*) 
src/preproc/tbl/main.cpp:256
     #7 0x000000402237 in main src/preproc/tbl/main.cpp:1710
     #8 0x7f0449a0a680 in __libc_start_call_main 
(/lib64/libc.so.6+0x3680) (BuildId: 
17f2e1fd905f485786f6fd6e3bede4ad737137e7)
     #9 0x7f0449a0a797 in __libc_start_main@GLIBC_2.2.5 
(/lib64/libc.so.6+0x3797) (BuildId: 
17f2e1fd905f485786f6fd6e3bede4ad737137e7)
     #10 0x000000402af4 in _start 
(/home/eggert/src/gnu/groff/tbl+0x402af4) (BuildId: 
c478463b4fa0a8213180485cd5ed9b4c8f3f7067)

0x7b6448be0560 is located 0 bytes inside of 62-byte region 
[0x7b6448be0560,0x7b6448be059e)
allocated by thread T0 here:
     #0 0x7f044a0ef41f in malloc (/lib64/libasan.so.8+0xef41f) (BuildId: 
5395ec74f54d9ec7bf97c06583dd39a96c230822)
     #1 0x000000436cc9 in string::extract() const 
src/libs/libgroff/string.cpp:308

SUMMARY: AddressSanitizer: alloc-dealloc-mismatch 
src/preproc/tbl/table.cpp:654 in block_entry::~block_entry()
==484606==HINT: if you don't care about these errors you may set 
ASAN_OPTIONS=alloc_dealloc_mismatch=0
==484606==ABORTING
troff: warning: name '3rele' not defined
troff: error: automatically ending diversion '3section' on exit
pdfmom: fatal error: groff exited with status 4


...
fonts_n.roff: listing fonts in ./font/devps
=================================================================
==484862==ERROR: AddressSanitizer: heap-use-after-free on address 
0x7c88d65e52c0 at pc 0x7f78d7aaf861 bp 0x7fffdd9e1100 sp 0x7fffdd9e08c0
READ of size 1 at 0x7c88d65e52c0 thread T0
     #0 0x7f78d7aaf860 in strcmp.part.0 (/lib64/libasan.so.8+0xaf860) 
(BuildId: 5395ec74f54d9ec7bf97c06583dd39a96c230822)
     #1 0x000000455a7f in file_iterator::get_location(bool, char 
const**, int*) src/roff/troff/input.cpp:499
     #2 0x000000455a7f in input_stack::get_location(bool, char const**, 
int*) src/roff/troff/input.cpp:800
     #3 0x000000493830 in macro::macro() src/roff/troff/input.cpp:3509
     #4 0x000000493830 in do_define_string(define_mode, comp_mode) 
src/roff/troff/input.cpp:4478
     #5 0x000000495133 in request::invoke(symbol, bool) 
src/roff/troff/input.cpp:3334
     #6 0x000000495133 in interpolate_macro src/roff/troff/input.cpp:4072
     #7 0x0000004a09f2 in process_input_stack() 
src/roff/troff/input.cpp:3100
     #8 0x0000004a2c4d in process_input_file src/roff/troff/input.cpp:8801
     #9 0x00000040a271 in main src/roff/troff/input.cpp:9153
     #10 0x7f78d740a680 in __libc_start_call_main 
(/lib64/libc.so.6+0x3680) (BuildId: 
17f2e1fd905f485786f6fd6e3bede4ad737137e7)
     #11 0x7f78d740a797 in __libc_start_main@GLIBC_2.2.5 
(/lib64/libc.so.6+0x3797) (BuildId: 
17f2e1fd905f485786f6fd6e3bede4ad737137e7)
     #12 0x00000040be74 in _start 
(/home/eggert/src/gnu/groff/troff+0x40be74) (BuildId: 
cf528e78ad252e121bde02c92df44d512e25e23d)

0x7c88d65e52c0 is located 0 bytes inside of 256-byte region 
[0x7c88d65e52c0,0x7c88d65e53c0)
freed by thread T0 here:
     #0 0x7f78d7af104f in operator delete[](void*) 
(/lib64/libasan.so.8+0xf104f) (BuildId: 
5395ec74f54d9ec7bf97c06583dd39a96c230822)
     #1 0x00000048c64c in pipe_source_request() 
src/roff/troff/input.cpp:6661

previously allocated by thread T0 here:
     #0 0x7f78d7af065f in operator new[](unsigned long) 
(/lib64/libasan.so.8+0xf065f) (BuildId: 
5395ec74f54d9ec7bf97c06583dd39a96c230822)
     #1 0x00000046a477 in read_string() src/roff/troff/input.cpp:8423

SUMMARY: AddressSanitizer: heap-use-after-free 
src/roff/troff/input.cpp:499 in file_iterator::get_location(bool, char 
const**, int*)
Shadow bytes around the buggy address:
   0x7c88d65e5000: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00
   0x7c88d65e5080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
   0x7c88d65e5100: 00 00 00 00 00 00 00 00 fa fa fa fa fa fa fa fa
   0x7c88d65e5180: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
   0x7c88d65e5200: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x7c88d65e5280: fa fa fa fa fa fa fa fa[fd]fd fd fd fd fd fd fd
   0x7c88d65e5300: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
   0x7c88d65e5380: fd fd fd fd fd fd fd fd fa fa fa fa fa fa fa fa
   0x7c88d65e5400: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
   0x7c88d65e5480: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
   0x7c88d65e5500: fa fa fa fa fa fa fa fa fd fd fd fd fd fd fd fd
Shadow byte legend (one shadow byte represents 8 application bytes):
   Addressable:           00
   Partially addressable: 01 02 03 04 05 06 07
   Heap left redzone:       fa
   Freed heap region:       fd
   Stack left redzone:      f1
   Stack mid redzone:       f2
   Stack right redzone:     f3
   Stack after return:      f5
   Stack use after scope:   f8
   Global redzone:          f9
   Global init order:       f6
   Poisoned by user:        f7
   Container overflow:      fc
   Array cookie:            ac
   Intra object redzone:    bb
   ASan internal:           fe
   Left alloca redzone:     ca
   Right alloca redzone:    cb
==484862==ABORTING
make[2]: *** [Makefile:17135: contrib/hdtbl/examples/fonts_n.ps] Error 4
make[2]: *** Deleting file 'contrib/hdtbl/examples/fonts_n.ps'
make[2]: Leaving directory '/home/eggert/src/gnu/groff'
make[1]: *** [Makefile:12162: all-recursive] Error 1
make[1]: Leaving directory '/home/eggert/src/gnu/groff'
make: *** [Makefile:6996: all] Error 2