Fix command substitution with nested functions and redirects
Resolves: RHEL-155803
This commit is contained in:
parent
422dba1b91
commit
d223cd74bf
147
ksh-1.0.10-issue-951-comsub-nested-func.patch
Normal file
147
ksh-1.0.10-issue-951-comsub-nested-func.patch
Normal file
@ -0,0 +1,147 @@
|
||||
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
|
||||
(re: e373e8c1, 274def65, 0ceb4864, 5def4398)
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Vincent Mihalkovič (@vmihalko) from Red Hat reports:
|
||||
> When executing a function in a subshell: the output is lost when
|
||||
> a previous line in the function redirects to stderr while not
|
||||
> having any output.
|
||||
>
|
||||
> ### Minimal reproducer
|
||||
>
|
||||
> #!/usr/bin/ksh
|
||||
> function echo_devnull {
|
||||
> echo "DEVNULL" >/dev/null
|
||||
> }
|
||||
> function func {
|
||||
> echo_devnull >&2
|
||||
> echo "FUNC"
|
||||
> }
|
||||
> OUT=$(func)
|
||||
> echo "OUT: ${OUT}"
|
||||
>
|
||||
> Expected: 'OUT: FUNC' Actual: 'OUT:' (empty)
|
||||
>
|
||||
> In 'OUT=$(func)', output from 'func' is lost when a prior line in
|
||||
> 'func' runs the customer pattern 'echo_devnull >&2' (redirect
|
||||
> that call’s stdout to stderr) and 'echo_devnull' itself sends
|
||||
> stdout to '/dev/null'. The following 'echo "FUNC"' should appear
|
||||
> in 'OUT' but 'OUT' is empty. bash is OK.
|
||||
|
||||
src/cmd/ksh93/sh/io.c: sh_redirect():
|
||||
- Amend the forking workaround yet again. Return to something
|
||||
closer to the original 93u+ workaround: fork if redirections
|
||||
persist past the command (flag==1 || flag==2) or standard output
|
||||
is on an Sfio string buffer. All regression tests pass, so this
|
||||
should not introduce the 93u+ bugs fixed in the meantime.
|
||||
|
||||
Resolves: https://github.com/ksh93/ksh/issues/951
|
||||
|
||||
Upstream-commit: 99028e9f709ee44f7c730d2883e31e37adab4d57
|
||||
Resolves: RHEL-155803
|
||||
---
|
||||
src/cmd/ksh93/sh/io.c | 4 +-
|
||||
src/cmd/ksh93/tests/subshell.sh | 67 +++++++++++++++++++++++++++++++++
|
||||
2 files changed, 68 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/cmd/ksh93/sh/io.c b/src/cmd/ksh93/sh/io.c
|
||||
index ea83132..d54c649 100644
|
||||
--- a/src/cmd/ksh93/sh/io.c
|
||||
+++ b/src/cmd/ksh93/sh/io.c
|
||||
@@ -1143,10 +1143,8 @@ int sh_redirect(struct ionod *iop, int flag)
|
||||
* '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.
|
||||
- * (Note that sh.redir0 is set to 1 in xec.c immediately before processing
|
||||
- * redirections for any built-in command, including 'exec' and 'redirect'.)
|
||||
*/
|
||||
- if(sh.subshell && sh.comsub && sh.redir0==1)
|
||||
+ if(sh.subshell && sh.comsub && (flag==1 || flag==2 || (sfset(sfstdout,0,0) & SFIO_STRING)))
|
||||
{
|
||||
struct ionod *i;
|
||||
for(i = iop; i; i = i->ionxt)
|
||||
diff --git a/src/cmd/ksh93/tests/subshell.sh b/src/cmd/ksh93/tests/subshell.sh
|
||||
index 7a91abf..1f896f1 100755
|
||||
--- a/src/cmd/ksh93/tests/subshell.sh
|
||||
+++ b/src/cmd/ksh93/tests/subshell.sh
|
||||
@@ -1219,5 +1219,72 @@ got=$("$SHELL" -c 'x=$(fn(){ return 265; };echo ok|fn); echo exited $?' 2>&1)
|
||||
[[ e=$? -eq 0 && $got == "$exp" ]] || err_exit "regression involving SIGPIPE in subshell" \
|
||||
"(expected status 0 and $(printf %q "$exp"), got status $e and $(printf %q "$got"))"
|
||||
|
||||
+# ======
|
||||
+# Command substitution loses stdout after nested function redirects stdout to /dev/null
|
||||
+# https://github.com/ksh93/ksh/issues/951
|
||||
+
|
||||
+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 "bug 951 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 "bug 951 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 "bug 951 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 "bug 951 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 "bug 951 test 3 (expected $(printf %q "$exp"), got $(printf %q "$got"))"
|
||||
+
|
||||
# ======
|
||||
exit $((Errors<125?Errors:125))
|
||||
--
|
||||
2.53.0
|
||||
|
||||
9
ksh.spec
9
ksh.spec
@ -4,7 +4,7 @@ URL: http://www.kornshell.com/
|
||||
License: EPL-2.0
|
||||
Epoch: 3
|
||||
Version: 1.0.10
|
||||
Release: 9%{?dist}
|
||||
Release: 10%{?dist}
|
||||
Source0: https://github.com/ksh93/%{name}/archive/v%{version}/%{name}-%{version}.tar.gz
|
||||
Source1: kshcomp.conf
|
||||
Source2: kshrc.rhs
|
||||
@ -31,6 +31,9 @@ Patch6: ksh-1.0.12-security.patch
|
||||
# upstream commit: https://github.com/ksh93/ksh/commit/c2cfcfc6f4b2d63472b2290debb9d0bb84c932df
|
||||
Patch7: ksh-1.0.11-devfd-memory-fault.patch
|
||||
|
||||
# upstream commit: https://github.com/ksh93/ksh/commit/99028e9f709ee44f7c730d2883e31e37adab4d57
|
||||
Patch8: ksh-1.0.10-issue-951-comsub-nested-func.patch
|
||||
|
||||
Conflicts: pdksh
|
||||
Requires: coreutils, diffutils
|
||||
BuildRequires: gcc
|
||||
@ -159,6 +162,10 @@ fi
|
||||
%config(noreplace) %{_sysconfdir}/binfmt.d/kshcomp.conf
|
||||
|
||||
%changelog
|
||||
* Wed Mar 25 2026 Vincent Mihalkovic <vmihalko@redhat.com> - 3:1.0.10-10
|
||||
- Fix command substitution with nested functions and redirects
|
||||
Resolves: RHEL-155803
|
||||
|
||||
* Wed Feb 04 2026 Vincent Mihalkovic <vmihalko@redhat.com> - 3:1.0.10-9
|
||||
- Fix /dev/fd/1 memory fault and $0 for /dev/fd scripts
|
||||
Resolves: RHEL-146565
|
||||
|
||||
Loading…
Reference in New Issue
Block a user