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

Re: segfault when name a local variable "path"



On Fri, 20 Nov 2015 11:38:40 +0100
Corentin Henry <corentinhenry@xxxxxxxxx> wrote:
> I have the following script:
> 
> # segfault.sh
> function foo() {
>     local path=
> }
> 
> 
> I source it an execute foo:
> 
> % source segfault.sh
> % foo
> 
> Then zsh segaults. Is this a known bug? If not, can anyone reproduce?

No, yes.  You get a bit more of a hint if DEBUG is defined.

1: builtin.c:2441: BUG: inconsistent scalar value for array

What's happening is "path" is special, and you haven't set the "hide"
attribute so the local still refers to that special variable, which is
an array, but the value is a scalar.

We should probably be lenient in a case like the above, where the intent
is obvious.

It's less clear we should be lenient in a case like

function foo() {
   local path=something
}

because if the something had ":" in it would be a mistake for assigning
PATH instead.  However, that's how normal assignment works, so unless we
change that the most consistent thing is to allow it in this case,
too.

[ws

diff --git a/Src/builtin.c b/Src/builtin.c
index 18dfdce..22479a7 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -2438,10 +2438,26 @@ typeset_single(char *cname, char *pname, Param pm, UNUSED(int func),
     if (ASG_VALUEP(asg) && !dont_set) {
 	Param ipm = pm;
 	if (pm->node.flags & (PM_ARRAY|PM_HASHED)) {
-	    DPUTS(!ASG_ARRAYP(asg), "BUG: inconsistent scalar value for array");
-	    if (!(pm=assignaparam(pname, asg->value.array ?
-				  zlinklist2array(asg->value.array) :
-				  mkarray(NULL), 0)))
+	    char **arrayval;
+	    if (!ASG_ARRAYP(asg)) {
+		/*
+		 * Attempt to assign a scalar value to an array.
+		 * This can happen if the array is special.
+		 * We'll be lenient and guess what the user meant.
+		 */
+		if (*asg->value.scalar) {
+		    /* Array with one value */
+		    arrayval = mkarray(ztrdup(asg->value.scalar));
+		} else {
+		    /* Empty array */
+		    arrayval = mkarray(NULL);
+		}
+	    }
+	    else if (asg->value.array)
+		arrayval = zlinklist2array(asg->value.array);
+	    else
+		arrayval = mkarray(NULL);
+	    if (!(pm=assignaparam(pname, arrayval, 0)))
 		return NULL;
 	} else {
 	    DPUTS(ASG_ARRAYP(asg), "BUG: inconsistent array value for scalar");
diff --git a/Test/D04parameter.ztst b/Test/D04parameter.ztst
index 210c0d8..a3c5d71 100644
--- a/Test/D04parameter.ztst
+++ b/Test/D04parameter.ztst
@@ -1847,3 +1847,22 @@
 0:nested parameter name references
 >all these worlds belong to foo
 >worlds
+
+  (
+  path=(/random /value)
+  testfn1() {
+    local path=
+    print $#path
+  }
+  testfn1
+  testfn2() {
+    local path=/somewhere
+    print $#path $path
+  }
+  testfn2
+  print $#path $path
+  )
+0:Local special variables with loose typing
+>0
+>1 /somewhere
+>2 /random /value



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