Skip to content

Commit b7879b0

Browse files
newrengitster
authored andcommitted
hashmap: allow re-use after hashmap_free()
Previously, once map->table had been freed, any calls to hashmap_put(), hashmap_get(), or hashmap_remove() would cause a NULL pointer dereference (since hashmap_free_() also zeros the memory; without that zeroing, calling these functions would cause a use-after-free problem). Modify these functions to check for a NULL table and automatically allocate as needed. Also add a HASHMAP_INIT(fn, data) macro for initializing hashmaps on the stack without calling hashmap_init(). Signed-off-by: Elijah Newren <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 97a39a4 commit b7879b0

File tree

2 files changed

+17
-2
lines changed

2 files changed

+17
-2
lines changed

hashmap.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ int hashmap_bucket(const struct hashmap *map, unsigned int hash)
114114

115115
static void rehash(struct hashmap *map, unsigned int newsize)
116116
{
117+
/* map->table MUST NOT be NULL when this function is called */
117118
unsigned int i, oldsize = map->tablesize;
118119
struct hashmap_entry **oldtable = map->table;
119120

@@ -134,6 +135,7 @@ static void rehash(struct hashmap *map, unsigned int newsize)
134135
static inline struct hashmap_entry **find_entry_ptr(const struct hashmap *map,
135136
const struct hashmap_entry *key, const void *keydata)
136137
{
138+
/* map->table MUST NOT be NULL when this function is called */
137139
struct hashmap_entry **e = &map->table[bucket(map, key)];
138140
while (*e && !entry_equals(map, *e, key, keydata))
139141
e = &(*e)->next;
@@ -196,6 +198,8 @@ struct hashmap_entry *hashmap_get(const struct hashmap *map,
196198
const struct hashmap_entry *key,
197199
const void *keydata)
198200
{
201+
if (!map->table)
202+
return NULL;
199203
return *find_entry_ptr(map, key, keydata);
200204
}
201205

@@ -211,8 +215,12 @@ struct hashmap_entry *hashmap_get_next(const struct hashmap *map,
211215

212216
void hashmap_add(struct hashmap *map, struct hashmap_entry *entry)
213217
{
214-
unsigned int b = bucket(map, entry);
218+
unsigned int b;
219+
220+
if (!map->table)
221+
alloc_table(map, HASHMAP_INITIAL_SIZE);
215222

223+
b = bucket(map, entry);
216224
/* add entry */
217225
entry->next = map->table[b];
218226
map->table[b] = entry;
@@ -230,7 +238,11 @@ struct hashmap_entry *hashmap_remove(struct hashmap *map,
230238
const void *keydata)
231239
{
232240
struct hashmap_entry *old;
233-
struct hashmap_entry **e = find_entry_ptr(map, key, keydata);
241+
struct hashmap_entry **e;
242+
243+
if (!map->table)
244+
return NULL;
245+
e = find_entry_ptr(map, key, keydata);
234246
if (!*e)
235247
return NULL;
236248

hashmap.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,9 @@ struct hashmap {
210210

211211
/* hashmap functions */
212212

213+
#define HASHMAP_INIT(fn, data) { .cmpfn = fn, .cmpfn_data = data, \
214+
.do_count_items = 1 }
215+
213216
/*
214217
* Initializes a hashmap structure.
215218
*

0 commit comments

Comments
 (0)