summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwillchan@chromium.org <willchan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-29 22:48:04 +0000
committerwillchan@chromium.org <willchan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-29 22:48:04 +0000
commit44b5204abe46182f22a4d29b5436df0ab145b11c (patch)
treebe15be70e874ced6eec27a9b377d06cc3889dab3
parentbdee5e011b02b20677c28a7914cc2edf57a3c54e (diff)
downloadchromium_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.cc61
-rw-r--r--net/http/http_stream_parser.cc17
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;