]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
headers: add length argument to Curl_headers_push()
authorDaniel Stenberg <daniel@haxx.se>
Tue, 9 Dec 2025 08:58:48 +0000 (09:58 +0100)
committerDaniel Stenberg <daniel@haxx.se>
Tue, 9 Dec 2025 09:49:28 +0000 (10:49 +0100)
- the length is already known by parent functions
- avoids strlen() calls
- avoids strchr() calls for trimming off newline characters

Closes #19886

lib/headers.c
lib/headers.h
lib/http2.c

index 7cf215c0800ebacb07b0c88c4f5199d6dd44a3aa..46de5d107bc981636fe57ad9553c6d06c29b37aa 100644 (file)
@@ -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)
index 7249355f0ccd24e49c8c2ac955e630fcf5d4160c..adb03af75b5e1fecf3713fcfb51dcd74fe4f98ff 100644 (file)
@@ -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
 
index deed6ece7ee172b1066a0706ee7be4915134f685..83b9280b2a155b46089fcf85aa58f00076e814ae 100644 (file)
@@ -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;