diff options
author | willchan@chromium.org <willchan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-29 22:48:04 +0000 |
---|---|---|
committer | willchan@chromium.org <willchan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-29 22:48:04 +0000 |
commit | 44b5204abe46182f22a4d29b5436df0ab145b11c (patch) | |
tree | be15be70e874ced6eec27a9b377d06cc3889dab3 | |
parent | bdee5e011b02b20677c28a7914cc2edf57a3c54e (diff) | |
download | chromium_src-44b5204abe46182f22a4d29b5436df0ab145b11c.zip chromium_src-44b5204abe46182f22a4d29b5436df0ab145b11c.tar.gz chromium_src-44b5204abe46182f22a4d29b5436df0ab145b11c.tar.bz2 |
Allow duplicate Content-Length headers.
BUG=56344,59077
TEST=new tests in HttpNetworkTransactionTest
Review URL: http://codereview.chromium.org/4192011
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@64513 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | net/http/http_network_transaction_unittest.cc | 61 | ||||
-rw-r--r-- | net/http/http_stream_parser.cc | 17 |
2 files changed, 73 insertions, 5 deletions
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc index b609511..1510186 100644 --- a/net/http/http_network_transaction_unittest.cc +++ b/net/http/http_network_transaction_unittest.cc @@ -460,6 +460,67 @@ TEST_F(HttpNetworkTransactionTest, } TEST_F(HttpNetworkTransactionTest, + DuplicateContentLengthHeadersNoTransferEncoding) { + MockRead data_reads[] = { + MockRead("HTTP/1.1 200 OK\r\n"), + MockRead("Content-Length: 5\r\n"), + MockRead("Content-Length: 5\r\n\r\n"), + MockRead("Hello"), + }; + SimpleGetHelperResult out = SimpleGetHelper(data_reads, + arraysize(data_reads)); + EXPECT_EQ(OK, out.rv); + EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); + EXPECT_EQ("Hello", out.response_data); +} + +TEST_F(HttpNetworkTransactionTest, + ComplexContentLengthHeadersNoTransferEncoding) { + // More than 2 dupes. + { + MockRead data_reads[] = { + MockRead("HTTP/1.1 200 OK\r\n"), + MockRead("Content-Length: 5\r\n"), + MockRead("Content-Length: 5\r\n"), + MockRead("Content-Length: 5\r\n\r\n"), + MockRead("Hello"), + }; + SimpleGetHelperResult out = SimpleGetHelper(data_reads, + arraysize(data_reads)); + EXPECT_EQ(OK, out.rv); + EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); + EXPECT_EQ("Hello", out.response_data); + } + // HTTP/1.0 + { + MockRead data_reads[] = { + MockRead("HTTP/1.0 200 OK\r\n"), + MockRead("Content-Length: 5\r\n"), + MockRead("Content-Length: 5\r\n"), + MockRead("Content-Length: 5\r\n\r\n"), + MockRead("Hello"), + }; + SimpleGetHelperResult out = SimpleGetHelper(data_reads, + arraysize(data_reads)); + EXPECT_EQ(OK, out.rv); + EXPECT_EQ("HTTP/1.0 200 OK", out.status_line); + EXPECT_EQ("Hello", out.response_data); + } + // 2 dupes and one mismatched. + { + MockRead data_reads[] = { + MockRead("HTTP/1.1 200 OK\r\n"), + MockRead("Content-Length: 10\r\n"), + MockRead("Content-Length: 10\r\n"), + MockRead("Content-Length: 5\r\n\r\n"), + }; + SimpleGetHelperResult out = SimpleGetHelper(data_reads, + arraysize(data_reads)); + EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv); + } +} + +TEST_F(HttpNetworkTransactionTest, MultipleContentLengthHeadersTransferEncoding) { MockRead data_reads[] = { MockRead("HTTP/1.1 200 OK\r\n"), diff --git a/net/http/http_stream_parser.cc b/net/http/http_stream_parser.cc index 0e7610c..4470199 100644 --- a/net/http/http_stream_parser.cc +++ b/net/http/http_stream_parser.cc @@ -510,13 +510,20 @@ int HttpStreamParser::DoParseResponseHeaders(int end_offset) { void* it = NULL; const std::string content_length_header("Content-Length"); - std::string ignored_header_value; + std::string content_length_value; if (!headers->HasHeader("Transfer-Encoding") && headers->EnumerateHeader( - &it, content_length_header, &ignored_header_value) && - headers->EnumerateHeader( - &it, content_length_header, &ignored_header_value)) { - return ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH; + &it, content_length_header, &content_length_value)) { + // Ok, there's no Transfer-Encoding header and there's at least one + // Content-Length header. Check if there are any more Content-Length + // headers, and if so, make sure they have the same value. Otherwise, it's + // a possible response smuggling attack. + std::string content_length_value2; + while (headers->EnumerateHeader( + &it, content_length_header, &content_length_value2)) { + if (content_length_value != content_length_value2) + return ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH; + } } response_->headers = headers; |