From bc8491c3dc939411546d0b5ee5fe25551bce424f Mon Sep 17 00:00:00 2001
From: Peter Stephenson
Date: Thu, 29 Jan 2015 21:05:17 +0000
Subject: 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.
---
Src/Modules/db_gdbm.c | 17 +++++++++++------
Src/params.c | 27 +++++++++++++++++++++++++--
2 files changed, 36 insertions(+), 8 deletions(-)
(limited to 'Src')
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);
--
cgit 1.4.1