]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
doh: fix cleanup
authorStefan Eissing <stefan@eissing.org>
Wed, 17 Jul 2024 12:46:47 +0000 (14:46 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Thu, 18 Jul 2024 13:13:30 +0000 (15:13 +0200)
When removing an easy handle that had DoH sub-easy handles going, those
were not removed from the multi handle. Their memory was reclaimed on
curl_easy_cleanup() of the owning handle, but multi still had them in
their list.

Add `Curl_doh_close()` and `Curl_doh_cleanup()` as common point for
handling the DoH resource management. Use the `multi` present in the doh
handles (if so), for removal, as the `data->multi` might already have
been NULLed at this time.

Reported-by: 罗朝辉
Fixes #14207
Closes #14212

lib/doh.c
lib/doh.h
lib/multi.c
lib/request.c

index 72b0c969d9fde6c6ff18b7ea5719d581f4b2c6a4..0dcca17ccda88c7da0465303e6383a05fd82e3ff 100644 (file)
--- a/lib/doh.c
+++ b/lib/doh.c
@@ -400,7 +400,6 @@ struct Curl_addrinfo *Curl_doh(struct Curl_easy *data,
                                int *waitp)
 {
   CURLcode result = CURLE_OK;
-  int slot;
   struct dohdata *dohp;
   struct connectdata *conn = data->conn;
 #ifdef USE_HTTPSRR
@@ -484,13 +483,7 @@ struct Curl_addrinfo *Curl_doh(struct Curl_easy *data,
   return NULL;
 
 error:
-  curl_slist_free_all(dohp->headers);
-  data->req.doh->headers = NULL;
-  for(slot = 0; slot < DOH_PROBE_SLOTS; slot++) {
-    (void)curl_multi_remove_handle(data->multi, dohp->probe[slot].easy);
-    Curl_close(&dohp->probe[slot].easy);
-  }
-  Curl_safefree(data->req.doh);
+  Curl_doh_cleanup(data);
   return NULL;
 }
 
@@ -1325,10 +1318,7 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
     struct dohentry de;
     int slot;
     /* remove DoH handles from multi handle and close them */
-    for(slot = 0; slot < DOH_PROBE_SLOTS; slot++) {
-      curl_multi_remove_handle(data->multi, dohp->probe[slot].easy);
-      Curl_close(&dohp->probe[slot].easy);
-    }
+    Curl_doh_close(data);
     /* parse the responses, create the struct and return it! */
     de_init(&de);
     for(slot = 0; slot < DOH_PROBE_SLOTS; slot++) {
@@ -1415,4 +1405,32 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
   return CURLE_OK;
 }
 
+void Curl_doh_close(struct Curl_easy *data)
+{
+  struct dohdata *doh = data->req.doh;
+  if(doh) {
+    size_t slot;
+    for(slot = 0; slot < DOH_PROBE_SLOTS; slot++) {
+      if(!doh->probe[slot].easy)
+        continue;
+      /* data->multi might already be reset at this time */
+      if(doh->probe[slot].easy->multi)
+        curl_multi_remove_handle(doh->probe[slot].easy->multi,
+                                 doh->probe[slot].easy);
+      Curl_close(&doh->probe[slot].easy);
+    }
+  }
+}
+
+void Curl_doh_cleanup(struct Curl_easy *data)
+{
+  struct dohdata *doh = data->req.doh;
+  if(doh) {
+    Curl_doh_close(data);
+    curl_slist_free_all(doh->headers);
+    data->req.doh->headers = NULL;
+    Curl_safefree(data->req.doh);
+  }
+}
+
 #endif /* CURL_DISABLE_DOH */
index 68924a41722a8922ee783b0fd11f1ea23d05c533..5e86bf44a5dd9687d48fba6e01a7cc5990abb9dd 100644 (file)
--- a/lib/doh.h
+++ b/lib/doh.h
@@ -140,6 +140,8 @@ struct dohentry {
 #endif
 };
 
+void Curl_doh_close(struct Curl_easy *data);
+void Curl_doh_cleanup(struct Curl_easy *data);
 
 #ifdef UNITTESTS
 UNITTEST DOHcode doh_encode(const char *host,
index c5330ebe10ea5d6bff256d89632b6145cfdaa4e2..521af63b90e7f9d4f84ba0dc9557a30808d6fc7f 100644 (file)
@@ -2799,6 +2799,9 @@ CURLMcode curl_multi_cleanup(struct Curl_multi *multi)
     /* First remove all remaining easy handles */
     data = multi->easyp;
     while(data) {
+      if(!GOOD_EASY_HANDLE(data))
+        return CURLM_BAD_HANDLE;
+
       nextdata = data->next;
       if(!data->state.done && data->conn)
         /* if DONE was never called for this handle */
index a4227de981b4360f28d1c8acc8610e147849b3a0..5c8d52f696be9985a2958aab04a39a8a04c93231 100644 (file)
@@ -116,10 +116,7 @@ void Curl_req_hard_reset(struct SingleRequest *req, struct Curl_easy *data)
     Curl_bufq_reset(&req->sendbuf);
 
 #ifndef CURL_DISABLE_DOH
-  if(req->doh) {
-    Curl_close(&req->doh->probe[0].easy);
-    Curl_close(&req->doh->probe[1].easy);
-  }
+  Curl_doh_close(data);
 #endif
   /* Can no longer memset() this struct as we need to keep some state */
   req->size = -1;
@@ -173,14 +170,7 @@ void Curl_req_free(struct SingleRequest *req, struct Curl_easy *data)
   Curl_client_cleanup(data);
 
 #ifndef CURL_DISABLE_DOH
-  if(req->doh) {
-    Curl_close(&req->doh->probe[0].easy);
-    Curl_close(&req->doh->probe[1].easy);
-    Curl_dyn_free(&req->doh->probe[0].serverdoh);
-    Curl_dyn_free(&req->doh->probe[1].serverdoh);
-    curl_slist_free_all(req->doh->headers);
-    Curl_safefree(req->doh);
-  }
+  Curl_doh_cleanup(data);
 #endif
 }