From 7f1140c8bfc47dd9b7a8010818e97e87a289bfaf Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 6 Oct 2017 01:11:17 +0200 Subject: multi_cleanup: call DONE on handles that never got that ... fixes a memory leak with at least IMAP when remove_handle is never called and the transfer is abruptly just abandoned early. Test 1552 added to verify Detected by OSS-fuzz Assisted-by: Max Dymond Closes #1954 --- lib/multi.c | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) (limited to 'lib/multi.c') diff --git a/lib/multi.c b/lib/multi.c index 70aa6bcf9..faf42f1fa 100644 --- a/lib/multi.c +++ b/lib/multi.c @@ -2224,6 +2224,27 @@ CURLMcode curl_multi_cleanup(struct Curl_multi *multi) multi->type = 0; /* not good anymore */ + /* Firsrt remove all remaining easy handles */ + data = multi->easyp; + while(data) { + nextdata = data->next; + if(!data->state.done && data->easy_conn) + /* if DONE was never called for this handle */ + (void)multi_done(&data->easy_conn, CURLE_OK, TRUE); + if(data->dns.hostcachetype == HCACHE_MULTI) { + /* clear out the usage of the shared DNS cache */ + Curl_hostcache_clean(data, data->dns.hostcache); + data->dns.hostcache = NULL; + data->dns.hostcachetype = HCACHE_NONE; + } + + /* Clear the pointer to the connection cache */ + data->state.conn_cache = NULL; + data->multi = NULL; /* clear the association */ + + data = nextdata; + } + /* Close all the connections in the connection cache */ close_all_connections(multi); @@ -2243,24 +2264,6 @@ CURLMcode curl_multi_cleanup(struct Curl_multi *multi) Curl_llist_destroy(&multi->msglist, NULL); Curl_llist_destroy(&multi->pending, NULL); - /* remove all easy handles */ - data = multi->easyp; - while(data) { - nextdata = data->next; - if(data->dns.hostcachetype == HCACHE_MULTI) { - /* clear out the usage of the shared DNS cache */ - Curl_hostcache_clean(data, data->dns.hostcache); - data->dns.hostcache = NULL; - data->dns.hostcachetype = HCACHE_NONE; - } - - /* Clear the pointer to the connection cache */ - data->state.conn_cache = NULL; - data->multi = NULL; /* clear the association */ - - data = nextdata; - } - Curl_hash_destroy(&multi->hostcache); /* Free the blacklists by setting them to NULL */ -- cgit v1.2.3