[PATCH 2/2 1.24] ash: backport fix for here document issues

Ron Yorston rmy at pobox.com
Fri Mar 18 11:32:37 UTC 2016


Backport the following from master:

   <9121510> ash: add test for issue with here document
   <6bd2fab> Revert "ash: fix a SEGV case in an invalid heredoc"
   <c0e0076> ash: simplify EOF/newline handling in list parser

Reported-by: Natanael Copa <ncopa at alpinelinux.org>
Signed-off-by: Ron Yorston <rmy at pobox.com>
---
 shell/ash.c                               | 72 +++++++++++++------------------
 shell/ash_test/ash-heredoc/heredoc2.right |  2 +
 shell/ash_test/ash-heredoc/heredoc2.tests |  7 +++
 3 files changed, 39 insertions(+), 42 deletions(-)
 create mode 100644 shell/ash_test/ash-heredoc/heredoc2.right
 create mode 100755 shell/ash_test/ash-heredoc/heredoc2.tests

diff --git a/shell/ash.c b/shell/ash.c
index 256e933..753eacf 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -10516,7 +10516,7 @@ static union node *andor(void);
 static union node *pipeline(void);
 static union node *parse_command(void);
 static void parseheredoc(void);
-static char nexttoken_ends_list(void);
+static int peektoken(void);
 static int readtoken(void);
 
 static union node *
@@ -10525,11 +10525,27 @@ list(int nlflag)
 	union node *n1, *n2, *n3;
 	int tok;
 
-	checkkwd = CHKNL | CHKKWD | CHKALIAS;
-	if (nlflag == 2 && nexttoken_ends_list())
-		return NULL;
 	n1 = NULL;
 	for (;;) {
+		switch (peektoken()) {
+		case TNL:
+			if (!(nlflag & 1))
+				break;
+			parseheredoc();
+			return n1;
+
+		case TEOF:
+			if (!n1 && (nlflag & 1))
+				n1 = NODE_EOF;
+			parseheredoc();
+			return n1;
+		}
+
+		checkkwd = CHKNL | CHKKWD | CHKALIAS;
+		if (nlflag == 2 && tokname_array[peektoken()][0])
+			return n1;
+		nlflag |= 2;
+
 		n2 = andor();
 		tok = readtoken();
 		if (tok == TBACKGND) {
@@ -10555,37 +10571,15 @@ list(int nlflag)
 			n1 = n3;
 		}
 		switch (tok) {
+		case TNL:
+		case TEOF:
+			tokpushback = 1;
+			/* fall through */
 		case TBACKGND:
 		case TSEMI:
-			tok = readtoken();
-			/* fall through */
-		case TNL:
-			if (tok == TNL) {
-				parseheredoc();
-				if (nlflag == 1)
-					return n1;
-			} else {
-				tokpushback = 1;
-			}
-			checkkwd = CHKNL | CHKKWD | CHKALIAS;
-			if (nexttoken_ends_list()) {
-				/* Testcase: "<<EOF; then <W".
-				 * It used to segfault w/o this check:
-				 */
-				if (heredoclist) {
-					raise_error_unexpected_syntax(-1);
-				}
-				return n1;
-			}
 			break;
-		case TEOF:
-			if (heredoclist)
-				parseheredoc();
-			else
-				pungetc();              /* push back EOF on input */
-			return n1;
 		default:
-			if (nlflag == 1)
+			if ((nlflag & 1))
 				raise_error_unexpected_syntax(-1);
 			tokpushback = 1;
 			return n1;
@@ -11955,14 +11949,14 @@ readtoken(void)
 	return t;
 }
 
-static char
-nexttoken_ends_list(void)
+static int
+peektoken(void)
 {
 	int t;
 
 	t = readtoken();
 	tokpushback = 1;
-	return tokname_array[t][0];
+	return t;
 }
 
 /*
@@ -11972,18 +11966,12 @@ nexttoken_ends_list(void)
 static union node *
 parsecmd(int interact)
 {
-	int t;
-
 	tokpushback = 0;
+	checkkwd = 0;
+	heredoclist = 0;
 	doprompt = interact;
 	setprompt_if(doprompt, doprompt);
 	needprompt = 0;
-	t = readtoken();
-	if (t == TEOF)
-		return NODE_EOF;
-	if (t == TNL)
-		return NULL;
-	tokpushback = 1;
 	return list(1);
 }
 
diff --git a/shell/ash_test/ash-heredoc/heredoc2.right b/shell/ash_test/ash-heredoc/heredoc2.right
new file mode 100644
index 0000000..a486f1a
--- /dev/null
+++ b/shell/ash_test/ash-heredoc/heredoc2.right
@@ -0,0 +1,2 @@
+bar
+bar
diff --git a/shell/ash_test/ash-heredoc/heredoc2.tests b/shell/ash_test/ash-heredoc/heredoc2.tests
new file mode 100755
index 0000000..6d9ccb6
--- /dev/null
+++ b/shell/ash_test/ash-heredoc/heredoc2.tests
@@ -0,0 +1,7 @@
+foo () {
+cat <<EOF && { echo "$1" ; }
+$1
+EOF
+}
+
+foo "bar"
-- 
2.5.0



More information about the busybox mailing list