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.li...@googlemail.com>
Suggested-by: Harald van Dijk <har...@gigawatt.nl>
Signed-off-by: Herbert Xu <herb...@gondor.apana.org.au>

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 <herb...@gondor.apana.org.au>
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 majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to