From e7de83aa2982a9be84a0f73a2533742702bd6351 Mon Sep 17 00:00:00 2001 From: Stefan Eissing Date: Mon, 3 Mar 2025 14:05:34 +0100 Subject: [PATCH] http2: reset stream on response header error We send a GOAWAY, but some servers ignore that and happily continue sending the stream response. RST the stream when response header errors are encountered. Fixes #16535 Reported-by: Peng-Yu Chen Closes #16544 --- lib/http2.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/lib/http2.c b/lib/http2.c index b8cace3a4e..ef95d03e00 100644 --- a/lib/http2.c +++ b/lib/http2.c @@ -1500,10 +1500,21 @@ static int on_begin_headers(nghttp2_session *session, return 0; } -static void report_header_error(struct Curl_easy *data, CURLcode result) +static void cf_h2_header_error(struct Curl_cfilter *cf, + struct Curl_easy *data, + struct h2_stream_ctx *stream, + CURLcode result) { + struct cf_h2_ctx *ctx = cf->ctx; + failf(data, "Error receiving HTTP2 header: %d(%s)", result, curl_easy_strerror(result)); + if(stream) { + nghttp2_submit_rst_stream(ctx->h2, NGHTTP2_FLAG_NONE, + stream->id, NGHTTP2_STREAM_CLOSED); + stream->closed = TRUE; + stream->reset = TRUE; + } } /* frame->hd.type is either NGHTTP2_HEADERS or NGHTTP2_PUSH_PROMISE */ @@ -1606,7 +1617,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame, (const char *)name, namelen, (const char *)value, valuelen); if(result) { - report_header_error(data_s, result); + cf_h2_header_error(cf, data_s, stream, result); return NGHTTP2_ERR_CALLBACK_FAILURE; } @@ -1620,14 +1631,14 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame, result = Curl_http_decode_status(&stream->status_code, (const char *)value, valuelen); if(result) { - report_header_error(data_s, result); + cf_h2_header_error(cf, data_s, stream, result); return NGHTTP2_ERR_CALLBACK_FAILURE; } msnprintf(buffer, sizeof(buffer), HTTP_PSEUDO_STATUS ":%u\r", stream->status_code); result = Curl_headers_push(data_s, buffer, CURLH_PSEUDO); if(result) { - report_header_error(data_s, result); + cf_h2_header_error(cf, data_s, stream, result); return NGHTTP2_ERR_CALLBACK_FAILURE; } Curl_dyn_reset(&ctx->scratch); @@ -1640,7 +1651,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame, h2_xfer_write_resp_hd(cf, data_s, stream, Curl_dyn_ptr(&ctx->scratch), Curl_dyn_len(&ctx->scratch), FALSE); if(result) { - report_header_error(data_s, result); + cf_h2_header_error(cf, data_s, stream, result); return NGHTTP2_ERR_CALLBACK_FAILURE; } /* if we receive data for another handle, wake that up */ @@ -1667,7 +1678,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame, h2_xfer_write_resp_hd(cf, data_s, stream, Curl_dyn_ptr(&ctx->scratch), Curl_dyn_len(&ctx->scratch), FALSE); if(result) { - report_header_error(data_s, result); + cf_h2_header_error(cf, data_s, stream, result); return NGHTTP2_ERR_CALLBACK_FAILURE; } /* if we receive data for another handle, wake that up */ -- 2.47.3