Commit 14597475 authored by Daniel Stenberg's avatar Daniel Stenberg
Browse files

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.
parent de3281a3
Loading
Loading
Loading
Loading
+10 −11
Original line number Diff line number Diff line
@@ -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
+1 −1
Original line number Diff line number Diff line
@@ -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,
+14 −7
Original line number Diff line number Diff line
@@ -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 */