diff options
author | Daniel Stenberg <daniel@haxx.se> | 2021-08-30 17:49:25 +0200 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2021-08-31 10:04:03 +0200 |
commit | 8a16e54c0cc71e15ef78d9eaf1f9155a0204202d (patch) | |
tree | b80a5c3e75caae769b2a9c0a5eeaeb32f0c4bcc2 /lib | |
parent | bde355c484a652fece6438e6c5b71830c08c2300 (diff) | |
download | curl-8a16e54c0cc71e15ef78d9eaf1f9155a0204202d.tar.gz |
http: ignore content-length if any transfer-encoding is used
Fixes #7643
Closes #7649
Diffstat (limited to 'lib')
-rw-r--r-- | lib/c-hyper.c | 5 | ||||
-rw-r--r-- | lib/http.c | 29 | ||||
-rw-r--r-- | lib/urldata.h | 11 |
3 files changed, 31 insertions, 14 deletions
diff --git a/lib/c-hyper.c b/lib/c-hyper.c index c43d9e327..26635cdc1 100644 --- a/lib/c-hyper.c +++ b/lib/c-hyper.c @@ -400,6 +400,11 @@ CURLcode Curl_hyper_stream(struct Curl_easy *data, /* end of transfer */ *done = TRUE; infof(data, "hyperstream is done!"); + if(!k->bodywrites) { + /* hyper doesn't always call the body write callback */ + bool stilldone; + result = Curl_http_firstwrite(data, data->conn, &stilldone); + } break; } else if(t != HYPER_TASK_RESPONSE) { diff --git a/lib/http.c b/lib/http.c index 65750d17d..d5c36dd54 100644 --- a/lib/http.c +++ b/lib/http.c @@ -2903,6 +2903,20 @@ CURLcode Curl_http_firstwrite(struct Curl_easy *data, { struct SingleRequest *k = &data->req; DEBUGASSERT(conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_RTSP)); + if(data->req.ignore_cl) { + k->size = k->maxdownload = -1; + } + else if(k->size != -1) { + /* We wait until after all headers have been received to set this so that + we know for sure Content-Length is valid. */ + if(data->set.max_filesize && + k->size > data->set.max_filesize) { + failf(data, "Maximum file size exceeded"); + return CURLE_FILESIZE_EXCEEDED; + } + Curl_pgrsSetDownloadSize(data, k->size); + } + if(data->req.newurl) { if(conn->bits.close) { /* Abort after the headers if "follow Location" is set @@ -3403,17 +3417,8 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn, NULL, 10, &contentlength); if(offt == CURL_OFFT_OK) { - if(data->set.max_filesize && - contentlength > data->set.max_filesize) { - failf(data, "Maximum file size exceeded"); - return CURLE_FILESIZE_EXCEEDED; - } k->size = contentlength; k->maxdownload = k->size; - /* we set the progress download size already at this point - just to make it easier for apps/callbacks to extract this - info as soon as possible */ - Curl_pgrsSetDownloadSize(data, k->size); } else if(offt == CURL_OFFT_FLOW) { /* out of range */ @@ -3504,6 +3509,12 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn, TRUE); if(result) return result; + if(!k->chunk) { + /* if this isn't chunked, only close can signal the end of this transfer + as Content-Length is said not to be trusted for transfer-encoding! */ + connclose(conn, "HTTP/1.1 transfer-encoding without chunks"); + k->ignore_cl = TRUE; + } } else if(!k->http_bodyless && checkprefix("Content-Encoding:", headp) && data->set.str[STRING_ENCODING]) { diff --git a/lib/urldata.h b/lib/urldata.h index 1d9911208..6ffd97621 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -704,14 +704,15 @@ struct SingleRequest { #ifndef CURL_DISABLE_DOH struct dohdata *doh; /* DoH specific data for this request */ #endif - BIT(header); /* incoming data has HTTP header */ + BIT(header); /* incoming data has HTTP header */ BIT(content_range); /* set TRUE if Content-Range: was found */ - BIT(upload_done); /* set to TRUE when doing chunked transfer-encoding - upload and we're uploading the last chunk */ - BIT(ignorebody); /* we read a response-body but we ignore it! */ + BIT(upload_done); /* set to TRUE when doing chunked transfer-encoding + upload and we're uploading the last chunk */ + BIT(ignorebody); /* we read a response-body but we ignore it! */ BIT(http_bodyless); /* HTTP response status code is between 100 and 199, 204 or 304 */ - BIT(chunk); /* if set, this is a chunked transfer-encoding */ + BIT(chunk); /* if set, this is a chunked transfer-encoding */ + BIT(ignore_cl); /* ignore content-length */ BIT(upload_chunky); /* set TRUE if we are doing chunked transfer-encoding on upload */ BIT(getheader); /* TRUE if header parsing is wanted */ |