lib: fix typesafe hash add with hash collision

The typesafe hash data structure enforces items to be unique, but their
hash values may still collide.  To this extent, when two items have the
same hash value, the compare function is called to see if it returns 0
(aka "equal").

While the _find() function handles this correctly, the _add() function
mistakenly only checked the first item with a colliding hash value for
equality, and if it was inequal proceeded to add the new item.  There
may however be additional items with the same hash value collision, one
of which could still compare as equal.  In that case, _add() would
mistakenly add the new element, failing to notice the already added
item.  Breakage ensues.

Fix by looking for an equal element among *all* existing items with the
same hash value, not just the first.

Signed-off-by: Francois Dumontet <francois.dumontet@6wind.com>
[DL: rewrote commit message, fixed whitespace/formatting]
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
This commit is contained in:
Francois Dumontet 2022-10-04 16:26:19 +02:00 committed by David Lamparter
parent 4b72a7be69
commit 5e0136c94f

View File

@ -850,9 +850,12 @@ macro_inline type *prefix ## _add(struct prefix##_head *h, type *item) \
struct thash_item **np = &h->hh.entries[hbits]; \
while (*np && (*np)->hashval < hval) \
np = &(*np)->next; \
if (*np && cmpfn(container_of(*np, type, field.hi), item) == 0) { \
h->hh.count--; \
return container_of(*np, type, field.hi); \
while (*np && (*np)->hashval == hval) { \
if (cmpfn(container_of(*np, type, field.hi), item) == 0) { \
h->hh.count--; \
return container_of(*np, type, field.hi); \
} \
np = &(*np)->next; \
} \
item->field.hi.next = *np; \
*np = &item->field.hi; \