aboutsummaryrefslogtreecommitdiff
path: root/lib/multi.c
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2017-10-06 01:11:17 +0200
committerDaniel Stenberg <daniel@haxx.se>2017-10-06 16:48:39 +0200
commit7f1140c8bfc47dd9b7a8010818e97e87a289bfaf (patch)
treea43d23fee735f039c24d43a8be3910cb7c90bead /lib/multi.c
parent454dae0092d6f367fe486bdfd49f781329bf4500 (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/multi.c')
-rw-r--r--lib/multi.c39
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 */