about summary refs log tree commit diff
path: root/Src
diff options
context:
space:
mode:
authorPeter Stephenson <p.w.stephenson@ntlworld.com>2015-01-18 22:38:57 +0000
committerPeter Stephenson <p.w.stephenson@ntlworld.com>2015-01-18 22:38:57 +0000
commitc6c9f5daf2e196e6ab7346dfbf5f5166a1d87f0c (patch)
treede064fa6ba629549d42868b7016dd3c28bfb0e34 /Src
parent6856ab39e32e0cba96fcdae004878938125890ac (diff)
downloadzsh-c6c9f5daf2e196e6ab7346dfbf5f5166a1d87f0c.tar.gz
zsh-c6c9f5daf2e196e6ab7346dfbf5f5166a1d87f0c.tar.xz
zsh-c6c9f5daf2e196e6ab7346dfbf5f5166a1d87f0c.zip
34322: bug with interface to parsestr() etc.
Was showing up in places like ${(e)...} where command substitution
could reallocate the token string, but actually there was never any
guarantee that the lexer wouldn't do that, so this was always
a bit iffy.
Diffstat (limited to 'Src')
-rw-r--r--Src/Zle/compctl.c4
-rw-r--r--Src/Zle/compresult.c3
-rw-r--r--Src/exec.c9
-rw-r--r--Src/init.c11
-rw-r--r--Src/lex.c30
-rw-r--r--Src/params.c3
-rw-r--r--Src/prompt.c2
-rw-r--r--Src/subst.c8
-rw-r--r--Src/utils.c2
9 files changed, 46 insertions, 26 deletions
diff --git a/Src/Zle/compctl.c b/Src/Zle/compctl.c
index 43dd4e2a9..189582d22 100644
--- a/Src/Zle/compctl.c
+++ b/Src/Zle/compctl.c
@@ -3853,7 +3853,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
 	    yaptr = get_user_var(uv);
 	if ((tt = cc->explain)) {
 	    tt = dupstring(tt);
-	    if ((cc->mask & CC_EXPANDEXPL) && !parsestr(tt)) {
+	    if ((cc->mask & CC_EXPANDEXPL) && !parsestr(&tt)) {
 		singsub(&tt);
 		untokenize(tt);
 	    }
@@ -3873,7 +3873,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
 	}
     } else if ((tt = cc->explain)) {
 	tt = dupstring(tt);
-	if ((cc->mask & CC_EXPANDEXPL) && !parsestr(tt)) {
+	if ((cc->mask & CC_EXPANDEXPL) && !parsestr(&tt)) {
 	    singsub(&tt);
 	    untokenize(tt);
 	}
diff --git a/Src/Zle/compresult.c b/Src/Zle/compresult.c
index dbef7f841..9f383f4b8 100644
--- a/Src/Zle/compresult.c
+++ b/Src/Zle/compresult.c
@@ -1090,7 +1090,8 @@ do_single(Cmatch m)
 		    }
 		    if (tryit) {
 			noerrs = 1;
-			parsestr(p);
+			p = dupstring(p);
+			parsestr(&p);
 			singsub(&p);
 			errflag &= ~ERRFLAG_ERROR;
 			noerrs = ne;
diff --git a/Src/exec.c b/Src/exec.c
index 7b6495113..f42fb2b9b 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -3772,19 +3772,20 @@ gethere(char **strp, int typ)
 	*bptr++ = '\n';
     }
     *t = '\0';
+    s = buf;
+    buf = dupstring(buf);
+    zfree(s, bsiz);
     if (!qt) {
 	int ef = errflag;
 
-	parsestr(buf);
+	parsestr(&buf);
 
 	if (!errflag) {
 	    /* Retain any user interrupt error */
 	    errflag = ef | (errflag & ERRFLAG_INT);
 	}
     }
-    s = dupstring(buf);
-    zfree(buf, bsiz);
-    return s;
+    return buf;
 }
 
 /* open here string fd */
diff --git a/Src/init.c b/Src/init.c
index e7d86feac..3e41fb9dd 100644
--- a/Src/init.c
+++ b/Src/init.c
@@ -1197,10 +1197,13 @@ run_init_scripts(void)
 	    if (islogin)
 		sourcehome(".profile");
 	    noerrs = 2;
-	    if (s && !parsestr(s)) {
-		singsub(&s);
-		noerrs = 0;
-		source(s);
+	    if (s) {
+		s = dupstring(s);
+		if (!parsestr(&s)) {
+		    singsub(&s);
+		    noerrs = 0;
+		    source(s);
+		}
 	    }
 	    noerrs = 0;
 	} else
