From 2caa454dc19237588ee3696fac2d74fb86eb0d98 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 23 Dec 2011 14:30:43 +0100 Subject: resolve: don't leak pre-populated dns entries 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 | 21 +++++++++++++++++++++ lib/hostip.h | 5 +++++ lib/url.c | 15 +++------------ 3 files changed, 29 insertions(+), 12 deletions(-) diff --git a/lib/hostip.c b/lib/hostip.c index d261a163a..44ed0a424 100644 --- a/lib/hostip.c +++ b/lib/hostip.c @@ -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; +} diff --git a/lib/hostip.h b/lib/hostip.h index dbbb1f7a2..100bdc58e 100644 --- a/lib/hostip.h +++ b/lib/hostip.h @@ -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 */ diff --git a/lib/url.c b/lib/url.c index 9896dd8c0..75b298706 100644 --- 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 */ { -- cgit v1.2.3