]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
hyper: fix ownership problems
authorNicholas Nethercote <n.nethercote@gmail.com>
Mon, 28 Aug 2023 04:35:08 +0000 (14:35 +1000)
committerDaniel Stenberg <daniel@haxx.se>
Mon, 28 Aug 2023 09:06:15 +0000 (11:06 +0200)
Some of these changes come from comparing `Curl_http` and
`start_CONNECT`, which are similar, and adding things to them that are
present in one and missing in another.

The most important changes:
- In `start_CONNECT`, add a missing `hyper_clientconn_free` call on the
  happy path.
- In `start_CONNECT`, add a missing `hyper_request_free` on the error
  path.
- In `bodysend`, add a missing `hyper_body_free` on an early-exit path.
- In `bodysend`, remove an unnecessary `hyper_body_free` on a different
  error path that would cause a double-free.
  https://docs.rs/hyper/latest/hyper/ffi/fn.hyper_request_set_body.html
  says of `hyper_request_set_body`: "This takes ownership of the
  hyper_body *, you must not use it or free it after setting it on the
  request." This is true even if `hyper_request_set_body` returns an
  error; I confirmed this by looking at the hyper source code.

Other changes are minor but make things slightly nicer.

Closes #11745

lib/c-hyper.c
lib/cf-h1-proxy.c

index 808e4e11725c837564ea9f0b341b6bd3ceb545a8..f0f49ce6c20d858ea15866ab2ae7095f66852f0b 100644 (file)
@@ -808,15 +808,16 @@ static CURLcode bodysend(struct Curl_easy *data,
       hyper_body_set_data_func(body, uploadpostfields);
     else {
       result = Curl_get_upload_buffer(data);
-      if(result)
+      if(result) {
+        hyper_body_free(body);
         return result;
+      }
       /* init the "upload from here" pointer */
       data->req.upload_fromhere = data->state.ulbuf;
       hyper_body_set_data_func(body, uploadstreamed);
     }
     if(HYPERE_OK != hyper_request_set_body(hyperreq, body)) {
       /* fail */
-      hyper_body_free(body);
       result = CURLE_OUT_OF_MEMORY;
     }
   }
@@ -1215,6 +1216,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
     result = CURLE_OUT_OF_MEMORY;
     goto error;
   }
+  sendtask = NULL; /* ownership passed on */
 
   hyper_clientconn_free(client);
   client = NULL;
index 981ef228da84d64090cae78605400a25acfc402e..e9bc13d2a8911eda3246afcbd9ad4c1c030121d8 100644 (file)
@@ -715,14 +715,13 @@ static CURLcode start_CONNECT(struct Curl_cfilter *cf,
   }
 
   options = hyper_clientconn_options_new();
-  hyper_clientconn_options_set_preserve_header_case(options, 1);
-  hyper_clientconn_options_set_preserve_header_order(options, 1);
-
   if(!options) {
     failf(data, "Couldn't create hyper client options");
     result = CURLE_OUT_OF_MEMORY;
     goto error;
   }
+  hyper_clientconn_options_set_preserve_header_case(options, 1);
+  hyper_clientconn_options_set_preserve_header_order(options, 1);
 
   hyper_clientconn_options_exec(options, h->exec);
 
@@ -753,6 +752,7 @@ static CURLcode start_CONNECT(struct Curl_cfilter *cf,
 
   client = hyper_task_value(task);
   hyper_task_free(task);
+
   req = hyper_request_new();
   if(!req) {
     failf(data, "Couldn't hyper_request_new");
@@ -861,12 +861,17 @@ static CURLcode start_CONNECT(struct Curl_cfilter *cf,
     result = CURLE_OUT_OF_MEMORY;
     goto error;
   }
+  req = NULL;
 
   if(HYPERE_OK != hyper_executor_push(h->exec, sendtask)) {
     failf(data, "Couldn't hyper_executor_push the send");
     result = CURLE_OUT_OF_MEMORY;
     goto error;
   }
+  sendtask = NULL; /* ownership passed on */
+
+  hyper_clientconn_free(client);
+  client = NULL;
 
 error:
   free(host);
@@ -879,6 +884,9 @@ error:
     hyper_task_free(handshake);
   if(client)
     hyper_clientconn_free(client);
+  if(req)
+    hyper_request_free(req);
+
   return result;
 }