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

PATCH: Re: PATCH: zsh-3.1.5-pws-7: "$a[@]" with $a unset



On Feb 12,  9:33am, Bart Schaefer wrote:
} Subject: Re: PATCH: zsh-3.1.5-pws-7: "$a[@]" with $a unset
} 
} zagzig% foo() { echo $# "$@" }
} zagzig% foo "$unset[@]"
} zsh: segmentation fault (core dumped)  Src/zsh -f

Here's a fix.  I don't think this can possibly cause anything else to go
wrong, but ...

The first two hunks go on top of PWS's patch and simply expand a bit more
on the test he changed, to be sure no null pointers are dereferenced.

I'm not sure the test of the PM_UNSET flag is necessary, but it seemed
to fit the semantics.

The third hunk (still params.c) causes getarrvalue() to return an empty
array rather than NULL for an unset parameter.  There are just too many
uses of the result in paramsubst() to be sure they're all prepared to
handle a NULL.  Note that `nular' is an array consisting of one empty
element, which may be the wrong thing to return in the pre-existing (!v)
branch, but I'm not prepared to muck with that.

It bugs me a little that the code in paramsubst() seems to "accidentally"
do the right thing given this return value.  It really should explictly
check (isarr < 0) and (vunset) -- which combined mean an unset variable
that was subscripted with [@] -- rather than stumbling into the correct
branch because (aval[0] == 0), which is what happens now.  However ...

Index: Src/params.c
===================================================================
--- params.c	1999/02/12 17:10:43	1.27
+++ params.c	1999/02/13 06:55:01
@@ -246,6 +246,10 @@
 };
 #undef BR
 
+#define IS_UNSET_VALUE(V) \
+	((V) && (!(V)->pm || ((V)->pm->flags & PM_UNSET) || \
+		 !(V)->pm->nam || !*(V)->pm->nam))
+
 static Param argvparam;
 
 /* hash table containing the parameters */
@@ -966,7 +970,7 @@
     if (*tbrack == Outbrack)
 	*tbrack = ']';
     if ((s[0] == '*' || s[0] == '@') && s[1] == ']') {
-	if ((v->isarr || !v->pm || !*v->pm->nam) && s[0] == '@')
+	if ((v->isarr || IS_UNSET_VALUE(v)) && s[0] == '@')
 	    v->isarr |= SCANPM_ISVAR_AT;
 	v->a = 0;
 	v->b = -1;
@@ -1205,6 +1209,8 @@
 
     if (!v)
 	return arrdup(nular);
+    else if (IS_UNSET_VALUE(v))
+	return arrdup(&nular[1]);
     if (v->inv) {
 	char buf[DIGBUFSIZE];
 

-- 
Bart Schaefer                                 Brass Lantern Enterprises
http://www.well.com/user/barts              http://www.brasslantern.com



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