Re: dash bug: double-quoted "\" breaks glob protection for next char

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Feb 21, 2018 at 11:47:58PM +0100, Harald van Dijk wrote:
> On 2/21/18 2:50 PM, Denys Vlasenko wrote:
> >I propose replacing this:
> 
> Agreed, that looks better. Thanks!

Good work guys.  However, could you check to see if this patch
works too? It passes all my tests so far.

---8<---
The commit "[EXPAND] Move parse-time quote flag detection to
run-time" broke the following case:

	case \\zzzz in "\*") echo bad;; esac

The reason is that the naked backslash gets attached to the newly
added backslash added for the special character "*" in preglob,
IOW you end up with "\\*" instead of just "\*" as it should be.

The reason the naked backslash exists in the first place is because
otherwise we cannot tell the difference between "\[" and "\\[" when
it occurs in a quoted pattern context such as "${var#\[}"

This patch restores the original behaviour for the buggy case
while keeping the naked backslash for the quoted pattern case.

Fixes: 7cfd8be0dc83 ("[EXPAND] Move parse-time quote flag...")
Reported-by: Denys Vlasenko <vda.linux@xxxxxxxxxxxxxx>
Suggested-by: Harald van Dijk <harald@xxxxxxxxxxx>
Signed-off-by: Herbert Xu <herbert@xxxxxxxxxxxxxxxxxxx>

diff --git a/src/Makefile.am b/src/Makefile.am
index 139355e..b5bff06 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -60,7 +60,7 @@ init.c: mkinit $(dash_CFILES)
 nodes.c nodes.h: mknodes nodetypes nodes.c.pat
 	./$^
 
-syntax.c syntax.h: mksyntax
+syntax.c syntax.h: mksyntax parser.h
 	./$^
 
 signames.c: mksignames
diff --git a/src/expand.c b/src/expand.c
index 2a50830..aeffe82 100644
--- a/src/expand.c
+++ b/src/expand.c
@@ -244,6 +244,7 @@ argstr(char *p, int flag)
 		CTLVAR,
 		CTLBACKQ,
 		CTLENDARI,
+		CTLBACK,
 		0
 	};
 	const char *reject = spclchars;
@@ -330,6 +331,7 @@ addquote:
 				startloc++;
 			}
 			break;
+		case CTLBACK:
 		case CTLESC:
 			startloc++;
 			length++;
@@ -340,7 +342,7 @@ addquote:
 			 * backslash.
 			 */
 			if (((flag | inquotes) & (EXP_QPAT | EXP_QUOTED)) ==
-			    EXP_QPAT && *p != '\\')
+			    EXP_QPAT && (*p != '\\' || c == CTLBACK))
 				break;
 
 			goto addquote;
