From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 8159 invoked by alias); 2 Feb 2015 02:35:16 -0000 Mailing-List: contact zsh-workers-help@zsh.org; run by ezmlm Precedence: bulk X-No-Archive: yes List-Id: Zsh Workers List List-Post: List-Help: X-Seq: 34447 Received: (qmail 6800 invoked from network); 2 Feb 2015 02:35:13 -0000 X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_NONE, T_FROM_12LTRDOM,T_MANY_HDRS_LCASE autolearn=ham version=3.3.2 X-CMAE-Score: 0 X-CMAE-Analysis: v=2.1 cv=Ko/6AtSI c=1 sm=1 tr=0 a=FT8er97JFeGWzr5TCOCO5w==:117 a=kj9zAlcOel0A:10 a=q2GGsy2AAAAA:8 a=oR5dmqMzAAAA:8 a=-9mUelKeXuEA:10 a=0HtSIViG9nkA:10 a=A4DsDFlRRuZTDfSMstIA:9 a=CjuIK1q_8ugA:10 From: Bart Schaefer Message-id: <150201183459.ZM27261@torch.brasslantern.com> Date: Sun, 01 Feb 2015 18:34:59 -0800 X-Mailer: OpenZMail Classic (0.9.2 24April2005) To: zsh-workers@zsh.org Subject: PATCH: Assigning to a ztie'd hash MIME-version: 1.0 Content-type: text/plain; charset=us-ascii This could use a valgrind pass, and I'm not sure I put the signal queuing in the best places, and there's probably some other misc. cleanup (more UNUSED() wrappers?), but I think this addresses the issue with assigning to the whole hash. I'm wondering about getstrvalue()+strlen() and the possibility of having embedded '\0' bytes in the values from the source hashtable, but this matches what's used in gdbmsetfn(). diff --git a/Src/Modules/db_gdbm.c b/Src/Modules/db_gdbm.c index a83e32a..2e2bd3a 100644 --- a/Src/Modules/db_gdbm.c +++ b/Src/Modules/db_gdbm.c @@ -45,7 +45,7 @@ static const struct gsu_scalar gdbm_gsu = { gdbmgetfn, gdbmsetfn, gdbmunsetfn }; /**/ static const struct gsu_hash gdbm_hash_gsu = -{ hashgetfn, hashsetfn, gdbmhashunsetfn }; +{ hashgetfn, gdbmhashsetfn, gdbmhashunsetfn }; static struct builtin bintab[] = { BUILTIN("ztie", 0, bin_ztie, 1, -1, 0, "d:f:r", NULL), @@ -194,7 +194,7 @@ gdbmsetfn(Param pm, char *val) /**/ static void -gdbmunsetfn(Param pm, int um) +gdbmunsetfn(Param pm, UNUSED(int um)) { datum key; GDBM_FILE dbf; @@ -232,9 +232,7 @@ scangdbmkeys(HashTable ht, ScanFunc func, int flags) { Param pm = NULL; datum key, content; - GDBM_FILE dbf; - - dbf = (GDBM_FILE)(ht->tmpdata); + GDBM_FILE dbf = (GDBM_FILE)(ht->tmpdata); pm = (Param) hcalloc(sizeof(struct param)); @@ -259,6 +257,59 @@ scangdbmkeys(HashTable ht, ScanFunc func, int flags) /**/ static void +gdbmhashsetfn(Param pm, HashTable ht) +{ + int i; + HashNode hn; + GDBM_FILE dbf; + datum key, content; + + if (!pm->u.hash || pm->u.hash == ht) + return; + + if (!(dbf = (GDBM_FILE)(pm->u.hash->tmpdata))) + return; + + key = gdbm_firstkey(dbf); + while (key.dptr) { + queue_signals(); + (void)gdbm_delete(dbf, key); + free(key.dptr); + unqueue_signals(); + key = gdbm_firstkey(dbf); + } + + /* just deleted everything, clean up */ + (void)gdbm_reorganize(dbf); + + if (!ht) + return; + + for (i = 0; i < ht->hsize; i++) + for (hn = ht->nodes[i]; hn; hn = hn->next) { + struct value v; + + v.isarr = v.flags = v.start = 0; + v.end = -1; + v.arr = NULL; + v.pm = (Param) hn; + + key.dptr = v.pm->node.nam; + key.dsize = strlen(key.dptr) + 1; + + queue_signals(); + + content.dptr = getstrvalue(&v); + content.dsize = strlen(content.dptr) + 1; + + (void)gdbm_store(dbf, key, content, GDBM_REPLACE); + + unqueue_signals(); + } +} + +/**/ +static void gdbmuntie(Param pm) { GDBM_FILE dbf = (GDBM_FILE)(pm->u.hash->tmpdata);