mirror of
https://github.com/moparisthebest/curl
synced 2024-12-22 08:08:50 -05:00
http: move HTTP/2 cleanup code off http_disconnect()
Otherwise it would never be called for an HTTP/2 connection, which has its own disconnect handler. I spotted this while debugging <https://bugzilla.redhat.com/1248389> where the http_disconnect() handler was called on an FTP session handle causing 'dnf' to crash. conn->data->req.protop of type (struct FTP *) was reinterpreted as type (struct HTTP *) which resulted in SIGSEGV in Curl_add_buffer_free() after printing the "Connection cache is full, closing the oldest one." message. A previously working version of libcurl started to crash after it was recompiled with the HTTP/2 support despite the HTTP/2 protocol was not actually used. This commit makes it work again although I suspect the root cause (reinterpreting session handle data of incompatible protocol) still has to be fixed. Otherwise the same will happen when mixing FTP and HTTP/2 connections and exceeding the connection cache limit. Reported-by: Tomas Tomecek Bug: https://bugzilla.redhat.com/1248389
This commit is contained in:
parent
ecf7618e12
commit
f7dcc7c118
25
lib/http.c
25
lib/http.c
@ -86,7 +86,6 @@
|
|||||||
* Forward declarations.
|
* Forward declarations.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static CURLcode http_disconnect(struct connectdata *conn, bool dead);
|
|
||||||
static int http_getsock_do(struct connectdata *conn,
|
static int http_getsock_do(struct connectdata *conn,
|
||||||
curl_socket_t *socks,
|
curl_socket_t *socks,
|
||||||
int numsocks);
|
int numsocks);
|
||||||
@ -117,7 +116,7 @@ const struct Curl_handler Curl_handler_http = {
|
|||||||
http_getsock_do, /* doing_getsock */
|
http_getsock_do, /* doing_getsock */
|
||||||
ZERO_NULL, /* domore_getsock */
|
ZERO_NULL, /* domore_getsock */
|
||||||
ZERO_NULL, /* perform_getsock */
|
ZERO_NULL, /* perform_getsock */
|
||||||
http_disconnect, /* disconnect */
|
ZERO_NULL, /* disconnect */
|
||||||
ZERO_NULL, /* readwrite */
|
ZERO_NULL, /* readwrite */
|
||||||
PORT_HTTP, /* defport */
|
PORT_HTTP, /* defport */
|
||||||
CURLPROTO_HTTP, /* protocol */
|
CURLPROTO_HTTP, /* protocol */
|
||||||
@ -141,7 +140,7 @@ const struct Curl_handler Curl_handler_https = {
|
|||||||
http_getsock_do, /* doing_getsock */
|
http_getsock_do, /* doing_getsock */
|
||||||
ZERO_NULL, /* domore_getsock */
|
ZERO_NULL, /* domore_getsock */
|
||||||
ZERO_NULL, /* perform_getsock */
|
ZERO_NULL, /* perform_getsock */
|
||||||
http_disconnect, /* disconnect */
|
ZERO_NULL, /* disconnect */
|
||||||
ZERO_NULL, /* readwrite */
|
ZERO_NULL, /* readwrite */
|
||||||
PORT_HTTPS, /* defport */
|
PORT_HTTPS, /* defport */
|
||||||
CURLPROTO_HTTPS, /* protocol */
|
CURLPROTO_HTTPS, /* protocol */
|
||||||
@ -169,26 +168,6 @@ CURLcode Curl_http_setup_conn(struct connectdata *conn)
|
|||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static CURLcode http_disconnect(struct connectdata *conn, bool dead_connection)
|
|
||||||
{
|
|
||||||
#ifdef USE_NGHTTP2
|
|
||||||
struct HTTP *http = conn->data->req.protop;
|
|
||||||
if(http) {
|
|
||||||
Curl_add_buffer_free(http->header_recvbuf);
|
|
||||||
http->header_recvbuf = NULL; /* clear the pointer */
|
|
||||||
for(; http->push_headers_used > 0; --http->push_headers_used) {
|
|
||||||
free(http->push_headers[http->push_headers_used - 1]);
|
|
||||||
}
|
|
||||||
free(http->push_headers);
|
|
||||||
http->push_headers = NULL;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
(void)conn;
|
|
||||||
#endif
|
|
||||||
(void)dead_connection;
|
|
||||||
return CURLE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* checkheaders() checks the linked list of custom HTTP headers for a
|
* checkheaders() checks the linked list of custom HTTP headers for a
|
||||||
* particular header (prefix).
|
* particular header (prefix).
|
||||||
|
11
lib/http2.c
11
lib/http2.c
@ -80,6 +80,7 @@ static int http2_getsock(struct connectdata *conn,
|
|||||||
static CURLcode http2_disconnect(struct connectdata *conn,
|
static CURLcode http2_disconnect(struct connectdata *conn,
|
||||||
bool dead_connection)
|
bool dead_connection)
|
||||||
{
|
{
|
||||||
|
struct HTTP *http = conn->data->req.protop;
|
||||||
struct http_conn *c = &conn->proto.httpc;
|
struct http_conn *c = &conn->proto.httpc;
|
||||||
(void)dead_connection;
|
(void)dead_connection;
|
||||||
|
|
||||||
@ -89,6 +90,16 @@ static CURLcode http2_disconnect(struct connectdata *conn,
|
|||||||
Curl_safefree(c->inbuf);
|
Curl_safefree(c->inbuf);
|
||||||
Curl_hash_destroy(&c->streamsh);
|
Curl_hash_destroy(&c->streamsh);
|
||||||
|
|
||||||
|
if(http) {
|
||||||
|
Curl_add_buffer_free(http->header_recvbuf);
|
||||||
|
http->header_recvbuf = NULL; /* clear the pointer */
|
||||||
|
for(; http->push_headers_used > 0; --http->push_headers_used) {
|
||||||
|
free(http->push_headers[http->push_headers_used - 1]);
|
||||||
|
}
|
||||||
|
free(http->push_headers);
|
||||||
|
http->push_headers = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
DEBUGF(infof(conn->data, "HTTP/2 DISCONNECT done\n"));
|
DEBUGF(infof(conn->data, "HTTP/2 DISCONNECT done\n"));
|
||||||
|
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
|
Loading…
Reference in New Issue
Block a user