diff options
Diffstat (limited to 'chromium/base/pickle.cc')
-rw-r--r-- | chromium/base/pickle.cc | 63 |
1 files changed, 48 insertions, 15 deletions
diff --git a/chromium/base/pickle.cc b/chromium/base/pickle.cc index cf4a865d35c..489c7f890a7 100644 --- a/chromium/base/pickle.cc +++ b/chromium/base/pickle.cc @@ -7,6 +7,10 @@ #include <stdlib.h> #include <algorithm> // for max() +#include <limits> + +#include "base/bits.h" +#include "base/macros.h" namespace base { @@ -34,7 +38,7 @@ inline bool PickleIterator::ReadBuiltinType(Type* result) { } inline void PickleIterator::Advance(size_t size) { - size_t aligned_size = AlignInt(size, sizeof(uint32_t)); + size_t aligned_size = bits::Align(size, sizeof(uint32_t)); if (end_index_ - read_index_ < aligned_size) { read_index_ = end_index_; } else { @@ -210,13 +214,15 @@ Pickle::Pickle() header_size_(sizeof(Header)), capacity_after_header_(0), write_offset_(0) { + static_assert((Pickle::kPayloadUnit & (Pickle::kPayloadUnit - 1)) == 0, + "Pickle::kPayloadUnit must be a power of two"); Resize(kPayloadUnit); header_->payload_size = 0; } Pickle::Pickle(int header_size) : header_(NULL), - header_size_(AlignInt(header_size, sizeof(uint32))), + header_size_(bits::Align(header_size, sizeof(uint32))), capacity_after_header_(0), write_offset_(0) { DCHECK_GE(static_cast<size_t>(header_size), sizeof(Header)); @@ -236,7 +242,7 @@ Pickle::Pickle(const char* data, int data_len) if (header_size_ > static_cast<unsigned int>(data_len)) header_size_ = 0; - if (header_size_ != AlignInt(header_size_, sizeof(uint32))) + if (header_size_ != bits::Align(header_size_, sizeof(uint32))) header_size_ = 0; // If there is anything wrong with the data, we're not going to use it. @@ -249,9 +255,8 @@ Pickle::Pickle(const Pickle& other) header_size_(other.header_size_), capacity_after_header_(0), write_offset_(other.write_offset_) { - size_t payload_size = header_size_ + other.header_->payload_size; - Resize(payload_size); - memcpy(header_, other.header_, payload_size); + Resize(other.header_->payload_size); + memcpy(header_, other.header_, header_size_ + other.header_->payload_size); } Pickle::~Pickle() { @@ -305,7 +310,7 @@ bool Pickle::WriteBytes(const void* data, int length) { } void Pickle::Reserve(size_t length) { - size_t data_len = AlignInt(length, sizeof(uint32)); + size_t data_len = bits::Align(length, sizeof(uint32)); DCHECK_GE(data_len, length); #ifdef ARCH_CPU_64_BITS DCHECK_LE(data_len, kuint32max); @@ -318,7 +323,7 @@ void Pickle::Reserve(size_t length) { void Pickle::Resize(size_t new_capacity) { CHECK_NE(capacity_after_header_, kCapacityReadOnly); - capacity_after_header_ = AlignInt(new_capacity, kPayloadUnit); + capacity_after_header_ = bits::Align(new_capacity, kPayloadUnit); void* p = realloc(header_, GetTotalAllocatedSize()); CHECK(p); header_ = reinterpret_cast<Header*>(p); @@ -334,17 +339,41 @@ size_t Pickle::GetTotalAllocatedSize() const { const char* Pickle::FindNext(size_t header_size, const char* start, const char* end) { - DCHECK_EQ(header_size, AlignInt(header_size, sizeof(uint32))); + size_t pickle_size = 0; + if (!PeekNext(header_size, start, end, &pickle_size)) + return NULL; + + if (pickle_size > static_cast<size_t>(end - start)) + return NULL; + + return start + pickle_size; +} + +// static +bool Pickle::PeekNext(size_t header_size, + const char* start, + const char* end, + size_t* pickle_size) { + DCHECK_EQ(header_size, bits::Align(header_size, sizeof(uint32))); + DCHECK_GE(header_size, sizeof(Header)); DCHECK_LE(header_size, static_cast<size_t>(kPayloadUnit)); size_t length = static_cast<size_t>(end - start); if (length < sizeof(Header)) - return NULL; + return false; const Header* hdr = reinterpret_cast<const Header*>(start); - if (length < header_size || length - header_size < hdr->payload_size) - return NULL; - return start + header_size + hdr->payload_size; + if (length < header_size) + return false; + + if (hdr->payload_size > std::numeric_limits<size_t>::max() - header_size) { + // If payload_size causes an overflow, we return maximum possible + // pickle size to indicate that. + *pickle_size = std::numeric_limits<size_t>::max(); + } else { + *pickle_size = header_size + hdr->payload_size; + } + return true; } template <size_t length> void Pickle::WriteBytesStatic(const void* data) { @@ -359,7 +388,7 @@ inline void Pickle::WriteBytesCommon(const void* data, size_t length) { DCHECK_NE(kCapacityReadOnly, capacity_after_header_) << "oops: pickle is readonly"; MSAN_CHECK_MEM_IS_INITIALIZED(data, length); - size_t data_len = AlignInt(length, sizeof(uint32)); + size_t data_len = bits::Align(length, sizeof(uint32)); DCHECK_GE(data_len, length); #ifdef ARCH_CPU_64_BITS DCHECK_LE(data_len, kuint32max); @@ -367,7 +396,11 @@ inline void Pickle::WriteBytesCommon(const void* data, size_t length) { DCHECK_LE(write_offset_, kuint32max - data_len); size_t new_size = write_offset_ + data_len; if (new_size > capacity_after_header_) { - Resize(std::max(capacity_after_header_ * 2, new_size)); + size_t new_capacity = capacity_after_header_ * 2; + const size_t kPickleHeapAlign = 4096; + if (new_capacity > kPickleHeapAlign) + new_capacity = bits::Align(new_capacity, kPickleHeapAlign) - kPayloadUnit; + Resize(std::max(new_capacity, new_size)); } char* write = mutable_payload() + write_offset_; |