http: when unfolding, leave single-space for new header line

Restore the unfolding behavior from before 67ae101666. This change
(leaving more whitespace in the delivered headers) turned out causing
some friction in the git project so presumably others might also find it
a little surprising.

Reported-by: Jeff King
Ref: https://marc.info/?l=git&m=176606332701171&w=2
Closes #20016
This commit is contained in:
Daniel Stenberg 2025-12-18 13:58:22 +01:00
parent 673e02a616
commit 9941e7c95b
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2
4 changed files with 42 additions and 11 deletions

View File

@ -4296,11 +4296,14 @@ static void unfold_header(struct Curl_easy *data)
{
size_t len = curlx_dyn_len(&data->state.headerb);
char *hd = curlx_dyn_ptr(&data->state.headerb);
if(len && (hd[len -1] == '\n'))
if(len && (hd[len - 1] == '\n'))
len--;
if(len && (hd[len -1] == '\r'))
if(len && (hd[len - 1] == '\r'))
len--;
while(len && (ISBLANK(hd[len - 1]))) /* strip off trailing whitespace */
len--;
curlx_dyn_setlen(&data->state.headerb, len);
data->state.leading_unfold = TRUE;
}
/*
@ -4379,14 +4382,41 @@ static CURLcode http_parse_headers(struct Curl_easy *data,
goto out; /* read more and try again */
}
/* decrease the size of the remaining (supposed) header line */
/* the size of the remaining (supposed) header line */
consumed = (end_ptr - buf) + 1;
result = curlx_dyn_addn(&data->state.headerb, buf, consumed);
if(result)
return result;
blen -= consumed;
buf += consumed;
*pconsumed += consumed;
{
/* preserve the whole original header piece size */
size_t header_piece = consumed;
if(data->state.leading_unfold) {
/* immediately after an unfold, keep only a single whitespace */
const size_t iblen = blen;
while(consumed && ISBLANK(buf[0])) {
consumed--;
buf++;
blen--;
}
if(consumed) {
if(iblen > blen) {
/* take one step back */
consumed++;
buf--;
blen++;
}
data->state.leading_unfold = FALSE; /* done now */
}
}
if(consumed) {
result = curlx_dyn_addn(&data->state.headerb, buf, consumed);
if(result)
return result;
blen -= consumed;
buf += consumed;
}
*pconsumed += header_piece;
}
/****
* We now have a FULL header line in 'headerb'.

View File

@ -1135,6 +1135,7 @@ struct UrlState {
BIT(http_hd_upgrade); /* Added HTTP header Upgrade: */
BIT(http_hd_h2_settings); /* Added HTTP header H2Settings: */
BIT(maybe_folded);
BIT(leading_unfold); /* unfold started, this is the leading bytes */
#endif
};

View File

@ -55,7 +55,7 @@ Server: test-server/ fake folded
Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
ETag: "21025-dc7-39462498"
Content-Length: 6
Connection:%repeat[46 x ]% close
Connection: close
</file>
</verify>

View File

@ -59,7 +59,7 @@ http://%HOSTIP:%HTTPPORT/%TESTNUMBER
- Set-Cookie == onecookie=data; (0/3)
- Set-Cookie == secondcookie=2data; (1/3)
- Set-Cookie == cookie3=data3; (2/3)
Fold == is folding a line
Fold == is folding a line
Blank ==%SP
Blank2 ==%SP
</stdout>