diff options
author | Ron Yorston <rmy@pobox.com> | 2024-04-30 09:08:00 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2024-04-30 09:08:00 +0100 |
commit | 6b164f335c548bcebacd8bf984fd5c34ede46891 (patch) | |
tree | 7f8cabff188d78874d213a8693c44487707de6d8 | |
parent | 818cf3b0c7dae0b06d0103998f1eef14964b63c7 (diff) | |
download | busybox-w32-6b164f335c548bcebacd8bf984fd5c34ede46891.tar.gz busybox-w32-6b164f335c548bcebacd8bf984fd5c34ede46891.tar.bz2 busybox-w32-6b164f335c548bcebacd8bf984fd5c34ede46891.zip |
ash: fix alias expansion followed by '&'
An alias expansion immediately followed by '&' is parsed
incorrectly:
~ $ alias x='sleep 2'
~ $ x&
~ $
sh: syntax error: unexpected "&"
The sleep happens in the foreground and the '&' is left in the
input buffer. The same problem occurs in upstream BusyBox but
not dash.
The difference between BusyBox and dash is that BusyBox supports
bash-style output redirection (BASH_REDIR_OUTPUT in the code).
This requires checking for '&>' in readtoken1().
When the end of the alias is found, the '&' and the following
newline are both read to check for '&>'. Since there's no match
both characters are pushed back.
The alias is then expanded and __pgetc() is called to fetch the
next character. Since there are none left in the alias string
__pgetc() calls preadbuffer() which pops the string, reverts to
the previous input and recursively calls __pgetc(). This request
is satisified from the pungetc buffer. But the first __pgetc()
doesn't know this: it sees the character has come from
preadbuffer() so it (incorrectly) updates the pungetc buffer.
Resolve the issue by moving the code to pop the string and fetch
the next character up from preadbuffer() into __pgetc().
Saves 32-48 bytes.
(GitHub issue #413)
-rw-r--r-- | shell/ash.c | 11 |
1 files changed, 10 insertions, 1 deletions
diff --git a/shell/ash.c b/shell/ash.c index da139f89b..3435c5f76 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -12155,10 +12155,12 @@ preadbuffer(void) | |||
12155 | char *q; | 12155 | char *q; |
12156 | int more; | 12156 | int more; |
12157 | 12157 | ||
12158 | #if !ENABLE_PLATFORM_MINGW32 | ||
12158 | if (unlikely(g_parsefile->strpush)) { | 12159 | if (unlikely(g_parsefile->strpush)) { |
12159 | popstring(); | 12160 | popstring(); |
12160 | return __pgetc(); | 12161 | return __pgetc(); |
12161 | } | 12162 | } |
12163 | #endif | ||
12162 | 12164 | ||
12163 | if (g_parsefile->buf == NULL) { | 12165 | if (g_parsefile->buf == NULL) { |
12164 | pgetc_debug("preadbuffer PEOF1"); | 12166 | pgetc_debug("preadbuffer PEOF1"); |
@@ -12274,8 +12276,15 @@ static int __pgetc(void) | |||
12274 | 12276 | ||
12275 | if (--g_parsefile->left_in_line >= 0) | 12277 | if (--g_parsefile->left_in_line >= 0) |
12276 | c = (unsigned char)*g_parsefile->next_to_pgetc++; | 12278 | c = (unsigned char)*g_parsefile->next_to_pgetc++; |
12277 | else | 12279 | else { |
12280 | #if ENABLE_PLATFORM_MINGW32 | ||
12281 | if (unlikely(g_parsefile->strpush)) { | ||
12282 | popstring(); | ||
12283 | return __pgetc(); | ||
12284 | } | ||
12285 | #endif | ||
12278 | c = preadbuffer(); | 12286 | c = preadbuffer(); |
12287 | } | ||
12279 | 12288 | ||
12280 | g_parsefile->lastc[1] = g_parsefile->lastc[0]; | 12289 | g_parsefile->lastc[1] = g_parsefile->lastc[0]; |
12281 | g_parsefile->lastc[0] = c; | 12290 | g_parsefile->lastc[0] = c; |