diff options
author | vandebo@chromium.org <vandebo@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-28 00:01:33 +0000 |
---|---|---|
committer | vandebo@chromium.org <vandebo@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-28 00:01:33 +0000 |
commit | 28658b28eea506af35897723adb7c69e67327351 (patch) | |
tree | 9810112b06a9e97066d652a1c384c68e7c885cf4 /net | |
parent | 403c148688f2c23d2c9b56fff236f4ddfe03377c (diff) | |
download | chromium_src-28658b28eea506af35897723adb7c69e67327351.zip chromium_src-28658b28eea506af35897723adb7c69e67327351.tar.gz chromium_src-28658b28eea506af35897723adb7c69e67327351.tar.bz2 |
Handle out of memory in GrowableIOBuffer more gracefully.
BUG=25826
TEST=none
Review URL: http://codereview.chromium.org/338049
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@30287 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r-- | net/base/io_buffer.cc | 11 | ||||
-rw-r--r-- | net/base/io_buffer.h | 6 | ||||
-rw-r--r-- | net/http/http_stream_parser.cc | 24 | ||||
-rw-r--r-- | net/websockets/websocket.cc | 4 |
4 files changed, 31 insertions, 14 deletions
diff --git a/net/base/io_buffer.cc b/net/base/io_buffer.cc index d348f37..9ae2746 100644 --- a/net/base/io_buffer.cc +++ b/net/base/io_buffer.cc @@ -19,15 +19,20 @@ void DrainableIOBuffer::SetOffset(int bytes) { data_ = base_->data() + used_; } -void GrowableIOBuffer::set_capacity(int capacity) { +bool GrowableIOBuffer::SetCapacity(int capacity) { DCHECK_GE(capacity, 0); - real_data_.reset(static_cast<char*>(realloc(real_data_.release(), capacity))); + char* cur_buf = real_data_.release(); + real_data_.reset(static_cast<char*>(realloc(cur_buf, capacity))); + if (real_data_.get() == NULL && capacity != 0) { + real_data_.reset(cur_buf); + return false; + } capacity_ = capacity; - CHECK(real_data_.get() != NULL || capacity == 0); if (offset_ > capacity) set_offset(capacity); else set_offset(offset_); // The pointer may have changed. + return true; } void GrowableIOBuffer::set_offset(int offset) { diff --git a/net/base/io_buffer.h b/net/base/io_buffer.h index eaf3a39..e301df8 100644 --- a/net/base/io_buffer.h +++ b/net/base/io_buffer.h @@ -106,12 +106,14 @@ class GrowableIOBuffer : public IOBuffer { GrowableIOBuffer() : IOBuffer(), capacity_(0), offset_(0) {} ~GrowableIOBuffer() { data_ = NULL; } + // realloc memory to the specified capacity. Returns true on success. + // On failure, the capacity and buffer are unchanged. + bool SetCapacity(int capacity); int capacity() { return capacity_; } - void set_capacity(int capacity); // |offset| moves the |data_| pointer, allowing "seeking" in the data. - int offset() { return offset_; } void set_offset(int offset); + int offset() { return offset_; } int RemainingCapacity() { return capacity_ - offset_; } char* StartOfBuffer() { return real_data_.get(); } diff --git a/net/http/http_stream_parser.cc b/net/http/http_stream_parser.cc index e7c5146..b5394d7 100644 --- a/net/http/http_stream_parser.cc +++ b/net/http/http_stream_parser.cc @@ -208,8 +208,10 @@ int HttpStreamParser::DoReadHeaders() { io_state_ = STATE_READ_HEADERS_COMPLETE; // Grow the read buffer if necessary. - if (read_buf_->RemainingCapacity() == 0) - read_buf_->set_capacity(read_buf_->capacity() + kHeaderBufInitialSize); + if (read_buf_->RemainingCapacity() == 0) { + if (!read_buf_->SetCapacity(read_buf_->capacity() + kHeaderBufInitialSize)) + return ERR_OUT_OF_MEMORY; + } // http://crbug.com/16371: We're seeing |user_buf_->data()| return NULL. // See if the user is passing in an IOBuffer with a NULL |data_|. @@ -300,7 +302,8 @@ int HttpStreamParser::DoReadHeadersComplete(int result) { read_buf_->StartOfBuffer() + read_buf_unused_offset_, extra_bytes); } - read_buf_->set_capacity(extra_bytes); + // Ok if this fails, since it only shrinks the buffer. + read_buf_->SetCapacity(extra_bytes); read_buf_unused_offset_ = 0; return OK; } @@ -324,12 +327,12 @@ int HttpStreamParser::DoReadBody() { bytes_read); read_buf_unused_offset_ += bytes_read; if (bytes_read == available) { - read_buf_->set_capacity(0); + read_buf_->SetCapacity(0); read_buf_unused_offset_ = 0; } return bytes_read; } else { - read_buf_->set_capacity(0); + read_buf_->SetCapacity(0); read_buf_unused_offset_ = 0; } } @@ -384,11 +387,18 @@ int HttpStreamParser::DoReadBodyComplete(int result) { result -= save_amount; } if (read_buf_->capacity() < save_amount + additional_save_amount) { - read_buf_->set_capacity(save_amount + additional_save_amount); + if (!read_buf_->SetCapacity(save_amount + additional_save_amount)) { + // This response is ok, but we weren't able to copy the extra data, + // so close the connection so that it is not reused. + connection_->socket()->Disconnect(); + connection_->Reset(); + read_buf_unused_offset_ = -1; // So that IsMoreDataBuffered works. + return result; + } } if (save_amount) { memcpy(read_buf_->StartOfBuffer(), user_read_buf_->data() + result, - save_amount); + save_amount); read_buf_->set_offset(save_amount); } if (additional_save_amount) { diff --git a/net/websockets/websocket.cc b/net/websockets/websocket.cc index a00f6bd..2d7169d 100644 --- a/net/websockets/websocket.cc +++ b/net/websockets/websocket.cc @@ -106,7 +106,7 @@ void WebSocket::OnConnected(SocketStream* socket_stream, // Use |max_pending_send_allowed| as hint for initial size of read buffer. current_read_buf_ = new GrowableIOBuffer(); - current_read_buf_->set_capacity(max_pending_send_allowed_); + current_read_buf_->SetCapacity(max_pending_send_allowed_); read_consumed_len_ = 0; DCHECK(!current_write_buf_); @@ -401,7 +401,7 @@ void WebSocket::AddToReadBuffer(const char* data, int len) { DCHECK(current_read_buf_); // Check if |current_read_buf_| has enough space to store |len| of |data|. if (len >= current_read_buf_->RemainingCapacity()) { - current_read_buf_->set_capacity( + current_read_buf_->SetCapacity( current_read_buf_->offset() + len); } |