[bug #68570] [PATCH] [tbl] SEGV when table format description consists only of horizontal span descriptors

"G. Branden Robinson" <[email protected]> Sun, 26 Jul 2026 21:22:09 -0400 (EDT)
Newsgroups gmane.comp.printing.groff.bugs
Message-ID <[email protected]>
--8323329-1714636915-1785115329=:3319944
Content-Type: TEXT/plain; CHARSET=utf-8
Content-Transfer-Encoding: QUOTED-PRINTABLE
Content-Disposition: inline

URL:=0A  <https://savannah.gnu.org/bugs/?68570>=0A=0A                 Summa=
ry: [PATCH] [tbl] SEGV when table format description=0Aconsists only of hor=
izontal span descriptors=0A                   Group: GNU roff=0A           =
    Submitter: gbranden=0A               Submitted: Mon 27 Jul 2026 01:22:0=
4 AM UTC=0A                Category: Preprocessor tbl=0A                Sev=
erity: 4 - Important=0A              Item Group: Crash/Unresponsive=0A     =
             Status: In Progress=0A                 Privacy: Public=0A     =
        Assigned to: gbranden=0A             Open/Closed: Open=0A         D=
iscussion Lock: Unlocked=0A         Planned Release: None=0A=0A=0A    _____=
__________________________________________________=0A=0AFollow-up Comments:=
=0A=0A=0A-------------------------------------------------------=0ADate: Mo=
n 27 Jul 2026 01:22:04 AM UTC By: G. Branden Robinson <gbranden>=0AThis rep=
ort came to me via private email.=0A=0AI don't regard it as sensitive.=0A=
=0A=0AHello Branden,=0A=0AI was fuzzing the groff preprocessors and found a=
 small, reproducible crash=0Ain tbl. It is=0Aa NULL pointer dereference, so=
 a denial of service rather than anything=0Aworse, but I wanted=0Ato send i=
t to you before writing anything up.=0A=0AWhen a table's format section mar=
ks the first column as horizontally=0Aspanned (s) across all=0Aof its forma=
t rows, no table entry ever gets created. tbl correctly prints=0Athe "first=
 column=0Acannot be horizontally spanned" diagnostic, but then continues in=
to=0Atable::init_output() and=0Adereferences entry_list, which is still NUL=
L because the table has no=0Aentries.=0A=0AReproducer (6 lines), crashes st=
ock /usr/bin/tbl:=0A=0A.TS=0As s=0As.=0A_=0Ax=0A.TE=0A=0A$ tbl < crash.tbl =
>/dev/null=0Atbl:<standard input>:2: error: first column cannot be horizont=
ally spanned=0Atbl:<standard input>:3: error: first column cannot be horizo=
ntally spanned=0ASegmentation fault (core dumped)=0A=0AReproduced on the gr=
off 1.23.0 shipped in Ubuntu 26.04 (groff-base=0A1.23.0-10), and the same=
=0Acode path looks present on current git: table::init_output() still calls=
=0Aentry_list->set_location() with no NULL check, and I could not find any=
=0Aentry_list =3D=3D 0 guard=0Anearby. There are sibling entry_list->set_lo=
cation() calls in the file that=0Alook like the same=0Ashape.=0A=0AThis is =
reachable wherever tbl runs on an untrusted document, for instance=0Aman re=
ndering a=0Aman page that requests table processing, so a crafted page or r=
off file=0Acrashes tbl. Impact=0Ais limited to the crash.=0A=0AA guard for =
the empty-table case would fix it, either skipping the=0Aentry_list->set_lo=
cation()=0Acalls when entry_list =3D=3D 0 or returning from init_output() e=
arly when the=0Atable has no entries.=0A=0AI have the reproducer and can sh=
are whatever is useful. I will hold off on=0Aany public writeup=0Auntil you=
 have looked and a fix is out. Thanks for all your work on groff.=0A=0ABest=
 regards,=0AElias=0A=0A=0AA few minutes' work produced this patch.=0A=0A=0A=
diff --git a/src/preproc/tbl/main.cpp b/src/preproc/tbl/main.cpp=0Aindex 82=
b6c581e..9c878c584 100644=0A--- a/src/preproc/tbl/main.cpp=0A+++ b/src/prep=
roc/tbl/main.cpp=0A@@ -791,6 +791,7 @@ static format *process_format(table_=
input &in, options=0A*opt,=0A   input_entry_format *list =3D 0 /* nullptr *=
/;=0A   bool have_expand =3D false;=0A   bool is_first_row =3D true;=0A+  b=
ool is_first_column =3D true;=0A   int c =3D in.get();=0A   for (;;) {=0A  =
   int vrule_count =3D 0;=0A@@ -833,8 +834,14 @@ static format *process_for=
mat(table_input &in, options=0A*opt,=0A        break;=0A       case 's':=0A=
       case 'S':=0A-       got_format =3D true;=0A-       t =3D FORMAT_SPAN=
;=0A+       if (is_first_column)=0A+         error("cannot horizontally spa=
n in first column;"=0A+               " ignoring column descriptor '%1'",=
=0A+               static_cast<char>(c));=0A+       else {=0A+         got_=
format =3D true;=0A+         t =3D FORMAT_SPAN;=0A+       }=0A        break=
;=0A       case '^':=0A        got_format =3D true;=0A@@ -872,6 +879,8 @@ s=
tatic format *process_format(table_input &in, options=0A*opt,=0A        lis=
t =3D 0 /* nullptr */;=0A        return 0 /* nullptr */;=0A       }=0A+    =
  if (got_format)=0A+       is_first_column =3D false;=0A       if (got_per=
iod)=0A        break;=0A       c =3D in.get();=0A@@ -1180,6 +1189,7 @@ stat=
ic format *process_format(table_input &in, options=0A*opt,=0A     if (c =3D=
=3D '\n' || c =3D=3D ',') {=0A       vrule_count =3D 0;=0A       is_first_r=
ow =3D false;=0A+      is_first_column =3D true;=0A       c =3D in.get();=
=0A       list->is_last_column =3D true;=0A     }=0A=0A=0AAll tests pass, b=
ut I'll need a new test of course.=0A=0A=0A=0A=0A=0A=0A=0A    _____________=
__________________________________________=0A=0AReply to this item at:=0A=
=0A  <https://savannah.gnu.org/bugs/?68570>=0A=0A__________________________=
_____________________=0AMessage sent via Savannah=0Ahttps://savannah.gnu.or=
g/=0A
--8323329-1714636915-1785115329=:3319944
Content-Type: APPLICATION/pgp-signature; name=signature.asc

-----BEGIN PGP SIGNATURE-----

iHUEABYIAB0WIQQk97aszIMMAvLLwm6qLAuaBUf3TgUCamaywQAKCRCqLAuaBUf3
ToH6AP9Xfx0DSYttin3T55F0MD4kGryVCydAIMWrRZPwWym/IQEAqpzyYSPlOGpQ
zgF6ZW7WiOkMCw53D1DwwHH4TaJRdwU=
=8k8D
-----END PGP SIGNATURE-----

--8323329-1714636915-1785115329=:3319944--