From d87f8e6f287c0c8a79cf18e13a7c6debd3a77bb3 Mon Sep 17 00:00:00 2001 From: "rvargas@google.com" <rvargas@google.com@0039d316-1c4b-4281-b951-d872f2087c98> Date: Mon, 15 Nov 2010 19:31:23 +0000 Subject: [PATCH] Pickle: handle invalid data on 64 bit systems. There was a problem with pointer arithmetic for 64 bit systems so invalid data was not properly detected. Now we do explicit tests. BUG=56449 TEST=base_unittests Review URL: http://codereview.chromium.org/4716006 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@66149 0039d316-1c4b-4281-b951-d872f2087c98 --- base/pickle.cc | 16 +++++++++++++--- base/pickle.h | 4 +++- base/pickle_unittest.cc | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 4 deletions(-) diff --git a/base/pickle.cc b/base/pickle.cc index 06a3be1a806db..3f376e3f1cf95 100644 --- a/base/pickle.cc +++ b/base/pickle.cc @@ -41,11 +41,21 @@ Pickle::Pickle(int header_size) Pickle::Pickle(const char* data, int data_len) : header_(reinterpret_cast<Header*>(const_cast<char*>(data))), - header_size_(data_len - header_->payload_size), + header_size_(0), capacity_(kCapacityReadOnly), variable_buffer_offset_(0) { - DCHECK(header_size_ >= sizeof(Header)); - DCHECK(header_size_ == AlignInt(header_size_, sizeof(uint32))); + if (data_len >= static_cast<int>(sizeof(Header))) + header_size_ = data_len - header_->payload_size; + + if (header_size_ > static_cast<unsigned int>(data_len)) + header_size_ = 0; + + if (header_size_ != AlignInt(header_size_, sizeof(uint32))) + header_size_ = 0; + + // If there is anything wrong with the data, we're not going to use it. + if (!header_size_) + header_ = NULL; } Pickle::Pickle(const Pickle& other) diff --git a/base/pickle.h b/base/pickle.h index c7aee67032454..6006e621a09be 100644 --- a/base/pickle.h +++ b/base/pickle.h @@ -177,10 +177,12 @@ class Pickle { // Returns the address of the byte immediately following the currently valid // header + payload. char* end_of_payload() { + // We must have a valid header_. return payload() + payload_size(); } const char* end_of_payload() const { - return payload() + payload_size(); + // This object may be invalid. + return header_ ? payload() + payload_size() : NULL; } size_t capacity() const { diff --git a/base/pickle_unittest.cc b/base/pickle_unittest.cc index aea3830e93e6c..fdc0664f39018 100644 --- a/base/pickle_unittest.cc +++ b/base/pickle_unittest.cc @@ -87,6 +87,39 @@ TEST(PickleTest, EncodeDecode) { VerifyResult(pickle3); } +// Tests that we can handle really small buffers. +TEST(PickleTest, SmallBuffer) { + scoped_array<char> buffer(new char[1]); + + // We should not touch the buffer. + Pickle pickle(buffer.get(), 1); + + void* iter = NULL; + int data; + EXPECT_FALSE(pickle.ReadInt(&iter, &data)); +} + +// Tests that we can handle improper headers. +TEST(PickleTest, BigSize) { + int buffer[] = { 0x56035200, 25, 40, 50 }; + + Pickle pickle(reinterpret_cast<char*>(buffer), sizeof(buffer)); + + void* iter = NULL; + int data; + EXPECT_FALSE(pickle.ReadInt(&iter, &data)); +} + +TEST(PickleTest, UnalignedSize) { + int buffer[] = { 10, 25, 40, 50 }; + + Pickle pickle(reinterpret_cast<char*>(buffer), sizeof(buffer)); + + void* iter = NULL; + int data; + EXPECT_FALSE(pickle.ReadInt(&iter, &data)); +} + TEST(PickleTest, ZeroLenStr) { Pickle pickle; EXPECT_TRUE(pickle.WriteString("")); -- GitLab