diff options
author | aedla@chromium.org <aedla@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-01-28 16:24:41 +0000 |
---|---|---|
committer | aedla@chromium.org <aedla@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-01-28 16:24:41 +0000 |
commit | 58936737b65052775b67b1409b87edbbbc09f72b (patch) | |
tree | 70b24a0d0b6d79dd561b142a05af20d4ca0867f5 /webkit/blob | |
parent | ebd1e2e7cff7e0134dc48f0eb208c2fc84963d8d (diff) | |
download | chromium_src-58936737b65052775b67b1409b87edbbbc09f72b.zip chromium_src-58936737b65052775b67b1409b87edbbbc09f72b.tar.gz chromium_src-58936737b65052775b67b1409b87edbbbc09f72b.tar.bz2 |
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
Diffstat (limited to 'webkit/blob')
-rw-r--r-- | webkit/blob/blob_url_request_job.cc | 70 | ||||
-rw-r--r-- | webkit/blob/blob_url_request_job.h | 1 |
2 files changed, 52 insertions, 19 deletions
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 <limits> + #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<int64>::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<int64>(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<int64>(item.length()); - if (item_length == -1) - item_length = result - item.offset(); + if (item_length == static_cast<uint64>(-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<int>(std::min( - static_cast<int64>(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<int>::max(); + + int64 min = std::min(std::min(std::min(item_remaining, + buf_remaining), + remaining_bytes_), + max_remaining); + + return static_cast<int>(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); |