From 07faf38425069f6ed05bdbc8f94bcfda6132e371 Mon Sep 17 00:00:00 2001 From: Martijn Dekker Date: Sat, 24 Apr 2021 12:41:40 +0100 Subject: [PATCH] Fix 'unset -f' in sub-subshell (re: 13c57e4b) A bug introduced in the previous commit caused 'unset -f' in a subshell of a subshell to fail to unset a function created in a parent subshell. Reproducer: $ ( f2() { echo WRONG; }; ( unset -f f2; f2 ) ) WRONG src/cmd/ksh93/bltins/typeset.c: unall(): - Do not nv_search() in sh.fun_base before setting the dummy node that marks the function as unset in this subshell. That search only reaches the base tree and not any of its subtrees. Setting the dummy unconditionally is not harmful; the cost is negligible. src/cmd/ksh93/tests/subshell.sh: - Add test for the bug. --- src/cmd/ksh93/bltins/typeset.c | 2 +- src/cmd/ksh93/tests/subshell.sh | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/cmd/ksh93/bltins/typeset.c b/src/cmd/ksh93/bltins/typeset.c index 4ddeb2789..7dc246fd9 100644 --- a/src/cmd/ksh93/bltins/typeset.c +++ b/src/cmd/ksh93/bltins/typeset.c @@ -1398,7 +1398,7 @@ static int unall(int argc, char **argv, register Dt_t *troot, Shell_t* shp) } else if(troot==shp->alias_tree) r = 1; - else if(troot==shp->fun_tree && troot!=shp->fun_base && nv_search(name,shp->fun_base,0)) + else if(troot==shp->fun_tree && troot!=shp->fun_base) nv_open(name,troot,NV_NOSCOPE); /* create dummy virtual subshell node without NV_FUNCTION attribute */ } sh_popcontext(shp,&buff); diff --git a/src/cmd/ksh93/tests/subshell.sh b/src/cmd/ksh93/tests/subshell.sh index bde31f1e6..2ba5cbe90 100755 --- a/src/cmd/ksh93/tests/subshell.sh +++ b/src/cmd/ksh93/tests/subshell.sh @@ -693,6 +693,12 @@ got=$( [[ $got == "$exp" ]] || err_exit 'unset -f fails in forked subshells if a function is defined before forking' \ "(expected $(printf %q "$exp"), got $(printf %q "$got"))" +# function set in subshell, unset in subshell of that subshell +exp='*: f: not found' +got=$( f() { echo WRONG; }; ( unset -f f; PATH=/dev/null f 2>&1 ) ) +[[ $got == $exp ]] || err_exit 'unset -f fails in sub-subshell on function set in subshell' \ + "(expected match of $(printf %q "$exp"), got $(printf %q "$got"))" + # ====== # Unsetting or redefining aliases within subshells