about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBart Schaefer <schaefer@zsh.org>2023-09-03 11:42:00 -0700
committerBart Schaefer <schaefer@zsh.org>2023-09-03 11:42:00 -0700
commit9ff1b2810e70658b2364b737478e9a996de0a644 (patch)
tree5b40cc9ed8601b7fcc6cdaef40eb2dba56571b66
parenta8853323dd631ba26869ea6e0bf1b8098247731d (diff)
downloadzsh-9ff1b2810e70658b2364b737478e9a996de0a644.tar.gz
zsh-9ff1b2810e70658b2364b737478e9a996de0a644.tar.xz
zsh-9ff1b2810e70658b2364b737478e9a996de0a644.zip
users/29220: fix bug with assignment to private following explicit unset
-rw-r--r--ChangeLog5
-rw-r--r--Src/Modules/param_private.c29
-rw-r--r--Test/V10private.ztst7
3 files changed, 30 insertions, 11 deletions
diff --git a/ChangeLog b/ChangeLog
index 356d7a48c..1fc00562c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2023-09-03  Bart Schaefer  <schaefer@zsh.org>
+
+	* users/29220: Src/Modules/param_private.c, Test/V10private.ztst:
+	fix bug with assignment to private following explicit unset
+
 2023-08-28  Jun-ichi Takimoto  <takimoto-j@kba.biglobe.ne.jp>
 
 	* Shohei YOSHIDA: 52098(+comment), 52099, 52100, 52105(+52106):
diff --git a/Src/Modules/param_private.c b/Src/Modules/param_private.c
index e43f0edb4..8e04b2b95 100644
--- a/Src/Modules/param_private.c
+++ b/Src/Modules/param_private.c
@@ -230,7 +230,9 @@ setfn_error(Param pm)
  * calling the original unsetfn.  This assures that if the old unsetfn
  * wants to use its getfn or setfn, they're unconditionally present.
  * The "explicit" flag indicates that "unset" was called, if zero the
- * parameter is going out of scope (see params.c).
+ * parameter is going out of scope (see params.c).  PM_DECLARED is
+ * asserted as if TYPESET_TO_UNSET were in use so that the private
+ * parameter is re-used rather than re-created when assigned again.
  *
  */
 
@@ -268,9 +270,10 @@ pps_unsetfn(Param pm, int explicit)
     pm->gsu.s = gsu;
     if (locallevel <= pm->level)
 	gsu->unsetfn(pm, explicit);
-    if (explicit)
+    if (explicit) {
+	pm->node.flags |= PM_DECLARED;
 	pm->gsu.s = (GsuScalar)c;
-    else
+    } else
 	zfree(c, sizeof(struct gsu_closure));
 }
 
@@ -307,9 +310,10 @@ ppi_unsetfn(Param pm, int explicit)
     pm->gsu.i = gsu;
     if (locallevel <= pm->level)
 	gsu->unsetfn(pm, explicit);
-    if (explicit)
+    if (explicit) {
+	pm->node.flags |= PM_DECLARED;
 	pm->gsu.i = (GsuInteger)c;
-    else
+    } else
 	zfree(c, sizeof(struct gsu_closure));
 }
 
@@ -346,9 +350,10 @@ ppf_unsetfn(Param pm, int explicit)
     pm->gsu.f = gsu;
     if (locallevel <= pm->level)
 	gsu->unsetfn(pm, explicit);
-    if (explicit)
+    if (explicit) {
+	pm->node.flags |= PM_DECLARED;
 	pm->gsu.f = (GsuFloat)c;
-    else
+    } else
 	zfree(c, sizeof(struct gsu_closure));
 }
 
@@ -386,9 +391,10 @@ ppa_unsetfn(Param pm, int explicit)
     pm->gsu.a = gsu;
     if (locallevel <= pm->level)
 	gsu->unsetfn(pm, explicit);
-    if (explicit)
+    if (explicit) {
+	pm->node.flags |= PM_DECLARED;
 	pm->gsu.a = (GsuArray)c;
-    else
+    } else
 	zfree(c, sizeof(struct gsu_closure));
 }
 
@@ -427,9 +433,10 @@ pph_unsetfn(Param pm, int explicit)
     pm->gsu.h = gsu;
     if (locallevel <= pm->level)
 	gsu->unsetfn(pm, explicit);
-    if (explicit)
+    if (explicit) {
+	pm->node.flags |= PM_DECLARED;
 	pm->gsu.h = (GsuHash)c;
-    else
+    } else
 	zfree(c, sizeof(struct gsu_closure));
 }
 
diff --git a/Test/V10private.ztst b/Test/V10private.ztst
index b191afcb7..b876f548d 100644
--- a/Test/V10private.ztst
+++ b/Test/V10private.ztst
@@ -377,6 +377,13 @@ F:Should we allow "public" namerefs to private parameters?
 *?*no such variable: ptr1
 *?*no such variable: ptr2
 
+ () {
+   private x=1
+   unset x
+   x=2
+ }
+0:regression test for unset private
+
 %clean
 
   rm -r private.TMP