From b1faac80396c98976f5911a08a73dadbe07cdd75 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 11 Mar 2025 17:40:21 +0100 Subject: [PATCH] multi: kill off remaining internal handles in curl_multi_cleanup - if there are pending internal handles left in the list, they are leftovers (from for example Doh) and must be freed. - unlink_all_msgsent_handles() did not properly move all msgsent handles over to the process list as intended Fixes a DoH memory leak found by oss-fuzz. Add test 2101 that can reproduce and verify. Closes #16674 --- lib/multi.c | 8 ++++--- tests/data/Makefile.am | 2 +- tests/data/test2101 | 50 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 4 deletions(-) create mode 100644 tests/data/test2101 diff --git a/lib/multi.c b/lib/multi.c index b5bb9fd503..71a7479d82 100644 --- a/lib/multi.c +++ b/lib/multi.c @@ -2478,7 +2478,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, case MSTATE_PENDING: case MSTATE_MSGSENT: /* handles in these states should NOT be in this list */ - DEBUGASSERT(0); break; default: @@ -2676,8 +2675,10 @@ CURLMcode curl_multi_perform(CURLM *m, int *running_handles) static void unlink_all_msgsent_handles(struct Curl_multi *multi) { struct Curl_llist_node *e; - for(e = Curl_llist_head(&multi->msgsent); e; e = Curl_node_next(e)) { + struct Curl_llist_node *n; + for(e = Curl_llist_head(&multi->msgsent); e; e = n) { struct Curl_easy *data = Curl_node_elem(e); + n = Curl_node_next(e); if(data) { DEBUGASSERT(data->mstate == MSTATE_MSGSENT); Curl_node_remove(&data->multi_queue); @@ -2725,8 +2726,9 @@ CURLMcode curl_multi_cleanup(CURLM *m) if(data->psl == &multi->psl) data->psl = NULL; #endif + if(data->state.internal) + Curl_close(&data); } - Curl_cpool_destroy(&multi->cpool); Curl_cshutdn_destroy(&multi->cshutdn, multi->admin); if(multi->admin) { diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am index 4d3f20ac86..213f53db32 100644 --- a/tests/data/Makefile.am +++ b/tests/data/Makefile.am @@ -252,7 +252,7 @@ test2064 test2065 test2066 test2067 test2068 test2069 test2070 test2071 \ test2072 test2073 test2074 test2075 test2076 test2077 test2078 test2079 \ test2080 test2081 test2082 test2083 test2084 test2085 test2086 test2087 \ \ -test2100 \ +test2100 test2101 \ \ test2200 test2201 test2202 test2203 test2204 test2205 \ \ diff --git a/tests/data/test2101 b/tests/data/test2101 new file mode 100644 index 0000000000..9402adfabf --- /dev/null +++ b/tests/data/test2101 @@ -0,0 +1,50 @@ + + + +HTTP +HTTP GET +DOH + + + +# +# Server-side + + + +idle + + + +# +# Client-side + + +http + + +# requires debug so that it can use the DoH server without https + + +Debug +DoH + + +DoH without response + + +http://neverreached.example.com/ --doh-url http://%HOSTIP:%HTTPPORT/%TESTNUMBER0001 -m 1 + + + +# +# Verify data after the test has been "shot" + + +# curl: (28) Resolving timed out +# curl: (6) Could not resolve hostname + +28,6 + + + -- 2.47.3