gbranden pushed a commit to branch master
in repository groff.

commit 41ce02672a795aa52d408e1e64c0c093934fdf3e
Author: G. Branden Robinson <[email protected]>
AuthorDate: Wed Aug 14 11:01:54 2024 -0500

    [troff]: Fix Savannah #64229.
    
    Throw diagnostic in event of a diversion's contents overflowing its
    vertical position.  We can't do anything sensible in this case, so make
    it a fatal error.  (It's also more likely that your host environment
    will exhaust memory available to the `troff` process before encountering
    this problem.)
    
    * src/roff/troff/div.cpp: New constant symbol `DIVERSION_LENGTH_MAX`
      defines the maximum permissible vertical size of a diversion in basic
      units.  Presently, it is `INT_MAX`.
    
      (macro_diversion::distance_to_next_trap): When there is no diversion
      trap, or it has already been passed, report the distance to
      `DIVERSION_LENGTH_MAX` (rather than `INT_MAX`) divided by the vertical
      resolution.
    
      (macro_diversion::output): Check for overflow when incrementing
      vertical position upon writing out a line, and emit fatal error
      diagnostic if it occurs.
    
    Fixes <https://savannah.gnu.org/bugs/?64229>.  Thanks to Dave Kemper for
    the discussion.
---
 ChangeLog              | 23 +++++++++++++++++++++++
 src/roff/troff/div.cpp | 15 ++++++++++++++-
 2 files changed, 37 insertions(+), 1 deletion(-)

diff --git a/ChangeLog b/ChangeLog
index 4dba2196c..aae3db6d0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,26 @@
+2024-08-14  G. Branden Robinson <[email protected]>
+
+       [troff]: Throw diagnostic in event of a diversion's contents
+       overflowing its vertical position.  We can't do anything
+       sensible in this case, so make it a fatal error.  (It's also
+       more likely that your host environment will exhaust memory
+       available to the `troff` process before encountering this
+       problem.)
+
+       * src/roff/troff/div.cpp: New constant symbol
+       `DIVERSION_LENGTH_MAX` defines the maximum permissible vertical
+       size of a diversion in basic units.  Presently, it is `INT_MAX`.
+       (macro_diversion::distance_to_next_trap): When there is no
+       diversion trap, or it has already been passed, report the
+       distance to `DIVERSION_LENGTH_MAX` (rather than `INT_MAX`)
+       divided by the vertical resolution.
+       (macro_diversion::output): Check for overflow when incrementing
+       vertical position upon writing out a line, and emit fatal error
+       diagnostic if it occurs.
+
+       Fixes <https://savannah.gnu.org/bugs/?64229>.  Thanks to Dave
+       Kemper for the discussion.
+
 2024-08-13  G. Branden Robinson <[email protected]>
 
        * tmac/e.tmac (n1, n2): Invoke the renamed `po` request
diff --git a/src/roff/troff/div.cpp b/src/roff/troff/div.cpp
index 772540c09..f79aabb6e 100644
--- a/src/roff/troff/div.cpp
+++ b/src/roff/troff/div.cpp
@@ -241,6 +241,8 @@ macro_diversion::~macro_diversion()
   dn_reg_contents = vertical_position.to_units();
 }
 
+static int DIVERSION_LENGTH_MAX = INT_MAX;
+
 vunits macro_diversion::distance_to_next_trap()
 {
   vunits distance = 0;
@@ -250,7 +252,7 @@ vunits macro_diversion::distance_to_next_trap()
   else
     // Do the (saturating) arithmetic ourselves to avoid an error
     // diagnostic from constructor in number.cpp.
-    distance = units(INT_MAX / vresolution);
+    distance = units(DIVERSION_LENGTH_MAX / vresolution);
   assert(distance >= 0);
   return distance;
 }
@@ -300,6 +302,17 @@ void macro_diversion::output(node *nd, int retain_size,
   if (width > max_width)
     max_width = width;
   vunits x = v.pre + v.pre_extra + v.post + v.post_extra;
+  int new_vpos = 0;
+  int vpos = vertical_position.to_units();
+  int lineht = x.to_units();
+  bool overflow = false;
+  if (ckd_add(&new_vpos, vpos, lineht))
+    overflow = true;
+  else if (new_vpos > DIVERSION_LENGTH_MAX)
+    overflow = true;
+  if (overflow)
+    fatal("diversion overflow (vertical position: %1u,"
+         " next line height: %2u)", vpos, lineht);
   if (vertical_position_traps_flag
       && !diversion_trap.is_null() && diversion_trap_pos > vertical_position
       && diversion_trap_pos <= vertical_position + x) {

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

Reply via email to