about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog3
-rw-r--r--Src/params.c19
-rw-r--r--Test/D04parameter.ztst34
3 files changed, 53 insertions, 3 deletions
diff --git a/ChangeLog b/ChangeLog
index 587c3f23b..19c899474 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,8 @@
 2005-08-22  Peter Stephenson  <pws@csr.com>
 
+	* 21678: Src/params.c, Test/D04parameter.ztst: unsetting
+	tied parameters was fraught with crashes.
+
 	* 21676: Doc/zmacros.yo, Doc/Zsh/contrib.yo,
 	Functions/Zle/.distfiles, Functions/Zle/insert-composed-char,
 	Functions/Zle/insert-unicode-char: insert-unicode-char is now
diff --git a/Src/params.c b/Src/params.c
index 396c97c3a..26b3f3133 100644
--- a/Src/params.c
+++ b/Src/params.c
@@ -2342,6 +2342,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);
@@ -2351,13 +2352,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) {
@@ -2373,6 +2381,8 @@ unsetparam_pm(Param pm, int altflag, int exp)
 	    }
 	    unsetparam_pm(altpm, 1, exp);
 	}
+
+	zsfree(altremove);
     }
 
     /*
@@ -2438,6 +2448,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;
 }
 
@@ -2815,6 +2827,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 7a6254300..3ad19368d 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]]