unexpand: fix stack overflow with large tabsizes

Resolves: RHEL-182699
This commit is contained in:
Lukáš Zaoral 2026-06-09 08:46:23 +02:00
parent a15874f42f
commit a84acf8a67
No known key found for this signature in database
GPG Key ID: 39157506DD67752D
3 changed files with 36 additions and 27 deletions

View File

@ -26,8 +26,8 @@ Co-authored-by: Pádraig Brady <pbrady@redhat.com>
src/unexpand.c | 57 ++++++---- src/unexpand.c | 57 ++++++----
tests/expand/mb.sh | 98 +++++++++++++++++ tests/expand/mb.sh | 98 +++++++++++++++++
tests/local.mk | 2 + tests/local.mk | 2 +
tests/unexpand/mb.sh | 99 +++++++++++++++++ tests/unexpand/mb.sh | 105 ++++++++++++++++++
10 files changed, 539 insertions(+), 35 deletions(-) 10 files changed, 545 insertions(+), 35 deletions(-)
create mode 100644 lib/mbfile.c create mode 100644 lib/mbfile.c
create mode 100644 lib/mbfile.h create mode 100644 lib/mbfile.h
create mode 100644 m4/mbfile.m4 create mode 100644 m4/mbfile.m4
@ -35,7 +35,7 @@ Co-authored-by: Pádraig Brady <pbrady@redhat.com>
create mode 100755 tests/unexpand/mb.sh create mode 100755 tests/unexpand/mb.sh
diff --git a/bootstrap.conf b/bootstrap.conf diff --git a/bootstrap.conf b/bootstrap.conf
index fcf29dc..3eaedc3 100644 index fcf29dc23..3eaedc3a5 100644
--- a/bootstrap.conf --- a/bootstrap.conf
+++ b/bootstrap.conf +++ b/bootstrap.conf
@@ -153,6 +153,7 @@ gnulib_modules=" @@ -153,6 +153,7 @@ gnulib_modules="
@ -47,7 +47,7 @@ index fcf29dc..3eaedc3 100644
mbrtowc mbrtowc
mbsalign mbsalign
diff --git a/configure.ac b/configure.ac diff --git a/configure.ac b/configure.ac
index 9b1ead0..c24ce2a 100644 index 9b1ead085..c24ce2aad 100644
--- a/configure.ac --- a/configure.ac
+++ b/configure.ac +++ b/configure.ac
@@ -439,6 +439,8 @@ fi @@ -439,6 +439,8 @@ fi
@ -61,7 +61,7 @@ index 9b1ead0..c24ce2a 100644
if test $gl_cv_sys_tiocgwinsz_needs_termios_h = no && \ if test $gl_cv_sys_tiocgwinsz_needs_termios_h = no && \
diff --git a/lib/mbfile.c b/lib/mbfile.c diff --git a/lib/mbfile.c b/lib/mbfile.c
new file mode 100644 new file mode 100644
index 0000000..b0a468e index 000000000..b0a468efa
--- /dev/null --- /dev/null
+++ b/lib/mbfile.c +++ b/lib/mbfile.c
@@ -0,0 +1,3 @@ @@ -0,0 +1,3 @@
@ -70,7 +70,7 @@ index 0000000..b0a468e
+#include "mbfile.h" +#include "mbfile.h"
diff --git a/lib/mbfile.h b/lib/mbfile.h diff --git a/lib/mbfile.h b/lib/mbfile.h
new file mode 100644 new file mode 100644
index 0000000..11f1b12 index 000000000..11f1b1242
--- /dev/null --- /dev/null
+++ b/lib/mbfile.h +++ b/lib/mbfile.h
@@ -0,0 +1,255 @@ @@ -0,0 +1,255 @@
@ -331,7 +331,7 @@ index 0000000..11f1b12
+#endif /* _MBFILE_H */ +#endif /* _MBFILE_H */
diff --git a/m4/mbfile.m4 b/m4/mbfile.m4 diff --git a/m4/mbfile.m4 b/m4/mbfile.m4
new file mode 100644 new file mode 100644
index 0000000..8589902 index 000000000..858990213
--- /dev/null --- /dev/null
+++ b/m4/mbfile.m4 +++ b/m4/mbfile.m4
@@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
@ -350,7 +350,7 @@ index 0000000..8589902
+ : + :
+]) +])
diff --git a/src/expand.c b/src/expand.c diff --git a/src/expand.c b/src/expand.c
index 6183fb8..34a559b 100644 index 6183fb820..34a559bcd 100644
--- a/src/expand.c --- a/src/expand.c
+++ b/src/expand.c +++ b/src/expand.c
@@ -37,6 +37,9 @@ @@ -37,6 +37,9 @@
@ -459,7 +459,7 @@ index 6183fb8..34a559b 100644
} }
diff --git a/src/unexpand.c b/src/unexpand.c diff --git a/src/unexpand.c b/src/unexpand.c
index 8fdd80f..6d5495f 100644 index 8fdd80f18..d12e36d7d 100644
--- a/src/unexpand.c --- a/src/unexpand.c
+++ b/src/unexpand.c +++ b/src/unexpand.c
@@ -38,6 +38,9 @@ @@ -38,6 +38,9 @@
@ -491,7 +491,7 @@ index 8fdd80f..6d5495f 100644
tab stop, then MAX_COLUMN_WIDTH - 1 blanks, then a non-blank; so tab stop, then MAX_COLUMN_WIDTH - 1 blanks, then a non-blank; so
allocate MAX_COLUMN_WIDTH bytes to store the blanks. */ allocate MAX_COLUMN_WIDTH bytes to store the blanks. */
- pending_blank = xmalloc (max_column_width); - pending_blank = xmalloc (max_column_width);
+ pending_blank = xmalloc (max_column_width * sizeof (mbf_char_t)); + pending_blank = xnmalloc (max_column_width, sizeof (mbf_char_t));
+ +
+ mbf_init (mbf, fp); + mbf_init (mbf, fp);
@ -620,7 +620,7 @@ index 8fdd80f..6d5495f 100644
diff --git a/tests/expand/mb.sh b/tests/expand/mb.sh diff --git a/tests/expand/mb.sh b/tests/expand/mb.sh
new file mode 100755 new file mode 100755
index 0000000..dab27b4 index 000000000..dab27b479
--- /dev/null --- /dev/null
+++ b/tests/expand/mb.sh +++ b/tests/expand/mb.sh
@@ -0,0 +1,98 @@ @@ -0,0 +1,98 @@
@ -723,7 +723,7 @@ index 0000000..dab27b4
+ +
+Exit $fail +Exit $fail
diff --git a/tests/local.mk b/tests/local.mk diff --git a/tests/local.mk b/tests/local.mk
index fb74b5d..1f19f1b 100644 index fb74b5dd0..1f19f1b01 100644
--- a/tests/local.mk --- a/tests/local.mk
+++ b/tests/local.mk +++ b/tests/local.mk
@@ -561,6 +561,7 @@ all_tests = \ @@ -561,6 +561,7 @@ all_tests = \
@ -744,10 +744,10 @@ index fb74b5d..1f19f1b 100644
# See tests/factor/create-test.sh. # See tests/factor/create-test.sh.
diff --git a/tests/unexpand/mb.sh b/tests/unexpand/mb.sh diff --git a/tests/unexpand/mb.sh b/tests/unexpand/mb.sh
new file mode 100755 new file mode 100755
index 0000000..a7b6ad0 index 000000000..4b797034f
--- /dev/null --- /dev/null
+++ b/tests/unexpand/mb.sh +++ b/tests/unexpand/mb.sh
@@ -0,0 +1,99 @@ @@ -0,0 +1,105 @@
+#!/bin/sh +#!/bin/sh
+ +
+# Copyright (C) 2012-2015 Free Software Foundation, Inc. +# Copyright (C) 2012-2015 Free Software Foundation, Inc.
@ -767,6 +767,7 @@ index 0000000..a7b6ad0
+ +
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src +. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ unexpand +print_ver_ unexpand
+getlimits_
+ +
+export LC_ALL=en_US.UTF-8 +export LC_ALL=en_US.UTF-8
+ +
@ -846,7 +847,12 @@ index 0000000..a7b6ad0
+unexpand -a < in > out || fail=1 +unexpand -a < in > out || fail=1
+compare exp out > /dev/null 2>&1 || fail=1 +compare exp out > /dev/null 2>&1 || fail=1
+ +
+for mb_mul in 4 6; do
+ printf ' \n' | unexpand -t $(expr $SIZE_MAX / $mb_mul + 1) 2>err; ret=$?
+ test "$ret" = 1 || test "$ret" = 0 || { cat err; fail=1; }
+done
+
+Exit $fail +Exit $fail
-- --
2.53.0 2.54.0

