summaryrefslogtreecommitdiff
path: root/chromium/base/pickle.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/base/pickle.cc')
-rw-r--r--chromium/base/pickle.cc63
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_;