From c7148e142bf613cf37ff0b4b32886277093836eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Zaoral?= Date: Wed, 10 Jun 2026 14:28:01 +0200 Subject: [PATCH] unexpand: fix heap overflow when a wide blank overshoots a tab stop Resolves: RHEL-182506 --- coreutils-i18n-expand-unexpand.patch | 28 +++++++++++++++++++--------- coreutils-i18n-un-expand-BOM.patch | 10 +++++----- coreutils.spec | 5 ++++- 3 files changed, 28 insertions(+), 15 deletions(-) diff --git a/coreutils-i18n-expand-unexpand.patch b/coreutils-i18n-expand-unexpand.patch index be1cf0f..5a9b983 100644 --- a/coreutils-i18n-expand-unexpand.patch +++ b/coreutils-i18n-expand-unexpand.patch @@ -24,11 +24,11 @@ Co-authored-by: Pádraig Brady m4/mbfile.m4 | 14 +++ src/expand.c | 43 +++++--- src/local.mk | 4 +- - src/unexpand.c | 57 ++++++---- + src/unexpand.c | 59 ++++++---- tests/expand/mb.sh | 98 +++++++++++++++++ tests/local.mk | 2 + - tests/unexpand/mb.sh | 105 ++++++++++++++++++ - 11 files changed, 547 insertions(+), 37 deletions(-) + tests/unexpand/mb.sh | 114 +++++++++++++++++++ + 11 files changed, 557 insertions(+), 38 deletions(-) create mode 100644 lib/mbfile.c create mode 100644 lib/mbfile.h create mode 100644 m4/mbfile.m4 @@ -475,7 +475,7 @@ index 72db9c704..ef3bfa469 100644 # Ensure we don't link against libcoreutils.a as that lib is # not compiled with -fPIC which causes issues on 64 bit at least diff --git a/src/unexpand.c b/src/unexpand.c -index 09dafdbe1..bcb3b11be 100644 +index 09dafdbe1..33f5425f0 100644 --- a/src/unexpand.c +++ b/src/unexpand.c @@ -38,6 +38,9 @@ @@ -542,7 +542,7 @@ index 09dafdbe1..bcb3b11be 100644 if (blank) { -@@ -180,16 +193,16 @@ unexpand (void) +@@ -180,30 +193,31 @@ unexpand (void) if (next_tab_column < column) die (EXIT_FAILURE, 0, _("input line is too long")); @@ -560,9 +560,10 @@ index 09dafdbe1..bcb3b11be 100644 - column++; + column += mb_width (c); - if (! (prev_blank && column == next_tab_column)) +- if (! (prev_blank && column == next_tab_column)) ++ if (! (prev_blank && column >= next_tab_column)) { -@@ -197,13 +210,14 @@ unexpand (void) + /* It is not yet known whether the pending blanks will be replaced by tabs. */ if (column == next_tab_column) one_blank_before_tab_stop = true; @@ -760,10 +761,10 @@ index 9e366ebed..5bf132ae8 100644 # See tests/factor/create-test.sh. diff --git a/tests/unexpand/mb.sh b/tests/unexpand/mb.sh new file mode 100755 -index 000000000..4b797034f +index 000000000..5b4252d8f --- /dev/null +++ b/tests/unexpand/mb.sh -@@ -0,0 +1,105 @@ +@@ -0,0 +1,114 @@ +#!/bin/sh + +# Copyright (C) 2012-2015 Free Software Foundation, Inc. @@ -868,6 +869,15 @@ index 000000000..4b797034f + 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 -- 2.54.0 diff --git a/coreutils-i18n-un-expand-BOM.patch b/coreutils-i18n-un-expand-BOM.patch index 579cbb9..2b22031 100644 --- a/coreutils-i18n-un-expand-BOM.patch +++ b/coreutils-i18n-un-expand-BOM.patch @@ -235,7 +235,7 @@ index 8144e4344..bf61aff7c 100644 } else diff --git a/src/unexpand.c b/src/unexpand.c -index c2d95fd74..6faa94eb7 100644 +index 95c80712f..345aa5820 100644 --- a/src/unexpand.c +++ b/src/unexpand.c @@ -116,16 +116,36 @@ unexpand (void) @@ -385,12 +385,12 @@ index 3a5eb95c2..6d6497a3d 100755 + Exit $fail diff --git a/tests/unexpand/mb.sh b/tests/unexpand/mb.sh -index 0ff44c508..17a149d1c 100755 +index b1f0b2ea4..4d31ffd33 100755 --- a/tests/unexpand/mb.sh +++ b/tests/unexpand/mb.sh -@@ -118,4 +118,62 @@ for mb_mul in 4 6; do - test "$ret" = 1 || test "$ret" = 0 || { cat err; fail=1; } - done +@@ -127,4 +127,62 @@ ideo_space=$(env printf '\u3000') + unexpand -t1 >out 2>err; ret=$? + test "$ret" = 0 || { cat err; fail=1; } +#BOM header test 1 +printf "\xEF\xBB\xBF" > in; cat <<\EOF >> in || framework_failure_ diff --git a/coreutils.spec b/coreutils.spec index 4e0ddeb..68ca9d5 100644 --- a/coreutils.spec +++ b/coreutils.spec @@ -1,7 +1,7 @@ Summary: A set of basic GNU tools commonly used in shell scripts Name: coreutils Version: 8.32 -Release: 42%{?dist} +Release: 43%{?dist} License: GPLv3+ Url: https://www.gnu.org/software/coreutils/ Source0: https://ftp.gnu.org/gnu/%{name}/%{name}-%{version}.tar.xz @@ -341,6 +341,9 @@ rm -f $RPM_BUILD_ROOT%{_infodir}/dir %license COPYING %changelog +* Wed Jun 10 2026 Lukáš Zaoral - 8.32-43 +- unexpand: fix heap overflow when a wide blank overshoots a tab stop (RHEL-182506) + * Fri Jun 05 2026 Lukáš Zaoral - 8.32-42 - CVE-2025-5278 - Fix Heap Buffer Under-Read in sort via Key Specification (RHEL-180332) - unexpand: fix stack overflow with large tabsizes (RHEL-182506)