summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--Src/Zle/zle_params.c43
2 files changed, 29 insertions, 19 deletions
diff --git a/ChangeLog b/ChangeLog
index 2119589ef..d4a63dd95 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
 2003-03-24  Peter Stephenson  <pws@csr.com>
 
+	* 18378: Src/Zle/params.c: memory management for $killring
+	was pathetic; setting $killring was in completely the wrong
+	order; getting $killring when empty didn't return the
+	default length.
+
 	* 18376: zshconfig.ac, Src/system.h, Src/utils.c: use of
 	wide characters needs some more header munging; also silence
 	a couple of related gcc warnings.
diff --git a/Src/Zle/zle_params.c b/Src/Zle/zle_params.c
index f14785f01..45df2fa8e 100644
--- a/Src/Zle/zle_params.c
+++ b/Src/Zle/zle_params.c
@@ -365,8 +365,8 @@ set_cutbuffer(Param pm, char *x)
     if (x) {
 	unmetafy(x, &cutbuf.len);
 	cutbuf.buf = zalloc(cutbuf.len);
-	strcpy((char *)cutbuf.buf, x);
-	zsfree(x);
+	memcpy((char *)cutbuf.buf, x, cutbuf.len);
+	free(x);
     } else {
 	cutbuf.buf = NULL;
 	cutbuf.len = 0;
@@ -398,7 +398,7 @@ set_killring(Param pm, char **x)
     if (kring) {
 	for (kptr = kring, kcnt = 0; kcnt < kringsize; kcnt++, kptr++)
 	    if (kptr->buf)
-		free(kptr->buf);
+		zfree(kptr->buf, kptr->len);
 	zfree(kring, kringsize * sizeof(struct cutbuffer));
 	kring = NULL;
 	kringsize = kringnum = 0;
@@ -408,23 +408,23 @@ set_killring(Param pm, char **x)
 	 * Insert the elements into the kill ring.
 	 * Regardless of the old order, we number it with the current
 	 * entry first.
+	 *
+	 * Be careful to add elements by looping backwards; this
+	 * fits in with how we cycle the ring.
 	 */
+	int kpos = 0;
 	kringsize = arrlen(x);
 	kring = (Cutbuffer)zcalloc(kringsize * sizeof(struct cutbuffer));
-	for (p = x, kptr = kring; *p; p++, kptr++) {
+	for (p = x; *p; p++) {
 	    int len = strlen(*p);
-	    kptr->buf = (char *)zalloc(len);
-	    strcpy(kptr->buf, *p);
-	    unmetafy(kptr->buf, &kptr->len);
-	    if (len != kptr->len) {
-		/* Might as well have the lengths consistent. */
-		char *p2 = zalloc(kptr->len);
-		memcpy(p2, kptr->buf, kptr->len);
-		zfree(kptr->buf, len);
-		kptr->buf = p2;
-	    }
+	    kptr = kring + kpos;
+	    unmetafy(*p, &kptr->len);
+	    kptr->buf = (char *)zalloc(kptr->len);
+	    memcpy(kptr->buf, *p, kptr->len);
+	    zfree(*p, len+1);
+	    kpos = (kpos + kringsize -1 ) % kringsize;
 	}
-	freearray(x);
+	free(x);
     }
 }
 
@@ -441,10 +441,9 @@ get_killring(Param pm)
     char **ret, **p;
 
     /* Supposed to work even if kring is NULL */
-    for (kpos = kringnum, kcnt = 0; kcnt < kringsize; kcnt++) {
-	if (!kring[kpos].buf)
-	    break;
-	kpos = (kpos + kringsize - 1) % kringsize;
+    if (!kring) {
+	kringsize = KRINGCTDEF;
+	kring = (Cutbuffer)zcalloc(kringsize * sizeof(struct cutbuffer));
     }
 
     p = ret = (char **)zhalloc((kringsize+1) * sizeof(char *));
@@ -452,7 +451,13 @@ get_killring(Param pm)
     for (kpos = kringnum, kcnt = 0; kcnt < kringsize; kcnt++) {
 	Cutbuffer kptr = kring + kpos;
 	if (kptr->buf)
+	{
+	    /*
+	     * Need to use HEAPDUP to make sure there's room for the
+	     * terminating NULL.
+	     */
 	    *p++ = metafy((char *)kptr->buf, kptr->len, META_HEAPDUP);
+	}
 	else
 	    *p++ = dupstring("");
 	kpos = (kpos + kringsize - 1) % kringsize;