Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(669)

Side by Side Diff: net/http/http_stream_parser.cc

Issue 338049: Handle out of memory in GrowableIOBuffer more gracefully.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/http/http_stream_parser.h" 5 #include "net/http/http_stream_parser.h"
6 6
7 #include "base/compiler_specific.h" 7 #include "base/compiler_specific.h"
8 #include "base/trace_event.h" 8 #include "base/trace_event.h"
9 #include "net/base/io_buffer.h" 9 #include "net/base/io_buffer.h"
10 #include "net/http/http_request_info.h" 10 #include "net/http/http_request_info.h"
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after
201 } else { 201 } else {
202 io_state_ = STATE_REQUEST_SENT; 202 io_state_ = STATE_REQUEST_SENT;
203 } 203 }
204 return result; 204 return result;
205 } 205 }
206 206
207 int HttpStreamParser::DoReadHeaders() { 207 int HttpStreamParser::DoReadHeaders() {
208 io_state_ = STATE_READ_HEADERS_COMPLETE; 208 io_state_ = STATE_READ_HEADERS_COMPLETE;
209 209
210 // Grow the read buffer if necessary. 210 // Grow the read buffer if necessary.
211 if (read_buf_->RemainingCapacity() == 0) 211 if (read_buf_->RemainingCapacity() == 0) {
212 read_buf_->set_capacity(read_buf_->capacity() + kHeaderBufInitialSize); 212 if (!read_buf_->SetCapacity(read_buf_->capacity() + kHeaderBufInitialSize))
213 return ERR_OUT_OF_MEMORY;
214 }
213 215
214 // http://crbug.com/16371: We're seeing |user_buf_->data()| return NULL. 216 // http://crbug.com/16371: We're seeing |user_buf_->data()| return NULL.
215 // See if the user is passing in an IOBuffer with a NULL |data_|. 217 // See if the user is passing in an IOBuffer with a NULL |data_|.
216 CHECK(read_buf_->data()); 218 CHECK(read_buf_->data());
217 219
218 int bytes_read = connection_->socket()->Read(read_buf_, 220 int bytes_read = connection_->socket()->Read(read_buf_,
219 read_buf_->RemainingCapacity(), 221 read_buf_->RemainingCapacity(),
220 &io_callback_); 222 &io_callback_);
221 if (bytes_read == 0) 223 if (bytes_read == 0)
222 bytes_read = ERR_CONNECTION_CLOSED; 224 bytes_read = ERR_CONNECTION_CLOSED;
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
293 // data here and transition to DONE. 295 // data here and transition to DONE.
294 if (response_body_length_ == 0) { 296 if (response_body_length_ == 0) {
295 io_state_ = STATE_DONE; 297 io_state_ = STATE_DONE;
296 int extra_bytes = read_buf_->offset() - read_buf_unused_offset_; 298 int extra_bytes = read_buf_->offset() - read_buf_unused_offset_;
297 if (extra_bytes) { 299 if (extra_bytes) {
298 CHECK(extra_bytes > 0); 300 CHECK(extra_bytes > 0);
299 memmove(read_buf_->StartOfBuffer(), 301 memmove(read_buf_->StartOfBuffer(),
300 read_buf_->StartOfBuffer() + read_buf_unused_offset_, 302 read_buf_->StartOfBuffer() + read_buf_unused_offset_,
301 extra_bytes); 303 extra_bytes);
302 } 304 }
303 read_buf_->set_capacity(extra_bytes); 305 // Ok if this fails, since it only shrinks the buffer.
wtc 2009/10/27 22:42:10 Sorry, I just realized that if this fails, the ori
wtc 2009/10/28 01:38:44 The memmove call at line 301 above moves extra_byt
vandebo (ex-Chrome) 2009/10/28 01:44:54 Ahh, indeed you are correct. I will change it bac
wtc 2009/10/28 01:55:29 I found that the read_buf_->set_offset(extra_byt
306 read_buf_->SetCapacity(extra_bytes);
304 read_buf_unused_offset_ = 0; 307 read_buf_unused_offset_ = 0;
305 return OK; 308 return OK;
306 } 309 }
307 } 310 }
308 } 311 }
309 return result; 312 return result;
310 } 313 }
311 314
312 int HttpStreamParser::DoReadBody() { 315 int HttpStreamParser::DoReadBody() {
313 io_state_ = STATE_READ_BODY_COMPLETE; 316 io_state_ = STATE_READ_BODY_COMPLETE;
314 317
315 int bytes_read; 318 int bytes_read;
316 // There may be some data left over from reading the response headers. 319 // There may be some data left over from reading the response headers.
317 if (read_buf_->offset()) { 320 if (read_buf_->offset()) {
318 int available = read_buf_->offset() - read_buf_unused_offset_; 321 int available = read_buf_->offset() - read_buf_unused_offset_;
319 if (available) { 322 if (available) {
320 CHECK(available > 0); 323 CHECK(available > 0);
321 bytes_read = std::min(available, user_read_buf_len_); 324 bytes_read = std::min(available, user_read_buf_len_);
322 memcpy(user_read_buf_->data(), 325 memcpy(user_read_buf_->data(),
323 read_buf_->StartOfBuffer() + read_buf_unused_offset_, 326 read_buf_->StartOfBuffer() + read_buf_unused_offset_,
324 bytes_read); 327 bytes_read);
325 read_buf_unused_offset_ += bytes_read; 328 read_buf_unused_offset_ += bytes_read;
326 if (bytes_read == available) { 329 if (bytes_read == available) {
327 read_buf_->set_capacity(0); 330 read_buf_->SetCapacity(0);
328 read_buf_unused_offset_ = 0; 331 read_buf_unused_offset_ = 0;
329 } 332 }
330 return bytes_read; 333 return bytes_read;
331 } else { 334 } else {
332 read_buf_->set_capacity(0); 335 read_buf_->SetCapacity(0);
333 read_buf_unused_offset_ = 0; 336 read_buf_unused_offset_ = 0;
334 } 337 }
335 } 338 }
336 339
337 // Check to see if we're done reading. 340 // Check to see if we're done reading.
338 if (IsResponseBodyComplete()) 341 if (IsResponseBodyComplete())
339 return 0; 342 return 0;
340 343
341 DCHECK_EQ(0, read_buf_->offset()); 344 DCHECK_EQ(0, read_buf_->offset());
342 bytes_read = connection_->socket()->Read(user_read_buf_, user_read_buf_len_, 345 bytes_read = connection_->socket()->Read(user_read_buf_, user_read_buf_len_,
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
377 } else if (response_body_length_ >= 0) { 380 } else if (response_body_length_ >= 0) {
378 save_amount = static_cast<int>(response_body_read_ - 381 save_amount = static_cast<int>(response_body_read_ -
379 response_body_length_); 382 response_body_length_);
380 if (save_amount < 0) 383 if (save_amount < 0)
381 save_amount = 0; 384 save_amount = 0;
382 385
383 if (result > 0) 386 if (result > 0)
384 result -= save_amount; 387 result -= save_amount;
385 } 388 }
386 if (read_buf_->capacity() < save_amount + additional_save_amount) { 389 if (read_buf_->capacity() < save_amount + additional_save_amount) {
387 read_buf_->set_capacity(save_amount + additional_save_amount); 390 if (!read_buf_->SetCapacity(save_amount + additional_save_amount)) {
391 // This response is ok, but we weren't able to copy the extra data,
392 // so close the connection so that it is not reused.
393 connection_->socket()->Disconnect();
394 connection_->Reset();
395 read_buf_unused_offset_ = -1; // So that IsMoreDataBuffered works.
396 return result;
397 }
388 } 398 }
389 if (save_amount) { 399 if (save_amount) {
390 memcpy(read_buf_->StartOfBuffer(), user_read_buf_->data() + result, 400 memcpy(read_buf_->StartOfBuffer(), user_read_buf_->data() + result,
391 save_amount); 401 save_amount);
392 read_buf_->set_offset(save_amount); 402 read_buf_->set_offset(save_amount);
393 } 403 }
394 if (additional_save_amount) { 404 if (additional_save_amount) {
395 memmove(read_buf_->data(), 405 memmove(read_buf_->data(),
396 read_buf_->StartOfBuffer() + read_buf_unused_offset_, 406 read_buf_->StartOfBuffer() + read_buf_unused_offset_,
397 additional_save_amount); 407 additional_save_amount);
398 read_buf_->set_offset(save_amount + additional_save_amount); 408 read_buf_->set_offset(save_amount + additional_save_amount);
399 } 409 }
400 read_buf_unused_offset_ = 0; 410 read_buf_unused_offset_ = 0;
401 } else { 411 } else {
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
511 521
512 bool HttpStreamParser::CanFindEndOfResponse() const { 522 bool HttpStreamParser::CanFindEndOfResponse() const {
513 return chunked_decoder_.get() || response_body_length_ >= 0; 523 return chunked_decoder_.get() || response_body_length_ >= 0;
514 } 524 }
515 525
516 bool HttpStreamParser::IsMoreDataBuffered() const { 526 bool HttpStreamParser::IsMoreDataBuffered() const {
517 return read_buf_->offset() > read_buf_unused_offset_; 527 return read_buf_->offset() > read_buf_unused_offset_;
518 } 528 }
519 529
520 } // namespace net 530 } // namespace net
OLDNEW
« net/base/io_buffer.cc ('K') | « net/base/io_buffer.cc ('k') | net/websockets/websocket.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698