]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
multi: kill off remaining internal handles in curl_multi_cleanup
authorDaniel Stenberg <daniel@haxx.se>
Tue, 11 Mar 2025 16:40:21 +0000 (17:40 +0100)
committerDaniel Stenberg <daniel@haxx.se>
Wed, 12 Mar 2025 08:22:32 +0000 (09:22 +0100)
- 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
tests/data/Makefile.am
tests/data/test2101 [new file with mode: 0644]

index b5bb9fd5030d468b73d7c646ccbaa8650f454d45..71a7479d82c520866bed9e838d9bb936fb51acf2 100644 (file)
@@ -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) {
index 4d3f20ac86ffeabc9e61e9bd524ffe5b527bbbf9..213f53db327c76b7b66e08cb10b34122851cfa50 100644 (file)
@@ -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 (file)
index 0000000..9402adf
--- /dev/null
@@ -0,0 +1,50 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+DOH
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+
+<servercmd>
+idle
+</servercmd>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+
+# requires debug so that it can use the DoH server without https
+
+<features>
+Debug
+DoH
+</features>
+<name>
+DoH without response
+</name>
+<command>
+http://neverreached.example.com/ --doh-url http://%HOSTIP:%HTTPPORT/%TESTNUMBER0001 -m 1
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+
+# curl: (28) Resolving timed out
+# curl: (6) Could not resolve hostname
+<errorcode>
+28,6
+</errorcode>
+</verify>
+</testcase>