diff --git a/Src/lex.c b/Src/lex.c
index e4dfdfaca..433c27fbb 100644
--- a/Src/lex.c
+++ b/Src/lex.c
@@ -1503,17 +1503,27 @@ dquote_parse(char endchar, int sub)
     return err;
 }
 
-/* Tokenize a string given in s. Parsing is done as in double *
- * quotes.  This is usually called before singsub().          */
+/*
+ * Tokenize a string given in s. Parsing is done as in double
+ * quotes.  This is usually called before singsub().
+ *
+ * parsestr() is noisier, reporting an error if the parse failed.
+ *
+ * On entry, *s must point to a string allocated from the stack of
+ * exactly the right length, i.e. strlen(*s) + 1, as the string
+ * is used as the lexical token string whose memory management
+ * demands this.  Usually the input string will therefore be
+ * the result of an immediately preceding dupstring().
+ */
 
 /**/
 mod_export int
-parsestr(char *s)
+parsestr(char **s)
 {
     int err;
 
     if ((err = parsestrnoerr(s))) {
-	untokenize(s);
+	untokenize(*s);
 	if (err > 32 && err < 127)
 	    zerr("parse error near `%c'", err);
 	else
@@ -1524,18 +1534,20 @@ parsestr(char *s)
 
 /**/
 mod_export int
-parsestrnoerr(char *s)
+parsestrnoerr(char **s)
 {
-    int l = strlen(s), err;
+    int l = strlen(*s), err;
 
     zcontext_save();
-    untokenize(s);
-    inpush(dupstring(s), 0, NULL);
+    untokenize(*s);
+    inpush(dupstring(*s), 0, NULL);
     strinbeg(0);
     lexbuf.len = 0;
-    lexbuf.ptr = tokstr = s;
+    lexbuf.ptr = tokstr = *s;
     lexbuf.siz = l + 1;
     err = dquote_parse('\0', 1);
+    if (tokstr)
+	*s = tokstr;
     *lexbuf.ptr = '\0';
     strinend();
     inpop();
diff --git a/Src/params.c b/Src/params.c
index b8e0c429b..64c78bd63 100644
--- a/Src/params.c
+++ b/Src/params.c
@@ -1260,7 +1260,8 @@ getarg(char **str, int *inv, Value v, int a2, zlong *w,
     if (ishash && (keymatch || !rev))
 	remnulargs(s);
     if (needtok) {
-	if (parsestr(s))
+	s = dupstring(s);
+	if (parsestr(&s))
 	    return 0;
 	singsub(&s);
     } else if (rev)
diff --git a/Src/prompt.c b/Src/prompt.c
index 3552575f3..ffc1d0df2 100644
--- a/Src/prompt.c
+++ b/Src/prompt.c
@@ -183,7 +183,7 @@ promptexpand(char *s, int ns, char *rs, char *Rs, unsigned int *txtchangep)
 	int oldval = lastval;
 
 	s = dupstring(s);
-	if (!parsestr(s))
+	if (!parsestr(&s))
 	    singsub(&s);
 	/*
 	 * We don't need the special Nularg hack here and we're
diff --git a/Src/subst.c b/Src/subst.c
index 5f993d6fd..a2bb6483a 100644
--- a/Src/subst.c
+++ b/Src/subst.c
@@ -1306,7 +1306,7 @@ get_intarg(char **s, int *delmatchp)
     p = dupstring(*s + arglen);
     *s = t + arglen;
     *t = sav;
-    if (parsestr(p))
+    if (parsestr(&p))
 	return -1;
     singsub(&p);
     if (errflag)
@@ -1329,7 +1329,8 @@ subst_parse_str(char **sp, int single, int err)
 
     *sp = s = dupstring(*sp);
 
-    if (!(err ? parsestr(s) : parsestrnoerr(s))) {
+    if (!(err ? parsestr(&s) : parsestrnoerr(&s))) {
+	*sp = s;
 	if (!single) {
             int qt = 0;
 
@@ -1439,7 +1440,8 @@ check_colon_subscript(char *str, char **endp)
     }
     sav = **endp;
     **endp = '\0';
-    if (parsestr(str = dupstring(str)))
+    str = dupstring(str);
+    if (parsestr(&str))
 	return NULL;
     singsub(&str);
     remnulargs(str);
diff --git a/Src/utils.c b/Src/utils.c
index f8d239458..4561b5e9a 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -1515,7 +1515,7 @@ checkmailpath(char **s)
 		    setunderscore(*s);
 
 		    u = dupstring(u);
-		    if (! parsestr(u)) {
+		    if (!parsestr(&u)) {
 			singsub(&u);
 			zputs(u, shout);
 			fputc('\n', shout);