From: Daniel Stenberg Date: Tue, 9 Dec 2025 08:58:48 +0000 (+0100) Subject: headers: add length argument to Curl_headers_push() X-Git-Tag: rc-8_18_0-2~83 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4c3614304faf07a643ca060eeccde21c8896940b;p=thirdparty%2Fcurl.git headers: add length argument to Curl_headers_push() - the length is already known by parent functions - avoids strlen() calls - avoids strchr() calls for trimming off newline characters Closes #19886 --- diff --git a/lib/headers.c b/lib/headers.c index 7cf215c080..46de5d107b 100644 --- a/lib/headers.c +++ b/lib/headers.c @@ -266,30 +266,31 @@ static CURLcode unfold_value(struct Curl_easy *data, const char *value, /* * Curl_headers_push() gets passed a full HTTP header to store. It gets called - * immediately before the header callback. The header is CRLF terminated. + * immediately before the header callback. The header is CRLF, CR or LF + * terminated. */ CURLcode Curl_headers_push(struct Curl_easy *data, const char *header, + size_t hlen, /* length of header */ unsigned char type) { char *value = NULL; char *name = NULL; - char *end; - size_t hlen; /* length of the incoming header */ struct Curl_header_store *hs; CURLcode result = CURLE_OUT_OF_MEMORY; + const size_t ilen = hlen; if((header[0] == '\r') || (header[0] == '\n')) /* ignore the body separator */ return CURLE_OK; - end = strchr(header, '\r'); - if(!end) { - end = strchr(header, '\n'); - if(!end) - /* neither CR nor LF as terminator is not a valid header */ - return CURLE_WEIRD_SERVER_REPLY; - } - hlen = end - header; + /* trim off newline characters */ + if(hlen && (header[hlen - 1] == '\n')) + hlen--; + if(hlen && (header[hlen - 1] == '\r')) + hlen--; + if(hlen == ilen) + /* neither CR nor LF as terminator is not a valid header */ + return CURLE_WEIRD_SERVER_REPLY; if((header[0] == ' ') || (header[0] == '\t')) { if(data->state.prevhead) @@ -359,7 +360,7 @@ static CURLcode hds_cw_collect_write(struct Curl_easy *data, (type & CLIENTWRITE_1XX ? CURLH_1XX : (type & CLIENTWRITE_TRAILER ? CURLH_TRAILER : CURLH_HEADER))); - CURLcode result = Curl_headers_push(data, buf, htype); + CURLcode result = Curl_headers_push(data, buf, blen, htype); CURL_TRC_WRITE(data, "header_collect pushed(type=%x, len=%zu) -> %d", htype, blen, result); if(result) diff --git a/lib/headers.h b/lib/headers.h index 7249355f0c..adb03af75b 100644 --- a/lib/headers.h +++ b/lib/headers.h @@ -46,7 +46,7 @@ CURLcode Curl_headers_init(struct Curl_easy *data); * Curl_headers_push() gets passed a full header to store. */ CURLcode Curl_headers_push(struct Curl_easy *data, const char *header, - unsigned char type); + size_t hlen, unsigned char type); /* * Curl_headers_cleanup(). Free all stored headers and associated memory. @@ -55,7 +55,7 @@ CURLcode Curl_headers_cleanup(struct Curl_easy *data); #else #define Curl_headers_init(x) CURLE_OK -#define Curl_headers_push(x, y, z) CURLE_OK +#define Curl_headers_push(x,y,z,a) CURLE_OK #define Curl_headers_cleanup(x) Curl_nop_stmt #endif diff --git a/lib/http2.c b/lib/http2.c index deed6ece7e..83b9280b2a 100644 --- a/lib/http2.c +++ b/lib/http2.c @@ -1664,15 +1664,16 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame, memcmp(HTTP_PSEUDO_STATUS, name, namelen) == 0) { /* nghttp2 guarantees :status is received first and only once. */ char buffer[32]; + size_t hlen; result = Curl_http_decode_status(&stream->status_code, (const char *)value, valuelen); if(result) { cf_h2_header_error(cf, data_s, stream, result); return NGHTTP2_ERR_CALLBACK_FAILURE; } - curl_msnprintf(buffer, sizeof(buffer), HTTP_PSEUDO_STATUS ":%u\r", - stream->status_code); - result = Curl_headers_push(data_s, buffer, CURLH_PSEUDO); + hlen = curl_msnprintf(buffer, sizeof(buffer), HTTP_PSEUDO_STATUS ":%u\r", + stream->status_code); + result = Curl_headers_push(data_s, buffer, hlen, CURLH_PSEUDO); if(result) { cf_h2_header_error(cf, data_s, stream, result); return NGHTTP2_ERR_CALLBACK_FAILURE;