Fix command substitution losing stdout after nested function redirects
Resolves: RHEL-162296
This commit is contained in:
parent
22283364a1
commit
c69b79809a
131
ksh-1.0.11-comsub-nested-func.patch
Normal file
131
ksh-1.0.11-comsub-nested-func.patch
Normal file
@ -0,0 +1,131 @@
|
||||
From 99028e9f709ee44f7c730d2883e31e37adab4d57 Mon Sep 17 00:00:00 2001
|
||||
From: Martijn Dekker <martijn@inlv.org>
|
||||
Date: Mon, 23 Mar 2026 22:45:04 +0000
|
||||
Subject: [PATCH] Fix bug in comsubs involving nested functions with redirects
|
||||
|
||||
Port of upstream commit 99028e9 for ksh 1.0.6: add sh_redirect() comsub fork
|
||||
workaround using flag==1/2 or string-buffer stdout (sfset & SF_STRING; 1.0.6
|
||||
sfio uses SF_STRING where newer trees use SFIO_STRING). 1.0.6 lacked the io.c
|
||||
block present in newer branches.
|
||||
|
||||
Upstream: https://github.com/ksh93/ksh/commit/99028e9f709ee44f7c730d2883e31e37adab4d57
|
||||
|
||||
---
|
||||
src/cmd/ksh93/sh/io.c | 27 +++++++++++
|
||||
src/cmd/ksh93/tests/subshell.sh | 66 ++++++++++++++++++++++++++++++
|
||||
2 files changed, 93 insertions(+)
|
||||
|
||||
diff --git a/src/cmd/ksh93/sh/io.c b/src/cmd/ksh93/sh/io.c
|
||||
index 130b0368..ccea238a 100644
|
||||
--- a/src/cmd/ksh93/sh/io.c
|
||||
+++ b/src/cmd/ksh93/sh/io.c
|
||||
@@ -1135,6 +1135,33 @@ int sh_redirect(struct ionod *iop, int flag)
|
||||
clexec = 1;
|
||||
if(iop)
|
||||
traceon = sh_trace(NULL,0);
|
||||
+ /*
|
||||
+ * A command substitution will hang on exit, writing infinite '\0', if,
|
||||
+ * within it, standard output (FD 1) is redirected for a built-in command
|
||||
+ * that calls sh_subfork(), or redirected permanently using 'exec' or
|
||||
+ * 'redirect'. This forking workaround is necessary to avoid that bug.
|
||||
+ * For shared-state comsubs, forking is incorrect, so error out then.
|
||||
+ * TODO: actually fix the bug and remove this workaround.
|
||||
+ */
|
||||
+ if(sh.subshell && sh.comsub && (flag==1 || flag==2 || (sfset(sfstdout,0,0) & SF_STRING)))
|
||||
+ {
|
||||
+ struct ionod *i;
|
||||
+ for(i = iop; i; i = i->ionxt)
|
||||
+ {
|
||||
+ if((i->iofile & IOUFD) != 1)
|
||||
+ continue;
|
||||
+ if(!sh.subshare)
|
||||
+ {
|
||||
+ sh_subfork();
|
||||
+ break;
|
||||
+ }
|
||||
+ if(flag==1 || flag==2)
|
||||
+ {
|
||||
+ errormsg(SH_DICT,ERROR_exit(1),"cannot redirect stdout inside shared-state comsub");
|
||||
+ UNREACHABLE();
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
for(;iop;iop=iop->ionxt)
|
||||
{
|
||||
iof=iop->iofile;
|
||||
diff --git a/src/cmd/ksh93/tests/subshell.sh b/src/cmd/ksh93/tests/subshell.sh
|
||||
index 0708c2ba..77c423d8 100755
|
||||
--- a/src/cmd/ksh93/tests/subshell.sh
|
||||
+++ b/src/cmd/ksh93/tests/subshell.sh
|
||||
@@ -1183,5 +1183,71 @@ exp='some output'
|
||||
[[ $got == "$exp" ]] || err_exit 'command substitution did not catch output' \
|
||||
"(expected $(printf %q "$exp"), got $(printf %q "$got"))"
|
||||
|
||||
+# ======
|
||||
+# Command substitution loses stdout after nested function redirects stdout to /dev/null
|
||||
+
|
||||
+got=$(
|
||||
+ function echo_devnull {
|
||||
+ echo "DEVNULL" >/dev/null
|
||||
+ }
|
||||
+ function func {
|
||||
+ echo_devnull >&2
|
||||
+ echo "FUNC"
|
||||
+ }
|
||||
+ OUT=$(func)
|
||||
+ echo "OUT: ${OUT}"
|
||||
+)
|
||||
+exp='OUT: FUNC'
|
||||
+[[ $got == "$exp" ]] || err_exit "comsub nested redirect test 1a (expected $(printf %q "$exp"), got $(printf %q "$got"))"
|
||||
+
|
||||
+got=$(
|
||||
+ function echo_devnull {
|
||||
+ echo "DEVNULL" >/dev/null
|
||||
+ }
|
||||
+ function func {
|
||||
+ echo_devnull >&2
|
||||
+ echo "FUNC"
|
||||
+ }
|
||||
+ OUT=${ func; }
|
||||
+ echo "OUT: ${OUT}"
|
||||
+)
|
||||
+exp='OUT: FUNC'
|
||||
+[[ $got == "$exp" ]] || err_exit "comsub nested redirect test 1b (expected $(printf %q "$exp"), got $(printf %q "$got"))"
|
||||
+
|
||||
+got=$(
|
||||
+ function echo_devnull {
|
||||
+ ulimit -c 0
|
||||
+ }
|
||||
+ function func {
|
||||
+ echo_devnull >&2
|
||||
+ echo "FUNC"
|
||||
+ }
|
||||
+ OUT=$(func)
|
||||
+ echo "OUT: ${OUT}"
|
||||
+)
|
||||
+exp='OUT: FUNC'
|
||||
+[[ $got == "$exp" ]] || err_exit "comsub nested redirect test 2a (expected $(printf %q "$exp"), got $(printf %q "$got"))"
|
||||
+
|
||||
+got=$(
|
||||
+ function echo_devnull {
|
||||
+ ulimit -c 0
|
||||
+ }
|
||||
+ function func {
|
||||
+ echo_devnull >&2
|
||||
+ echo "FUNC"
|
||||
+ }
|
||||
+ OUT=${ func; }
|
||||
+ echo "OUT: ${OUT}"
|
||||
+)
|
||||
+exp='OUT: FUNC'
|
||||
+[[ $got == "$exp" ]] || err_exit "comsub nested redirect test 2b (expected $(printf %q "$exp"), got $(printf %q "$got"))"
|
||||
+
|
||||
+got=$(
|
||||
+ OUT=$(ulimit -c 0 >&2; echo OK)
|
||||
+ echo "OUT: ${OUT}"
|
||||
+)
|
||||
+exp='OUT: OK'
|
||||
+[[ $got == "$exp" ]] || err_exit "comsub nested redirect test 3 (expected $(printf %q "$exp"), got $(printf %q "$got"))"
|
||||
+
|
||||
# ======
|
||||
exit $((Errors<125?Errors:125))
|
||||
9
ksh.spec
9
ksh.spec
@ -4,7 +4,7 @@ URL: http://www.kornshell.com/
|
||||
License: EPL-1.0
|
||||
Epoch: 3
|
||||
Version: 1.0.6
|
||||
Release: 15%{?dist}
|
||||
Release: 16%{?dist}
|
||||
Source0: https://github.com/ksh93/%{name}/archive/v%{version}/%{name}-%{version}.tar.gz
|
||||
Source1: kshcomp.conf
|
||||
Source2: kshrc.rhs
|
||||
@ -63,6 +63,9 @@ Patch15: ksh-1.0.12-security.patch
|
||||
# upstream commit: https://github.com/ksh93/ksh/commit/c2cfcfc6f4b2d63472b2290debb9d0bb84c932df
|
||||
Patch16: ksh-1.0.11-devfd-memory-fault.patch
|
||||
|
||||
# upstream commit: https://github.com/ksh93/ksh/commit/99028e9f709ee44f7c730d2883e31e37adab4d57
|
||||
Patch17: ksh-1.0.11-comsub-nested-func.patch
|
||||
|
||||
Conflicts: pdksh
|
||||
Requires: coreutils, diffutils
|
||||
BuildRequires: gcc
|
||||
@ -184,6 +187,10 @@ fi
|
||||
%config(noreplace) %{_sysconfdir}/binfmt.d/kshcomp.conf
|
||||
|
||||
%changelog
|
||||
* Mon Mar 30 2026 Vincent Mihalkovic <vmihalko@redhat.com> - 3:1.0.6-16
|
||||
- Fix command substitution losing stdout after nested function redirects
|
||||
Resolves: RHEL-162296
|
||||
|
||||
* Wed Feb 04 2026 Vincent Mihalkovic <vmihalko@redhat.com> - 3:1.0.6-15
|
||||
- Fix /dev/fd/1 memory fault and $0 for /dev/fd scripts
|
||||
Resolves: RHEL-146564
|
||||
|
||||
Loading…
Reference in New Issue
Block a user