]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
conn_shutdown: if closed during CONNECT cleanup properly
authorDaniel Stenberg <daniel@haxx.se>
Wed, 9 Jun 2021 06:38:07 +0000 (08:38 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Fri, 11 Jun 2021 10:43:53 +0000 (12:43 +0200)
Reported-by: Alex Xu
Reported-by: Phil E. Taylor
Fixes #7236
Closes #7237

lib/http_proxy.c
lib/http_proxy.h
lib/url.c

index a67d9d3b4115b782e86fdfcf4c22e412600c71e9..e0a4987063d771143fd572de8023568a5c5e863c 100644 (file)
@@ -129,13 +129,13 @@ CURLcode Curl_proxy_connect(struct Curl_easy *data, int sockindex)
 bool Curl_connect_complete(struct connectdata *conn)
 {
   return !conn->connect_state ||
-    (conn->connect_state->tunnel_state == TUNNEL_COMPLETE);
+    (conn->connect_state->tunnel_state >= TUNNEL_COMPLETE);
 }
 
 bool Curl_connect_ongoing(struct connectdata *conn)
 {
   return conn->connect_state &&
-    (conn->connect_state->tunnel_state != TUNNEL_COMPLETE);
+    (conn->connect_state->tunnel_state <= TUNNEL_COMPLETE);
 }
 
 /* when we've sent a CONNECT to a proxy, we should rather either wait for the
@@ -202,13 +202,16 @@ static void connect_done(struct Curl_easy *data)
 {
   struct connectdata *conn = data->conn;
   struct http_connect_state *s = conn->connect_state;
-  s->tunnel_state = TUNNEL_COMPLETE;
-  Curl_dyn_free(&s->rcvbuf);
-  Curl_dyn_free(&s->req);
+  if(s->tunnel_state != TUNNEL_EXIT) {
+    s->tunnel_state = TUNNEL_EXIT;
+    Curl_dyn_free(&s->rcvbuf);
+    Curl_dyn_free(&s->req);
 
-  /* retore the protocol pointer */
-  data->req.p.http = s->prot_save;
-  infof(data, "CONNECT phase completed!\n");
+    /* retore the protocol pointer */
+    data->req.p.http = s->prot_save;
+    s->prot_save = NULL;
+    infof(data, "CONNECT phase completed!\n");
+  }
 }
 
 static CURLcode CONNECT_host(struct Curl_easy *data,
index f5a4cb07cf1b4fccc44800fb6515dc9875fa83ee..cdf8de4fba861861ce69cfdedfe830eecd3acbf2 100644 (file)
@@ -65,9 +65,10 @@ struct http_connect_state {
   } keepon;
   curl_off_t cl; /* size of content to read and ignore */
   enum {
-    TUNNEL_INIT,    /* init/default/no tunnel state */
-    TUNNEL_CONNECT, /* CONNECT has been sent off */
-    TUNNEL_COMPLETE /* CONNECT response received completely */
+    TUNNEL_INIT,     /* init/default/no tunnel state */
+    TUNNEL_CONNECT,  /* CONNECT has been sent off */
+    TUNNEL_COMPLETE, /* CONNECT response received completely */
+    TUNNEL_EXIT
   } tunnel_state;
   BIT(chunked_encoding);
   BIT(close_connection);
index 84d37a560eaf55cb696f2ed256c7af1c9f1b9bb2..27ba7d6b52ce341bcd148c6141e83a03b21e0b1d 100644 (file)
--- a/lib/url.c
+++ b/lib/url.c
@@ -727,6 +727,15 @@ static void conn_shutdown(struct Curl_easy *data, struct connectdata *conn)
   DEBUGASSERT(data);
   infof(data, "Closing connection %ld\n", conn->connection_id);
 
+#ifndef USE_HYPER
+  if(conn->connect_state && conn->connect_state->prot_save) {
+    /* If this was closed with a CONNECT in progress, cleanup this temporary
+       struct arrangement */
+    data->req.p.http = NULL;
+    Curl_safefree(conn->connect_state->prot_save);
+  }
+#endif
+
   /* possible left-overs from the async name resolvers */
   Curl_resolver_cancel(data);