about summary refs log tree commit diff
path: root/Src/lex.c
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/lex.c
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/lex.c')
-rw-r--r--Src/lex.c30
1 files changed, 21 insertions, 9 deletions
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();