[PATCH] ash: reset tokpushback before prompting while parsing heredoc
Alexander Dahl
ada at thorsis.com
Tue Nov 13 08:38:23 UTC 2018
Hei hei,
I just tested the bugfix on top of current master (1_29_0-154-g375fc78d5), the
output is like this:
% ./busybox ash
/mnt/data_2/adahl/src/busybox $ cat <<EOF
> $(echo abc)
> EOF
abc
/mnt/data_2/adahl/src/busybox $ cat <<EOF
> `echo abc`
> EOF
abc
/mnt/data_2/adahl/src/busybox $ %
Looks right to me, so you may add my
Tested-by: Alexander Dahl <post at lespocky.de>
Greets
Alex
Am Sonntag, 11. November 2018, 13:59:58 CET schrieb Christoph Schulz:
> The parser reads from an already freed memory location, thereby causing
> unpredictable results, in the following situation:
>
> - ENABLE_ASH_EXPAND_PRMT is enabled
> - heredoc is being parsed
> - command substitution is used within heredoc
>
> Examples where this bug crops up are (PS2 is set to "> "):
>
> $ cat <<EOF
>
> > `echo abc`
> > EOF
>
> -sh: O: not found
>
> $ cat <<EOF
>
> > $(echo abc)
> > EOF
>
> -sh: ���i�: not found
>
> The presumable reason is that setprompt_if() causes a nested expansion when
> ENABLE_ASH_EXPAND_PRMT is enabled, therefore leaving "wordtext" in an
> unusable state. However, when parseheredoc() is called, "tokpushback" is
> non-zero, which causes the next call to xxreadtoken() to return TWORD,
> causing the caller to use the invalid "wordtoken" instead of reading the
> next valid token.
>
> The call chain is:
>
> list()
> -> peektoken() [sets tokpushback to 1]
> -> parseheredoc()
> -> setprompt_if()
> -> pushstackmark()
> -> expandstr()
> -> readtoken1()
> [sets lasttoken to TWORD, wordtoken points to expanded prompt]
> -> popstackmark() [invalidates wordtoken, leaves lasttoken as is]
> -> readtoken1()
> -> ...parsebackq
> -> list()
> -> andor()
> -> pipeline()
> -> readtoken()
> -> xxreadtoken()
> [tokpushback non-zero, reuse lasttoken and wordtext]
>
> Note that in almost all other contexts, each call to setprompt_if() is
> preceded by setting "tokpushback" to zero. One exception is "oldstyle"
> backquote parsing in readtoken1(), but there "tokpushback" is reset
> afterwards. The other exception is nlprompt(), but this function is only
> used within readtoken1() (but in contexts where no nested calls to
> xxreadtoken() occur) and xxreadtoken() (where "tokpushback" is guaranteed
> to be zero).
>
> Signed-off-by: Christoph Schulz <develop at kristov.de>
> ---
> shell/ash.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/shell/ash.c b/shell/ash.c
> index 051cc671f..18848c7db 100644
> --- a/shell/ash.c
> +++ b/shell/ash.c
> @@ -12913,6 +12913,7 @@ parseheredoc(void)
> heredoclist = NULL;
>
> while (here) {
> + tokpushback = 0;
> setprompt_if(needprompt, 2);
> readtoken1(pgetc(), here->here->type == NHERE ? SQSYNTAX : DQSYNTAX,
> here->eofmark, here->striptabs);
More information about the busybox
mailing list