Skip to content

Commit

Permalink
Fix unset non-namespace funct. from within namespace (re: dbccda1)
Browse files Browse the repository at this point in the history
The referenced commit more or less accidentally worked because
it set 'name' to the namespace-prefixed function name, which then
triggered the code at the bottom of unall() to set a dummy node in
the virtual subshell. However, this also bypassed the lookup for
the non-namespaced name, which made it impossible to unset a
function defined outside a namespace from within the namespace.

src/cmd/ksh93/bltins/typeset.c: unall():
- When prefixing the namespace name, use a local 'nsname' for the
  prefixed name and do not change 'name'. This fixes the bug, but
  on its own this fix would also reintroduce the subshell bug.
- To avoid that, add code to set a dummy node in a virtual subshell
  for a namespace function. If that is done, simply return, because
  nothing else needs doing now.
  • Loading branch information
McDutchie committed Feb 12, 2024
1 parent 19af097 commit cbc9027
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 6 deletions.
3 changes: 3 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ Uppercase BUG_* IDs are shell bug IDs as used by the Modernish shell library.
behaviour of the system's external printf(1) determines whether this is
compiled in or out by default. Normal ksh printf options keep working.

- Fixed a bug, introduced on 2023-06-02, that made it impossible within a
namespace to unset a function defined outside the namespace.

2024-02-09:

- Fixed multiple inaccurate or missing values in the /opt/ast/bin/getconf
Expand Down
21 changes: 15 additions & 6 deletions src/cmd/ksh93/bltins/typeset.c
Original file line number Diff line number Diff line change
Expand Up @@ -1352,13 +1352,22 @@ static int unall(int argc, char **argv, Dt_t *troot)
if(jmpval==0)
{
#if SHOPT_NAMESPACE
if(sh.namespace && troot==sh.fun_tree && *name!='.')
if(sh.namespace && troot==sh.fun_tree && !sh.prefix && *name!='.')
{
char *nsname;
Namval_t *np2;
/* prefix the namespace name */
sfputr(sh.stk,nv_name(sh.namespace),'.');
sfputr(sh.stk,name,'\0');
name = stkfreeze(sh.stk,0);
sfputr(sh.strbuf,nv_name(sh.namespace),'.');
sfputr(sh.strbuf,name,'\0');
nsname = sfstruse(sh.strbuf);
np = nv_search(nsname,troot,NV_NOSCOPE);
if(troot!=sh.fun_base && !np && (np2=nv_search(nsname,troot,0)) && is_afunction(np2))
{ /* create dummy virtual subshell node without NV_FUNCTION attribute */
nv_open(nsname,troot,NV_NOSCOPE);
return r;
}
}
if(!np)
#endif /* SHOPT_NAMESPACE */
np=nv_open(name,troot,NV_NOADD|nflag);
}
Expand Down Expand Up @@ -1421,8 +1430,8 @@ static int unall(int argc, char **argv, Dt_t *troot)
}
else if(troot==sh.alias_tree)
r = 1;
else if(troot==sh.fun_tree && troot!=sh.fun_base && (np=nv_search(name,sh.fun_tree,0)) && is_afunction(np))
nv_open(name,troot,NV_NOSCOPE); /* create dummy virtual subshell node without NV_FUNCTION attribute */
else if(troot==sh.fun_tree && troot!=sh.fun_base && !np && (np=nv_search(name,troot,0)) && is_afunction(np))
nv_open(name,troot,NV_NOSCOPE); /* create dummy virtual subshell node without NV_FUNCTION attribute */
}
return r;
}
Expand Down
12 changes: 12 additions & 0 deletions src/cmd/ksh93/tests/namespace.sh
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,18 @@ do
[[ e=$? -eq 2 && $got =~ $exp ]] || err_exit "'unset -f $b' fails in subshell (1b)" \
"(expected status 2 and ERE match of $(printf %q "$exp"), got status $e and $(printf %q "$got"))"

# bug introduced on 2023-06-02
got=$(
eval "$b() { echo BAD; }"
namespace ns
{
(unset -f "$b"; PATH=/dev/null; "$b" --version 2>&1)
exit # avoid optimizing out the subshell
}
)
[[ e=$? -eq 2 && $got =~ $exp ]] || err_exit "'unset -f $b' fails in subshell (1c)" \
"(expected status 2 and ERE match of $(printf %q "$exp"), got status $e and $(printf %q "$got"))"

got=$(
namespace ns
{
Expand Down

0 comments on commit cbc9027

Please sign in to comment.