about summary refs log tree commit diff
path: root/Src
diff options
context:
space:
mode:
authorPeter Stephenson <p.w.stephenson@ntlworld.com>2015-01-29 21:05:17 +0000
committerPeter Stephenson <p.w.stephenson@ntlworld.com>2015-01-29 21:05:17 +0000
commitbc8491c3dc939411546d0b5ee5fe25551bce424f (patch)
tree9ce77362bb55f9c83317233a0a0b14363908c32e /Src
parent22ad56296d9f2c2f57c1e6d38ad3f4b94afc9a41 (diff)
downloadzsh-bc8491c3dc939411546d0b5ee5fe25551bce424f.tar.gz
zsh-bc8491c3dc939411546d0b5ee5fe25551bce424f.tar.xz
zsh-bc8491c3dc939411546d0b5ee5fe25551bce424f.zip
34430: parameter fixes for gdbm tied hash.
Probably fix the issue with correct parameter hiding or not hiding.

A little extra safety checking.

Possibly fixed a memory leak with untying.
Diffstat (limited to 'Src')
-rw-r--r--Src/Modules/db_gdbm.c17
-rw-r--r--Src/params.c27
2 files changed, 36 insertions, 8 deletions
diff --git a/Src/Modules/db_gdbm.c b/Src/Modules/db_gdbm.c
index d75af980b..a6027deaf 100644
--- a/Src/Modules/db_gdbm.c
+++ b/Src/Modules/db_gdbm.c
@@ -105,7 +105,6 @@ static int
 bin_zuntie(char *nam, char **args, Options ops, UNUSED(int func))
 {
     Param pm;
-    GDBM_FILE dbf;
     char *pmname;
     int ret = 0;
 
@@ -116,12 +115,18 @@ bin_zuntie(char *nam, char **args, Options ops, UNUSED(int func))
 	    ret = 1;
 	    continue;
 	}
+	if (pm->gsu.h != &gdbm_hash_gsu) {
+	    zwarnnam(nam, "not a tied gdbm hash: %s", pmname);
+	    ret = 1;
+	    continue;
+	}
 
-	dbf = (GDBM_FILE)(pm->u.hash->tmpdata);
-	gdbm_close(dbf);
-	/* free(pm->u.hash->tmpdata); */
-	pm->u.hash->tmpdata = NULL;
-	paramtab->removenode(paramtab, pm->node.nam);
+	queue_signals();
+	if (unsetparam_pm(pm, 0, 1)) {
+	    /* assume already reported */
+	    ret = 1;
+	}
+	unqueue_signals();
     }
 
     return ret;
diff --git a/Src/params.c b/Src/params.c
index 64c78bd63..e8a90104c 100644
--- a/Src/params.c
+++ b/Src/params.c
@@ -927,7 +927,15 @@ shempty(void)
 {
 }
 
-/* Create a simple special hash parameter. */
+/*
+ * Create a simple special hash parameter.
+ *
+ * This is for hashes added internally --- it's not possible to add
+ * special hashes from shell commands.  It's currently used
+ * - by addparamdef() for special parameters in the zsh/parameter
+ *   module
+ * - by ztie for special parameters tied to databases.
+ */
 
 /**/
 mod_export Param
@@ -939,7 +947,22 @@ createspecialhash(char *name, GetNodeFunc get, ScanTabFunc scan, int flags)
     if (!(pm = createparam(name, PM_SPECIAL|PM_HASHED|flags)))
 	return NULL;
 
-    pm->level = pm->old ? locallevel : 0;
+    /*
+     * If there's an old parameter, we'll put the new one at
+     * the current locallevel, so that the old parameter is
+     * exposed again after leaving the function.  Otherwise,
+     * we'll leave it alone.  Usually this means the parameter
+     * will stay in place until explicitly unloaded, however
+     * if the parameter was previously unset within a function
+     * we'll inherit the level of that function and follow the
+     * standard convention that the parameter remains local
+     * even if unset.
+     *
+     * These semantics are similar to those of a normal parameter set
+     * within a function without a local definition.
+     */
+    if (pm->old)
+	pm->level = locallevel;
     pm->gsu.h = (flags & PM_READONLY) ? &stdhash_gsu :
 	&nullsethash_gsu;
     pm->u.hash = ht = newhashtable(0, name, NULL);