diff options
author | rtenneti <rtenneti@chromium.org> | 2016-01-25 12:40:13 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-01-25 20:42:50 +0000 |
commit | 637f9f66268e04d1242b630f3e4f5f49d5aeab3a (patch) | |
tree | 0bbdf28df918771179fdd216b4554e13bbde9ab9 | |
parent | d268d9fcc84d01275b995779c11cd408b7165731 (diff) | |
download | chromium_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.cc | 8 | ||||
-rw-r--r-- | net/quic/quic_http_stream_test.cc | 57 |
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 |