http: only accept ';' as a separator for custom headers
No binary (build failed)
—
(log yok)
| @@ -277,14 +277,13 @@ static bool http_header_is_empty(const char *header) | |
| /* | |
| * Strip off leading and trailing whitespace from the value in the given HTTP | |
| - | * header line and return a strdup()ed copy. Returns NULL in case of |
| - | * allocation failure or bad input. Returns an empty string if the header |
| - | * value consists entirely of whitespace. |
| + | * header line and return a strdup()ed copy in 'valp' - returns an empty |
| + | * string if the header value consists entirely of whitespace. |
| * | |
| - | * If the header is provided as "name;", ending with a semicolon, it must |
| - | * return a blank string. |
| + | * If the header is provided as "name;", ending with a semicolon, it returns a |
| + | * blank string. |
| */ | |
| - | char *Curl_copy_header_value(const char *header) |
| + | static CURLcode copy_custom_value(const char *header, char **valp) |
| { | |
| struct Curl_str out; | |
| @@ -294,9 +293,37 @@ char *Curl_copy_header_value(const char *header) | |
| curlx_str_untilnl(&header, &out, MAX_HTTP_RESP_HEADER_SIZE); | |
| curlx_str_trimblanks(&out); | |
| - | return Curl_memdup0(curlx_str(&out), curlx_strlen(&out)); |
| + | *valp = Curl_memdup0(curlx_str(&out), curlx_strlen(&out)); |
| + | if(*valp) |
| + | return CURLE_OK; |
| + | return CURLE_OUT_OF_MEMORY; |
| } | |
| /* bad input */ | |
| + | *valp = NULL; |
| + | return CURLE_BAD_FUNCTION_ARGUMENT; |
| + | } |
| + | |
| + | /* |
| + | * Strip off leading and trailing whitespace from the value in the given HTTP |
| + | * header line and return a strdup()ed copy in 'valp' - returns an empty |
| + | * string if the header value consists entirely of whitespace. |
| + | * |
| + | * This function MUST be used after the header has already been confirmed to |
| + | * lead with "word:". |
| + | */ |
| + | char *Curl_copy_header_value(const char *header) |
| + | { |
| + | struct Curl_str out; |
| + | |
| + | /* find the end of the header name */ |
| + | if(!curlx_str_until(&header, &out, MAX_HTTP_RESP_HEADER_SIZE, ':') && |
| + | !curlx_str_single(&header, ':')) { |
| + | curlx_str_untilnl(&header, &out, MAX_HTTP_RESP_HEADER_SIZE); |
| + | curlx_str_trimblanks(&out); |
| + | return Curl_memdup0(curlx_str(&out), curlx_strlen(&out)); |
| + | } |
| + | /* bad input, should never happen */ |
| + | DEBUGASSERT(0); |
| return NULL; | |
| } | |
| @@ -1906,9 +1933,10 @@ static CURLcode http_set_aptr_host(struct Curl_easy *data) | |
| custom Host: header if this is NOT a redirect, as setting Host: in the | |
| redirected request is being out on thin ice. Except if the hostname | |
| is the same as the first one! */ | |
| - | char *cookiehost = Curl_copy_header_value(ptr); |
| - | if(!cookiehost) |
| - | return CURLE_OUT_OF_MEMORY; |
| + | char *cookiehost; |
| + | CURLcode result = copy_custom_value(ptr, &cookiehost); |
| + | if(result) |
| + | return result; |
| if(!*cookiehost) | |
| /* ignore empty data */ | |
| free(cookiehost); | |
| @@ -2657,7 +2685,6 @@ static CURLcode http_add_connection_hd(struct Curl_easy *data, | |
| const char *sep = "Connection: "; | |
| CURLcode result = CURLE_OK; | |
| size_t rlen = curlx_dyn_len(req); | |
| - | char *value; |
| bool skip; | |
| /* Add the 1st custom "Connection: " header, if there is one */ | |
| @@ -2665,9 +2692,10 @@ static CURLcode http_add_connection_hd(struct Curl_easy *data, | |
| if(curl_strnequal(head->data, "Connection", 10) && | |
| Curl_headersep(head->data[10]) && | |
| !http_header_is_empty(head->data)) { | |
| - | value = Curl_copy_header_value(head->data); |
| - | if(!value) |
| - | return CURLE_OUT_OF_MEMORY; |
| + | char *value; |
| + | result = copy_custom_value(head->data, &value); |
| + | if(result) |
| + | return result; |
| result = curlx_dyn_addf(req, "%s%s", sep, value); | |
| sep = ", "; | |
| free(value); | |
| @@ -3346,11 +3374,11 @@ static CURLcode http_header_p(struct Curl_easy *data, | |
| #endif | |
| if((407 == k->httpcode) && HD_IS(hd, hdlen, "Proxy-authenticate:")) { | |
| char *auth = Curl_copy_header_value(hd); | |
| - | CURLcode result; |
| - | if(!auth) |
| - | return CURLE_OUT_OF_MEMORY; |
| - | result = Curl_http_input_auth(data, TRUE, auth); |
| - | free(auth); |
| + | CURLcode result = auth ? CURLE_OK : CURLE_OUT_OF_MEMORY; |
| + | if(!result) { |
| + | result = Curl_http_input_auth(data, TRUE, auth); |
| + | free(auth); |
| + | } |
| return result; | |
| } | |
| #ifdef USE_SPNEGO | |
| @@ -3525,9 +3553,11 @@ static CURLcode http_header_w(struct Curl_easy *data, | |
| if((401 == k->httpcode) && HD_IS(hd, hdlen, "WWW-Authenticate:")) { | |
| char *auth = Curl_copy_header_value(hd); | |
| if(!auth) | |
| - | return CURLE_OUT_OF_MEMORY; |
| - | result = Curl_http_input_auth(data, FALSE, auth); |
| - | free(auth); |
| + | result = CURLE_OUT_OF_MEMORY; |
| + | else { |
| + | result = Curl_http_input_auth(data, FALSE, auth); |
| + | free(auth); |
| + | } |
| } | |
| return result; | |
| } | |