Skip to content

Commit

Permalink
hashmap_entry: detect improper initialization
Browse files Browse the repository at this point in the history
By renaming the "hash" field to "_hash", it's easy to spot
improper initialization of hashmap_entry structs which
can leave "hashmap_entry.next" uninitialized.

Signed-off-by: Eric Wong <e@80x24.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
Eric Wong authored and gitster committed Aug 26, 2019
1 parent 92b660d commit 7a55822
Show file tree
Hide file tree
Showing 6 changed files with 21 additions and 16 deletions.
5 changes: 3 additions & 2 deletions builtin/fast-export.c
Expand Up @@ -144,18 +144,19 @@ static const void *anonymize_mem(struct hashmap *map,
const void *orig, size_t *len)
{
struct anonymized_entry key, *ret;
unsigned int hash = memhash(orig, *len);

if (!map->cmpfn)
hashmap_init(map, anonymized_entry_cmp, NULL, 0);

hashmap_entry_init(&key.hash, memhash(orig, *len));
hashmap_entry_init(&key.hash, hash);
key.orig = orig;
key.orig_len = *len;
ret = hashmap_get(map, &key, NULL);

if (!ret) {
ret = xmalloc(sizeof(*ret));
hashmap_entry_init(&ret->hash, key.hash.hash);
hashmap_entry_init(&ret->hash, hash);
ret->orig = xstrdup(orig);
ret->orig_len = *len;
ret->anon = generate(orig, len);
Expand Down
9 changes: 5 additions & 4 deletions hashmap.c
Expand Up @@ -96,14 +96,14 @@ static inline int entry_equals(const struct hashmap *map,
const void *keydata)
{
return (e1 == e2) ||
(e1->hash == e2->hash &&
(e1->_hash == e2->_hash &&
!map->cmpfn(map->cmpfn_data, e1, e2, keydata));
}

static inline unsigned int bucket(const struct hashmap *map,
const struct hashmap_entry *key)
{
return key->hash & (map->tablesize - 1);
return key->_hash & (map->tablesize - 1);
}

int hashmap_bucket(const struct hashmap *map, unsigned int hash)
Expand Down Expand Up @@ -287,19 +287,20 @@ const void *memintern(const void *data, size_t len)
{
static struct hashmap map;
struct pool_entry key, *e;
unsigned int hash = memhash(data, len);

/* initialize string pool hashmap */
if (!map.tablesize)
hashmap_init(&map, (hashmap_cmp_fn) pool_entry_cmp, NULL, 0);

/* lookup interned string in pool */
hashmap_entry_init(&key.ent, memhash(data, len));
hashmap_entry_init(&key.ent, hash);
key.len = len;
e = hashmap_get(&map, &key, data);
if (!e) {
/* not found: create it */
FLEX_ALLOC_MEM(e, data, data, len);
hashmap_entry_init(&e->ent, key.ent.hash);
hashmap_entry_init(&e->ent, hash);
e->len = len;
hashmap_add(&map, e);
}
Expand Down
4 changes: 2 additions & 2 deletions hashmap.h
Expand Up @@ -145,7 +145,7 @@ struct hashmap_entry {
struct hashmap_entry *next;

/* entry's hash code */
unsigned int hash;
unsigned int _hash;
};

/*
Expand Down Expand Up @@ -247,7 +247,7 @@ void hashmap_free(struct hashmap *map, int free_entries);
static inline void
hashmap_entry_init(struct hashmap_entry *e, unsigned int hash)
{
e->hash = hash;
e->_hash = hash;
e->next = NULL;
}

Expand Down
9 changes: 5 additions & 4 deletions name-hash.c
Expand Up @@ -268,7 +268,7 @@ static struct dir_entry *hash_dir_entry_with_parent_and_prefix(
assert((parent != NULL) ^ (strchr(prefix->buf, '/') == NULL));

if (parent)
hash = memihash_cont(parent->ent.hash,
hash = memihash_cont(parent->ent._hash,
prefix->buf + parent->namelen,
prefix->len - parent->namelen);
else
Expand All @@ -289,7 +289,8 @@ static struct dir_entry *hash_dir_entry_with_parent_and_prefix(
unlock_dir_mutex(lock_nr);

/* All I really need here is an InterlockedIncrement(&(parent->nr)) */
lock_nr = compute_dir_lock_nr(&istate->dir_hash, parent->ent.hash);
lock_nr = compute_dir_lock_nr(&istate->dir_hash,
parent->ent._hash);
lock_dir_mutex(lock_nr);
parent->nr++;
}
Expand Down Expand Up @@ -427,10 +428,10 @@ static int handle_range_1(
lazy_entries[k].dir = parent;
if (parent) {
lazy_entries[k].hash_name = memihash_cont(
parent->ent.hash,
parent->ent._hash,
ce_k->name + parent->namelen,
ce_namelen(ce_k) - parent->namelen);
lazy_entries[k].hash_dir = parent->ent.hash;
lazy_entries[k].hash_dir = parent->ent._hash;
} else {
lazy_entries[k].hash_name = memihash(ce_k->name, ce_namelen(ce_k));
}
Expand Down
6 changes: 4 additions & 2 deletions remote.c
Expand Up @@ -136,14 +136,16 @@ static struct remote *make_remote(const char *name, int len)
struct remote *ret, *replaced;
struct remotes_hash_key lookup;
struct hashmap_entry lookup_entry;
unsigned int hash;

if (!len)
len = strlen(name);

init_remotes_hash();
lookup.str = name;
lookup.len = len;
hashmap_entry_init(&lookup_entry, memhash(name, len));
hash = memhash(name, len);
hashmap_entry_init(&lookup_entry, hash);

if ((ret = hashmap_get(&remotes_hash, &lookup_entry, &lookup)) != NULL)
return ret;
Expand All @@ -158,7 +160,7 @@ static struct remote *make_remote(const char *name, int len)
ALLOC_GROW(remotes, remotes_nr + 1, remotes_alloc);
remotes[remotes_nr++] = ret;

hashmap_entry_init(&ret->ent, lookup_entry.hash);
hashmap_entry_init(&ret->ent, hash);
replaced = hashmap_put(&remotes_hash, ret);
assert(replaced == NULL); /* no previous entry overwritten */
return ret;
Expand Down
4 changes: 2 additions & 2 deletions t/helper/test-lazy-init-name-hash.c
Expand Up @@ -43,13 +43,13 @@ static void dump_run(void)

dir = hashmap_iter_first(&the_index.dir_hash, &iter_dir);
while (dir) {
printf("dir %08x %7d %s\n", dir->ent.hash, dir->nr, dir->name);
printf("dir %08x %7d %s\n", dir->ent._hash, dir->nr, dir->name);
dir = hashmap_iter_next(&iter_dir);
}

ce = hashmap_iter_first(&the_index.name_hash, &iter_cache);
while (ce) {
printf("name %08x %s\n", ce->ent.hash, ce->name);
printf("name %08x %s\n", ce->ent._hash, ce->name);
ce = hashmap_iter_next(&iter_cache);
}

Expand Down

0 comments on commit 7a55822

Please sign in to comment.