http: make Content-Length parser more WHATWG
No binary (build failed)
—
(log yok)
| @@ -519,6 +519,7 @@ static CURLcode http_perhapsrewind(struct Curl_easy *data, | |
| /* We decided to abort the ongoing transfer */ | |
| streamclose(conn, "Mid-auth HTTP and much data left to send"); | |
| data->req.size = 0; /* do not download any more than 0 bytes */ | |
| + | data->req.http_bodyless = TRUE; |
| } | |
| return CURLE_OK; | |
| } | |
| @@ -3118,32 +3119,50 @@ static CURLcode http_header_c(struct Curl_easy *data, | |
| struct SingleRequest *k = &data->req; | |
| const char *v; | |
| - | /* Check for Content-Length: header lines to get size */ |
| + | /* Check for Content-Length: header lines to get size. Browsers insist we |
| + | should accept multiple Content-Length headers and that a comma separated |
| + | list also is fine and then we should accept them all as long as they are |
| + | the same value. Different values trigger error. |
| + | */ |
| v = (!k->http_bodyless && !data->set.ignorecl) ? | |
| HD_VAL(hd, hdlen, "Content-Length:") : NULL; | |
| if(v) { | |
| - | curl_off_t contentlength; |
| - | int offt = curlx_str_numblanks(&v, &contentlength); |
| + | do { |
| + | curl_off_t contentlength; |
| + | int offt = curlx_str_numblanks(&v, &contentlength); |
| + | |
| + | if(offt == STRE_OVERFLOW) { |
| + | /* out of range */ |
| + | if(data->set.max_filesize) { |
| + | failf(data, "Maximum file size exceeded"); |
| + | return CURLE_FILESIZE_EXCEEDED; |
| + | } |
| + | streamclose(conn, "overflow content-length"); |
| + | infof(data, "Overflow Content-Length: value"); |
| + | return CURLE_OK; |
| + | } |
| + | else { |
| + | if((offt == STRE_OK) && |
| + | ((k->size == -1) || /* not set to something before */ |
| + | (k->size == contentlength))) { /* or the same value */ |
| - | if(offt == STRE_OK) { |
| - | k->size = contentlength; |
| - | k->maxdownload = k->size; |
| - | } |
| - | else if(offt == STRE_OVERFLOW) { |
| - | /* out of range */ |
| - | if(data->set.max_filesize) { |
| - | failf(data, "Maximum file size exceeded"); |
| - | return CURLE_FILESIZE_EXCEEDED; |
| + | k->size = contentlength; |
| + | curlx_str_passblanks(&v); |
| + | |
| + | /* on a comma, loop and get the next instead */ |
| + | if(!curlx_str_single(&v, ',')) |
| + | continue; |
| + | |
| + | if(!curlx_str_newline(&v)) { |
| + | k->maxdownload = k->size; |
| + | return CURLE_OK; |
| + | } |
| + | } |
| + | /* negative, different value or just rubbish - bad HTTP */ |
| + | failf(data, "Invalid Content-Length: value"); |
| + | return CURLE_WEIRD_SERVER_REPLY; |
| } | |
| - | streamclose(conn, "overflow content-length"); |
| - | infof(data, "Overflow Content-Length: value"); |
| - | } |
| - | else { |
| - | /* negative or just rubbish - bad HTTP */ |
| - | failf(data, "Invalid Content-Length: value"); |
| - | return CURLE_WEIRD_SERVER_REPLY; |
| - | } |
| - | return CURLE_OK; |
| + | } while(1); |
| } | |
| v = (!k->http_bodyless && data->set.str[STRING_ENCODING]) ? | |
| HD_VAL(hd, hdlen, "Content-Encoding:") : NULL; | |
| @@ -109,7 +109,7 @@ test727 test728 test729 test730 test731 test732 test733 test734 test735 \ | |
| test736 test737 test738 test739 test740 test741 test742 test743 test744 \ | |
| test745 test746 test747 test748 test749 test750 test751 test752 test753 \ | |
| test754 test755 test756 test757 test758 test759 test760 test761 test762 \ | |
| - | test763 test764 test765 test766 \ |
| + | test763 test764 test765 test766 test767 test768 test769 test770 test771 \ |
| \ | |
| test780 test781 test782 test783 test784 test785 test786 test787 test788 \ | |
| test789 test790 test791 test792 test793 test794 test796 test797 \ | |
| @@ -0,0 +1,58 @@ | |
| + | <testcase> |
| + | <info> |
| + | <keywords> |
| + | HTTP |
| + | HTTP GET |
| + | </keywords> |
| + | </info> |
| + | |
| + | # |
| + | # Server-side |
| + | <reply> |
| + | <data crlf="yes"> |
| + | HTTP/1.1 200 OK |
| + | Date: Tue, 09 Nov 2010 14:49:00 GMT |
| + | Server: test-server/fake |
| + | Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT |
| + | ETag: "21025-dc7-39462498" |
| + | Accept-Ranges: bytes |
| + | Content-Length: 6 |
| + | Content-Length: 6 |
| + | Connection: close |
| + | Content-Type: text/html |
| + | Funny-head: yesyes |
| + | |
| + | -foo- |
| + | </data> |
| + | </reply> |
| + | |
| + | # |
| + | # Client-side |
| + | <client> |
| + | <server> |
| + | http |
| + | </server> |
| + | <name> |
| + | HTTP with two Content-Length response header fields same size |
| + | </name> |
| + | <command> |
| + | http://%HOSTIP:%HTTPPORT/%TESTNUMBER |
| + | </command> |
| + | </client> |
| + | |
| + | # |
| + | # Verify data after the test has been "shot" |
| + | <verify> |
| + | <protocol crlf="yes"> |
| + | GET /%TESTNUMBER HTTP/1.1 |
| + | Host: %HOSTIP:%HTTPPORT |
| + | User-Agent: curl/%VERSION |
| + | Accept: */* |
| + | |
| + | </protocol> |
| + | <limits> |
| + | Allocations: 135 |
| + | Maximum allocated: 136000 |
| + | </limits> |
| + | </verify> |
| + | </testcase> |
| @@ -0,0 +1,57 @@ | |
| + | <testcase> |
| + | <info> |
| + | <keywords> |
| + | HTTP |
| + | HTTP GET |
| + | </keywords> |
| + | </info> |
| + | |
| + | # |
| + | # Server-side |
| + | <reply> |
| + | <data crlf="yes" nocheck="yes"> |
| + | HTTP/1.1 200 OK |
| + | Date: Tue, 09 Nov 2010 14:49:00 GMT |
| + | Server: test-server/fake |
| + | Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT |
| + | ETag: "21025-dc7-39462498" |
| + | Accept-Ranges: bytes |
| + | Content-Length: 6badness |
| + | Content-Length: 44 |
| + | Connection: close |
| + | Content-Type: text/html |
| + | Funny-head: yesyes |
| + | |
| + | -foo- |
| + | </data> |
| + | </reply> |
| + | |
| + | # |
| + | # Client-side |
| + | <client> |
| + | <server> |
| + | http |
| + | </server> |
| + | <name> |
| + | HTTP with letters after the number in Content-Length |
| + | </name> |
| + | <command> |
| + | http://%HOSTIP:%HTTPPORT/%TESTNUMBER |
| + | </command> |
| + | </client> |
| + | |
| + | # |
| + | # Verify data after the test has been "shot" |
| + | <verify> |
| + | <protocol crlf="yes"> |
| + | GET /%TESTNUMBER HTTP/1.1 |
| + | Host: %HOSTIP:%HTTPPORT |
| + | User-Agent: curl/%VERSION |
| + | Accept: */* |
| + | |
| + | </protocol> |
| + | <errorcode> |
| + | 8 |
| + | </errorcode> |
| + | </verify> |
| + | </testcase> |
| @@ -0,0 +1,53 @@ | |
| + | <testcase> |
| + | <info> |
| + | <keywords> |
| + | HTTP |
| + | HTTP GET |
| + | </keywords> |
| + | </info> |
| + | |
| + | # |
| + | # Server-side |
| + | <reply> |
| + | <data crlf="yes"> |
| + | HTTP/1.1 200 OK |
| + | Date: Tue, 09 Nov 2010 14:49:00 GMT |
| + | Server: test-server/fake |
| + | Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT |
| + | ETag: "21025-dc7-39462498" |
| + | Accept-Ranges: bytes |
| + | Content-Length: 6 |
| + | Connection: close |
| + | Content-Type: text/html |
| + | Funny-head: yesyes |
| + | |
| + | -foo- |
| + | </data> |
| + | </reply> |
| + | |
| + | # |
| + | # Client-side |
| + | <client> |
| + | <server> |
| + | http |
| + | </server> |
| + | <name> |
| + | HTTP with space after Content-Length number |
| + | </name> |
| + | <command> |
| + | http://%HOSTIP:%HTTPPORT/%TESTNUMBER |
| + | </command> |
| + | </client> |
| + | |
| + | # |
| + | # Verify data after the test has been "shot" |
| + | <verify> |
| + | <protocol crlf="yes"> |
| + | GET /%TESTNUMBER HTTP/1.1 |
| + | Host: %HOSTIP:%HTTPPORT |
| + | User-Agent: curl/%VERSION |
| + | Accept: */* |
| + | |
| + | </protocol> |
| + | </verify> |
| + | </testcase> |
| @@ -0,0 +1,58 @@ | |
| + | <testcase> |
| + | <info> |
| + | <keywords> |
| + | HTTP |
| + | HTTP GET |
| + | </keywords> |
| + | </info> |
| + | |
| + | # |
| + | # Server-side |
| + | <reply> |
| + | <data crlf="yes"> |
| + | HTTP/1.1 200 OK |
| + | Date: Tue, 09 Nov 2010 14:49:00 GMT |
| + | Server: test-server/fake |
| + | Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT |
| + | ETag: "21025-dc7-39462498" |
| + | Accept-Ranges: bytes |
| + | Content-Length: 6,06,6 |
| + | Content-Length: 6, 6 |
| + | Connection: close |
| + | Content-Type: text/html |
| + | Funny-head: yesyes |
| + | |
| + | -foo- |
| + | </data> |
| + | </reply> |
| + | |
| + | # |
| + | # Client-side |
| + | <client> |
| + | <server> |
| + | http |
| + | </server> |
| + | <name> |
| + | HTTP with Content-Length headers using comma separated list |
| + | </name> |
| + | <command> |
| + | http://%HOSTIP:%HTTPPORT/%TESTNUMBER |
| + | </command> |
| + | </client> |
| + | |
| + | # |
| + | # Verify data after the test has been "shot" |
| + | <verify> |
| + | <protocol crlf="yes"> |
| + | GET /%TESTNUMBER HTTP/1.1 |
| + | Host: %HOSTIP:%HTTPPORT |
| + | User-Agent: curl/%VERSION |
| + | Accept: */* |
| + | |
| + | </protocol> |
| + | <limits> |
| + | Allocations: 135 |
| + | Maximum allocated: 136000 |
| + | </limits> |
| + | </verify> |
| + | </testcase> |
| @@ -0,0 +1,57 @@ | |
| + | <testcase> |
| + | <info> |
| + | <keywords> |
| + | HTTP |
| + | HTTP GET |
| + | </keywords> |
| + | </info> |
| + | |
| + | # |
| + | # Server-side |
| + | <reply> |
| + | <data crlf="yes" nocheck="yes"> |
| + | HTTP/1.1 200 OK |
| + | Date: Tue, 09 Nov 2010 14:49:00 GMT |
| + | Server: test-server/fake |
| + | Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT |
| + | ETag: "21025-dc7-39462498" |
| + | Accept-Ranges: bytes |
| + | Content-Length: 44 |
| + | Content-Length: 6 |
| + | Connection: close |
| + | Content-Type: text/html |
| + | Funny-head: yesyes |
| + | |
| + | -foo- |
| + | </data> |
| + | </reply> |
| + | |
| + | # |
| + | # Client-side |
| + | <client> |
| + | <server> |
| + | http |
| + | </server> |
| + | <name> |
| + | HTTP with two Content-Length headers using different sizes |
| + | </name> |
| + | <command> |
| + | http://%HOSTIP:%HTTPPORT/%TESTNUMBER |
| + | </command> |
| + | </client> |
| + | |
| + | # |
| + | # Verify data after the test has been "shot" |
| + | <verify> |
| + | <protocol crlf="yes"> |
| + | GET /%TESTNUMBER HTTP/1.1 |
| + | Host: %HOSTIP:%HTTPPORT |
| + | User-Agent: curl/%VERSION |
| + | Accept: */* |
| + | |
| + | </protocol> |
| + | <errorcode> |
| + | 8 |
| + | </errorcode> |
| + | </verify> |
| + | </testcase> |