mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-02-13 03:32:24 +00:00
Fix wrong syntax error upon process substitution after redirection
Grammatically, redirections may occur anywhere within a command line and are removed after processing them, whereas a process substitution (<(commandlist) or >(commandlist)) is replaced by a file name which should be treated as just another simple word. So the following should not be a syntax error: $ cat </dev/null <(true) -ksh: syntax error: `)' unexpected $ cat </dev/null >(true) -ksh: syntax error: `)' unexpected $ cat >/dev/null <(true) -ksh: syntax error: `)' unexpected $ cat >/dev/null >(true) -ksh: syntax error: `)' unexpected This bug is in every ksh93 version. The problem is in the parser (parse.c). The process substitution is misparsed as a redirection due to inout() recursively parsing multiple redirections without recognising process substitutions. inout() is mistaking '<(' for '<' and '>(' for '>', which explains the incorrect syntax error. This also causes the following to fail to detect a syntax error: $ cat >&1 <(README.md [the contents of README.md are shown] ...and other syntax errors detected in the wrong spot, for example: $ { true; } <(echo wrong) -ksh: syntax error: `wrong' unexpected which should be: -ksh: syntax error: `<(' unexpected src/cmd/ksh93/sh/parse.c: - Add global inout_found_procsub flag. - inout(): On encountering a process substitution, set this flag and return, otherwise clear the flag. - simple(): After calling inout(), check this flag and, if set, jump back to where process substitutions are parsed. Resolves: https://github.com/ksh93/ksh/issues/418
This commit is contained in:
parent
8a0920ea0a
commit
06e56251b9
4 changed files with 44 additions and 1 deletions
6
NEWS
6
NEWS
|
@ -3,6 +3,12 @@ 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-07-05:
|
||||
|
||||
- Fixed a spurious syntax error on encountering a process substitution
|
||||
following a redirection without being an argument to a redirection.
|
||||
For example, this now writes 'OK' to standard error: cat >&2 <(echo OK)
|
||||
|
||||
2022-07-02:
|
||||
|
||||
- Fixed a bug where, if the last command in a subshell was an external
|
||||
|
|
|
@ -23,7 +23,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-07-02" /* must be in this format for $((.sh.version)) */
|
||||
#define SH_RELEASE_DATE "2022-07-05" /* 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. */
|
||||
|
|
|
@ -48,6 +48,7 @@ static Shnode_t *makeparent(Lex_t*, int, Shnode_t*);
|
|||
static Shnode_t *makelist(Lex_t*, int, Shnode_t*, Shnode_t*);
|
||||
static struct argnod *qscan(struct comnod*, int);
|
||||
static struct ionod *inout(Lex_t*,struct ionod*, int);
|
||||
static char inout_found_procsub;
|
||||
static Shnode_t *sh_cmd(Lex_t*,int,int);
|
||||
static Shnode_t *term(Lex_t*,int);
|
||||
static Shnode_t *list(Lex_t*,int);
|
||||
|
@ -1583,6 +1584,7 @@ static Shnode_t *simple(Lex_t *lexp,int flag, struct ionod *io)
|
|||
lexp->token = tok = 0;
|
||||
if((tok==IPROCSYM || tok==OPROCSYM))
|
||||
{
|
||||
procsub:
|
||||
argp = process_sub(lexp,tok);
|
||||
argno = -1;
|
||||
*argtail = argp;
|
||||
|
@ -1655,6 +1657,8 @@ static Shnode_t *simple(Lex_t *lexp,int flag, struct ionod *io)
|
|||
}
|
||||
else
|
||||
t->comio = io = inout(lexp,(struct ionod*)0,0);
|
||||
if(inout_found_procsub)
|
||||
goto procsub;
|
||||
}
|
||||
}
|
||||
*argtail = 0;
|
||||
|
@ -1753,6 +1757,9 @@ static struct ionod *inout(Lex_t *lexp,struct ionod *lastio,int flag)
|
|||
Stk_t *stkp = sh.stk;
|
||||
char *iovname=0;
|
||||
register int errout=0;
|
||||
/* return if a process substitution is found without a redirection */
|
||||
if(inout_found_procsub = (token==IPROCSYM || token==OPROCSYM))
|
||||
return(lastio);
|
||||
if(token==IOVNAME)
|
||||
{
|
||||
iovname=lexp->arg->argval+1;
|
||||
|
|
|
@ -974,5 +974,35 @@ then
|
|||
"(expected $(printf %q "$exp"), got $(printf %q "$got"))"
|
||||
fi
|
||||
|
||||
# ======
|
||||
# A process substitution should be valid after a redirection
|
||||
# https://github.com/ksh93/ksh/issues/418
|
||||
got=$(set +x; eval ': </dev/null <(true)' 2>&1)
|
||||
[[ e=$? -eq 0 && -z $got ]] || err_exit "spurious syntax error on process substitution following redirection" \
|
||||
"(expected status 0 and '', got status $e and $(printf %q "$got"))"
|
||||
got=$(set +x; eval ': <&1 <(/dev/null' 2>&1)
|
||||
exp='*: syntax error at line *: `end of file'\'' unexpected'
|
||||
[[ $got == $exp ]] || err_exit "': <&1 <(/dev/null' fails to throw a syntax error" \
|
||||
"(expected match of $(printf %q "$exp"), got $(printf %q "$got"))"
|
||||
got=$(set +x; eval '{ :; } <(: wrong)' 2>&1)
|
||||
exp='*: syntax error at line *: `<('\'' unexpected'
|
||||
[[ $got == $exp ]] || err_exit "'{ :; } <(: wrong)' throws incorrect syntax error" \
|
||||
"(expected match of $(printf %q "$exp"), got $(printf %q "$got"))"
|
||||
got=$(set +x; eval ': >/dev/null >(true)' 2>&1)
|
||||
[[ e=$? -eq 0 && -z $got ]] || err_exit "spurious syntax error on process substitution following redirection" \
|
||||
"(expected status 0 and '', got status $e and $(printf %q "$got"))"
|
||||
got=$(set +x; eval ': >&1 >(/dev/null' 2>&1)
|
||||
exp='*: syntax error at line *: `end of file'\'' unexpected'
|
||||
[[ $got == $exp ]] || err_exit "': >&1 >(/dev/null' fails to throw a syntax error" \
|
||||
"(expected match of $(printf %q "$exp"), got $(printf %q "$got"))"
|
||||
got=$(set +x; eval '{ :; } >(: wrong)' 2>&1)
|
||||
exp='*: syntax error at line *: `>('\'' unexpected'
|
||||
[[ $got == $exp ]] || err_exit "'{ :; } >(: wrong)' throws incorrect syntax error" \
|
||||
"(expected match of $(printf %q "$exp"), got $(printf %q "$got"))"
|
||||
got=$(set +x; eval 'cat >out <(echo OK)' 2>&1; echo ===; cat out)
|
||||
exp=$'===\nOK'
|
||||
[[ $got == "$exp" ]] || err_exit "process substitution nixes output redirection" \
|
||||
"(expected $(printf %q "$exp"), got $(printf %q "$got"))"
|
||||
|
||||
# ======
|
||||
exit $((Errors<125?Errors:125))
|
||||
|
|
Loading…
Reference in a new issue