diff options
author | vandebo@chromium.org <vandebo@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-01-07 01:42:38 +0000 |
---|---|---|
committer | vandebo@chromium.org <vandebo@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-01-07 01:42:38 +0000 |
commit | ee9410e7f9f920f30269a806d9aa2a3e403b49a4 (patch) | |
tree | 7b12f3b2539330c41dc998d198bcc5e88bf5ecbd /net | |
parent | 1916c65b2f88e95efc11fea6e553923f192849ff (diff) | |
download | chromium_src-ee9410e7f9f920f30269a806d9aa2a3e403b49a4.zip chromium_src-ee9410e7f9f920f30269a806d9aa2a3e403b49a4.tar.gz chromium_src-ee9410e7f9f920f30269a806d9aa2a3e403b49a4.tar.bz2 |
A 1xx response code followed by an EOF triggered an infinite loop. Fix the problem and add a regression test.
BUG=31324
TEST=new net unittest
Review URL: http://codereview.chromium.org/523075
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@35680 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r-- | net/http/http_network_transaction.cc | 1 | ||||
-rw-r--r-- | net/http/http_network_transaction_unittest.cc | 56 | ||||
-rw-r--r-- | net/http/http_stream_parser.cc | 7 |
3 files changed, 63 insertions, 1 deletions
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc index e038935..5dc01ca 100644 --- a/net/http/http_network_transaction.cc +++ b/net/http/http_network_transaction.cc @@ -1017,6 +1017,7 @@ int HttpNetworkTransaction::DoReadHeadersComplete(int result) { // We treat any other 1xx in this same way (although in practice getting // a 1xx that isn't a 100 is rare). if (response_.headers->response_code() / 100 == 1) { + response_.headers = new HttpResponseHeaders(""); next_state_ = STATE_READ_HEADERS; return OK; } diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc index 66c2659..380bd49 100644 --- a/net/http/http_network_transaction_unittest.cc +++ b/net/http/http_network_transaction_unittest.cc @@ -537,6 +537,62 @@ TEST_F(HttpNetworkTransactionTest, Ignores1xx) { EXPECT_EQ("hello world", response_data); } +TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) { + SessionDependencies session_deps; + scoped_ptr<HttpTransaction> trans( + new HttpNetworkTransaction(CreateSession(&session_deps))); + + HttpRequestInfo request; + request.method = "POST"; + request.url = GURL("http://www.foo.com/"); + request.load_flags = 0; + + MockRead data_reads[] = { + MockRead(false, "HTTP/1.0 100 Continue\r\n"), + MockRead(true, 0), + }; + StaticSocketDataProvider data(data_reads, NULL); + session_deps.socket_factory.AddSocketDataProvider(&data); + + TestCompletionCallback callback; + + int rv = trans->Start(&request, &callback, NULL); + EXPECT_EQ(ERR_IO_PENDING, rv); + + rv = callback.WaitForResult(); + EXPECT_EQ(OK, rv); + + std::string response_data; + rv = ReadTransaction(trans.get(), &response_data); + EXPECT_EQ(OK, rv); + EXPECT_EQ("", response_data); +} + +TEST_F(HttpNetworkTransactionTest, EmptyResponse) { + SessionDependencies session_deps; + scoped_ptr<HttpTransaction> trans( + new HttpNetworkTransaction(CreateSession(&session_deps))); + + HttpRequestInfo request; + request.method = "POST"; + request.url = GURL("http://www.foo.com/"); + request.load_flags = 0; + + MockRead data_reads[] = { + MockRead(true, 0), + }; + StaticSocketDataProvider data(data_reads, NULL); + session_deps.socket_factory.AddSocketDataProvider(&data); + + TestCompletionCallback callback; + + int rv = trans->Start(&request, &callback, NULL); + EXPECT_EQ(ERR_IO_PENDING, rv); + + rv = callback.WaitForResult(); + EXPECT_EQ(ERR_EMPTY_RESPONSE, rv); +} + // read_failure specifies a read failure that should cause the network // transaction to resend the request. void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest( diff --git a/net/http/http_stream_parser.cc b/net/http/http_stream_parser.cc index a83616b..abbf112 100644 --- a/net/http/http_stream_parser.cc +++ b/net/http/http_stream_parser.cc @@ -62,10 +62,15 @@ int HttpStreamParser::SendRequest(const HttpRequestInfo* request, } int HttpStreamParser::ReadResponseHeaders(CompletionCallback* callback) { - DCHECK_EQ(STATE_REQUEST_SENT, io_state_); + DCHECK(io_state_ == STATE_REQUEST_SENT || io_state_ == STATE_DONE); DCHECK(!user_callback_); DCHECK(callback); + // This function can be called with io_state_ == STATE_DONE if the + // connection is closed after seeing just a 1xx response code. + if (io_state_ == STATE_DONE) + return ERR_CONNECTION_CLOSED; + int result = OK; io_state_ = STATE_READ_HEADERS; |