[git commit] ash: parser: Fix handling of empty aliases

Denys Vlasenko vda.linux at googlemail.com
Tue Sep 7 22:39:16 UTC 2021


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

Upstream commit:

    Date: Tue, 28 Apr 2020 01:15:26 +1000
    parser: Fix handling of empty aliases

    Dash was incorrectly handling empty aliases. When attempting to use an
    empty alias with nothing else, I'm (incorrectly) prompted for more
    input:

    ```
    $ alias empty=''
    $ empty
    >
    ```

    Other shells (e.g., bash, yash) correctly handle the lone, empty alias as an
    empty command:

    ```
    $ alias empty=''
    $ empty
    $
    ```

    The problem here is that we incorrectly enter the loop eating TNLs
    in readtoken().  This patch fixes it by setting checkkwd correctly.

function                                             old     new   delta
list                                                 351     355      +4

Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 shell/ash.c | 36 +++++++++++++++---------------------
 1 file changed, 15 insertions(+), 21 deletions(-)

diff --git a/shell/ash.c b/shell/ash.c
index 35dbb2f28..5a18ff1a1 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -11755,27 +11755,28 @@ static union node *andor(void);
 static union node *pipeline(void);
 static union node *parse_command(void);
 static void parseheredoc(void);
-static int peektoken(void);
 static int readtoken(void);
 
 static union node *
 list(int nlflag)
 {
+	int chknl = nlflag & 1 ? 0 : CHKNL;
 	union node *n1, *n2, *n3;
 	int tok;
 
 	n1 = NULL;
 	for (;;) {
-		switch (readtoken()) {
+		checkkwd = chknl | CHKKWD | CHKALIAS;
+		tok = readtoken();
+		switch (tok) {
 		case TNL:
-			if (!(nlflag & 1))
-				break;
 			parseheredoc();
 			return n1;
 
 		case TEOF:
-			if (!n1 && (nlflag & 1))
+			if (!n1 && !chknl)
 				n1 = NODE_EOF;
+ out_eof:
 			parseheredoc();
 			tokpushback++;
 			lasttoken = TEOF;
@@ -11783,8 +11784,7 @@ list(int nlflag)
 		}
 
 		tokpushback++;
-		checkkwd = CHKNL | CHKKWD | CHKALIAS;
-		if (nlflag == 2 && ((1 << peektoken()) & tokendlist))
+		if (nlflag == 2 && ((1 << tok) & tokendlist))
 			return n1;
 		nlflag |= 2;
 
@@ -11813,15 +11813,16 @@ list(int nlflag)
 			n1 = n3;
 		}
 		switch (tok) {
-		case TNL:
 		case TEOF:
+			goto out_eof;
+		case TNL:
 			tokpushback = 1;
 			/* fall through */
 		case TBACKGND:
 		case TSEMI:
 			break;
 		default:
-			if ((nlflag & 1))
+			if (!chknl)
 				raise_error_unexpected_syntax(-1);
 			tokpushback = 1;
 			return n1;
@@ -11995,8 +11996,9 @@ simplecmd(void)
 		switch (t) {
 #if BASH_FUNCTION
 		case TFUNCTION:
-			if (peektoken() != TWORD)
+			if (readtoken() != TWORD)
 				raise_error_unexpected_syntax(TWORD);
+			tokpushback = 1;
 			function_flag = 1;
 			break;
 #endif
@@ -12033,7 +12035,9 @@ simplecmd(void)
 #if BASH_FUNCTION
 			if (function_flag) {
 				checkkwd = CHKNL | CHKKWD;
-				switch (peektoken()) {
+				t = readtoken();
+				tokpushback = 1;
+				switch (t) {
 				case TBEGIN:
 				case TIF:
 				case TCASE:
@@ -13306,16 +13310,6 @@ readtoken(void)
 	return t;
 }
 
-static int
-peektoken(void)
-{
-	int t;
-
-	t = readtoken();
-	tokpushback = 1;
-	return t;
-}
-
 /*
  * Read and parse a command.  Returns NODE_EOF on end of file.
  * (NULL is a valid parse tree indicating a blank line.)


More information about the busybox-cvs mailing list