@@ -373,6 +375,7 @@ exptilde(char *startp, char *p, int flag)
 
 	while ((c = *++p) != '\0') {
 		switch(c) {
+		case CTLBACK:
 		case CTLESC:
 			return (startp);
 		case CTLQUOTEMARK:
@@ -594,7 +597,7 @@ scanleft(
 		*loc2 = c;
 		if (match)
 			return loc;
-		if (quotes && *loc == (char)CTLESC)
+		if (quotes && (*loc == (char)CTLESC || *loc == (char)CTLBACK))
 			loc++;
 		loc++;
 		loc2++;
@@ -821,7 +824,8 @@ end:
 	if (subtype != VSNORMAL) {	/* skip to end of alternative */
 		int nesting = 1;
 		for (;;) {
-			if ((c = (signed char)*p++) == CTLESC)
+			if ((c = (signed char)*p++) == CTLESC ||
+			    c == CTLBACK)
 				p++;
 			else if (c == CTLBACKQ) {
 				if (varlen >= 0)
@@ -1052,7 +1056,7 @@ ifsbreakup(char *string, int maxargs, struct arglist *arglist)
 
 				q = p;
 				c = *p++;
-				if (c == (char)CTLESC)
+				if (c == (char)CTLESC || c == (char)CTLBACK)
 					c = *p++;
 
 				isifs = strchr(ifs, c);
@@ -1684,7 +1688,7 @@ _rmescapes(char *str, int flag)
 			notescaped = globbing;
 			continue;
 		}
-		if (*p == (char)CTLESC) {
+		if (*p == (char)CTLESC || *p == (char)CTLBACK) {
 			p++;
 			if (notescaped)
 				*q++ = '\\';
diff --git a/src/jobs.c b/src/jobs.c
index 4f02e38..a3aef20 100644
--- a/src/jobs.c
+++ b/src/jobs.c
@@ -1386,6 +1386,7 @@ cmdputs(const char *s)
 	while ((c = *p++) != 0) {
 		str = 0;
 		switch (c) {
+		case CTLBACK:
 		case CTLESC:
 			c = *p++;
 			break;
diff --git a/src/mystring.c b/src/mystring.c
index 0106bd2..2573d1f 100644
--- a/src/mystring.c
+++ b/src/mystring.c
@@ -62,7 +62,7 @@ const char spcstr[] = " ";
 const char snlfmt[] = "%s\n";
 const char dolatstr[] = { CTLQUOTEMARK, CTLVAR, VSNORMAL, '@', '=',
 			  CTLQUOTEMARK, '\0' };
-const char qchars[] = { CTLESC, CTLQUOTEMARK, 0 };
+const char qchars[] = { CTLESC, CTLQUOTEMARK, CTLBACK, 0 };
 const char illnum[] = "Illegal number: %s";
 const char homestr[] = "HOME";
 
diff --git a/src/parser.c b/src/parser.c
index 382658e..22fc84a 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -930,7 +930,7 @@ readtoken1(int firstc, char const *syntax, char *eofmark, int striptabs)
 			case CBACK:
 				c = pgetc2();
 				if (c == PEOF) {
-					USTPUTC(CTLESC, out);
+					USTPUTC(CTLBACK, out);
 					USTPUTC('\\', out);
 					pungetc();
 				} else if (c == '\n') {
@@ -944,6 +944,7 @@ readtoken1(int firstc, char const *syntax, char *eofmark, int striptabs)
 							eofmark != NULL
 						)
 					) {
+						USTPUTC(CTLBACK, out);
 						USTPUTC('\\', out);
 					}
 					USTPUTC(CTLESC, out);
diff --git a/src/parser.h b/src/parser.h
index 2875cce..54c02eb 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -45,7 +45,8 @@
 #define	CTLARI -122		/* arithmetic expression */
 #define	CTLENDARI -121
 #define	CTLQUOTEMARK -120
-#define	CTL_LAST -120		/* last 'special' character */
+#define	CTLBACK -119
+#define	CTL_LAST -119		/* last 'special' character */
 
 /* variable substitution byte (follows CTLVAR) */
 #define VSTYPE	0x0f		/* type of variable substitution */
diff --git a/src/show.c b/src/show.c
index 4a049e9..ed840aa 100644
--- a/src/show.c
+++ b/src/show.c
@@ -166,6 +166,7 @@ sharg(union node *arg, FILE *fp)
 	bqlist = arg->narg.backquote;
 	for (p = arg->narg.text ; *p ; p++) {
 		switch ((signed char)*p) {
+		case CTLBACK:
 		case CTLESC:
 			putc(*++p, fp);
 			break;
@@ -311,6 +312,7 @@ trstring(char *s)
 		case '\r':  c = 'r';  goto backslash;
 		case '"':  c = '"';  goto backslash;
 		case '\\':  c = '\\';  goto backslash;
+		case CTLBACK:
 		case CTLESC:  c = 'e';  goto backslash;
 		case CTLVAR:  c = 'v';  goto backslash;
 		case CTLBACKQ:  c = 'q';  goto backslash;
-- 
Email: Herbert Xu <herbert@xxxxxxxxxxxxxxxxxxx>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
--
To unsubscribe from this list: send the line "unsubscribe dash" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [LARTC]     [Bugtraq]     [Yosemite Forum]     [Photo]

  Powered by Linux