mirror of
https://github.com/moparisthebest/curl
synced 2024-12-21 23:58:49 -05:00
Jeff Pohlmeyer did some marvelous debugging to track this one down. We MUST
NOT free the existing hash entry when we try to add a new one that matches an existing entry. We now instead free the new one, and make the parent function use the old entry's struct instead.
This commit is contained in:
parent
de3281a3a8
commit
14597475b1
21
lib/hash.c
21
lib/hash.c
@ -138,34 +138,33 @@ mk_hash_element(char *key, size_t key_len, const void *p)
|
||||
|
||||
#define FETCH_LIST(x,y,z) x->table[find_slot(x, y, z)]
|
||||
|
||||
int
|
||||
Curl_hash_add(curl_hash *h, char *key, size_t key_len, const void *p)
|
||||
/* Return the data in the hash. If there already was a match in the hash,
|
||||
that data is returned. */
|
||||
void *
|
||||
Curl_hash_add(curl_hash *h, char *key, size_t key_len, void *p)
|
||||
{
|
||||
curl_hash_element *he;
|
||||
curl_llist_element *le;
|
||||
curl_llist *l = FETCH_LIST(h, key, key_len);
|
||||
|
||||
for (le = l->head;
|
||||
le;
|
||||
le = le->next) {
|
||||
for (le = l->head; le; le = le->next) {
|
||||
he = (curl_hash_element *) le->ptr;
|
||||
if (hash_key_compare(he->key, he->key_len, key, key_len)) {
|
||||
h->dtor(he->ptr);
|
||||
he->ptr = (void *) p;
|
||||
return 1;
|
||||
h->dtor(p); /* remove the NEW entry */
|
||||
return he->ptr; /* return the EXISTING entry */
|
||||
}
|
||||
}
|
||||
|
||||
he = mk_hash_element(key, key_len, p);
|
||||
if (!he)
|
||||
return 0;
|
||||
return NULL; /* failure */
|
||||
|
||||
if (Curl_llist_insert_next(l, l->tail, he)) {
|
||||
++h->size;
|
||||
return 1;
|
||||
return p; /* return the new entry */
|
||||
}
|
||||
|
||||
return 0;
|
||||
return NULL; /* failure */
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
@ -47,7 +47,7 @@ typedef struct _curl_hash_element {
|
||||
|
||||
int Curl_hash_init(curl_hash *, int, curl_hash_dtor);
|
||||
curl_hash *Curl_hash_alloc(int, curl_hash_dtor);
|
||||
int Curl_hash_add(curl_hash *, char *, size_t, const void *);
|
||||
void *Curl_hash_add(curl_hash *, char *, size_t, void *);
|
||||
int Curl_hash_delete(curl_hash *h, char *key, size_t key_len);
|
||||
void *Curl_hash_pick(curl_hash *, char *, size_t);
|
||||
void Curl_hash_apply(curl_hash *h, void *user,
|
||||
|
19
lib/hostip.c
19
lib/hostip.c
@ -231,15 +231,22 @@ cache_resolv_response(struct SessionHandle *data,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dns->inuse = 0;
|
||||
dns->addr = addr;
|
||||
dns->inuse = 0; /* init to not used */
|
||||
dns->addr = addr; /* this is the address(es) */
|
||||
|
||||
/* Store it in our dns cache */
|
||||
Curl_hash_add(data->hostcache, entry_id, entry_len+1,
|
||||
(const void *) dns);
|
||||
/* Store the resolved data in our DNS cache. This function may return a
|
||||
pointer to an existing struct already present in the hash, and it may
|
||||
return the same argument we pass in. Make no assumptions. */
|
||||
dns = Curl_hash_add(data->hostcache, entry_id, entry_len+1, (void *) dns);
|
||||
if(!dns) {
|
||||
/* major badness, run away! */
|
||||
Curl_freeaddrinfo(addr);
|
||||
free(entry_id);
|
||||
return NULL;
|
||||
}
|
||||
time(&now);
|
||||
|
||||
dns->timestamp = now;
|
||||
dns->timestamp = now; /* used now */
|
||||
dns->inuse++; /* mark entry as in-use */
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user