From: aizu-m Date: Tue, 9 Jun 2026 07:07:06 +0000 (+0530) Subject: unexpand: fix heap overflow when a wide blank overshoots a tab stop X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4ade9cf77f6c7b39e3fdc5ce97a778f8e294694c;p=thirdparty%2Fcoreutils.git unexpand: fix heap overflow when a wide blank overshoots a tab stop * 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 --- diff --git a/NEWS b/NEWS index 40822ceccc..b822ae46ae 100644 --- 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. diff --git a/src/unexpand.c b/src/unexpand.c index c859c17a3e..6a9881c215 100644 --- a/src/unexpand.c +++ b/src/unexpand.c @@ -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. */ diff --git a/tests/unexpand/mb.sh b/tests/unexpand/mb.sh index 076a1c1ae5..84ba0354eb 100755 --- a/tests/unexpand/mb.sh +++ b/tests/unexpand/mb.sh @@ -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