diff --git a/NEWS b/NEWS index 18134d46e..51dd10539 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,12 @@ For full details, see the git log at: https://github.com/ksh93/ksh Any uppercase BUG_* names are modernish shell bug IDs. +2020-09-05: + +- Fixed erroneous syntax errors in parameter expansions such as ${var:-wor)d} + or ${var+w(ord}. The parentheses now correctly lose their normal grammatical + meaning within the braces. Fix by Eric Scrivner backported from ksh2020. + 2020-09-04: - Fixed a bug that caused a syntax error to be thrown if the special parameter diff --git a/src/cmd/ksh93/include/version.h b/src/cmd/ksh93/include/version.h index 1f72bd3c0..e06fe1525 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-09-04" +#define SH_RELEASE "93u+m 2020-09-05" diff --git a/src/cmd/ksh93/sh/lex.c b/src/cmd/ksh93/sh/lex.c index 2aa71a776..da21d9d56 100644 --- a/src/cmd/ksh93/sh/lex.c +++ b/src/cmd/ksh93/sh/lex.c @@ -1018,6 +1018,11 @@ int sh_lex(Lex_t* lp) if(lp->kiafile) refvar(lp,1); #endif /* SHOPT_KIA */ + if(c == ':' || c == '-' || c == '+' || c == '=') + { + mode = ST_QUOTE; + continue; + } if(c!=':' && fcgetc(n)>0) { if(n!=c) diff --git a/src/cmd/ksh93/sh/macro.c b/src/cmd/ksh93/sh/macro.c index 36b299988..67c454925 100644 --- a/src/cmd/ksh93/sh/macro.c +++ b/src/cmd/ksh93/sh/macro.c @@ -1628,7 +1628,8 @@ retry1: } else { - sh_lexskip(lp,RBRACE,0,(!newops&&mp->quote)?ST_QUOTE:ST_NESTED); + int state = (!newops && mp->quote || c=='-' || c=='+' || c=='=') ? ST_QUOTE : ST_NESTED; + sh_lexskip(lp, RBRACE, 0, state); stkseek(stkp,offset); } argp=stkptr(stkp,offset); diff --git a/src/cmd/ksh93/tests/variables.sh b/src/cmd/ksh93/tests/variables.sh index 3604c1267..f122ed5d4 100755 --- a/src/cmd/ksh93/tests/variables.sh +++ b/src/cmd/ksh93/tests/variables.sh @@ -1040,5 +1040,39 @@ wait # ${.sh.pid} should be the same as $$ in the parent shell [[ $$ == ${.sh.pid} ]] || err_exit "\${.sh.pid} and \$$ differ in the parent shell (expected $$, got ${.sh.pid})" +# ====== +# Parentheses after the '-', '+', and '=' expansion operators were causing syntax errors. +# Check both the unset variable case and the set variable case for each set of symbols. + +unset -v foo +for op in - :- = := +do for word in '(word)' 'w(or)d' '(wor)d' 'w(ord)' 'w(ord' 'wor)d' + do exp=$(set +x; eval "echo \${foo${op}${word}}" 2>&1) + if [[ $exp != "$word" ]] + then err_exit "\${foo${op}${word}} when foo is not set: expected \"$word\", got \"$exp\"" + fi + done +done + +foo=some_value +for op in - :- = := +do for word in '(word)' 'w(or)d' '(wor)d' 'w(ord)' 'w(ord' 'wor)d' + do exp=$(set +x; eval "echo \${foo${op}${word}}" 2>&1) + if [[ $exp != "$foo" ]] + then err_exit "\${foo${op}${word}} when foo is set: expected \"$foo\", got \"$exp\"" + fi + done +done + +unset -v foo +for op in + :+ +do for word in '(word)' 'w(or)d' '(wor)d' 'w(ord)' 'w(ord' 'wor)d' + do exp=$(set +x; eval "echo \${foo${op}${word}}" 2>&1) + if [[ $exp != "" ]] + then err_exit "\${foo${op}${word}} when foo is not set: expected null, got \"$exp\"" + fi + done +done + # ====== exit $((Errors<125?Errors:125))