From 14a2ca85ecb8478772a30d8c2521e5e1d1d98b3d Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 9 Jun 2021 08:38:07 +0200 Subject: [PATCH] conn_shutdown: if closed during CONNECT cleanup properly Reported-by: Alex Xu Reported-by: Phil E. Taylor Fixes #7236 Closes #7237 --- lib/http_proxy.c | 19 +++++++++++-------- lib/http_proxy.h | 7 ++++--- lib/url.c | 9 +++++++++ 3 files changed, 24 insertions(+), 11 deletions(-) diff --git a/lib/http_proxy.c b/lib/http_proxy.c index a67d9d3b4..e0a498706 100644 --- a/lib/http_proxy.c +++ b/lib/http_proxy.c @@ -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, diff --git a/lib/http_proxy.h b/lib/http_proxy.h index f5a4cb07c..cdf8de4fb 100644 --- a/lib/http_proxy.h +++ b/lib/http_proxy.h @@ -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); diff --git a/lib/url.c b/lib/url.c index 84d37a560..27ba7d6b5 100644 --- 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);