gbranden pushed a commit to branch master
in repository groff.

commit 1bbb5ff2f10362979e1609ae5ad95ba2a9f57394
Author: G. Branden Robinson <[email protected]>
AuthorDate: Sun Jul 26 20:48:40 2026 -0500

    [tbl]: Fix Savannah #68570.
    
    * src/preproc/tbl/main.cpp (process_format): Fix invalid memory access
      (SEGV) when a table description consists of multiple rows of
      horizontal span column classifiers (only).  When processing each row
      descriptor, keep track--with new local Boolean `is_first_column` of
      whether we're processing the first column descriptor in that row.  If
      we encounter a horizontal span column classifier in the first column,
      throw an error diagnostic instead of setting `got_format` true and
      assigning the "type" `t` to `FORMAT_SPAN`.  Set the new Boolean false
      after successfully interpreting one column descriptor in the row
      descriptor.  Reset the new Boolean to true when advancing to a new
      row description.
    
    Fixes <https://savannah.gnu.org/bugs/?68570>.  Problem appears to date
    back to groff's birth.  Thanks to Elias Hasas for the report and an
    economical reproducer.
    
    ANNOUNCE: Acknowledge Elias.
---
 ANNOUNCE                 |  1 +
 ChangeLog                | 21 +++++++++++++++++++++
 src/preproc/tbl/main.cpp | 16 +++++++++++++---
 3 files changed, 35 insertions(+), 3 deletions(-)

diff --git a/ANNOUNCE b/ANNOUNCE
index b58a66db6..175c4977b 100644
--- a/ANNOUNCE
+++ b/ANNOUNCE
@@ -227,6 +227,7 @@ Colin Watson
 Dave Kemper
 Deri James
 Dmytro Bagrii
+Elias Hasas
 Hilmar Preuße
 Hubert Garavel
 Ingo Schwarze
diff --git a/ChangeLog b/ChangeLog
index 90143d12f..650965c86 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,24 @@
+2026-07-26  G. Branden Robinson <[email protected]>
+
+       [tbl]: Fix Savannah #68570.
+
+       * src/preproc/tbl/main.cpp (process_format): Fix invalid memory
+       access (SEGV) when a table description consists of multiple rows
+       of horizontal span column classifiers (only).  When processing
+       each row descriptor, keep track--with new local Boolean
+       `is_first_column` of whether we're processing the first column
+       descriptor in that row.  If we encounter a horizontal span
+       column classifier in the first column, throw an error diagnostic
+       instead of setting `got_format` true and assigning the "type"
+       `t` to `FORMAT_SPAN`.  Set the new Boolean false after
+       successfully interpreting one column descriptor in the row
+       descriptor.  Reset the new Boolean to true when advancing to a
+       new row description.
+
+       Fixes <https://savannah.gnu.org/bugs/?68570>.  Problem appears
+       to date back to groff's birth.  Thanks to Elias Hasas for the
+       report and an economical reproducer.
+
 2026-07-26  G. Branden Robinson <[email protected]>
 
        [tbl]: Regression-test Savannah #68570.
diff --git a/src/preproc/tbl/main.cpp b/src/preproc/tbl/main.cpp
index 82b6c581e..a79bbcc0f 100644
--- a/src/preproc/tbl/main.cpp
+++ b/src/preproc/tbl/main.cpp
@@ -791,6 +791,7 @@ static format *process_format(table_input &in, options *opt,
   input_entry_format *list = 0 /* nullptr */;
   bool have_expand = false;
   bool is_first_row = true;
+  bool is_first_column = true;
   int c = in.get();
   for (;;) {
     int vrule_count = 0;
@@ -833,8 +834,14 @@ static format *process_format(table_input &in, options 
*opt,
        break;
       case 's':
       case 'S':
-       got_format = true;
-       t = FORMAT_SPAN;
+       if (is_first_column)
+         error("cannot horizontally span in first column;"
+               " ignoring column classifier '%1'",
+               static_cast<char>(c));
+       else {
+         got_format = true;
+         t = FORMAT_SPAN;
+       }
        break;
       case '^':
        got_format = true;
@@ -875,8 +882,10 @@ static format *process_format(table_input &in, options 
*opt,
       if (got_period)
        break;
       c = in.get();
-      if (got_format)
+      if (got_format) {
+       is_first_column = false;
        break;
+      }
     }
     if (got_period)
       break;
@@ -1180,6 +1189,7 @@ static format *process_format(table_input &in, options 
*opt,
     if (c == '\n' || c == ',') {
       vrule_count = 0;
       is_first_row = false;
+      is_first_column = true;
       c = in.get();
       list->is_last_column = true;
     }

_______________________________________________
groff-commit mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/groff-commit

Reply via email to