]> granicus.if.org Git - curl/commitdiff
Jeff Pohlmeyer did some marvelous debugging to track this one down. We MUST
authorDaniel Stenberg <daniel@haxx.se>
Sun, 14 Sep 2003 21:17:54 +0000 (21:17 +0000)
committerDaniel Stenberg <daniel@haxx.se>
Sun, 14 Sep 2003 21:17:54 +0000 (21:17 +0000)
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.

lib/hash.c
lib/hash.h
lib/hostip.c

index 1743db3c7074bf663ccf381b599671a38ffc4cb2..89078d1f370318de25787925e5e2642f2fde9668 100644 (file)
@@ -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
index 03c771a4788c0070b643bb25bde9a9ab4619481e..9009df75a3b0ac6cb4fb8cde14bcde53feaf432b 100644 (file)
@@ -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,
index c397a3c7538201a2798d521f406b923b04285657..3f465a0d05151ec451baea0fd3a0b9161c5c8ba3 100644 (file)
@@ -231,15 +231,22 @@ cache_resolv_response(struct SessionHandle *data,
     return NULL;
   }
 
-  dns->inuse = 0;
-  dns->addr = addr;
-
-  /* Store it in our dns cache */
-  Curl_hash_add(data->hostcache, entry_id, entry_len+1,
-                (const void *) dns);
+  dns->inuse = 0;   /* init to not used */
+  dns->addr = addr; /* this is the address(es) */
+
+  /* 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 */