summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrtenneti <rtenneti@chromium.org>2016-01-25 12:40:13 -0800
committerCommit bot <commit-bot@chromium.org>2016-01-25 20:42:50 +0000
commit637f9f66268e04d1242b630f3e4f5f49d5aeab3a (patch)
tree0bbdf28df918771179fdd216b4554e13bbde9ab9
parentd268d9fcc84d01275b995779c11cd408b7165731 (diff)
downloadchromium_src-637f9f66268e04d1242b630f3e4f5f49d5aeab3a.zip
chromium_src-637f9f66268e04d1242b630f3e4f5f49d5aeab3a.tar.gz
chromium_src-637f9f66268e04d1242b630f3e4f5f49d5aeab3a.tar.bz2
QUIC - fix crash when writing part of the request body fails synchronously.
BUG=577377 TBR=rch@chromium.org NOTRY=true NOPRESUBMIT=true Review URL: https://codereview.chromium.org/1626703002 Cr-Commit-Position: refs/heads/master@{#371136} (cherry picked from commit 15656aeb0349b493090c47e6cdbf0a6ad70a3e60) Review URL: https://codereview.chromium.org/1635683002 Cr-Commit-Position: refs/branch-heads/2623@{#123} Cr-Branched-From: 92d77538a86529ca35f9220bd3cd512cbea1f086-refs/heads/master@{#369907}
-rw-r--r--net/quic/quic_http_stream.cc8
-rw-r--r--net/quic/quic_http_stream_test.cc57
2 files changed, 63 insertions, 2 deletions
diff --git a/net/quic/quic_http_stream.cc b/net/quic/quic_http_stream.cc
index 20d1e36..81b57f8 100644
--- a/net/quic/quic_http_stream.cc
+++ b/net/quic/quic_http_stream.cc
@@ -471,6 +471,10 @@ int QuicHttpStream::DoReadRequestBodyComplete(int rv) {
if (rv < 0)
return rv;
+ // If the stream is already closed, don't continue.
+ if (!stream_)
+ return response_status_;
+
request_body_buf_ = new DrainableIOBuffer(raw_request_body_buf_.get(), rv);
if (rv == 0) { // Reached the end.
DCHECK(request_body_stream_->IsEOF());
@@ -504,6 +508,10 @@ int QuicHttpStream::DoSendBodyComplete(int rv) {
if (rv < 0)
return rv;
+ // If the stream is already closed, don't continue.
+ if (!stream_)
+ return response_status_;
+
request_body_buf_->DidConsume(request_body_buf_->BytesRemaining());
if (!request_body_stream_->IsEOF()) {
diff --git a/net/quic/quic_http_stream_test.cc b/net/quic/quic_http_stream_test.cc
index a92266b..be3364c 100644
--- a/net/quic/quic_http_stream_test.cc
+++ b/net/quic/quic_http_stream_test.cc
@@ -125,8 +125,10 @@ class QuicHttpStreamTest : public ::testing::TestWithParam<QuicVersion> {
struct PacketToWrite {
PacketToWrite(IoMode mode, QuicEncryptedPacket* packet)
: mode(mode), packet(packet) {}
+ PacketToWrite(IoMode mode, int rv) : mode(mode), packet(nullptr), rv(rv) {}
IoMode mode;
QuicEncryptedPacket* packet;
+ int rv;
};
QuicHttpStreamTest()
@@ -157,6 +159,10 @@ class QuicHttpStreamTest : public ::testing::TestWithParam<QuicVersion> {
writes_.push_back(PacketToWrite(SYNCHRONOUS, packet.release()));
}
+ void AddWrite(IoMode mode, int rv) {
+ writes_.push_back(PacketToWrite(mode, rv));
+ }
+
// Returns the packet to be written at position |pos|.
QuicEncryptedPacket* GetWrite(size_t pos) { return writes_[pos].packet; }
@@ -173,8 +179,12 @@ class QuicHttpStreamTest : public ::testing::TestWithParam<QuicVersion> {
void Initialize() {
mock_writes_.reset(new MockWrite[writes_.size()]);
for (size_t i = 0; i < writes_.size(); i++) {
- mock_writes_[i] = MockWrite(writes_[i].mode, writes_[i].packet->data(),
- writes_[i].packet->length());
+ if (writes_[i].packet == nullptr) {
+ mock_writes_[i] = MockWrite(writes_[i].mode, writes_[i].rv, i);
+ } else {
+ mock_writes_[i] = MockWrite(writes_[i].mode, writes_[i].packet->data(),
+ writes_[i].packet->length());
+ }
};
socket_data_.reset(new StaticSocketDataProvider(
@@ -936,5 +946,48 @@ TEST_P(QuicHttpStreamTest, CheckPriorityWithNoDelegate) {
EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
}
+TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendHeadersComplete) {
+ SetRequest("POST", "/", DEFAULT_PRIORITY);
+ AddWrite(SYNCHRONOUS, ERR_FAILED);
+ Initialize();
+
+ ChunkedUploadDataStream upload_data_stream(0);
+
+ request_.method = "POST";
+ request_.url = GURL("http://www.google.com/");
+ request_.upload_data_stream = &upload_data_stream;
+ ASSERT_EQ(OK, request_.upload_data_stream->Init(
+ TestCompletionCallback().callback()));
+
+ ASSERT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY, net_log_,
+ callback_.callback()));
+ ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
+ stream_->SendRequest(headers_, &response_, callback_.callback()));
+}
+
+TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendBodyComplete) {
+ SetRequest("POST", "/", DEFAULT_PRIORITY);
+ size_t spdy_request_headers_frame_length;
+ AddWrite(ConstructRequestHeadersPacket(1, !kFin, DEFAULT_PRIORITY,
+ &spdy_request_headers_frame_length));
+ AddWrite(SYNCHRONOUS, ERR_FAILED);
+ Initialize();
+
+ ChunkedUploadDataStream upload_data_stream(0);
+ size_t chunk_size = strlen(kUploadData);
+ upload_data_stream.AppendData(kUploadData, chunk_size, false);
+
+ request_.method = "POST";
+ request_.url = GURL("http://www.google.com/");
+ request_.upload_data_stream = &upload_data_stream;
+ ASSERT_EQ(OK, request_.upload_data_stream->Init(
+ TestCompletionCallback().callback()));
+
+ ASSERT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY, net_log_,
+ callback_.callback()));
+ ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
+ stream_->SendRequest(headers_, &response_, callback_.callback()));
+}
+
} // namespace test
} // namespace net