diff --git a/NEWS b/NEWS index 9745404a7..ff7aac20b 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,10 @@ Any uppercase BUG_* names are modernish shell bug IDs. 2022-02-05: +- Fixed: for indexed arrays, given an unset array member a[i] with i > 0, + ${a[i]=value} failed to assign the value and ${v[i]?error} failed to throw + an error. + - Fixed: the -a/--allexport shell option incorrectly exported some variables with names containing a dot to the environment. Note that the '-x' typeset attribute may still be set for them, but this will now not have any diff --git a/src/cmd/ksh93/include/shell.h b/src/cmd/ksh93/include/shell.h index ca7cf8265..3de9a7209 100644 --- a/src/cmd/ksh93/include/shell.h +++ b/src/cmd/ksh93/include/shell.h @@ -354,6 +354,7 @@ struct Shell_s void *defpathlist; void *cdpathlist; char **argaddr; + char cond_expan; /* set while processing ${var=val}, ${var:=val}, ${var?err}, ${var:?err} */ void *optlist; struct sh_scoped global; struct checkpt checkbase; diff --git a/src/cmd/ksh93/sh/array.c b/src/cmd/ksh93/sh/array.c index a848be72c..4281c1eba 100644 --- a/src/cmd/ksh93/sh/array.c +++ b/src/cmd/ksh93/sh/array.c @@ -1247,7 +1247,7 @@ Namval_t *nv_putsub(Namval_t *np,register char *sp,register long mode) nv_arraychild(np,mp,0); nv_setvtree(mp); } - else + else if(!sh.cond_expan) ap->val[size].cp = Empty; if(!sp && !array_covered(np,ap)) ap->header.nelem++; diff --git a/src/cmd/ksh93/sh/macro.c b/src/cmd/ksh93/sh/macro.c index 3f04e415b..72e1ad6dc 100644 --- a/src/cmd/ksh93/sh/macro.c +++ b/src/cmd/ksh93/sh/macro.c @@ -1304,27 +1304,28 @@ retry1: if(c=='=' || (c==':' && d=='=')) flag |= NV_ASSIGN; flag &= ~NV_NOADD; + sh.cond_expan = 1; /* tell nv_putsub() not to change value from null to empty */ + np = nv_open(id,sh.var_tree,flag|NV_NOFAIL); + sh.cond_expan = 0; } #if SHOPT_FILESCAN - if(sh.cur_line && *id=='R' && strcmp(id,"REPLY")==0) + else if(sh.cur_line && strcmp(id,REPLYNOD->nvname)==0) { sh.argaddr=0; np = REPLYNOD; } - else #endif /* SHOPT_FILESCAN */ + else { if(sh.argaddr) flag &= ~NV_NOADD; - /* - * Get a node pointer (np) to the parameter, if any. - */ np = nv_open(id,sh.var_tree,flag|NV_NOFAIL); - if(!np) - { - sfprintf(sh.strbuf,"%s%c",id,0); - id = sfstruse(sh.strbuf); - } + } + if(!np) + { + /* id points to stack, which will be overwritten; save it for error message */ + sfputr(sh.strbuf,id,-1); + id = sfstruse(sh.strbuf); } if(isastchar(mode)) var = 0; diff --git a/src/cmd/ksh93/tests/arrays.sh b/src/cmd/ksh93/tests/arrays.sh index 8b701406c..b29b6d360 100755 --- a/src/cmd/ksh93/tests/arrays.sh +++ b/src/cmd/ksh93/tests/arrays.sh @@ -783,5 +783,25 @@ got=$("$SHELL" -c ' [[ $exp == $got ]] || err_exit 'Unsetting all elements of an array adds a spurious [0] element' \ "(expected $(printf %q "$exp"), got $(printf %q "$got"))" +# ====== +# https://github.com/ksh93/ksh/issues/383 +unset foo +exp=bar +got=$(echo "${foo[42]=bar}") +[[ $got == "$exp" ]] || err_exit '${array[index]=value} does not assign value' \ + "(expected $(printf %q "$exp"), got $(printf %q "$got"))" +exp=baz +got=$(echo "${foo[42]:=baz}") +[[ $got == "$exp" ]] || err_exit '${array[index]:=value} does not assign value' \ + "(expected $(printf %q "$exp"), got $(printf %q "$got"))" +exp=': parameter not set' +got=$(set +x; redirect 2>&1; : ${foo[42]?}) +[[ $got == *"$exp" ]] || err_exit '${array[index]?error} does not throw error' \ + "(expected match of *$(printf %q "$exp"), got $(printf %q "$got"))" +exp=': parameter null' +got=$(set +x; redirect 2>&1; foo[42]=''; : ${foo[42]:?}) +[[ $got == *"$exp" ]] || err_exit '${array[index]:?error} does not throw error' \ + "(expected match of *$(printf %q "$exp"), got $(printf %q "$got"))" + # ====== exit $((Errors<125?Errors:125))