aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2024-04-30 09:08:00 +0100
committerRon Yorston <rmy@pobox.com>2024-04-30 09:08:00 +0100
commit6b164f335c548bcebacd8bf984fd5c34ede46891 (patch)
tree7f8cabff188d78874d213a8693c44487707de6d8
parent818cf3b0c7dae0b06d0103998f1eef14964b63c7 (diff)
downloadbusybox-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.c11
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;