View File

@ -13,7 +13,7 @@ Subject: [PATCH] coreutils-i18n-un-expand-BOM.patch
6 files changed, 341 insertions(+), 2 deletions(-) 6 files changed, 341 insertions(+), 2 deletions(-)
diff --git a/src/expand-common.c b/src/expand-common.c diff --git a/src/expand-common.c b/src/expand-common.c
index 20ab023..e1c8943 100644 index 20ab02350..e1c8943fd 100644
--- a/src/expand-common.c --- a/src/expand-common.c
+++ b/src/expand-common.c +++ b/src/expand-common.c
@@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
@ -145,7 +145,7 @@ index 20ab023..e1c8943 100644
to the list of tab stops. */ to the list of tab stops. */
extern void extern void
diff --git a/src/expand-common.h b/src/expand-common.h diff --git a/src/expand-common.h b/src/expand-common.h
index cd32509..2ecf5e6 100644 index cd32509a6..2ecf5e656 100644
--- a/src/expand-common.h --- a/src/expand-common.h
+++ b/src/expand-common.h +++ b/src/expand-common.h
@@ -34,6 +34,18 @@ extern size_t max_column_width; @@ -34,6 +34,18 @@ extern size_t max_column_width;
@ -168,7 +168,7 @@ index cd32509..2ecf5e6 100644
extern void extern void
add_tab_stop (uintmax_t tabval); add_tab_stop (uintmax_t tabval);
diff --git a/src/expand.c b/src/expand.c diff --git a/src/expand.c b/src/expand.c
index 52d6ec1..50a4590 100644 index 52d6ec155..50a4590f5 100644
--- a/src/expand.c --- a/src/expand.c
+++ b/src/expand.c +++ b/src/expand.c
@@ -103,11 +103,33 @@ expand (void) @@ -103,11 +103,33 @@ expand (void)
@ -235,7 +235,7 @@ index 52d6ec1..50a4590 100644
} }
else else
diff --git a/src/unexpand.c b/src/unexpand.c diff --git a/src/unexpand.c b/src/unexpand.c
index fdef1d5..7cc7d32 100644 index ce57c1334..41b1ed55b 100644
--- a/src/unexpand.c --- a/src/unexpand.c
+++ b/src/unexpand.c +++ b/src/unexpand.c
@@ -116,16 +116,36 @@ unexpand (void) @@ -116,16 +116,36 @@ unexpand (void)
@ -266,7 +266,7 @@ index fdef1d5..7cc7d32 100644
/* The worst case is a non-blank character, then one blank, then a /* The worst case is a non-blank character, then one blank, then a
tab stop, then MAX_COLUMN_WIDTH - 1 blanks, then a non-blank; so tab stop, then MAX_COLUMN_WIDTH - 1 blanks, then a non-blank; so
allocate MAX_COLUMN_WIDTH bytes to store the blanks. */ allocate MAX_COLUMN_WIDTH bytes to store the blanks. */
pending_blank = xmalloc (max_column_width * sizeof (mbf_char_t)); pending_blank = xnmalloc (max_column_width, sizeof (mbf_char_t));
- mbf_init (mbf, fp); - mbf_init (mbf, fp);
+ if (found_bom == true) + if (found_bom == true)
@ -305,7 +305,7 @@ index fdef1d5..7cc7d32 100644
} }
else else
diff --git a/tests/expand/mb.sh b/tests/expand/mb.sh diff --git a/tests/expand/mb.sh b/tests/expand/mb.sh
index 3a5eb95..6d6497a 100755 index 3a5eb95c2..6d6497a3d 100755
--- a/tests/expand/mb.sh --- a/tests/expand/mb.sh
+++ b/tests/expand/mb.sh +++ b/tests/expand/mb.sh
@@ -109,4 +109,75 @@ env printf '12345678 @@ -109,4 +109,75 @@ env printf '12345678
@ -385,12 +385,12 @@ index 3a5eb95..6d6497a 100755
+ +
Exit $fail Exit $fail
diff --git a/tests/unexpand/mb.sh b/tests/unexpand/mb.sh diff --git a/tests/unexpand/mb.sh b/tests/unexpand/mb.sh
index 92962f6..f64542e 100755 index 0ff44c508..17a149d1c 100755
--- a/tests/unexpand/mb.sh --- a/tests/unexpand/mb.sh
+++ b/tests/unexpand/mb.sh +++ b/tests/unexpand/mb.sh
@@ -112,4 +112,62 @@ env printf '12345678 @@ -118,4 +118,62 @@ for mb_mul in 4 6; do
unexpand -a < in > out || fail=1 test "$ret" = 1 || test "$ret" = 0 || { cat err; fail=1; }
compare exp out > /dev/null 2>&1 || fail=1 done
+#BOM header test 1 +#BOM header test 1
+printf "\xEF\xBB\xBF" > in; cat <<\EOF >> in || framework_failure_ +printf "\xEF\xBB\xBF" > in; cat <<\EOF >> in || framework_failure_
@ -452,5 +452,5 @@ index 92962f6..f64542e 100755
+ +
Exit $fail Exit $fail
-- --
2.53.0 2.54.0

View File

@ -1,7 +1,7 @@
Summary: A set of basic GNU tools commonly used in shell scripts Summary: A set of basic GNU tools commonly used in shell scripts
Name: coreutils Name: coreutils
Version: 8.30 Version: 8.30
Release: 18%{?dist} Release: 19%{?dist}
License: GPLv3+ License: GPLv3+
Group: System Environment/Base Group: System Environment/Base
Url: https://www.gnu.org/software/coreutils/ Url: https://www.gnu.org/software/coreutils/
@ -296,6 +296,9 @@ fi
%license COPYING %license COPYING
%changelog %changelog
* Mon Jun 08 2026 Lukáš Zaoral <lzaoral@redhat.com> - 8.30-19
- unexpand: fix stack overflow with large tabsizes (RHEL-182699)
* Sat Mar 21 2026 Lukáš Zaoral <lzaoral@redhat.com> - 8.30-18 * Sat Mar 21 2026 Lukáš Zaoral <lzaoral@redhat.com> - 8.30-18
- fix df/direct.sh and unexpand/mb.sh tests (RHEL-151533) - fix df/direct.sh and unexpand/mb.sh tests (RHEL-151533)