headers: add length argument to Curl_headers_push()
No binary (build failed)
—
(log yok)
| @@ -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) | |
| @@ -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 | |
| @@ -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; | |