Fixed up a potential SEGFAULT if memory for an entry could not be

allocated.  Also, thanks to Justin Guyett for finding a problem the
hashmap_remove() function.  There was a problem where an entry's "prev"
pointer could be pointing to freed memory.

Finally, renamed all "maps" to bucket to make the source more
understandable.
This commit is contained in:
Robert James Kaes 2002-05-13 18:47:46 +00:00
parent f0b0990612
commit 73e3b495e0
2 changed files with 43 additions and 26 deletions

View File

@ -1,3 +1,11 @@
2002-05-13 Robert James Kaes <rjkaes@flarenet.com>
* src/hashmap.c (hashmap_insert): Fixed a potential SEGFAULT if
the memory for the new hashmap entry could not be allocated.
(hashmap_remove): Fixed a problem where an entry could have it's
"prev" pointer still pointing at freed memory. Thanks to Justin
Guyett for finding and fixing this problem.
2002-05-10 Robert James Kaes <rjkaes@flarenet.com> 2002-05-10 Robert James Kaes <rjkaes@flarenet.com>
* Makefile.am (install-data-local): Fixed up the tinyproxy.conf * Makefile.am (install-data-local): Fixed up the tinyproxy.conf

View File

@ -1,4 +1,4 @@
/* $Id: hashmap.c,v 1.7 2002-04-26 16:51:29 rjkaes Exp $ /* $Id: hashmap.c,v 1.8 2002-05-13 18:47:46 rjkaes Exp $
* *
* A hashmap implementation. The keys are case-insensitive NULL terminated * A hashmap implementation. The keys are case-insensitive NULL terminated
* strings, and the data is arbitrary lumps of data. Copies of both the * strings, and the data is arbitrary lumps of data. Copies of both the
@ -48,7 +48,7 @@ struct hashmap_s {
unsigned int size; unsigned int size;
hashmap_iter end_iterator; hashmap_iter end_iterator;
struct hashentry_s **maps; struct hashentry_s **buckets;
}; };
/* /*
@ -102,8 +102,8 @@ hashmap_create(unsigned int nbuckets)
return NULL; return NULL;
ptr->size = nbuckets; ptr->size = nbuckets;
ptr->maps = safecalloc(nbuckets, sizeof(struct hashentry_s *)); ptr->buckets = safecalloc(nbuckets, sizeof(struct hashentry_s *));
if (!ptr->maps) { if (!ptr->buckets) {
safefree(ptr); safefree(ptr);
return NULL; return NULL;
} }
@ -122,7 +122,7 @@ hashmap_create(unsigned int nbuckets)
* negative number is returned if "entry" was NULL * negative number is returned if "entry" was NULL
*/ */
static inline int static inline int
delete_hashentries(struct hashentry_s* entry) delete_hashbucket(struct hashentry_s* entry)
{ {
struct hashentry_s *nextptr; struct hashentry_s *nextptr;
struct hashentry_s *ptr; struct hashentry_s *ptr;
@ -159,11 +159,13 @@ hashmap_delete(hashmap_t map)
return -EINVAL; return -EINVAL;
for (i = 0; i < map->size; i++) { for (i = 0; i < map->size; i++) {
if (map->maps[i] != NULL) if (map->buckets[i] != NULL) {
delete_hashentries(map->maps[i]); delete_hashbucket(map->buckets[i]);
map->buckets[i] = NULL;
}
} }
safefree(map->maps); safefree(map->buckets);
safefree(map); safefree(map);
return 0; return 0;
@ -202,8 +204,6 @@ hashmap_insert(hashmap_t map, const char *key,
if (hash < 0) if (hash < 0)
return hash; return hash;
ptr = map->maps[hash];
/* /*
* First make copies of the key and data in case there is a memory * First make copies of the key and data in case there is a memory
* problem later. * problem later.
@ -223,6 +223,7 @@ hashmap_insert(hashmap_t map, const char *key,
data_copy = NULL; data_copy = NULL;
} }
ptr = map->buckets[hash];
if (ptr) { if (ptr) {
/* There is already an entry, so tack onto the end */ /* There is already an entry, so tack onto the end */
while (ptr) { while (ptr) {
@ -231,16 +232,18 @@ hashmap_insert(hashmap_t map, const char *key,
} }
ptr = safecalloc(1, sizeof(struct hashentry_s)); ptr = safecalloc(1, sizeof(struct hashentry_s));
if (!ptr)
goto MEM_ERROR_EXIT;
ptr->prev = prevptr; ptr->prev = prevptr;
ptr->next = NULL;
prevptr->next = ptr; prevptr->next = ptr;
} else { } else {
ptr = map->maps[hash] = safecalloc(1, sizeof(struct hashentry_s)); ptr = map->buckets[hash] = safecalloc(1, sizeof(struct hashentry_s));
} if (!ptr)
goto MEM_ERROR_EXIT;
if (!ptr) { ptr->next = ptr->prev = NULL;
safefree(key_copy);
safefree(data_copy);
return -ENOMEM;
} }
ptr->key = key_copy; ptr->key = key_copy;
@ -249,6 +252,11 @@ hashmap_insert(hashmap_t map, const char *key,
map->end_iterator++; map->end_iterator++;
return 0; return 0;
MEM_ERROR_EXIT:
safefree(key_copy);
safefree(data_copy);
return -ENOMEM;
} }
/* /*
@ -317,7 +325,7 @@ hashmap_find(hashmap_t map, const char* key)
* of a particular key. * of a particular key.
*/ */
for (i = 0; i < map->size; i++) { for (i = 0; i < map->size; i++) {
ptr = map->maps[i]; ptr = map->buckets[i];
while (ptr) { while (ptr) {
if (strcasecmp(ptr->key, key) == 0) { if (strcasecmp(ptr->key, key) == 0) {
@ -357,7 +365,7 @@ hashmap_return_entry(hashmap_t map, hashmap_iter iter,
return -EINVAL; return -EINVAL;
for (i = 0; i < map->size; i++) { for (i = 0; i < map->size; i++) {
ptr = map->maps[i]; ptr = map->buckets[i];
while (ptr) { while (ptr) {
if (count == iter) { if (count == iter) {
/* This is the data so return it */ /* This is the data so return it */
@ -395,7 +403,7 @@ hashmap_search(hashmap_t map, const char *key)
if (hash < 0) if (hash < 0)
return hash; return hash;
ptr = map->maps[hash]; ptr = map->buckets[hash];
/* Okay, there is an entry here, now see if it's the one we want */ /* Okay, there is an entry here, now see if it's the one we want */
while (ptr) { while (ptr) {
@ -430,7 +438,7 @@ hashmap_entry_by_key(hashmap_t map, const char* key, void** data)
if (hash < 0) if (hash < 0)
return hash; return hash;
ptr = map->maps[hash]; ptr = map->buckets[hash];
while (ptr) { while (ptr) {
if (strcasecmp(ptr->key, key) == 0) { if (strcasecmp(ptr->key, key) == 0) {
@ -466,8 +474,7 @@ hashmap_remove(hashmap_t map, const char *key)
if (hash < 0) if (hash < 0)
return hash; return hash;
ptr = map->maps[hash]; ptr = map->buckets[hash];
while (ptr) { while (ptr) {
if (strcasecmp(ptr->key, key) == 0) { if (strcasecmp(ptr->key, key) == 0) {
/* /*
@ -475,13 +482,15 @@ hashmap_remove(hashmap_t map, const char *key)
* and update the hashmap. * and update the hashmap.
*/ */
struct hashentry_s* prevptr = ptr->prev; struct hashentry_s* prevptr = ptr->prev;
if (prevptr) { if (prevptr != NULL) {
prevptr->next = ptr->next; prevptr->next = ptr->next;
if (ptr->next) if (ptr->next)
ptr->next->prev = prevptr; ptr->next->prev = prevptr;
} else { } else {
map->maps[hash] = ptr->next; /* Entry was first in map */
ptr->prev = NULL; map->buckets[hash] = ptr->next;
if (ptr->next)
ptr->next->prev = NULL;
} }
safefree(ptr->key); safefree(ptr->key);
@ -494,7 +503,7 @@ hashmap_remove(hashmap_t map, const char *key)
if (prevptr) if (prevptr)
ptr = prevptr; ptr = prevptr;
else else
ptr = map->maps[hash]; ptr = map->buckets[hash];
continue; continue;
} }