From e53177abcaf022f25bf4770248a66125de5c3896 Mon Sep 17 00:00:00 2001 From: Johnothan King Date: Wed, 5 Aug 2020 10:14:30 -0700 Subject: [PATCH] Fix unset method in multidimensional arrays (#105) A segfault happens when an array with an unset method is turned into a multidimensional array. Reproducer: function foo { typeset -a a a.unset() { print unset } a[3][6][11][20]=7 } foo src/cmd/ksh93/sh/nvdisc: - Fix the multidimensional array unset method crash by checking if np->nvenv is an array, since multidimensional arrays need to be handled as arrays. This bugfix was backported from ksh93v- 2013-10-10-alpha. src/cmd/ksh93/tests/arrays2.sh: - Add the reproducer as a regression test for the crash with multidimensional arrays. Bug report on the old mailing list: https://www.mail-archive.com/ast-developers@lists.research.att.com/msg01195.html --- NEWS | 3 +++ src/cmd/ksh93/sh/nvdisc.c | 5 +++++ src/cmd/ksh93/tests/arrays2.sh | 17 +++++++++++++++++ 3 files changed, 25 insertions(+) diff --git a/NEWS b/NEWS index 6b9e2101a..f752478f0 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,9 @@ Any uppercase BUG_* names are modernish shell bug IDs. 2020-08-05: +- Fixed a bug in functions that caused ksh to crash when an array with an + unset method was turned into a multidimensional array. + - Fixed a bug that caused scripts to continue running after over-shifting in a function when the function call had a redirection. diff --git a/src/cmd/ksh93/sh/nvdisc.c b/src/cmd/ksh93/sh/nvdisc.c index 9ea9a1523..d187778da 100644 --- a/src/cmd/ksh93/sh/nvdisc.c +++ b/src/cmd/ksh93/sh/nvdisc.c @@ -331,13 +331,18 @@ static void assign(Namval_t *np,const char* val,int flags,Namfun_t *handle) else if(!nq || !isblocked(bp,type)) { Dt_t *root = sh_subfuntree(1); + Namval_t *pp=0; int n; Namarr_t *ap; block(bp,type); nv_disc(np,handle,NV_POP); + if(!nv_isattr(np,NV_MINIMAL)) + pp = (Namval_t*)np->nvenv; nv_putv(np, val, flags, handle); if(sh.subshell) goto done; + if(pp && nv_isarray(pp)) + goto done; if(nv_isarray(np) && (ap=nv_arrayptr(np)) && ap->nelem>0) goto done; for(n=0; n < sizeof(vp->disc)/sizeof(*vp->disc); n++) diff --git a/src/cmd/ksh93/tests/arrays2.sh b/src/cmd/ksh93/tests/arrays2.sh index f3e208927..3d5ab530f 100755 --- a/src/cmd/ksh93/tests/arrays2.sh +++ b/src/cmd/ksh93/tests/arrays2.sh @@ -224,4 +224,21 @@ print -v cx > /dev/null print -v cx | read -C l 2> /dev/null || err_exit 'read -C fails from output of print -v' [[ ${cx%cx=} == "${l%l=}" ]] || err_exit 'print -v for compound variable with fixed 2d array not working' +# ====== +# Multidimensional arrays with an unset method shouldn't cause a crash. +# The test itself must be run inside of a function. +multiarray_unset="$tmp/multiarray_unset.sh" +cat >| "$multiarray_unset" << EOF +function foo { + typeset -a a + a.unset() { + print unset + } + a[3][6][11][20]=7 +} +foo +EOF +$SHELL "$multiarray_unset" > /dev/null || err_exit 'Multidimensional arrays with an unset method crash ksh' + +# ====== exit $((Errors<125?Errors:125))