1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-02-13 11:42:21 +00:00

The unalias builtin should return an error for non-existent aliases

This commit fixes a bug that caused unalias to return a zero status
when it tries to remove an alias twice. The following set of commands
will no longer end with an error:

$ alias foo=bar
$ unalias foo
$ unalias foo && echo 'Error'

This commit is based on the fix present in ksh2020, but it has been
extended with another bugfix. The initial fix for this problem tried to
remove aliases from the alias tree without accounting for NV_NOFREE. This
caused any attempt to remove a predefined aliases (e.g. `unalias float`)
to trigger an error with free, as all predefined aliases are in read-only
memory. The fix for this problem is to set NV_NOFREE when removing aliases
from the alias tree, but only if the alias is in read-only memory. All
other aliases must be freed from memory to prevent memory leaks.

I'll also note that I am using an `isalias` variable rather than the `type`
enum from ksh2020, as the `VARIABLE` value is never used and was replaced
with a bool called `aliases` in the ksh2020 release. The `isalias` variable
is an int as the ksh93u+ codebase does not use C99 bools.

Previous discussion: https://github.com/att/ast/issues/909

- src/cmd/ksh93/bltins/typeset.c:
  Remove aliases from the alias tree by using nv_delete. NV_NOFREE
  is only used when it is necessary.

- src/cmd/ksh93/tests/alias.sh:
  Add two regression tests for the bugs fixed by this commit.

(cherry picked from commit 16d5ea9b52ba51f9d1bca115ce8f4f18e97abbc4)
This commit is contained in:
Johnothan King 2020-06-09 08:31:00 -07:00 committed by Martijn Dekker
parent d18469d608
commit 5d50f825e4
3 changed files with 28 additions and 3 deletions

5
NEWS
View file

@ -4,6 +4,11 @@ For full details, see the git log at:
Any uppercase BUG_* names are modernish shell bug IDs.
2020-06-09:
- The 'unalias' builtin will now return a non-zero status if it tries
to remove a previously set alias that is not currently set.
2020-06-08:
- Fix an issue with the up arrow key in Emacs editing mode.

View file

@ -1161,11 +1161,13 @@ static int unall(int argc, char **argv, register Dt_t *troot, Shell_t* shp)
register const char *name;
volatile int r;
Dt_t *dp;
int nflag=0,all=0,isfun,jmpval;
int nflag=0,all=0,isalias=0,isfun,jmpval;
struct checkpt buff;
NOT_USED(argc);
if(troot==shp->alias_tree)
if(troot==shp->alias_tree) {
isalias = 1;
name = sh_optunalias;
}
else
name = sh_optunset;
while(r = optget(argv,name)) switch(r)
@ -1281,6 +1283,7 @@ static int unall(int argc, char **argv, register Dt_t *troot, Shell_t* shp)
if(shp->subshell)
np=sh_assignok(np,0);
}
if(!nv_isnull(np) || nv_size(np) || nv_isattr(np,~(NV_MINIMAL|NV_NOFREE)))
_nv_unset(np,0);
if(troot==shp->var_tree && shp->st.real_fun && (dp=shp->var_tree->walk) && dp==shp->st.real_fun->sdict)
@ -1298,6 +1301,13 @@ static int unall(int argc, char **argv, register Dt_t *troot, Shell_t* shp)
while((troottmp = troottmp->view) && (np = nv_search(name,troottmp,0)) && is_afunction(np))
nv_delete(np,troottmp,0);
}
/* The alias has been unset by call to _nv_unset, remove it from the tree */
else if(isalias) {
if(nv_isattr(np, NV_NOFREE))
nv_delete(np,troot,NV_NOFREE); /* The alias is in read-only memory (shtab_aliases) */
else
nv_delete(np,troot,0);
}
#if 0
/* causes unsetting local variable to expose global */
else if(shp->var_tree==troot && shp->var_tree!=shp->var_base && nv_search((char*)np,shp->var_tree,HASH_BUCKET|HASH_NOSCOPE))

View file

@ -103,6 +103,16 @@ fi
( alias :pr=print) 2> /dev/null || err_exit 'alias beginning with : fails'
( alias p:r=print) 2> /dev/null || err_exit 'alias with : in name fails'
unalias no_such_alias && err_exit 'unalias should return non-zero for unknown alias'
unalias no_such_alias && err_exit 'unalias should return non-zero for unknown alias'
# ======
# Attempting to unalias a previously set alias twice should be an error
alias foo=bar
unalias foo
unalias foo && err_exit 'unalias should return non-zero when a previously set alias is unaliased twice'
# Removing a predefined alias should work without an error from free(3)
$SHELL -c 'unalias history' 2> /dev/null || err_exit 'removing a predefined alias does not work'
# ======
exit $((Errors<125?Errors:125))