about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Stephenson <pws@users.sourceforge.net>2005-08-22 11:43:58 +0000
committerPeter Stephenson <pws@users.sourceforge.net>2005-08-22 11:43:58 +0000
commit2fb1a9f13c0c465c41d8c08366fb8c41dccf2880 (patch)
tree1dfd3bd93762f67168e4383bbcf35b94bd93ca53
parent50826130a47ba331306f479187d689bcf06f9e2c (diff)
downloadzsh-2fb1a9f13c0c465c41d8c08366fb8c41dccf2880.tar.gz
zsh-2fb1a9f13c0c465c41d8c08366fb8c41dccf2880.tar.xz
zsh-2fb1a9f13c0c465c41d8c08366fb8c41dccf2880.zip
21678: Unsetting tied parameters caused various crashes
-rw-r--r--ChangeLog5
-rw-r--r--Src/params.c19
-rw-r--r--Test/D04parameter.ztst34
3 files changed, 55 insertions, 3 deletions
diff --git a/ChangeLog b/ChangeLog
index 4b0d219d7..0aeb201fc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2005-08-22  Peter Stephenson  <pws@csr.com>
+
+	* 21678: Src/params.c, Test/D04parameter.ztst: unsetting
+	tied parameters was fraught with crashes.
+
 2005-08-09  Peter Stephenson  <pws@csr.com>
 
 	* 21577: Dan Bullok: Src/Zle/zle_main.c, Src/init.c,
diff --git a/Src/params.c b/Src/params.c
index 7f91bd048..80647aa28 100644
--- a/Src/params.c
+++ b/Src/params.c
@@ -2329,6 +2329,7 @@ mod_export int
 unsetparam_pm(Param pm, int altflag, int exp)
 {
     Param oldpm, altpm;
+    char *altremove;
 
     if ((pm->flags & PM_READONLY) && pm->level <= locallevel) {
 	zerr("read-only variable: %s", pm->nam, 0);
@@ -2338,13 +2339,20 @@ unsetparam_pm(Param pm, int altflag, int exp)
 	zerr("%s: restricted", pm->nam, 0);
 	return 1;
     }
-    pm->gsu.s->unsetfn(pm, exp);
+
+    if (pm->ename && !altflag)
+	altremove = ztrdup(pm->ename);
+    else
+	altremove = NULL;
+
+    if (!(pm->flags & PM_UNSET))
+	pm->gsu.s->unsetfn(pm, exp);
     if (pm->env)
 	delenv(pm);
 
     /* remove it under its alternate name if necessary */
-    if (pm->ename && !altflag) {
-	altpm = (Param) paramtab->getnode(paramtab, pm->ename);
+    if (altremove) {
+	altpm = (Param) paramtab->getnode(paramtab, altremove);
 	/* tied parameters are at the same local level as each other */
 	oldpm = NULL;
 	while (altpm && altpm->level > pm->level) {
@@ -2360,6 +2368,8 @@ unsetparam_pm(Param pm, int altflag, int exp)
 	    }
 	    unsetparam_pm(altpm, 1, exp);
 	}
+
+	zsfree(altremove);
     }
 
     /*
@@ -2425,6 +2435,8 @@ stdunsetfn(Param pm, UNUSED(int exp))
 	    	pm->u.str = NULL;
 	    break;
     }
+    if (!(pm->flags & PM_SPECIAL))
+	pm->flags &= ~PM_TIED;
     pm->flags |= PM_UNSET;
 }
 
@@ -2802,6 +2814,7 @@ tiedarrunsetfn(Param pm, UNUSED(int exp))
     zsfree(pm->ename);
     pm->ename = NULL;
     pm->flags &= ~PM_TIED;
+    pm->flags |= PM_UNSET;
 }
 
 /**/
diff --git a/Test/D04parameter.ztst b/Test/D04parameter.ztst
index 7f2ed4670..6623ebd24 100644
--- a/Test/D04parameter.ztst
+++ b/Test/D04parameter.ztst
@@ -568,6 +568,40 @@
 >0
 >/elsewhere /somewhere
 
+  local STRING=a:b
+  typeset -T STRING string
+  print $STRING $string
+  unset STRING
+  set -A string x y z
+  print $STRING $string
+  STRING=a:b
+  typeset -T STRING string
+  print $STRING $string
+  unset STRING
+  set -A string x y z
+  print $STRING $string
+  STRING=a:b
+  typeset -T STRING string
+  print $STRING $string
+  unset string
+  STRING=x:y:z
+  print $STRING $string
+  STRING=a:b
+  typeset -T STRING string
+  print $STRING $string
+  unset string
+  STRING=x:y:z
+  print $STRING $string
+0:Unsetting and recreation of tied normal parameters
+>a:b a b
+>x y z
+>a:b a b
+>x y z
+>a:b a b
+>x:y:z
+>a:b a b
+>x:y:z
+
   string='look for a match in here'
   if [[ ${string%%(#b)(match)*} = "look for a " ]]; then
     print $match[1] $mbegin[1] $mend[1] $string[$mbegin[1],$mend[1]]