Bug 1111065 - Backport some upstream IPC serialization fixes. r=bent, a=lmandel
authorJed Davis <jld@mozilla.com>
Thu, 19 Mar 2015 16:07:40 -0700
changeset 250460 a2295cc0de06
parent 250459 5bb1bb65cc28
child 250461 2e6977da201e
push id4594
push userryanvm@gmail.com
push date2015-03-20 00:14 +0000
treeherdermozilla-beta@a2295cc0de06 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbent, lmandel
bugs1111065
milestone37.0
Bug 1111065 - Backport some upstream IPC serialization fixes. r=bent, a=lmandel
ipc/chromium/src/base/pickle.cc
ipc/chromium/src/base/pickle.h
--- a/ipc/chromium/src/base/pickle.cc
+++ b/ipc/chromium/src/base/pickle.cc
@@ -119,21 +119,31 @@ Pickle::Pickle(int header_size)
   if (!header_) {
     NS_ABORT_OOM(kPayloadUnit);
   }
   header_->payload_size = 0;
 }
 
 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_));
+  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_))
+    header_size_ = 0;
+
+  // If there is anything wrong with the data, we're not going to use it.
+  if (!header_size_)
+    header_ = nullptr;
 }
 
 Pickle::Pickle(const Pickle& other)
     : header_(NULL),
       header_size_(other.header_size_),
       capacity_(0),
       variable_buffer_offset_(other.variable_buffer_offset_) {
   uint32_t payload_size = header_size_ + other.header_->payload_size;
@@ -643,16 +653,20 @@ bool Pickle::Resize(uint32_t new_capacit
 
 // static
 const char* Pickle::FindNext(uint32_t header_size,
                              const char* start,
                              const char* end) {
   DCHECK(header_size == AlignInt(header_size));
   DCHECK(header_size <= static_cast<memberAlignmentType>(kPayloadUnit));
 
+  if (end < start)
+    return nullptr;
+  size_t length = static_cast<size_t>(end - start);
+  if (length < sizeof(Header))
+    return nullptr;
+
   const Header* hdr = reinterpret_cast<const Header*>(start);
-  const char* payload_base = start + header_size;
-  const char* payload_end = payload_base + hdr->payload_size;
-  if (payload_end < payload_base)
-    return NULL;
+  if (length < header_size || length - header_size < hdr->payload_size)
+    return nullptr;
 
-  return (payload_end > end) ? NULL : payload_end;
+  return start + header_size + hdr->payload_size;
 }
--- a/ipc/chromium/src/base/pickle.h
+++ b/ipc/chromium/src/base/pickle.h
@@ -221,20 +221,22 @@ class Pickle {
   }
   const char* payload() const {
     return reinterpret_cast<const char*>(header_) + header_size_;
   }
 
   // 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() : nullptr;
   }
 
   uint32_t capacity() const {
     return capacity_;
   }
 
   // Resizes the buffer for use when writing the specified amount of data. The
   // location that the data should be written at is returned, or NULL if there