LCOV - code coverage report
Current view: top level - ipc/chromium/src/base - pickle.cc (source / functions) Hit Total Coverage
Test: output.info Lines: 176 287 61.3 %
Date: 2017-07-14 16:53:18 Functions: 41 56 73.2 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
       4             : // Use of this source code is governed by a BSD-style license that can be
       5             : // found in the LICENSE file.
       6             : 
       7             : #include "base/pickle.h"
       8             : 
       9             : #include "mozilla/Alignment.h"
      10             : #include "mozilla/CheckedInt.h"
      11             : #include "mozilla/EndianUtils.h"
      12             : #include "mozilla/TypeTraits.h"
      13             : #include "mozilla/Telemetry.h"
      14             : #include "mozilla/ipc/ProtocolUtils.h"
      15             : 
      16             : #include <stdlib.h>
      17             : 
      18             : #include <limits>
      19             : #include <string>
      20             : #include <algorithm>
      21             : 
      22             : #include "nsDebug.h"
      23             : 
      24             : //------------------------------------------------------------------------------
      25             : 
      26             : static_assert(MOZ_ALIGNOF(Pickle::memberAlignmentType) >= MOZ_ALIGNOF(uint32_t),
      27             :               "Insufficient alignment");
      28             : 
      29             : #ifndef MOZ_TASK_TRACER
      30             : static const uint32_t kHeaderSegmentCapacity = 64;
      31             : #else
      32             : // TaskTracer would add extra fields to the header to carry task ID and
      33             : // other information.
      34             : // \see class Message::HeaderTaskTracer
      35             : static const uint32_t kHeaderSegmentCapacity = 128;
      36             : #endif
      37             : 
      38             : static const uint32_t kDefaultSegmentCapacity = 4096;
      39             : 
      40             : static const char kBytePaddingMarker = char(0xbf);
      41             : 
      42             : // Note: we round the time to the nearest millisecond. So a min value of 1 ms
      43             : // actually captures from 500us and above.
      44             : static const uint32_t kMinTelemetryIPCReadLatencyMs = 1;
      45             : 
      46             : namespace {
      47             : 
      48             : // We want to copy data to our payload as efficiently as possible.
      49             : // memcpy fits the bill for copying, but not all compilers or
      50             : // architectures support inlining memcpy from void*, which has unknown
      51             : // static alignment.  However, we know that all the members of our
      52             : // payload will be aligned on memberAlignmentType boundaries.  We
      53             : // therefore use that knowledge to construct a copier that will copy
      54             : // efficiently (via standard C++ assignment mechanisms) if the datatype
      55             : // needs that alignment or less, and memcpy otherwise.  (The compiler
      56             : // may still inline memcpy, of course.)
      57             : 
      58             : template<typename T, size_t size, bool hasSufficientAlignment>
      59             : struct Copier
      60             : {
      61        1657 :   static void Copy(T* dest, const char* iter) {
      62        1657 :     memcpy(dest, iter, sizeof(T));
      63        1657 :   }
      64             : };
      65             : 
      66             : // Copying 64-bit quantities happens often enough and can easily be made
      67             : // worthwhile on 32-bit platforms, so handle it specially.  Only do it
      68             : // if 64-bit types aren't sufficiently aligned; the alignment
      69             : // requirements for them vary between 32-bit platforms.
      70             : #ifndef HAVE_64BIT_BUILD
      71             : template<typename T>
      72             : struct Copier<T, sizeof(uint64_t), false>
      73             : {
      74             :   static void Copy(T* dest, const char* iter) {
      75             : #if MOZ_LITTLE_ENDIAN
      76             :     static const int loIndex = 0, hiIndex = 1;
      77             : #else
      78             :     static const int loIndex = 1, hiIndex = 0;
      79             : #endif
      80             :     static_assert(MOZ_ALIGNOF(uint32_t*) == MOZ_ALIGNOF(void*),
      81             :                   "Pointers have different alignments");
      82             :     const uint32_t* src = reinterpret_cast<const uint32_t*>(iter);
      83             :     uint32_t* uint32dest = reinterpret_cast<uint32_t*>(dest);
      84             :     uint32dest[loIndex] = src[loIndex];
      85             :     uint32dest[hiIndex] = src[hiIndex];
      86             :   }
      87             : };
      88             : #endif
      89             : 
      90             : template<typename T, size_t size>
      91             : struct Copier<T, size, true>
      92             : {
      93      124728 :   static void Copy(T* dest, const char* iter) {
      94      124728 :     *dest = *reinterpret_cast<const T*>(iter);
      95      124728 :   }
      96             : };
      97             : 
      98             : } // anonymous namespace
      99             : 
     100         550 : PickleIterator::PickleIterator(const Pickle& pickle)
     101         550 :    : iter_(pickle.buffers_.Iter())
     102         550 :    , start_(mozilla::TimeStamp::Now()) {
     103         550 :   iter_.Advance(pickle.buffers_, pickle.header_size_);
     104         550 : }
     105             : 
     106             : template<typename T>
     107             : void
     108      126384 : PickleIterator::CopyInto(T* dest) {
     109             :   static_assert(mozilla::IsPod<T>::value, "Copied type must be a POD type");
     110      126384 :   Copier<T, sizeof(T), (MOZ_ALIGNOF(T) <= sizeof(Pickle::memberAlignmentType))>::Copy(dest, iter_.Data());
     111      126385 : }
     112             : 
     113      126384 : bool Pickle::IteratorHasRoomFor(const PickleIterator& iter, uint32_t len) const {
     114             :   // Make sure we don't get into trouble where AlignInt(len) == 0.
     115      126384 :   MOZ_RELEASE_ASSERT(len < 64);
     116             : 
     117      126384 :   return iter.iter_.HasRoomFor(AlignInt(len));
     118             : }
     119             : 
     120      126385 : void Pickle::UpdateIter(PickleIterator* iter, uint32_t bytes) const {
     121             :   // Make sure we don't get into trouble where AlignInt(bytes) == 0.
     122      126385 :   MOZ_RELEASE_ASSERT(bytes < 64);
     123             : 
     124      126385 :   iter->iter_.Advance(buffers_, AlignInt(bytes));
     125      126385 : }
     126             : 
     127             : // Payload is sizeof(Pickle::memberAlignmentType) aligned.
     128             : 
     129         570 : Pickle::Pickle(uint32_t header_size, size_t segment_capacity)
     130         570 :     : buffers_(AlignInt(header_size),
     131             :                segment_capacity ? segment_capacity : kHeaderSegmentCapacity,
     132             :                segment_capacity ? segment_capacity : kDefaultSegmentCapacity),
     133             :       header_(nullptr),
     134        1140 :       header_size_(AlignInt(header_size)) {
     135         570 :   DCHECK(static_cast<memberAlignmentType>(header_size) >= sizeof(Header));
     136         570 :   DCHECK(header_size_ <= kHeaderSegmentCapacity);
     137         570 :   header_ = reinterpret_cast<Header*>(buffers_.Start());
     138         570 :   header_->payload_size = 0;
     139         570 : }
     140             : 
     141         388 : Pickle::Pickle(uint32_t header_size, const char* data, uint32_t length)
     142         388 :     : buffers_(length, AlignCapacity(length), kDefaultSegmentCapacity),
     143             :       header_(nullptr),
     144         388 :       header_size_(AlignInt(header_size)) {
     145         388 :   DCHECK(static_cast<memberAlignmentType>(header_size) >= sizeof(Header));
     146         388 :   DCHECK(header_size <= kHeaderSegmentCapacity);
     147         388 :   MOZ_RELEASE_ASSERT(header_size <= length);
     148             : 
     149         388 :   header_ = reinterpret_cast<Header*>(buffers_.Start());
     150         388 :   memcpy(header_, data, length);
     151         388 : }
     152             : 
     153         476 : Pickle::Pickle(Pickle&& other)
     154         476 :    : buffers_(mozilla::Move(other.buffers_)),
     155         476 :      header_(other.header_),
     156         952 :      header_size_(other.header_size_) {
     157         476 :   other.header_ = nullptr;
     158         476 : }
     159             : 
     160        1418 : Pickle::~Pickle() {
     161        1418 : }
     162             : 
     163          56 : Pickle& Pickle::operator=(Pickle&& other) {
     164         112 :   BufferList tmp = mozilla::Move(other.buffers_);
     165          56 :   other.buffers_ = mozilla::Move(buffers_);
     166          56 :   buffers_ = mozilla::Move(tmp);
     167             : 
     168             :   //std::swap(buffers_, other.buffers_);
     169          56 :   std::swap(header_, other.header_);
     170          56 :   std::swap(header_size_, other.header_size_);
     171         112 :   return *this;
     172             : }
     173             : 
     174       13711 : bool Pickle::ReadBool(PickleIterator* iter, bool* result) const {
     175       13711 :   DCHECK(iter);
     176             : 
     177             :   int tmp;
     178       13711 :   if (!ReadInt(iter, &tmp))
     179           0 :     return false;
     180       13711 :   DCHECK(0 == tmp || 1 == tmp);
     181       13711 :   *result = tmp ? true : false;
     182       13711 :   return true;
     183             : }
     184             : 
     185          19 : bool Pickle::ReadInt16(PickleIterator* iter, int16_t* result) const {
     186          19 :   DCHECK(iter);
     187             : 
     188          19 :   if (!IteratorHasRoomFor(*iter, sizeof(*result)))
     189           0 :     return ReadBytesInto(iter, result, sizeof(*result));
     190             : 
     191          19 :   iter->CopyInto(result);
     192             : 
     193          19 :   UpdateIter(iter, sizeof(*result));
     194          19 :   return true;
     195             : }
     196             : 
     197          29 : bool Pickle::ReadUInt16(PickleIterator* iter, uint16_t* result) const {
     198          29 :   DCHECK(iter);
     199             : 
     200          29 :   if (!IteratorHasRoomFor(*iter, sizeof(*result)))
     201           0 :     return ReadBytesInto(iter, result, sizeof(*result));
     202             : 
     203          29 :   iter->CopyInto(result);
     204             : 
     205          29 :   UpdateIter(iter, sizeof(*result));
     206          29 :   return true;
     207             : }
     208             : 
     209       41500 : bool Pickle::ReadInt(PickleIterator* iter, int* result) const {
     210       41500 :   DCHECK(iter);
     211             : 
     212       41500 :   if (!IteratorHasRoomFor(*iter, sizeof(*result)))
     213           0 :     return ReadBytesInto(iter, result, sizeof(*result));
     214             : 
     215       41500 :   iter->CopyInto(result);
     216             : 
     217       41500 :   UpdateIter(iter, sizeof(*result));
     218       41500 :   return true;
     219             : }
     220             : 
     221             : // Always written as a 64-bit value since the size for this type can
     222             : // differ between architectures.
     223           0 : bool Pickle::ReadLong(PickleIterator* iter, long* result) const {
     224           0 :   DCHECK(iter);
     225             : 
     226           0 :   int64_t big_result = 0;
     227           0 :   if (IteratorHasRoomFor(*iter, sizeof(big_result))) {
     228           0 :     iter->CopyInto(&big_result);
     229           0 :     UpdateIter(iter, sizeof(big_result));
     230             :   } else {
     231           0 :     if (!ReadBytesInto(iter, &big_result, sizeof(big_result))) {
     232           0 :       return false;
     233             :     }
     234             :   }
     235             :   DCHECK(big_result <= LONG_MAX && big_result >= LONG_MIN);
     236           0 :   *result = static_cast<long>(big_result);
     237             : 
     238           0 :   return true;
     239             : }
     240             : 
     241             : // Always written as a 64-bit value since the size for this type can
     242             : // differ between architectures.
     243           0 : bool Pickle::ReadULong(PickleIterator* iter, unsigned long* result) const {
     244           0 :   DCHECK(iter);
     245             : 
     246           0 :   uint64_t big_result = 0;
     247           0 :   if (IteratorHasRoomFor(*iter, sizeof(big_result))) {
     248           0 :     iter->CopyInto(&big_result);
     249           0 :     UpdateIter(iter, sizeof(big_result));
     250             :   } else {
     251           0 :     if (!ReadBytesInto(iter, &big_result, sizeof(big_result))) {
     252           0 :       return false;
     253             :     }
     254             :   }
     255             :   DCHECK(big_result <= ULONG_MAX);
     256           0 :   *result = static_cast<unsigned long>(big_result);
     257             : 
     258           0 :   return true;
     259             : }
     260             : 
     261           0 : bool Pickle::ReadLength(PickleIterator* iter, int* result) const {
     262           0 :   if (!ReadInt(iter, result))
     263           0 :     return false;
     264           0 :   return ((*result) >= 0);
     265             : }
     266             : 
     267             : // Always written as a 64-bit value since the size for this type can
     268             : // differ between architectures.
     269        1644 : bool Pickle::ReadSize(PickleIterator* iter, size_t* result) const {
     270        1644 :   DCHECK(iter);
     271             : 
     272        1644 :   uint64_t big_result = 0;
     273        1644 :   if (IteratorHasRoomFor(*iter, sizeof(big_result))) {
     274        1644 :     iter->CopyInto(&big_result);
     275        1644 :     UpdateIter(iter, sizeof(big_result));
     276             :   } else {
     277           0 :     if (!ReadBytesInto(iter, &big_result, sizeof(big_result))) {
     278           0 :       return false;
     279             :     }
     280             :   }
     281        1644 :   DCHECK(big_result <= std::numeric_limits<size_t>::max());
     282        1644 :   *result = static_cast<size_t>(big_result);
     283             : 
     284        1644 :   return true;
     285             : }
     286             : 
     287           0 : bool Pickle::ReadInt32(PickleIterator* iter, int32_t* result) const {
     288           0 :   DCHECK(iter);
     289             : 
     290           0 :   if (!IteratorHasRoomFor(*iter, sizeof(*result)))
     291           0 :     return ReadBytesInto(iter, result, sizeof(*result));
     292             : 
     293           0 :   iter->CopyInto(result);
     294             : 
     295           0 :   UpdateIter(iter, sizeof(*result));
     296           0 :   return true;
     297             : }
     298             : 
     299       83179 : bool Pickle::ReadUInt32(PickleIterator* iter, uint32_t* result) const {
     300       83179 :   DCHECK(iter);
     301             : 
     302       83179 :   if (!IteratorHasRoomFor(*iter, sizeof(*result)))
     303           0 :     return ReadBytesInto(iter, result, sizeof(*result));
     304             : 
     305       83179 :   iter->CopyInto(result);
     306             : 
     307       83180 :   UpdateIter(iter, sizeof(*result));
     308       83180 :   return true;
     309             : }
     310             : 
     311          11 : bool Pickle::ReadInt64(PickleIterator* iter, int64_t* result) const {
     312          11 :   DCHECK(iter);
     313             : 
     314          11 :   if (!IteratorHasRoomFor(*iter, sizeof(*result)))
     315           0 :     return ReadBytesInto(iter, result, sizeof(*result));
     316             : 
     317          11 :   iter->CopyInto(result);
     318             : 
     319          11 :   UpdateIter(iter, sizeof(*result));
     320          11 :   return true;
     321             : }
     322             : 
     323           0 : bool Pickle::ReadUInt64(PickleIterator* iter, uint64_t* result) const {
     324           0 :   DCHECK(iter);
     325             : 
     326           0 :   if (!IteratorHasRoomFor(*iter, sizeof(*result)))
     327           0 :     return ReadBytesInto(iter, result, sizeof(*result));
     328             : 
     329           0 :   iter->CopyInto(result);
     330             : 
     331           0 :   UpdateIter(iter, sizeof(*result));
     332           0 :   return true;
     333             : }
     334             : 
     335           2 : bool Pickle::ReadDouble(PickleIterator* iter, double* result) const {
     336           2 :   DCHECK(iter);
     337             : 
     338           2 :   if (!IteratorHasRoomFor(*iter, sizeof(*result)))
     339           0 :     return ReadBytesInto(iter, result, sizeof(*result));
     340             : 
     341           2 :   iter->CopyInto(result);
     342             : 
     343           2 :   UpdateIter(iter, sizeof(*result));
     344           2 :   return true;
     345             : }
     346             : 
     347             : // Always written as a 64-bit value since the size for this type can
     348             : // differ between architectures.
     349           0 : bool Pickle::ReadIntPtr(PickleIterator* iter, intptr_t* result) const {
     350           0 :   DCHECK(iter);
     351             : 
     352           0 :   int64_t big_result = 0;
     353           0 :   if (IteratorHasRoomFor(*iter, sizeof(big_result))) {
     354           0 :     iter->CopyInto(&big_result);
     355           0 :     UpdateIter(iter, sizeof(big_result));
     356             :   } else {
     357           0 :     if (!ReadBytesInto(iter, &big_result, sizeof(big_result))) {
     358           0 :       return false;
     359             :     }
     360             :   }
     361             : 
     362           0 :   DCHECK(big_result <= std::numeric_limits<intptr_t>::max() && big_result >= std::numeric_limits<intptr_t>::min());
     363           0 :   *result = static_cast<intptr_t>(big_result);
     364             : 
     365           0 :   return true;
     366             : }
     367             : 
     368           0 : bool Pickle::ReadUnsignedChar(PickleIterator* iter, unsigned char* result) const {
     369           0 :   DCHECK(iter);
     370             : 
     371           0 :   if (!IteratorHasRoomFor(*iter, sizeof(*result)))
     372           0 :     return ReadBytesInto(iter, result, sizeof(*result));
     373             : 
     374           0 :   iter->CopyInto(result);
     375             : 
     376           0 :   UpdateIter(iter, sizeof(*result));
     377           0 :   return true;
     378             : }
     379             : 
     380           0 : bool Pickle::ReadString(PickleIterator* iter, std::string* result) const {
     381           0 :   DCHECK(iter);
     382             : 
     383             :   int len;
     384           0 :   if (!ReadLength(iter, &len))
     385           0 :     return false;
     386             : 
     387           0 :   auto chars = mozilla::MakeUnique<char[]>(len);
     388           0 :   if (!ReadBytesInto(iter, chars.get(), len)) {
     389           0 :     return false;
     390             :   }
     391           0 :   result->assign(chars.get(), len);
     392             : 
     393           0 :   return true;
     394             : }
     395             : 
     396           0 : bool Pickle::ReadWString(PickleIterator* iter, std::wstring* result) const {
     397           0 :   DCHECK(iter);
     398             : 
     399             :   int len;
     400           0 :   if (!ReadLength(iter, &len))
     401           0 :     return false;
     402             :   // Avoid integer multiplication overflow.
     403           0 :   if (len > INT_MAX / static_cast<int>(sizeof(wchar_t)))
     404           0 :     return false;
     405             : 
     406           0 :   auto chars = mozilla::MakeUnique<wchar_t[]>(len);
     407           0 :   if (!ReadBytesInto(iter, chars.get(), len * sizeof(wchar_t))) {
     408           0 :     return false;
     409             :   }
     410           0 :   result->assign(chars.get(), len);
     411             : 
     412           0 :   return true;
     413             : }
     414             : 
     415          40 : bool Pickle::ExtractBuffers(PickleIterator* iter, size_t length, BufferList* buffers,
     416             :                             uint32_t alignment) const
     417             : {
     418          40 :   DCHECK(iter);
     419          40 :   DCHECK(buffers);
     420          40 :   DCHECK(alignment == 4 || alignment == 8);
     421          40 :   DCHECK(intptr_t(header_) % alignment == 0);
     422             : 
     423          40 :   if (AlignInt(length) < length) {
     424           0 :     return false;
     425             :   }
     426             : 
     427          40 :   uint32_t padding_len = intptr_t(iter->iter_.Data()) % alignment;
     428          40 :   if (!iter->iter_.AdvanceAcrossSegments(buffers_, padding_len)) {
     429           0 :     return false;
     430             :   }
     431             : 
     432             :   bool success;
     433          40 :   *buffers = const_cast<BufferList*>(&buffers_)->Extract(iter->iter_, length, &success);
     434          40 :   if (!success) {
     435           0 :     return false;
     436             :   }
     437             : 
     438          40 :   return iter->iter_.AdvanceAcrossSegments(buffers_, AlignInt(length) - length);
     439             : }
     440             : 
     441       11278 : bool Pickle::ReadBytesInto(PickleIterator* iter, void* data, uint32_t length) const {
     442       11278 :   if (AlignInt(length) < length) {
     443           0 :     return false;
     444             :   }
     445             : 
     446       11278 :   if (!buffers_.ReadBytes(iter->iter_, reinterpret_cast<char*>(data), length)) {
     447           0 :     return false;
     448             :   }
     449             : 
     450       11278 :   return iter->iter_.AdvanceAcrossSegments(buffers_, AlignInt(length) - length);
     451             : }
     452             : 
     453             : #ifdef MOZ_PICKLE_SENTINEL_CHECKING
     454       70354 : bool Pickle::ReadSentinel(PickleIterator* iter, uint32_t sentinel) const {
     455             :   uint32_t found;
     456       70354 :   if (!ReadUInt32(iter, &found)) {
     457           0 :     return false;
     458             :   }
     459       70354 :   return found == sentinel;
     460             : }
     461             : 
     462           2 : bool Pickle::IgnoreSentinel(PickleIterator* iter) const {
     463             :   uint32_t found;
     464           2 :   return ReadUInt32(iter, &found);
     465             : }
     466             : 
     467       70459 : bool Pickle::WriteSentinel(uint32_t sentinel) {
     468       70459 :   return WriteUInt32(sentinel);
     469             : }
     470             : #endif
     471             : 
     472         435 : void Pickle::EndRead(PickleIterator& iter, uint32_t ipcMsgType) const {
     473         435 :   DCHECK(iter.iter_.Done());
     474             : 
     475         435 :   if (NS_IsMainThread() && ipcMsgType != 0) {
     476         272 :     uint32_t latencyMs = round((mozilla::TimeStamp::Now() - iter.start_).ToMilliseconds());
     477         272 :     if (latencyMs >= kMinTelemetryIPCReadLatencyMs) {
     478             :       mozilla::Telemetry::Accumulate(mozilla::Telemetry::IPC_READ_MAIN_THREAD_LATENCY_MS,
     479           8 :                                      nsDependentCString(mozilla::ipc::StringFromIPCMessageType(ipcMsgType)),
     480           4 :                                      latencyMs);
     481             :     }
     482             :   }
     483         435 : }
     484             : 
     485      138415 : void Pickle::BeginWrite(uint32_t length, uint32_t alignment) {
     486      138415 :   DCHECK(alignment % 4 == 0) << "Must be at least 32-bit aligned!";
     487             : 
     488             :   // write at an alignment-aligned offset from the beginning of the header
     489      138415 :   uint32_t offset = AlignInt(header_->payload_size);
     490      138415 :   uint32_t padding = (header_size_ + offset) % alignment;
     491      138415 :   uint32_t new_size = offset + padding + AlignInt(length);
     492      138415 :   MOZ_RELEASE_ASSERT(new_size >= header_->payload_size);
     493             : 
     494      138415 :   DCHECK(intptr_t(header_) % alignment == 0);
     495             : 
     496             : #ifdef ARCH_CPU_64_BITS
     497      138415 :   DCHECK_LE(length, std::numeric_limits<uint32_t>::max());
     498             : #endif
     499             : 
     500      138415 :   if (padding) {
     501          15 :     MOZ_RELEASE_ASSERT(padding <= 8);
     502             :     static const char padding_data[8] = {
     503             :       kBytePaddingMarker, kBytePaddingMarker, kBytePaddingMarker, kBytePaddingMarker,
     504             :       kBytePaddingMarker, kBytePaddingMarker, kBytePaddingMarker, kBytePaddingMarker,
     505             :     };
     506          15 :     buffers_.WriteBytes(padding_data, padding);
     507             :   }
     508             : 
     509      138415 :   DCHECK((header_size_ + header_->payload_size + padding) % alignment == 0);
     510             : 
     511      138415 :   header_->payload_size = new_size;
     512      138415 : }
     513             : 
     514      138414 : void Pickle::EndWrite(uint32_t length) {
     515             :   // Zero-pad to keep tools like purify from complaining about uninitialized
     516             :   // memory.
     517      138414 :   uint32_t padding = AlignInt(length) - length;
     518      138414 :   if (padding) {
     519        6841 :     MOZ_RELEASE_ASSERT(padding <= 4);
     520             :     static const char padding_data[4] = {
     521             :       kBytePaddingMarker, kBytePaddingMarker, kBytePaddingMarker, kBytePaddingMarker,
     522             :     };
     523        6841 :     buffers_.WriteBytes(padding_data, padding);
     524             :   }
     525      138414 : }
     526             : 
     527      138415 : bool Pickle::WriteBytes(const void* data, uint32_t data_len, uint32_t alignment) {
     528      138415 :   DCHECK(alignment == 4 || alignment == 8);
     529      138415 :   DCHECK(intptr_t(header_) % alignment == 0);
     530             : 
     531      138415 :   BeginWrite(data_len, alignment);
     532             : 
     533      138415 :   buffers_.WriteBytes(reinterpret_cast<const char*>(data), data_len);
     534             : 
     535      138414 :   EndWrite(data_len);
     536      138414 :   return true;
     537             : }
     538             : 
     539           0 : bool Pickle::WriteString(const std::string& value) {
     540             : #ifdef FUZZING
     541             :   std::string v(value);
     542             :   Singleton<mozilla::ipc::Faulty>::get()->FuzzString(v);
     543             :   if (!WriteInt(static_cast<int>(v.size())))
     544             :     return false;
     545             : 
     546             :   return WriteBytes(v.data(), static_cast<int>(v.size()));
     547             : #else
     548           0 :   if (!WriteInt(static_cast<int>(value.size())))
     549           0 :     return false;
     550             : 
     551           0 :   return WriteBytes(value.data(), static_cast<int>(value.size()));
     552             : #endif
     553             : }
     554             : 
     555           0 : bool Pickle::WriteWString(const std::wstring& value) {
     556             : #ifdef FUZZING
     557             :   std::wstring v(value);
     558             :   Singleton<mozilla::ipc::Faulty>::get()->FuzzWString(v);
     559             :   if (!WriteInt(static_cast<int>(v.size())))
     560             :     return false;
     561             : 
     562             :   return WriteBytes(v.data(),
     563             :                     static_cast<int>(v.size() * sizeof(wchar_t)));
     564             : #else
     565           0 :   if (!WriteInt(static_cast<int>(value.size())))
     566           0 :     return false;
     567             : 
     568           0 :   return WriteBytes(value.data(),
     569           0 :                     static_cast<int>(value.size() * sizeof(wchar_t)));
     570             : #endif
     571             : }
     572             : 
     573           0 : bool Pickle::WriteData(const char* data, uint32_t length) {
     574             : #ifdef FUZZING
     575             :   std::string v(data, length);
     576             :   Singleton<mozilla::ipc::Faulty>::get()->FuzzData(v, v.size());
     577             :   return WriteInt(v.size()) && WriteBytes(v.data(), v.size());
     578             : #else
     579           0 :    return WriteInt(length) && WriteBytes(data, length);
     580             : #endif
     581             : }
     582             : 
     583         419 : void Pickle::InputBytes(const char* data, uint32_t length) {
     584         419 :   buffers_.WriteBytes(data, length);
     585         419 : }
     586             : 
     587           0 : int32_t* Pickle::GetInt32PtrForTest(uint32_t offset) {
     588           0 :   size_t pos = buffers_.Size() - offset;
     589           0 :   BufferList::IterImpl iter(buffers_);
     590           0 :   MOZ_RELEASE_ASSERT(iter.AdvanceAcrossSegments(buffers_, pos));
     591           0 :   return reinterpret_cast<int32_t*>(iter.Data());
     592             : }
     593             : 
     594             : // static
     595         388 : uint32_t Pickle::MessageSize(uint32_t header_size,
     596             :                              const char* start,
     597             :                              const char* end) {
     598         388 :   DCHECK(header_size == AlignInt(header_size));
     599         388 :   DCHECK(header_size <= static_cast<memberAlignmentType>(kHeaderSegmentCapacity));
     600             : 
     601         388 :   if (end < start)
     602           0 :     return 0;
     603         388 :   size_t length = static_cast<size_t>(end - start);
     604         388 :   if (length < sizeof(Header))
     605           0 :     return 0;
     606             : 
     607         388 :   const Header* hdr = reinterpret_cast<const Header*>(start);
     608         388 :   if (length < header_size)
     609           0 :     return 0;
     610             : 
     611         388 :   mozilla::CheckedInt<uint32_t> sum(header_size);
     612         388 :   sum += hdr->payload_size;
     613             : 
     614         388 :   if (!sum.isValid())
     615           0 :     return 0;
     616             : 
     617         388 :   return sum.value();
     618             : }

Generated by: LCOV version 1.13