changeset: 6905:fc6990144167 user: Kevin McCarthy <ke...@8t8.us> date: Tue Jan 17 16:09:11 2017 -0800 link: http://dev.mutt.org/hg/mutt/rev/fc6990144167
Add casecmp and strdup_key flags to hash_create() Aliases and (in the future), X-Label hashes will require a hash that strdups the key. Convert the casecmp parameter of hash_create() to a flags parameter, and add a flag to strdup the keys. changeset: 6906:a555ada578b8 user: Kevin McCarthy <ke...@8t8.us> date: Tue Jan 17 16:09:16 2017 -0800 link: http://dev.mutt.org/hg/mutt/rev/a555ada578b8 Fix several alias hashtable issues. Convert to use the strdup keys hash. Addresses can be converted back and forth from intl to local forms. This frees and recreates a new addr->mailbox string, resulting in the hash table key being a dangling pointer. Change alias hash table insert/remove to ensure the address is in intl form. The alias menu (previously) converted address entries to local form when performing a completion. Even with the pointer issue fixed, the entries may not be removed from the hash if the intl and local forms are different. Lastly, there is no reason for the alias menu to manually convert to local form before writing the address to the output buffer. rfc822_write_address() has a display parameter that will call mutt_addr_for_display() instead when set. Change to set the display parameter and remove the conversion calls. This last change obviates the first two changes, but they are a good idea in any case. diffs (148 lines): diff -r ac1a2af3aff4 -r a555ada578b8 addrbook.c --- a/addrbook.c Sun Jan 15 10:00:55 2017 -0800 +++ b/addrbook.c Tue Jan 17 16:09:16 2017 -0800 @@ -227,16 +227,14 @@ { if (AliasTable[i]->tagged) { - mutt_addrlist_to_local (AliasTable[i]->addr); - rfc822_write_address (buf, buflen, AliasTable[i]->addr, 0); + rfc822_write_address (buf, buflen, AliasTable[i]->addr, 1); t = -1; } } - if(t != -1) + if (t != -1) { - mutt_addrlist_to_local (AliasTable[t]->addr); - rfc822_write_address (buf, buflen, AliasTable[t]->addr, 0); + rfc822_write_address (buf, buflen, AliasTable[t]->addr, 1); } mutt_menuDestroy (&menu); diff -r ac1a2af3aff4 -r a555ada578b8 alias.c --- a/alias.c Sun Jan 15 10:00:55 2017 -0800 +++ b/alias.c Tue Jan 17 16:09:16 2017 -0800 @@ -456,7 +456,12 @@ ADDRESS *ap; if (!t) return; - + + /* Note that the address mailbox should be converted to intl form + * before using as a key in the hash. This is currently done + * by all callers, but added here mostly as documentation.. */ + mutt_addrlist_to_intl (t->addr, NULL); + for (ap = t->addr; ap; ap = ap->next) { if (!ap->group && ap->mailbox) @@ -469,7 +474,11 @@ ADDRESS *ap; if (!t) return; - + + /* If the alias addresses were converted to local form, they won't + * match the hash entries. */ + mutt_addrlist_to_intl (t->addr, NULL); + for (ap = t->addr; ap; ap = ap->next) { if (!ap->group && ap->mailbox) diff -r ac1a2af3aff4 -r a555ada578b8 hash.c --- a/hash.c Sun Jan 15 10:00:55 2017 -0800 +++ b/hash.c Tue Jan 17 16:09:16 2017 -0800 @@ -79,7 +79,7 @@ static HASH *new_hash (int nelem) { - HASH *table = safe_malloc (sizeof (HASH)); + HASH *table = safe_calloc (1, sizeof (HASH)); if (nelem == 0) nelem = 2; table->nelem = nelem; @@ -87,10 +87,10 @@ return table; } -HASH *hash_create (int nelem, int lower) +HASH *hash_create (int nelem, int flags) { HASH *table = new_hash (nelem); - if (lower) + if (flags & MUTT_HASH_STRCASECMP) { table->gen_hash = gen_case_string_hash; table->cmp_key = cmp_case_string_key; @@ -100,6 +100,8 @@ table->gen_hash = gen_string_hash; table->cmp_key = cmp_string_key; } + if (flags & MUTT_HASH_STRDUP_KEYS) + table->strdup_keys = 1; return table; } @@ -159,7 +161,7 @@ int hash_insert (HASH * table, const char *strkey, void *data, int allow_dup) { union hash_key key; - key.strkey = strkey; + key.strkey = table->strdup_keys ? safe_strdup (strkey) : strkey; return union_hash_insert (table, key, data, allow_dup); } @@ -236,6 +238,8 @@ *last = ptr->next; if (destroy) destroy (ptr->data); + if (table->strdup_keys) + FREE (&ptr->key.strkey); FREE (&ptr); ptr = *last; @@ -285,6 +289,8 @@ elem = elem->next; if (destroy) destroy (tmp->data); + if (pptr->strdup_keys) + FREE (&tmp->key.strkey); FREE (&tmp); } } diff -r ac1a2af3aff4 -r a555ada578b8 hash.h --- a/hash.h Sun Jan 15 10:00:55 2017 -0800 +++ b/hash.h Tue Jan 17 16:09:16 2017 -0800 @@ -35,12 +35,17 @@ typedef struct { int nelem; + int strdup_keys; /* if set, the key->strkey is strdup'ed */ struct hash_elem **table; unsigned int (*gen_hash)(union hash_key, unsigned int); int (*cmp_key)(union hash_key, union hash_key); } HASH; +/* flags for hash_create() */ +#define MUTT_HASH_STRCASECMP (1<<0) /* use strcasecmp() to compare keys */ +#define MUTT_HASH_STRDUP_KEYS (1<<1) /* make a copy of the keys */ + HASH *hash_create (int nelem, int lower); HASH *int_hash_create (int nelem); diff -r ac1a2af3aff4 -r a555ada578b8 init.c --- a/init.c Sun Jan 15 10:00:55 2017 -0800 +++ b/init.c Tue Jan 17 16:09:16 2017 -0800 @@ -3158,7 +3158,8 @@ err.dptr = err.data; Groups = hash_create (1031, 0); - ReverseAlias = hash_create (1031, 1); + /* reverse alias keys need to be strdup'ed because of idna conversions */ + ReverseAlias = hash_create (1031, MUTT_HASH_STRCASECMP | MUTT_HASH_STRDUP_KEYS); mutt_menu_init (); mutt_srandom ();