summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog7
-rw-r--r--Src/hist.c18
2 files changed, 21 insertions, 4 deletions
diff --git a/ChangeLog b/ChangeLog
index 0d9395ced..745ce27dd 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2009-02-25  Peter Stephenson  <pws@csr.com>
+
+	* Src/hist.c: 26602: history substitution buffer could overflow
+	with no test.
+
 2009-02-25  Clint Adams  <clint@zsh.org>
 
 	* Mikael Magnusson: 26596: Completion/Unix/Command/_git: new git
@@ -11232,5 +11237,5 @@
 
 *****************************************************
 * This is used by the shell to define $ZSH_PATCHLEVEL
-* $Revision: 1.4578 $                         
+* $Revision: 1.4579 $                         
 *****************************************************
diff --git a/Src/hist.c b/Src/hist.c
index 838c06993..dbe1d98a4 100644
--- a/Src/hist.c
+++ b/Src/hist.c
@@ -394,9 +394,10 @@ histsubchar(int c)
     zlong ev;
     static int marg = -1;
     static zlong mev = -1;
-    char buf[256], *ptr;
+    char *buf, *ptr;
     char *sline;
     Histent ehist;
+    size_t buflen;
 
     /* look, no goto's */
     if (isfirstch && c == hatchar) {
@@ -445,7 +446,7 @@ histsubchar(int c)
 	    return bangchar;
 	}
 	cflag = 0;
-	ptr = buf;
+	ptr = buf = zhalloc(buflen = 265);
 
 	/* get event number */
 
@@ -455,8 +456,14 @@ histsubchar(int c)
 		c = ingetc();
 		if (c == '?' || c == '\n' || lexstop)
 		    break;
-		else
+		else {
 		    *ptr++ = c;
+		    if (ptr == buf + buflen) {
+			buf = hrealloc(buf, buflen, 2 * buflen);
+			ptr = buf + buflen;
+			buflen *= 2;
+		    }
+		}
 	    }
 	    if (c != '\n' && !lexstop)
 		c = ingetc();
@@ -484,6 +491,11 @@ histsubchar(int c)
 			break;
 		}
 		*ptr++ = c;
+		if (ptr == buf + buflen) {
+		    buf = hrealloc(buf, buflen, 2 * buflen);
+		    ptr = buf + buflen;
+		    buflen *= 2;
+		}
 		if (c == '#' || c == bangchar) {
 		    c = ingetc();
 		    break;