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

Re: Bug Report: Variable becomes unset without reason



On Wed, 2019-08-14 at 10:37 +0100, Stephane Chazelas wrote:
> 2019-08-08 20:38:05 +0430, Aryn Starr:
> Now, that being said, as discussed on U&L it looks like a bug
> indeed and a shorter reproducer is:
> 
> $ zsh -xc 'v=1; f() { local v; v=2 true; }; f; typeset -p v'
> +zsh:1> v=1
> +zsh:1> f
> +f:0> local v
> +f:0> v=2 +f:0> true
> +zsh:1> typeset -p v
> zsh:typeset:1: no such variable: v
> 
> Most likely, that's the "v=2 true" (where "true" is a builtin) that ends up
> unsetting the "v" from the global scope.

Yes, the saved version of "v" that we restore after the builtin is
missing the pointer back to the version of v in the enclosing scope.  So
it's not only not shown as set, it will leak memory.

This simply preserves that pointer in the copy, but this assumes we've
correctly blocked off the old parameter from being altered inside the
function scope --- if we haven't that preserved old pointer is going to
get us into trouble.  However, if we haven't that's already a bug, so
this shouldn't make things worse.

pws

diff --git a/Src/params.c b/Src/params.c
index 1499e3a40..a253a9d8e 100644
--- a/Src/params.c
+++ b/Src/params.c
@@ -1124,8 +1124,10 @@ copyparam(Param tpm, Param pm, int fakecopy)
     tpm->base = pm->base;
     tpm->width = pm->width;
     tpm->level = pm->level;
-    if (!fakecopy)
+    if (!fakecopy) {
+	tpm->old = pm->old;
 	tpm->node.flags &= ~PM_SPECIAL;
+    }
     switch (PM_TYPE(pm->node.flags)) {
     case PM_SCALAR:
 	tpm->u.str = ztrdup(pm->gsu.s->getfn(pm));
diff --git a/Test/D04parameter.ztst b/Test/D04parameter.ztst
index 194c3e287..b6e85a9fe 100644
--- a/Test/D04parameter.ztst
+++ b/Test/D04parameter.ztst
@@ -2522,3 +2522,15 @@ F:behavior, see http://austingroupbugs.net/view.php?id=888
 >trailing/slashes
 >removed
 >are/removed
+
+ foo=global-value
+ fn() {
+    local foo=function-value
+    foo=export-value true
+    print $foo
+ }
+ fn
+ print $foo
+0:Global variables are not trashed by "foo=bar builtin" (regression test)
+>function-value
+>global-value



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