[git commit] ash: fix parsing of alias expansion + bash features

Denys Vlasenko vda.linux at googlemail.com
Wed Jul 10 05:11:23 UTC 2024


commit: https://git.busybox.net/busybox/commit/?id=ba0f94458bf992bb1f34c75e36960811d77b5f55
branch: https://git.busybox.net/busybox/commit/?id=refs/heads/master

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 at pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 shell/ash.c | 12 ++++++------
 1 file 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)
 	char *q;
 	int more;
 
-	if (unlikely(g_parsefile->strpush)) {
-		popstring();
-		return __pgetc();
-	}
-
 	if (g_parsefile->buf == NULL) {
 		pgetc_debug("preadbuffer PEOF1");
 		return PEOF;
@@ -11053,8 +11048,13 @@ static int __pgetc(void)
 
 	if (--g_parsefile->left_in_line >= 0)
 		c = (unsigned char)*g_parsefile->next_to_pgetc++;
-	else
+	else {
+		if (unlikely(g_parsefile->strpush)) {
+			popstring();
+			return __pgetc();
+		}
 		c = preadbuffer();
+	}
 
 	g_parsefile->lastc[1] = g_parsefile->lastc[0];
 	g_parsefile->lastc[0] = c;


More information about the busybox-cvs mailing list