From d087b031f02ecf9104cce043017ede4e37e9e655 Mon Sep 17 00:00:00 2001 From: Martijn Dekker Date: Fri, 30 Apr 2021 05:10:04 +0100 Subject: [PATCH] Fix single quotes in expansion operator string (re: 5ed9ffd6) The referenced commit introduced the following bug: > The closing quote does not appear to be registering during the > parse of the following: > > echo ${var:+'{}'} > > Within a script, this will result in: > > syntax error at line 1: `'' unmatched src/cmd/ksh93/data/lexstates.c, src/cmd/ksh93/include/lexstates.h: - Add new ST_MOD1 state table that is a copy of ST_QUOTE, but adds a special meaning (ST_LIT) for the single quote (position 39). src/cmd/ksh93/sh/lex.c: sh_lex(): - For parameter expansion operators with old-style quoting (S_MOD1), use the new ST_MOD1 state table instead of ST_QUOTE. This causes single quotes within them to be processed properly. src/cmd/ksh93/tests/quoting2.sh: - Add tests. Thanks to @gkamat for the bug report. Resolves: https://github.com/ksh93/ksh/issues/290 --- NEWS | 5 +++++ src/cmd/ksh93/data/lexstates.c | 26 +++++++++++++++++++++++++- src/cmd/ksh93/include/lexstates.h | 3 ++- src/cmd/ksh93/include/version.h | 2 +- src/cmd/ksh93/sh/lex.c | 2 +- src/cmd/ksh93/tests/quoting2.sh | 13 +++++++++++++ 6 files changed, 47 insertions(+), 4 deletions(-) diff --git a/NEWS b/NEWS index e7bb8927b..b81d7e5d0 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,11 @@ For full details, see the git log at: https://github.com/ksh93/ksh Any uppercase BUG_* names are modernish shell bug IDs. +2021-04-30: + +- Fixed a bug introduced on 2020-09-05 that caused "echo ${var:+'{}'}" + to be misparsed. + 2021-04-26: - Fixed a bug introduced on 2021-02-20 in which a shared-state command diff --git a/src/cmd/ksh93/data/lexstates.c b/src/cmd/ksh93/data/lexstates.c index 41344f3cc..2465e268a 100644 --- a/src/cmd/ksh93/data/lexstates.c +++ b/src/cmd/ksh93/data/lexstates.c @@ -387,6 +387,30 @@ static const char sh_lexstate9[256] = 0, 0, 0, S_BRACE,S_PAT, S_ENDCH,0, 0 }; +/* + * ST_MOD1 + * for skipping over a string S in ${v-S}, ${v+S}, ${v:-S}, ${v:+S} + */ +static const char sh_lexstate11[256] = +{ + S_EOF, 0, 0, 0, 0, 0, 0, 0, + 0, 0, S_NL, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, S_QUOTE,0, S_DOL, 0, 0, S_LIT, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, S_ESC, 0, 0, 0, + S_GRAVE,0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, S_RBRA, 0, 0 +}; + /* * This must be kept synchronous with all the above and the ST_* definitions in lexstates.h */ @@ -394,7 +418,7 @@ const char *sh_lexrstates[ST_NONE] = { sh_lexstate0, sh_lexstate1, sh_lexstate2, sh_lexstate3, sh_lexstate4, sh_lexstate5, sh_lexstate6, sh_lexstate7, - sh_lexstate8, sh_lexstate9, sh_lexstate5 + sh_lexstate8, sh_lexstate9, sh_lexstate5, sh_lexstate11 }; diff --git a/src/cmd/ksh93/include/lexstates.h b/src/cmd/ksh93/include/lexstates.h index d1fbaee37..fb882a66e 100644 --- a/src/cmd/ksh93/include/lexstates.h +++ b/src/cmd/ksh93/include/lexstates.h @@ -79,7 +79,8 @@ #define ST_DOLNAME 8 #define ST_MACRO 9 #define ST_QNEST 10 -#define ST_NONE 11 +#define ST_MOD1 11 +#define ST_NONE 12 #include "FEATURE/locale" diff --git a/src/cmd/ksh93/include/version.h b/src/cmd/ksh93/include/version.h index 3de355fd9..b09b3e228 100644 --- a/src/cmd/ksh93/include/version.h +++ b/src/cmd/ksh93/include/version.h @@ -21,7 +21,7 @@ #define SH_RELEASE_FORK "93u+m" /* only change if you develop a new ksh93 fork */ #define SH_RELEASE_SVER "1.0.0-alpha" /* semantic version number: https://semver.org */ -#define SH_RELEASE_DATE "2021-04-26" /* must be in this format for $((.sh.version)) */ +#define SH_RELEASE_DATE "2021-04-30" /* must be in this format for $((.sh.version)) */ #define SH_RELEASE_CPYR "(c) 2020-2021 Contributors to ksh " SH_RELEASE_FORK /* Scripts sometimes field-split ${.sh.version}, so don't change amount of whitespace. */ diff --git a/src/cmd/ksh93/sh/lex.c b/src/cmd/ksh93/sh/lex.c index 14ef46ae8..a65f8fbe7 100644 --- a/src/cmd/ksh93/sh/lex.c +++ b/src/cmd/ksh93/sh/lex.c @@ -992,7 +992,7 @@ int sh_lex(Lex_t* lp) mode = ST_NESTED; continue; case S_MOD1: - mode = ST_QUOTE; + mode = ST_MOD1; continue; case S_MOD2: #if SHOPT_KIA diff --git a/src/cmd/ksh93/tests/quoting2.sh b/src/cmd/ksh93/tests/quoting2.sh index 8fc4ce609..cab135481 100755 --- a/src/cmd/ksh93/tests/quoting2.sh +++ b/src/cmd/ksh93/tests/quoting2.sh @@ -250,5 +250,18 @@ actual=$(printf %q $'1\x[11]1') [[ $actual == "$expect" ]] || err_exit 'shell-quoting: hex bytes not protected from subsequent hex-like chars' \ "(expected $expect; got $actual)" +# ====== +# https://github.com/ksh93/ksh/issues/290 +var=dummy +exp='{}' +got=$(eval 'echo ${var:+'\''{}'\''}' 2>&1) +[[ $got == "$exp" ]] || err_exit "Single quotes misparsed in expansion operator string (1)" \ + "(expected $(printf %q "$exp"), got $(printf %q "$got"))" +unset var +exp='}' +got=$(eval 'echo ${var:-'\''}'\''}' 2>&1) +[[ $got == "$exp" ]] || err_exit "Single quotes misparsed in expansion operator string (2)" \ + "(expected $(printf %q "$exp"), got $(printf %q "$got"))" + # ====== exit $((Errors<125?Errors:125))