aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2024-05-02 13:08:14 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2024-07-10 07:11:23 +0200
commitba0f94458bf992bb1f34c75e36960811d77b5f55 (patch)
tree7e84333f9253f37a9d5c63fbbcdd89adb9f4be87
parent0a88a7ae3bb350d72712628078cf79517f627e99 (diff)
downloadbusybox-w32-ba0f94458bf992bb1f34c75e36960811d77b5f55.tar.gz
busybox-w32-ba0f94458bf992bb1f34c75e36960811d77b5f55.tar.bz2
busybox-w32-ba0f94458bf992bb1f34c75e36960811d77b5f55.zip
ash: fix parsing of alias expansion + bash features
An alias expansion immediately followed by '<' and a newline is parsed incorrectly: ~ $ alias x='echo yo' ~ $ x< yo ~ $ sh: syntax error: unexpected newline The echo is executed and an error is printed on the next command submission. In dash the echo isn't executed and the error is reported immediately: $ alias x='echo yo' $ x< dash: 3: Syntax error: newline unexpected $ The difference between BusyBox and dash is that BusyBox supports bash-style process substitution and output redirection. These require checking for '<(', '>(' and '&>' in readtoken1(). In the case above, 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 next input is obtained by reading the expansion of the alias. Once this string is exhausted the next call to __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(). function old new delta pgetc 28 589 +561 __pgetc 607 - -607 ------------------------------------------------------------------------------ (add/remove: 0/1 grow/shrink: 1/0 up/down: 561/-607) Total: -46 bytes Signed-off-by: Ron Yorston <rmy@pobox.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--shell/ash.c12
1 files changed, 6 insertions, 6 deletions
diff --git a/shell/ash.c b/shell/ash.c
index 4ca4c6c56..5df0ba625 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -10934,11 +10934,6 @@ preadbuffer(void)
10934 char *q; 10934 char *q;
10935 int more; 10935 int more;
10936 10936
10937 if (unlikely(g_parsefile->strpush)) {
10938 popstring();
10939 return __pgetc();
10940 }
10941
10942 if (g_parsefile->buf == NULL) { 10937 if (g_parsefile->buf == NULL) {
10943 pgetc_debug("preadbuffer PEOF1"); 10938 pgetc_debug("preadbuffer PEOF1");
10944 return PEOF; 10939 return PEOF;
@@ -11053,8 +11048,13 @@ static int __pgetc(void)
11053 11048
11054 if (--g_parsefile->left_in_line >= 0) 11049 if (--g_parsefile->left_in_line >= 0)
11055 c = (unsigned char)*g_parsefile->next_to_pgetc++; 11050 c = (unsigned char)*g_parsefile->next_to_pgetc++;
11056 else 11051 else {
11052 if (unlikely(g_parsefile->strpush)) {
11053 popstring();
11054 return __pgetc();
11055 }
11057 c = preadbuffer(); 11056 c = preadbuffer();
11057 }
11058 11058
11059 g_parsefile->lastc[1] = g_parsefile->lastc[0]; 11059 g_parsefile->lastc[1] = g_parsefile->lastc[0];
11060 g_parsefile->lastc[0] = c; 11060 g_parsefile->lastc[0] = c;