From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 15778 invoked by alias); 20 Nov 2015 11:11:31 -0000 Mailing-List: contact zsh-users-help@zsh.org; run by ezmlm Precedence: bulk X-No-Archive: yes List-Id: Zsh Users List List-Post: List-Help: X-Seq: 20974 Received: (qmail 14914 invoked from network); 20 Nov 2015 11:11:30 -0000 X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.0 X-AuditID: cbfec7f4-f79026d00000418a-f1-564effdd3003 Date: Fri, 20 Nov 2015 11:11:22 +0000 From: Peter Stephenson To: zsh-users@zsh.org Subject: Re: segfault when name a local variable "path" Message-id: <20151120111122.38dcdaac@pwslap01u.europe.root.pri> In-reply-to: References: Organization: Samsung Cambridge Solution Centre X-Mailer: Claws Mail 3.7.9 (GTK+ 2.22.0; i386-redhat-linux-gnu) MIME-version: 1.0 Content-type: text/plain; charset=US-ASCII Content-transfer-encoding: 7bit X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFrrALMWRmVeSWpSXmKPExsVy+t/xq7p3//uFGVy+J2ex4+RKRgdGj1UH PzAFMEZx2aSk5mSWpRbp2yVwZbzesYK9YKdYxfKpF9kbGKcJdjFyckgImEj82NrGBmGLSVy4 tx7MFhJYyiixZhNrFyMXkD2NSeLZzEvsEM45RolNK58yQzhnGSVO72wEa2ERUJXY+XsRC4jN JmAoMXXTbEYQW0RAVGL5is3sILawgLnEqWedrCA2r4C9xKtbt8DqOQWCJXZ+72eBWB0gcej7 FzCbX0Bf4urfT0wQ59lLzLxyhhGiV1Dix+R7YDXMAloSm7c1sULY8hKb17xlhpijLnHj7m72 CYzCs5C0zELSMgtJywJG5lWMoqmlyQXFSem5hnrFibnFpXnpesn5uZsYIeH8ZQfj4mNWhxgF OBiVeHgbxP3ChFgTy4orcw8xSnAwK4nwHngHFOJNSaysSi3Kjy8qzUktPsQozcGiJM47d9f7 ECGB9MSS1OzU1ILUIpgsEwenVAOjiPqLzDnHS+wTnDfV8joUczxJVzKv4+E01/WIVXUOeyR2 4c+niKUM26wl6zdI5K37VPBwgfSxO4GWthbfL27aePO8rk5DkuLzC+nTL/TzrVjxzd7Ktl9n Qeg21dLqY2avT05Qi1dL1c0681rU/dblvSF/YxlXPfzjvTztW4Xq7Emivz/nv7dWYinOSDTU Yi4qTgQAStUw1mMCAAA= On Fri, 20 Nov 2015 11:38:40 +0100 Corentin Henry 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