From 06021776465dc3b4e54f9d2d01074ab966cedbfd Mon Sep 17 00:00:00 2001 From: Martijn Dekker Date: Wed, 8 Jun 2022 20:56:18 +0100 Subject: [PATCH] posix: block brace expansion of unquoted expansions (re: a14d17c0) Historically, ksh (including ksh88 and mksh) allow brace expansion not just on literal patterns but also on patterns resulting from unquoted variable expansions or command substitutions: $ a='{a,b}' ksh -c 'echo X{a,b} Y$a' Xa Xb Ya Yb Most people expect only the first (literal) pattern to be expanded, as in bash and zsh: $ a='{a,b}' bash -c 'echo X{a,b} Y$a' Xa Xb Y{a,b} The historic ksh behaviour is poorly documented and nearly unknown, violates the principle of least astonishment, and makes unquoted variable expansions even more unsafe. See discussion at: https://www.austingroupbugs.net/view.php?id=1193 https://github.com/ksh93/ksh/issues/140 Unfortunately, we cannot change it in default ksh without breaking backward compatibility. But we can at least fix it for the POSIX mode (which disables brace expansion by default but allows turning it back on), particularly as it looks like POSIX, if it decides to specify brace expansion in a future version of the standard, will disallow brace expansion on unquoted variable expansions. src/cmd/ksh93/sh/macro.c: endfield(): - When deciding whether to do brace expansion + globbing or only globbing, also check that we do not have POSIX mode and an unquoted variable expansion (mp->pattern==1). --- NEWS | 8 ++++++++ src/cmd/ksh93/include/version.h | 2 +- src/cmd/ksh93/sh.1 | 3 +++ src/cmd/ksh93/sh/macro.c | 3 ++- src/cmd/ksh93/tests/posix.sh | 14 ++++++++++++++ 5 files changed, 28 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index 04d9b2dc5..6f54dff3f 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,14 @@ For full details, see the git log at: https://github.com/ksh93/ksh/tree/1.0 Any uppercase BUG_* names are modernish shell bug IDs. +2022-06-08: + +- If -B/--braceexpand is turned on in --posix mode, it now only allows brace + expansion on literal strings and not on the values of unquoted expansions. + This behaviour is like bash and zsh, as well as compliant with a future + version of the POSIX standard that may specify brace expansion: + https://www.austingroupbugs.net/view.php?id=1193 + 2022-06-07: - Fixed a bug in 'typeset' where compound variables could acquire a spurious diff --git a/src/cmd/ksh93/include/version.h b/src/cmd/ksh93/include/version.h index 4cc62d08e..dcf1e9c1f 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-beta.2" /* semantic version number: https://semver.org */ -#define SH_RELEASE_DATE "2022-06-07" /* must be in this format for $((.sh.version)) */ +#define SH_RELEASE_DATE "2022-06-08" /* must be in this format for $((.sh.version)) */ #define SH_RELEASE_CPYR "(c) 2020-2022 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.1 b/src/cmd/ksh93/sh.1 index 290c3c34e..391dd5032 100644 --- a/src/cmd/ksh93/sh.1 +++ b/src/cmd/ksh93/sh.1 @@ -7704,6 +7704,9 @@ In addition, while on, the \fBposix\fR option disables exporting variable type attributes to the environment for other ksh processes to import; .IP \[bu] +if the \fB\-B\fR/\fBbraceexpand\fR option is turned back on, +disallows brace expansion on the results of unquoted expansions; +.IP \[bu] disables the special handling of repeated .I isspace class characters in the diff --git a/src/cmd/ksh93/sh/macro.c b/src/cmd/ksh93/sh/macro.c index b1ade153e..dcc95d70c 100644 --- a/src/cmd/ksh93/sh/macro.c +++ b/src/cmd/ksh93/sh/macro.c @@ -2494,7 +2494,8 @@ static void endfield(register Mac_t *mp,int split) { sh.argaddr = 0; #if SHOPT_BRACEPAT - if(sh_isoption(SH_BRACEEXPAND)) + /* in POSIX mode, disallow brace expansion for unquoted expansions */ + if(sh_isoption(SH_BRACEEXPAND) && !(sh_isoption(SH_POSIX) && mp->pattern==1)) count = path_generate(argp,mp->arghead); else #endif /* SHOPT_BRACEPAT */ diff --git a/src/cmd/ksh93/tests/posix.sh b/src/cmd/ksh93/tests/posix.sh index 8f98907ea..4330c2898 100644 --- a/src/cmd/ksh93/tests/posix.sh +++ b/src/cmd/ksh93/tests/posix.sh @@ -45,6 +45,20 @@ if ((SHOPT_BRACEPAT)); then fi (set --noposix; ((SHOPT_BRACEPAT)) && set +B; eval 'set {1..4}'; let "$# == 1") || err_exit "--noposix does not allow independent control of braceexpand" +# When brace expansion is turned back on in POSIX mode, the values of unquoted variable expansions are not subject to it. +# (note that, in typical quirky ksh fashion, this only happens if pathname expansion is also on, i.e. -f/--noglob is off.) +if ((SHOPT_BRACEPAT)) +then + got=$(set -B +f; a='x{1,2}'; print $a) + exp='x{1,2}' + [[ $got == "$exp" ]] || err_exit "posix braceexpand expands unquoted variable expansions" \ + "(expected $(printf %q "$exp"), got $(printf %q "$got"))" + got=$(set --noposix +f; a='x{1,2}'; print $a) + exp='x1 x2' + [[ $got == "$exp" ]] || err_exit "non-posix braceexpand does not expand unquoted variable expansions" \ + "(expected $(printf %q "$exp"), got $(printf %q "$got"))" +fi + # Furthermore, the posix option is automatically turned on upon invocation if the shell is invoked as sh or rsh, # or if -o posix or --posix is specified on the shell invocation command line, or when executing scripts # without a #! path with this option active in the invoking shell.