gbranden pushed a commit to branch master
in repository groff.
commit fb2432fe60225d6c34e43b630e67cbc1c24e61d5
Author: G. Branden Robinson <[email protected]>
AuthorDate: Sun May 17 14:32:33 2026 -0500
[troff]: Remove heap-overreading optimization.
* src/roff/troff/input.cpp (char_list::get): De-optimize read access at
the end of a `char_list`, because the pointer arithmetic used can
access heap storage beyond the end of the underlying `char_block` used
to house the list.
Fixes <https://savannah.gnu.org/bugs/?68340>. Resolves ASAN runtime
error when formatting the groff_mdoc(7) man page in troff mode. Thanks
to Bjarni Ingi Gislason for the report.
Performance analysis
====================
This change slows groff pipline operation by about 5% across the corpus
of documents produced in its own build. If someone would like to craft
a new, more memory-safe optimization to recover the performance, please
contact the groff at gnu dot org mailing list and share your proposal.
(A better long-term fix might be to migrate `char_list` to an ISO C++98
STL templated container type; these are often performance-tuned already
by the compiler vendor.)
$ cat measure.bash
shopt -s extglob
make -C build -j >/dev/null 2>&1
for n in $(seq 20)
do
rm -f build/doc/!(groff).pdf build/doc/*.ps \
build/doc/!(groff).html \
build/contrib/hdtbl/examples/*.ps \
build/contrib/mom/examples/*.pdf \
contrib/sboxes/msboxes.pdf \
doc/groff-man-pages.utf8.txt
t=$({ time -p make -C build >/dev/null 2>&1; } 2>/dev/stdout)
echo "$t" | awk '/real/ { print $2; }'
done
Before
------
$ bash ./measure.bash | tee | datamash range 1 mean 1 sstdev 1
0.86 31.9025 0.24063239052218
After
-----
$ bash ./measure.bash | tee | datamash range 1 mean 1 sstdev 1
6.91 33.545 1.8817363202498
---
ChangeLog | 11 +++++++++++
src/roff/troff/input.cpp | 4 ----
2 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 1e14c8dd9..b1e70ef92 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2026-05-17 G. Branden Robinson <[email protected]>
+
+ * src/roff/troff/input.cpp (char_list::get): De-optimize read
+ access at the end of a `char_list`, because the pointer
+ arithmetic used can access heap storage beyond the end of the
+ underlying `char_block` used to house the list.
+
+ Fixes <https://savannah.gnu.org/bugs/?68340>. Resolves ASAN
+ runtime error when formatting the groff_mdoc(7) man page in
+ troff mode. Thanks to Bjarni Ingi Gislason for the report.
+
2026-05-17 G. Branden Robinson <[email protected]>
* src/roff/troff/input.cpp: Trivially refactor and fix code
diff --git a/src/roff/troff/input.cpp b/src/roff/troff/input.cpp
index ff6900247..3af87823c 100644
--- a/src/roff/troff/input.cpp
+++ b/src/roff/troff/input.cpp
@@ -4000,10 +4000,6 @@ void char_list::set(unsigned char c, int offset)
unsigned char char_list::get(int offset)
{
assert(length > offset);
- // optimization for access at the end
- int boundary = length - (length % char_block::SIZE);
- if (offset >= boundary)
- return *(tail->s + offset - boundary);
char_block *tem = head;
int l = 0;
for (;;) {
_______________________________________________
groff-commit mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/groff-commit