From f61b218e7de1c0a5278bee544977189aa66d8f38 Mon Sep 17 00:00:00 2001 From: Peng-Yu Chen Date: Sun, 2 Mar 2025 17:15:21 +0000 Subject: [PATCH] http2: enhance error messages on Curl_dyn* upon receiving headers This is a partial fix of #16535. The error message format is borrowed from the existing code[1]. Sample message before: curl: (56) process_pending_input: nghttp2_session_mem_recv() returned -902:The user callback function failed Sample message after: curl: (56) Error receiving HTTP2 header: 100(A value or data field grew larger than allowed) [1]: https://github.com/curl/curl/blob/df672695e5992ad9b99819e9950de682e243cb48/lib/http2.c#L1999-L2000 Closes #16536 --- lib/http2.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/lib/http2.c b/lib/http2.c index 45436ff83a..b8cace3a4e 100644 --- a/lib/http2.c +++ b/lib/http2.c @@ -1500,6 +1500,12 @@ static int on_begin_headers(nghttp2_session *session, return 0; } +static void report_header_error(struct Curl_easy *data, CURLcode result) +{ + failf(data, "Error receiving HTTP2 header: %d(%s)", result, + curl_easy_strerror(result)); +} + /* frame->hd.type is either NGHTTP2_HEADERS or NGHTTP2_PUSH_PROMISE */ static int on_header(nghttp2_session *session, const nghttp2_frame *frame, const uint8_t *name, size_t namelen, @@ -1599,8 +1605,10 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame, result = Curl_dynhds_add(&stream->resp_trailers, (const char *)name, namelen, (const char *)value, valuelen); - if(result) + if(result) { + report_header_error(data_s, result); return NGHTTP2_ERR_CALLBACK_FAILURE; + } return 0; } @@ -1611,13 +1619,17 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame, char buffer[32]; result = Curl_http_decode_status(&stream->status_code, (const char *)value, valuelen); - if(result) + if(result) { + report_header_error(data_s, 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) + if(result) { + report_header_error(data_s, result); return NGHTTP2_ERR_CALLBACK_FAILURE; + } Curl_dyn_reset(&ctx->scratch); result = Curl_dyn_addn(&ctx->scratch, STRCONST("HTTP/2 ")); if(!result) @@ -1627,8 +1639,10 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame, if(!result) h2_xfer_write_resp_hd(cf, data_s, stream, Curl_dyn_ptr(&ctx->scratch), Curl_dyn_len(&ctx->scratch), FALSE); - if(result) + if(result) { + report_header_error(data_s, result); return NGHTTP2_ERR_CALLBACK_FAILURE; + } /* if we receive data for another handle, wake that up */ if(CF_DATA_CURRENT(cf) != data_s) Curl_expire(data_s, 0, EXPIRE_RUN_NOW); @@ -1652,8 +1666,10 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame, if(!result) h2_xfer_write_resp_hd(cf, data_s, stream, Curl_dyn_ptr(&ctx->scratch), Curl_dyn_len(&ctx->scratch), FALSE); - if(result) + if(result) { + report_header_error(data_s, result); return NGHTTP2_ERR_CALLBACK_FAILURE; + } /* if we receive data for another handle, wake that up */ if(CF_DATA_CURRENT(cf) != data_s) Curl_expire(data_s, 0, EXPIRE_RUN_NOW); -- 2.47.3