diff --git a/NEWS b/NEWS index ab951b925588..2b9911b038dc 100644 --- a/NEWS +++ b/NEWS @@ -4,6 +4,12 @@ For full details, see the git log at: Any uppercase BUG_* names are modernish shell bug IDs. +2020-06-08: + +- If 'set -u'/'set -o nounset' is active, then the shell now errors out if a + nonexistent positional parameter such as $1, $2, ... is accessed, as other + shells do and POSIX requires. (This does *not* apply to "$@" and "$*".) + 2020-06-06: - The 'times' command is now a builtin command that conforms to POSIX diff --git a/src/cmd/ksh93/include/version.h b/src/cmd/ksh93/include/version.h index ab4e2f3676b3..06a3d6a92a4e 100644 --- a/src/cmd/ksh93/include/version.h +++ b/src/cmd/ksh93/include/version.h @@ -17,4 +17,4 @@ * David Korn * * * ***********************************************************************/ -#define SH_RELEASE "93u+m 2020-06-06" +#define SH_RELEASE "93u+m 2020-06-08" diff --git a/src/cmd/ksh93/sh.1 b/src/cmd/ksh93/sh.1 index e1055265b265..1793ab156608 100644 --- a/src/cmd/ksh93/sh.1 +++ b/src/cmd/ksh93/sh.1 @@ -7041,6 +7041,10 @@ Sort the positional parameters lexicographically. .TP 8 .B \-u Treat unset parameters as an error when substituting. +.B "$@" +and +.B "$\(**" +are exempt. .TP 8 .B \-v Print shell input lines as they are read. diff --git a/src/cmd/ksh93/sh/macro.c b/src/cmd/ksh93/sh/macro.c index 26af5691b3de..d789d1941bb5 100644 --- a/src/cmd/ksh93/sh/macro.c +++ b/src/cmd/ksh93/sh/macro.c @@ -1195,6 +1195,14 @@ static int varsub(Mac_t *mp) } else v = 0; + /* Handle 'set -u'/'set -o nounset' for positional parameters */ + if(!v && sh_isoption(SH_NOUNSET)) + { + d=fcget(); + fcseek(-1); + if(!(d && strchr(":+-?=",d))) + errormsg(SH_DICT,ERROR_exit(1),e_notset,ltos(c)); + } break; case S_ALP: if(c=='.' && type==0) diff --git a/src/cmd/ksh93/tests/options.sh b/src/cmd/ksh93/tests/options.sh index 6bbb31508d47..1375440e4a08 100755 --- a/src/cmd/ksh93/tests/options.sh +++ b/src/cmd/ksh93/tests/options.sh @@ -512,6 +512,9 @@ $SHELL -uc 'var=foo;unset var;: ${!var}' >/dev/null 2>&1 && err_exit '${!var} sh $SHELL -uc 'var=foo;unset var;: ${#var}' >/dev/null 2>&1 && err_exit '${#var} should fail with set -u' $SHELL -uc 'var=foo;unset var;: ${var-OK}' >/dev/null 2>&1 || err_exit '${var-OK} should not fail with set -u' $SHELL -uc 'var=foo;nset var;: ${var:-OK}' >/dev/null 2>&1 || err_exit '${var:-OK} should not fail with set -u' +(set -u -- one two; : $2) 2>/dev/null || err_exit "an unset PP failed with set -u" +(set -u -- one two; : $3) 2>/dev/null && err_exit "a set PP failed to fail with set -u" +(set -u --; : $@ $*) 2>/dev/null || err_exit '$@ and/or $* fail to be exempt from set -u' z=$($SHELL 2>&1 -uc 'print ${X23456789012345}') [[ $z == *X23456789012345:* ]] || err_exit "error message garbled with set -u got $z"