]> granicus.if.org Git - curl/commitdiff
resolve: don't leak pre-populated dns entries
authorDaniel Stenberg <daniel@haxx.se>
Fri, 23 Dec 2011 13:30:43 +0000 (14:30 +0100)
committerDaniel Stenberg <daniel@haxx.se>
Fri, 23 Dec 2011 13:46:20 +0000 (14:46 +0100)
CURLOPT_RESOLVE populates the DNS cache with entries that are marked as
eternally in use. Those entries need to be taken care of when the cache
is killed off.

Bug: http://curl.haxx.se/bug/view.cgi?id=3463121
Reported by: "tw84452852"

lib/hostip.c
lib/hostip.h
lib/url.c

index d261a163a438a2d3830ff41125fdb6e6ff111b51..44ed0a42480b9e9bdbb3d180047b300353d1ce09 100644 (file)
@@ -721,4 +721,25 @@ struct curl_hash *Curl_mk_dnscache(void)
   return Curl_hash_alloc(7, Curl_hash_str, Curl_str_key_compare, freednsentry);
 }
 
+static int hostcache_inuse(void *data, void *hc)
+{
+  struct Curl_dns_entry *c = (struct Curl_dns_entry *) hc;
+
+  if(c->inuse == 1)
+    Curl_resolv_unlock(data, c);
+
+  return 1; /* free all entries */
+}
 
+void Curl_hostcache_destroy(struct SessionHandle *data)
+{
+  /* Entries added to the hostcache with the CURLOPT_RESOLVE function are
+   * still present in the cache with the inuse counter set to 1. Detect them
+   * and cleanup!
+   */
+  Curl_hash_clean_with_criterium(data->dns.hostcache, data, hostcache_inuse);
+
+  Curl_hash_destroy(data->dns.hostcache);
+  data->dns.hostcachetype = HCACHE_NONE;
+  data->dns.hostcache = NULL;
+}
index dbbb1f7a258b18943500e49414c67dc42b02d847..100bdc58e10b6a30afded87930f42537c6ec02fb 100644 (file)
@@ -200,4 +200,9 @@ extern sigjmp_buf curl_jmpenv;
  */
 CURLcode Curl_set_dns_servers(struct SessionHandle *data, char *servers);
 
+/*
+ * Destroy the hostcache of this handle.
+ */
+void Curl_hostcache_destroy(struct SessionHandle *data);
+
 #endif /* HEADER_CURL_HOSTIP_H */
index 9896dd8c0c5f349cd85fe2786788886e8c55f3a1..75b298706f58eaec7962d62a7ac28cf7938d02e1 100644 (file)
--- a/lib/url.c
+++ b/lib/url.c
@@ -467,11 +467,8 @@ CURLcode Curl_close(struct SessionHandle *data)
     return CURLE_OK;
   }
 
-  if(data->dns.hostcachetype == HCACHE_PRIVATE) {
-    Curl_hash_destroy(data->dns.hostcache);
-    data->dns.hostcachetype = HCACHE_NONE;
-    data->dns.hostcache = NULL;
-  }
+  if(data->dns.hostcachetype == HCACHE_PRIVATE)
+    Curl_hostcache_destroy(data);
 
   if(data->state.rangestringalloc)
     free(data->state.range);
@@ -2131,7 +2128,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
       if(data->share->hostcache) {
         /* use shared host cache, first free the private one if any */
         if(data->dns.hostcachetype == HCACHE_PRIVATE)
-          Curl_hash_destroy(data->dns.hostcache);
+          Curl_hostcache_destroy(data);
 
         data->dns.hostcache = data->share->hostcache;
         data->dns.hostcachetype = HCACHE_SHARED;
@@ -2626,12 +2623,6 @@ CURLcode Curl_disconnect(struct connectdata *conn, bool dead_connection)
     conn->dns_entry = NULL;
   }
 
-#if defined(DEBUGBUILD) && defined(AGGRESIVE_TEST)
-  /* scan for DNS cache entries still marked as in use */
-  Curl_hash_apply(data->hostcache,
-                  NULL, Curl_scan_cache_used);
-#endif
-
   Curl_hostcache_prune(data); /* kill old DNS cache entries */
 
   {