summaryrefslogtreecommitdiffstats
path: root/net/http
diff options
context:
space:
mode:
authorericroman@google.com <ericroman@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-10-23 18:26:19 +0000
committerericroman@google.com <ericroman@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-10-23 18:26:19 +0000
commit4ddaf2503578f90ac32766828e31e68d25a37207 (patch)
treea1c4504bca5bd1d5c5327a51bde72f6eb7312c4c /net/http
parent3d08fef8b62ff30092f38874eb4ad062540e9165 (diff)
downloadchromium_src-4ddaf2503578f90ac32766828e31e68d25a37207.zip
chromium_src-4ddaf2503578f90ac32766828e31e68d25a37207.tar.gz
chromium_src-4ddaf2503578f90ac32766828e31e68d25a37207.tar.bz2
Bound the maximum buffer size for response headers.
http://code.google.com/p/chromium/issues/detail?id=3654 Review URL: http://codereview.chromium.org/7882 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@3827 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/http')
-rw-r--r--net/http/http_network_transaction.cc4
-rw-r--r--net/http/http_network_transaction.h10
-rw-r--r--net/http/http_network_transaction_unittest.cc56
3 files changed, 70 insertions, 0 deletions
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc
index d0a26d0..f7d7058 100644
--- a/net/http/http_network_transaction.cc
+++ b/net/http/http_network_transaction.cc
@@ -660,6 +660,10 @@ int HttpNetworkTransaction::DoReadHeadersComplete(int result) {
int eoh = HttpUtil::LocateEndOfHeaders(
header_buf_.get(), header_buf_len_, header_buf_http_offset_);
if (eoh == -1) {
+ // Prevent growing the headers buffer indefinitely.
+ if (header_buf_len_ >= kMaxHeaderBufSize)
+ return ERR_RESPONSE_HEADERS_TOO_BIG;
+
// Haven't found the end of headers yet, keep reading.
next_state_ = STATE_READ_HEADERS;
return OK;
diff --git a/net/http/http_network_transaction.h b/net/http/http_network_transaction.h
index 7fd0b3c..dc850b5 100644
--- a/net/http/http_network_transaction.h
+++ b/net/http/http_network_transaction.h
@@ -206,7 +206,17 @@ class HttpNetworkTransaction : public HttpTransaction {
int header_buf_capacity_;
int header_buf_len_;
int header_buf_body_offset_;
+
+ // The number of bytes by which the header buffer is grown when it reaches
+ // capacity.
enum { kHeaderBufInitialSize = 4096 };
+
+ // |kMaxHeaderBufSize| is the number of bytes that the response headers can
+ // grow to. If the body start is not found within this range of the
+ // response, the transaction will fail with ERR_RESPONSE_HEADERS_TOO_BIG.
+ // Note: |kMaxHeaderBufSize| should be a multiple of |kHeaderBufInitialSize|.
+ enum { kMaxHeaderBufSize = 32768 }; // 32 kilobytes.
+
// The position where status line starts; -1 if not found yet.
int header_buf_http_offset_;
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc
index 45fda4b..8568ec9 100644
--- a/net/http/http_network_transaction_unittest.cc
+++ b/net/http/http_network_transaction_unittest.cc
@@ -268,6 +268,23 @@ SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[]) {
return out;
}
+// Create a long header list that consumes >= |size| bytes. The caller is
+// responsible for freeing the memory.
+char* MakeLargeHeadersString(int size) {
+ const char* row =
+ "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
+ const int sizeof_row = strlen(row);
+ const int num_rows = static_cast<int>(
+ ceil(static_cast<float>(size) / sizeof_row));
+ const int sizeof_data = num_rows * sizeof_row;
+ DCHECK(sizeof_data >= size);
+
+ char* data = new char[sizeof_data];
+ for (int i = 0; i < num_rows; ++i)
+ memcpy(data + i * sizeof_row, row, sizeof_row);
+ return data;
+}
+
//-----------------------------------------------------------------------------
TEST_F(HttpNetworkTransactionTest, Basic) {
@@ -802,3 +819,42 @@ TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
EXPECT_TRUE(response->auth_challenge.get() == NULL);
EXPECT_EQ(100, response->headers->GetContentLength());
}
+
+// Test reading a server response which has only headers, and no body.
+// After some maximum number of bytes is consumed, the transaction should
+// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
+TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
+ scoped_ptr<net::HttpTransaction> trans(new net::HttpNetworkTransaction(
+ CreateSession(), &mock_socket_factory));
+
+ net::HttpRequestInfo request;
+ request.method = "GET";
+ request.url = GURL("http://www.google.com/");
+ request.load_flags = 0;
+
+ // Respond with 50 kb of headers (we should fail after 32 kb).
+ scoped_array<char> large_headers_string(MakeLargeHeadersString(
+ 50 * 1024));
+
+ MockRead data_reads[] = {
+ MockRead("HTTP/1.0 200 OK\r\n"),
+ MockRead(large_headers_string.get()),
+ MockRead("\r\nBODY"),
+ MockRead(false, net::OK),
+ };
+ MockSocket data;
+ data.reads = data_reads;
+ mock_sockets[0] = &data;
+ mock_sockets[1] = NULL;
+
+ TestCompletionCallback callback;
+
+ int rv = trans->Start(&request, &callback);
+ EXPECT_EQ(net::ERR_IO_PENDING, rv);
+
+ rv = callback.WaitForResult();
+ EXPECT_EQ(net::ERR_RESPONSE_HEADERS_TOO_BIG, rv);
+
+ const net::HttpResponseInfo* response = trans->GetResponseInfo();
+ EXPECT_TRUE(response == NULL);
+}