[bug #68552] [troff] double-free via `exit()` in `write_any_trailer_and_exit()` using Clang on Termux
Bruno Haible <[email protected]> Fri, 24 Jul 2026 12:40:59 -0400 (EDT)
| Newsgroups | gmane.comp.printing.groff.bugs |
|---|---|
| Message-ID | <[email protected]> |
--8323329-424238335-1784911259=:108508
Content-Type: TEXT/plain; CHARSET=utf-8
Content-Transfer-Encoding: QUOTED-PRINTABLE
Content-Disposition: inline
Follow-up Comment #3, bug #68552 (group groff):=0A=0AI reproduce it on Term=
ux (32-bit arm) with clang 21.1.8.=0A=0APreparations:=0A=0A1)=0A=0A$ printf=
'.rr \\a\n' > in=0A=0A=0A2) Execute all environment variable commands from=
'test-groff'.=0A=0AFirst result: The issue comes from the object file src/=
roff/troff/input.o=0Abeing compiled with optimizations.=0A=0AWhen I compile=
all object files with CFLAGS=3D"-ggdb" and CXXFLAGS=3D"-ggdb",=0A"./groff =
< in" prints a message 'error: expected identifier, got a=0Anon-interpreted=
character node token; treated as missing', but no "Aborted".=0A=0AWhen I c=
ompile all object files except src/roff/troff/input.o with=0ACFLAGS=3D"-ggd=
b" and CXXFLAGS=3D"-ggdb", and only src/roff/troff/input.o with=0ACFLAGS=3D=
"-ggdb -O2" and CXXFLAGS=3D"-ggdb -O2", "./groff < in" prints the same=0Ame=
ssage and then "groff: error: troff: Aborted".=0A=0ASecond result: stack tr=
ace from troff.=0A=0A=0A$ ./groff -V < in=0Atroff -Tps | grops=0A=0A=0ARepr=
oduce with 'troff' alone:=0A=0A=0A$ ./troff -Tps < in > out=0A./troff:<stan=
dard input>:1: error: expected identifier, got a non-interpreted=0Acharacte=
r node token; treated as missing=0AAborted ./troff -Tps =
< in > out=0A=0A=0AThe gdb session:=0A=0A=0A(gdb) run -Tps < in > out=0A(gd=
b) break abort=0A(gdb) break exit=0A(gdb) break _exit=0A(gdb) break error=
=0A(gdb) run -Tps < in > out=0A=0A(gdb) where=0A#0 error (format=3D<optimi=
zed out>, arg1=3D..., arg2=3D..., arg3=3D...) at=0A../src/roff/troff/input.=
cpp:10978=0A#1 diagnose_missing_identifier (is_mandatory=3D<optimized out>=
) at=0A../src/roff/troff/input.cpp:3273=0A#2 0x0045b08c in read_input_unti=
l_terminator (want_diagnostic=3Dfalse,=0Aend_char=3D0 '\000', want_identifi=
er=3Dtrue) at ../src/roff/troff/input.cpp:3369=0A#3 0x004a0ca0 in remove_r=
egister_request () at ../src/roff/troff/reg.cpp:541=0A#4 0x0045c3e8 in int=
erpolate_macro_or_invoke_request (nm=3D...,=0Ado_not_want_next_token=3Dfals=
e) at ../src/roff/troff/input.cpp:4755=0A#5 0x0045bd00 in process_input_st=
ack () at ../src/roff/troff/input.cpp:3649=0A#6 0x004677c0 in process_inpu=
t_file (name=3D<optimized out>) at=0A../src/roff/troff/input.cpp:9948=0A#7 =
0x00463c54 in main (argc=3D<optimized out>, argv=3D<optimized out>) at=0A.=
./src/roff/troff/input.cpp:10319=0A=0A(gdb) where=0A#0 0x0045aed0 in error=
(format=3D<optimized out>, arg1=3D..., arg2=3D..., arg3=3D...)=0Aat ../src=
/roff/troff/input.cpp:10978=0A#1 0x0045aed0 in diagnose_missing_identifier=
(is_mandatory=3D<optimized out>)=0A#2 0x0045b08c in read_input_until_term=
inator (want_diagnostic=3Dfalse,=0Aend_char=3D0 '\000', want_identifier=3Dt=
rue) at ../src/roff/troff/input.cpp:3369=0A#3 0x004a0ca0 in remove_registe=
r_request () at ../src/roff/troff/reg.cpp:541=0A#4 0x0045c3e8 in interpola=
te_macro_or_invoke_request (nm=3D...,=0Ado_not_want_next_token=3Dfalse) at =
../src/roff/troff/input.cpp:4755=0A#5 0x0045bd00 in process_input_stack ()=
at ../src/roff/troff/input.cpp:3649=0A#6 0x004677c0 in process_input_file=
(name=3D<optimized out>) at=0A../src/roff/troff/input.cpp:9948=0A#7 0x004=
63c54 in main (argc=3D<optimized out>, argv=3D<optimized out>) at=0A../src/=
roff/troff/input.cpp:10319=0A=0A(gdb) where=0A#0 0xb6b07724 in exit () fro=
m /apex/com.android.runtime/lib/bionic/libc.so=0A#1 0x004338b0 in write_an=
y_trailer_and_exit (exit_code=3D0) at=0A../src/roff/troff/div.cpp:668=0A#2 =
0x00432b08 in top_level_diversion::begin_page (this=3D0xb6280640, n=3D...)=
at=0A../src/roff/troff/div.cpp:680=0A#3 0x0043caac in environment::do_bre=
ak (this=3D0xb5e030f0,=0Awant_forced_adjustment=3Dfalse) at ../src/roff/tro=
ff/env.cpp:2682=0A#4 0x004404c0 in environment::final_break (this=3D0xb5e0=
30f0) at=0A../src/roff/troff/env.cpp:2541=0A#5 0x004679e0 in exit_troff ()=
at ../src/roff/troff/input.cpp:3405=0A#6 0x00463c58 in main (argc=3D<opti=
mized out>, argv=3D<optimized out>) at=0A../src/roff/troff/input.cpp:10320=
=0A=0A(gdb) where=0A#0 0xb6ac178a in abort () from /apex/com.android.runti=
me/lib/bionic/libc.so=0A#1 0xb6ab73ce in scudo::die() () from=0A/apex/com.=
android.runtime/lib/bionic/libc.so=0A#2 0xb6ab77bc in scudo::ScopedErrorRe=
port::~ScopedErrorReport() () from=0A/apex/com.android.runtime/lib/bionic/l=
ibc.so=0A#3 0xb6ab798a in scudo::reportMisalignedPointer(scudo::AllocatorA=
ction,=0Avoid*) () from /apex/com.android.runtime/lib/bionic/libc.so=0A#4 =
0xb6ab8604 in scudo::Allocator<scudo::AndroidConfig,=0A&scudo_malloc_postin=
it>::deallocate(void*, scudo::Chunk::Origin, unsigned=0Along, unsigned long=
) ()=0A from /apex/com.android.runtime/lib/bionic/libc.so=0A#5 0xb6ab851=
2 in scudo_free () from=0A/apex/com.android.runtime/lib/bionic/libc.so=0A#6=
0x00478608 in std::__ndk1::__libcpp_operator_delete[abi:ne210000]<bool*,=
=0Aunsigned int>(bool*, unsigned int) (__args=3D4096, __args=3D4096)=0A =
at=0A/data/data/com.termux/files/usr/bin/../../usr/include/c++/v1/__new/all=
ocate.h:46=0A#7=0Astd::__ndk1::__libcpp_deallocate[abi:ne210000]<bool>(std:=
:__ndk1::__type_identity<bool>::type*,=0Astd::__ndk1::__element_count, unsi=
gned int) (__ptr=3D0xbeffe8b0, __n=3D4096, =0A __align=3D1) at=0A/data/d=
ata/com.termux/files/usr/bin/../../usr/include/c++/v1/__new/allocate.h:86=
=0A#8 std::__ndk1::allocator<bool>::deallocate[abi:ne210000](bool*, unsign=
ed=0Aint) (this=3D0x4ccb44 <want_att_compat_stack+20>, __p=3D0xbeffe8b0, __=
n=3D4096)=0A at=0A/data/data/com.termux/files/usr/bin/../../usr/include/=
c++/v1/__memory/allocator.h:120=0A#9 std::__ndk1::allocator_traits<std::__=
ndk1::allocator<bool>=0A>::deallocate[abi:ne210000](std::__ndk1::allocator<=
bool>&, bool*, unsigned=0Aint) (__a=3D..., __p=3D0xbeffe8b0, __n=3D4096)=0A=
at=0A/data/data/com.termux/files/usr/bin/../../usr/include/c++/v1/__mem=
ory/allocator_traits.h:302=0A#10 std::__ndk1::deque<bool, std::__ndk1::allo=
cator<bool> >::clear=0A(this=3D0x4ccb30 <want_att_compat_stack>)=0A at=
=0A/data/data/com.termux/files/usr/bin/../../usr/include/c++/v1/deque:2531=
=0A#11 std::__ndk1::deque<bool, std::__ndk1::allocator<bool>=0A>::~deque[ab=
i:ne210000]() (this=3D0x4ccb30 <want_att_compat_stack>)=0A at /data/data=
/com.termux/files/usr/bin/../../usr/include/c++/v1/deque:614=0A#12 0xb6b0c0=
3a in __cxa_finalize () from=0A/apex/com.android.runtime/lib/bionic/libc.so=
=0A#13 0xb6b0772e in exit () from /apex/com.android.runtime/lib/bionic/libc=
.so=0A#14 0x004338b0 in write_any_trailer_and_exit (exit_code=3D0) at=0A../=
src/roff/troff/div.cpp:668=0A#15 0x00432b08 in top_level_diversion::begin_p=
age (this=3D0xb6280640, n=3D...) at=0A../src/roff/troff/div.cpp:680=0A#16 0=
x0043caac in environment::do_break (this=3D0xb5e030f0,=0Awant_forced_adjust=
ment=3Dfalse) at ../src/roff/troff/env.cpp:2682=0A#17 0x004404c0 in environ=
ment::final_break (this=3D0xb5e030f0) at=0A../src/roff/troff/env.cpp:2541=
=0A#18 0x004679e0 in exit_troff () at ../src/roff/troff/input.cpp:3405=0A#1=
9 0x00463c58 in main (argc=3D<optimized out>, argv=3D<optimized out>) at=0A=
../src/roff/troff/input.cpp:10320=0A=0A=0ASo it looks like __cxa_finalize()=
got into trouble because the memory=0Amanagement data structures were inco=
nsistent, leading to a misaligned pointer=0Asomewhere.=0A=0ATogether with t=
he first result, it smells a memory overrun error somewhere=0A(anywhere!). =
The best tool for diagnosing this is valgrind; ASAN is good but=0Aonly of l=
imited usefulness.=0A=0ASo, if I were you, I would=0A=0A1) try ASAN on that=
platform (Termux),=0A=0A2) if not successful, run the entire 'troff' test =
suite under valgrind. Gnulib=0Adocumentation:=0Ahttps://www.gnu.org/softwar=
e/gnulib/manual/html_node/Running-self_002dtests-under-valgrind.html=0A.=0A=
=0A3) If that is not enough to highlight a problem, extend the 'troff' test=
suite=0Awith more test cases.=0A=0A=0A=0A _____________________________=
__________________________=0A=0AReply to this item at:=0A=0A <https://sava=
nnah.gnu.org/bugs/?68552>=0A=0A____________________________________________=
___=0AMessage sent via Savannah=0Ahttps://savannah.gnu.org/=0A
--8323329-424238335-1784911259=:108508
Content-Type: APPLICATION/pgp-signature; name=signature.asc
-----BEGIN PGP SIGNATURE-----
iHUEABYIAB0WIQQk97aszIMMAvLLwm6qLAuaBUf3TgUCamOVmwAKCRCqLAuaBUf3
To/SAQD2+ZHqy8g/S0lLFyOopjPNpraocLdbURJK9YjnqJinYQD/bofvaE4vHbGM
G2PW1v4dbZtjnMcviOJjPWcRb+7klQA=
=/NBB
-----END PGP SIGNATURE-----
--8323329-424238335-1784911259=:108508--