Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

[PATCH] Re: dirstack history: loving zsh, crashing zsh...



On Saturday 04 March 2006 11:04, Andrey Borzenkov wrote:
> [moved to workers]
>
> On Thursday 02 March 2006 20:52, Francisco Borges wrote:
> > % typeset -U dirstack
> >
> > and the shell crashed.
>
> The problem is rather non-trivial. dirsgetfn returns array built on-the-fly
> in heap, while typeset -U calls uniqarray() that tries to zfree array
> elements. There are at least two problems here:
>
> - typeset -U is not prepared to deal with "pseudo" parameters at all. It
> assumes a->getfn() returns pointer to real parameter value. So it would
> have not worked for dirstack anyway
>
> - I was about to change typeset -U to pm->gsu.a->setfn(pm,
> pm->gsu.a->getfn(pm)) (basically doing foo=($foo)) and adding uniqarray
> call to dirssetfn() when I realized that it would not help at all in this
> case as dirssetfn() tries to free passed value too; so it would have
> crashed just the same.
>
> Apparently to solve it in general we need one of
>
> - per-parameter type ->uniq function (is it an overkill?) Possibly
> generalized to per-parameter ->setflags function.
>
> - some way to know if passed pointer was allocated from heap or not. I
> guess it should be possible; something like isheap(p)?
>

Assuming the issue with freeing heap memory is resolved, the patch adds 
support for -U to dirstack. It also adds framework for adding uniqueness 
support to any parameter by changing typeset to simply do equiv. of 
'foo=($foo)'. It also uncovered one case of using free() instead of zfree(); 
assuming previous patch is accepted it is necessary to audit code and replace 
all plain free() with zfree().

-andrey
Index: Src/builtin.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/builtin.c,v
retrieving revision 1.151
diff -u -p -r1.151 builtin.c
--- Src/builtin.c	7 Nov 2005 09:37:34 -0000	1.151
+++ Src/builtin.c	4 Mar 2006 09:19:18 -0000
@@ -1920,24 +1920,17 @@ typeset_single(char *cname, char *pname,
 	    zerrnam(cname, "%s: restricted", pname, 0);
 	    return pm;
 	}
+	pm->flags = (pm->flags | (on & ~PM_READONLY)) & ~(off | PM_UNSET);
 	if ((on & PM_UNIQUE) && !(pm->flags & PM_READONLY & ~off)) {
 	    Param apm;
-	    char **x;
-	    if (PM_TYPE(pm->flags) == PM_ARRAY) {
-		x = (*pm->gsu.a->getfn)(pm);
-		uniqarray(x);
-		if (pm->ename && x)
-		    arrfixenv(pm->ename, x);
-	    } else if (PM_TYPE(pm->flags) == PM_SCALAR && pm->ename &&
-		       (apm =
-			(Param) paramtab->getnode(paramtab, pm->ename))) {
-		x = (*apm->gsu.a->getfn)(apm);
-		uniqarray(x);
-		if (x)
-		    arrfixenv(pm->nam, x);
-	    }
+
+	    if (PM_TYPE(pm->flags) == PM_ARRAY)
+		apm = pm;
+	    else if (PM_TYPE(pm->flags) == PM_SCALAR && pm->ename)
+		apm = (Param) paramtab->getnode(paramtab, pm->ename);
+	    if (apm)
+		apm->gsu.a->setfn(pm, apm->gsu.a->getfn(apm));
 	}
-	pm->flags = (pm->flags | (on & ~PM_READONLY)) & ~(off | PM_UNSET);
 	if (on & (PM_LEFT | PM_RIGHT_B | PM_RIGHT_Z)) {
 	    if (typeset_setwidth(cname, pm, ops, on, 0))
 		return NULL;
Index: Src/utils.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/utils.c,v
retrieving revision 1.118
diff -u -p -r1.118 utils.c
--- Src/utils.c	1 Mar 2006 14:50:52 -0000	1.118
+++ Src/utils.c	4 Mar 2006 09:19:21 -0000
@@ -2499,7 +2499,7 @@ freearray(char **s)
 
     while (*s)
 	zsfree(*s++);
-    free(t);
+    zfree(t, 0);
 }
 
 /**/
Index: Src/Modules/parameter.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Modules/parameter.c,v
retrieving revision 1.35
diff -u -p -r1.35 parameter.c
--- Src/Modules/parameter.c	10 Mar 2005 17:56:05 -0000	1.35
+++ Src/Modules/parameter.c	4 Mar 2006 09:19:21 -0000
@@ -929,15 +929,19 @@ scanpmmodules(UNUSED(HashTable ht), Scan
 
 /**/
 static void
-dirssetfn(UNUSED(Param pm), char **x)
+dirssetfn(Param pm, char **x)
 {
     char **ox = x;
 
     if (!incleanup) {
 	freelinklist(dirstack, freestr);
 	dirstack = znewlinklist();
-	while (x && *x)
-	    zaddlinknode(dirstack, ztrdup(*x++));
+	if (x) {
+	    if (pm->flags & PM_UNIQUE)
+		uniqarray(x);
+	    while (*x)
+		zaddlinknode(dirstack, ztrdup(*x++));
+	}
     }
     if (ox)
 	freearray(ox);

Attachment: pgpSm7Ty4U9Qb.pgp
Description: PGP signature



Messages sorted by: Reverse Date, Date, Thread, Author