summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorvandebo@chromium.org <vandebo@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-01-07 01:42:38 +0000
committervandebo@chromium.org <vandebo@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-01-07 01:42:38 +0000
commitee9410e7f9f920f30269a806d9aa2a3e403b49a4 (patch)
tree7b12f3b2539330c41dc998d198bcc5e88bf5ecbd /net
parent1916c65b2f88e95efc11fea6e553923f192849ff (diff)
downloadchromium_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.cc1
-rw-r--r--net/http/http_network_transaction_unittest.cc56
-rw-r--r--net/http/http_stream_parser.cc7
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;