From 58936737b65052775b67b1409b87edbbbc09f72b Mon Sep 17 00:00:00 2001 From: "aedla@chromium.org" Date: Mon, 28 Jan 2013 16:24:41 +0000 Subject: Avoid integer overflows in BlobURLRequestJob. BUG=169685 Review URL: https://chromiumcodereview.appspot.com/12047012 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@179154 0039d316-1c4b-4281-b951-d872f2087c98 --- webkit/blob/blob_url_request_job.cc | 70 +++++++++++++++++++++++++++---------- webkit/blob/blob_url_request_job.h | 1 + 2 files changed, 52 insertions(+), 19 deletions(-) (limited to 'webkit') diff --git a/webkit/blob/blob_url_request_job.cc b/webkit/blob/blob_url_request_job.cc index ae3dd24..13c46b9 100644 --- a/webkit/blob/blob_url_request_job.cc +++ b/webkit/blob/blob_url_request_job.cc @@ -4,6 +4,8 @@ #include "webkit/blob/blob_url_request_job.h" +#include + #include "base/bind.h" #include "base/compiler_specific.h" #include "base/files/file_util_proxy.h" @@ -46,6 +48,8 @@ const char kHTTPRequestedRangeNotSatisfiableText[] = "Requested Range Not Satisfiable"; const char kHTTPInternalErrorText[] = "Internal Server Error"; +const int64 kMaxTotalSize = std::numeric_limits::max(); + bool IsFileType(BlobData::Item::Type type) { switch (type) { case BlobData::Item::TYPE_FILE: @@ -183,6 +187,19 @@ void BlobURLRequestJob::DidStart() { CountSize(); } +bool BlobURLRequestJob::AddItemLength(size_t index, int64 item_length) { + if (item_length > kMaxTotalSize - total_size_) { + NotifyFailure(net::ERR_FAILED); + return false; + } + + // Cache the size and add it to the total size. + DCHECK_LT(index, item_length_list_.size()); + item_length_list_[index] = item_length; + total_size_ += item_length; + return true; +} + void BlobURLRequestJob::CountSize() { error_ = false; pending_get_file_info_count_ = 0; @@ -198,10 +215,9 @@ void BlobURLRequestJob::CountSize() { weak_factory_.GetWeakPtr(), i)); continue; } - // Cache the size and add it to the total size. - int64 item_length = static_cast(item.length()); - item_length_list_[i] = item_length; - total_size_ += item_length; + + if (!AddItemLength(i, item.length())) + return; } if (pending_get_file_info_count_ == 0) @@ -251,16 +267,28 @@ void BlobURLRequestJob::DidGetFileItemLength(size_t index, int64 result) { const BlobData::Item& item = blob_data_->items().at(index); DCHECK(IsFileType(item.type())); + uint64 file_length = result; + uint64 item_offset = item.offset(); + uint64 item_length = item.length(); + + if (item_offset > file_length) { + NotifyFailure(net::ERR_FILE_NOT_FOUND); + return; + } + + uint64 max_length = file_length - item_offset; + // If item length is -1, we need to use the file size being resolved // in the real time. - int64 item_length = static_cast(item.length()); - if (item_length == -1) - item_length = result - item.offset(); + if (item_length == static_cast(-1)) { + item_length = max_length; + } else if (item_length > max_length) { + NotifyFailure(net::ERR_FILE_NOT_FOUND); + return; + } - // Cache the size and add it to the total size. - DCHECK_LT(index, item_length_list_.size()); - item_length_list_[index] = item_length; - total_size_ += item_length; + if (!AddItemLength(index, item_length)) + return; if (--pending_get_file_info_count_ == 0) DidCountSize(net::OK); @@ -420,14 +448,18 @@ int BlobURLRequestJob::BytesReadCompleted() { } int BlobURLRequestJob::ComputeBytesToRead() const { - int64 current_item_remaining_bytes = - item_length_list_[current_item_index_] - current_item_offset_; - int64 remaining_bytes = std::min(current_item_remaining_bytes, - remaining_bytes_); - - return static_cast(std::min( - static_cast(read_buf_->BytesRemaining()), - remaining_bytes)); + int64 current_item_length = item_length_list_[current_item_index_]; + + int64 item_remaining = current_item_length - current_item_offset_; + int64 buf_remaining = read_buf_->BytesRemaining(); + int64 max_remaining = std::numeric_limits::max(); + + int64 min = std::min(std::min(std::min(item_remaining, + buf_remaining), + remaining_bytes_), + max_remaining); + + return static_cast(min); } bool BlobURLRequestJob::ReadLoop(int* bytes_read) { diff --git a/webkit/blob/blob_url_request_job.h b/webkit/blob/blob_url_request_job.h index 437dd3b..e24a491 100644 --- a/webkit/blob/blob_url_request_job.h +++ b/webkit/blob/blob_url_request_job.h @@ -60,6 +60,7 @@ class WEBKIT_STORAGE_EXPORT BlobURLRequestJob : public net::URLRequestJob { // For preparing for read: get the size, apply the range and perform seek. void DidStart(); + bool AddItemLength(size_t index, int64 item_length); void CountSize(); void DidCountSize(int error); void DidGetFileItemLength(size_t index, int64 result); -- cgit v1.1