diff options
author | Daniel Stenberg <daniel@haxx.se> | 2017-10-06 01:11:17 +0200 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2017-10-06 16:48:39 +0200 |
commit | 7f1140c8bfc47dd9b7a8010818e97e87a289bfaf (patch) | |
tree | a43d23fee735f039c24d43a8be3910cb7c90bead /lib | |
parent | 454dae0092d6f367fe486bdfd49f781329bf4500 (diff) |
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
Diffstat (limited to 'lib')
-rw-r--r-- | lib/multi.c | 39 |
1 files changed, 21 insertions, 18 deletions
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 */ |