]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
unexpand: fix heap overflow when a wide blank overshoots a tab stop
authoraizu-m <aizumusheer2@gmail.com>
Tue, 9 Jun 2026 07:07:06 +0000 (12:37 +0530)
committerCollin Funk <collin.funk1@gmail.com>
Wed, 10 Jun 2026 01:20:39 +0000 (18:20 -0700)
* NEWS: Mention the bug fix.
* src/unexpand.c (unexpand): Check if the column is greater or equal to
the next_tab_column.
* tests/unexpand/mb.sh: Add a test case.
https://github.com/coreutils/coreutils/pull/285
Copyright-paperwork-exempt: Yes

NEWS
src/unexpand.c
tests/unexpand/mb.sh

diff --git a/NEWS b/NEWS
index 40822ceccc3db2d0fcfab5f664ad07502b5d8c2c..b822ae46ae32e25d722aa5ce968835940bbab98a 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -25,7 +25,8 @@ GNU coreutils NEWS                                    -*- outline -*-
   'tee' no longer treats short writes as errors.
   [bug introduced in coreutils-9.11]
 
-  'unexpand -t' no longer overflows a heap buffer, for tab values > SIZE_MAX/16.
+  'unexpand -t' no longer overflows a heap buffer, for tab values > SIZE_MAX/16,
+  or with multi-byte blank characters longer than the tab value.
   [bug introduced in coreutils-9.11]
 
   'uniq -w' no longer overruns the read buffer in multibyte locales.
index c859c17a3e5314b916ca2c8761cf141717a856a3..6a9881c2153304031cab37f562fa970de43ca207 100644 (file)
@@ -201,7 +201,7 @@ unexpand (void)
                         {
                           column += c32width (g.ch);
 
-                          if (! (prev_blank && column == next_tab_column))
+                          if (! (prev_blank && column >= next_tab_column))
                             {
                               /* It is not yet known whether the pending blanks
                                  will be replaced by tabs.  */
index 076a1c1ae52e0f27034d9c0984beab62ba5240a2..84ba0354ebab4f3e3e5e5783e6f6b6571c48af84 100755 (executable)
@@ -169,4 +169,13 @@ for mb_mul in 4 6; do
   test "$ret" = 1 || test "$ret" = 0 || { cat err; fail=1; }
 done
 
+# A blank whose display width exceeds the tab distance must not overrun
+# the pending-blank buffer.  With -t1 every column is a tab stop, so a
+# width-2 ideographic space steps over the stop without landing on it;
+# the run of blanks then grew pending_blank without bound.
+ideo_space=$(env printf '\u3000')
+{ yes "$ideo_space" | head -n 40000 | tr -d '\n'; echo; } |
+  unexpand -t1 >out 2>err; ret=$?
+test "$ret" = 0 || { cat err; fail=1; }
+
 Exit $fail