LCOV - code coverage report
Current view: top level - ipc/chromium/src/base - pickle.h (source / functions) Hit Total Coverage
Test: output.info Lines: 33 35 94.3 %
Date: 2017-07-14 16:53:18 Functions: 18 19 94.7 %
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             : #ifndef BASE_PICKLE_H__
       8             : #define BASE_PICKLE_H__
       9             : 
      10             : #include <string>
      11             : 
      12             : #include "base/basictypes.h"
      13             : #include "base/logging.h"
      14             : #include "base/string16.h"
      15             : 
      16             : #include "mozilla/Attributes.h"
      17             : #include "mozilla/BufferList.h"
      18             : #include "mozilla/mozalloc.h"
      19             : #include "mozilla/TimeStamp.h"
      20             : 
      21             : #ifdef FUZZING
      22             : #include "base/singleton.h"
      23             : #include "mozilla/ipc/Faulty.h"
      24             : #endif
      25             : 
      26             : #if !defined(RELEASE_OR_BETA) || defined(DEBUG)
      27             : #define MOZ_PICKLE_SENTINEL_CHECKING
      28             : #endif
      29             : 
      30             : class Pickle;
      31             : 
      32             : class PickleIterator {
      33             : public:
      34             :   explicit PickleIterator(const Pickle& pickle);
      35             : 
      36             : private:
      37             :   friend class Pickle;
      38             : 
      39             :   mozilla::BufferList<InfallibleAllocPolicy>::IterImpl iter_;
      40             :   mozilla::TimeStamp start_;
      41             : 
      42             :   template<typename T>
      43             :   void CopyInto(T* dest);
      44             : };
      45             : 
      46             : // This class provides facilities for basic binary value packing and unpacking.
      47             : //
      48             : // The Pickle class supports appending primitive values (ints, strings, etc.)
      49             : // to a pickle instance.  The Pickle instance grows its internal memory buffer
      50             : // dynamically to hold the sequence of primitive values.   The internal memory
      51             : // buffer is exposed as the "data" of the Pickle.  This "data" can be passed
      52             : // to a Pickle object to initialize it for reading.
      53             : //
      54             : // When reading from a Pickle object, it is important for the consumer to know
      55             : // what value types to read and in what order to read them as the Pickle does
      56             : // not keep track of the type of data written to it.
      57             : //
      58             : // The Pickle's data has a header which contains the size of the Pickle's
      59             : // payload.  It can optionally support additional space in the header.  That
      60             : // space is controlled by the header_size parameter passed to the Pickle
      61             : // constructor.
      62             : //
      63             : class Pickle {
      64             :  public:
      65             :   ~Pickle();
      66             : 
      67             :   Pickle() = delete;
      68             : 
      69             :   // Initialize a Pickle object with the specified header size in bytes, which
      70             :   // must be greater-than-or-equal-to sizeof(Pickle::Header).  The header size
      71             :   // will be rounded up to ensure that the header size is 32bit-aligned.
      72             :   explicit Pickle(uint32_t header_size, size_t segment_capacity = 0);
      73             : 
      74             :   Pickle(uint32_t header_size, const char* data, uint32_t length);
      75             : 
      76             :   Pickle(const Pickle& other) = delete;
      77             : 
      78             :   Pickle(Pickle&& other);
      79             : 
      80             :   // Performs a deep copy.
      81             :   Pickle& operator=(const Pickle& other) = delete;
      82             : 
      83             :   Pickle& operator=(Pickle&& other);
      84             : 
      85             :   // Returns the size of the Pickle's data.
      86        1312 :   uint32_t size() const { return header_size_ + header_->payload_size; }
      87             : 
      88             :   typedef mozilla::BufferList<InfallibleAllocPolicy> BufferList;
      89             : 
      90        2293 :   const BufferList& Buffers() const { return buffers_; }
      91             : 
      92         838 :   uint32_t CurrentSize() const { return buffers_.Size(); }
      93             : 
      94             :   // Methods for reading the payload of the Pickle.  To read from the start of
      95             :   // the Pickle, initialize *iter to NULL.  If successful, these methods return
      96             :   // true.  Otherwise, false is returned to indicate that the result could not
      97             :   // be extracted.
      98             :   MOZ_MUST_USE bool ReadBool(PickleIterator* iter, bool* result) const;
      99             :   MOZ_MUST_USE bool ReadInt16(PickleIterator* iter, int16_t* result) const;
     100             :   MOZ_MUST_USE bool ReadUInt16(PickleIterator* iter, uint16_t* result) const;
     101             :   MOZ_MUST_USE bool ReadShort(PickleIterator* iter, short* result) const;
     102             :   MOZ_MUST_USE bool ReadInt(PickleIterator* iter, int* result) const;
     103             :   MOZ_MUST_USE bool ReadLong(PickleIterator* iter, long* result) const;
     104             :   MOZ_MUST_USE bool ReadULong(PickleIterator* iter, unsigned long* result) const;
     105             :   MOZ_MUST_USE bool ReadSize(PickleIterator* iter, size_t* result) const;
     106             :   MOZ_MUST_USE bool ReadInt32(PickleIterator* iter, int32_t* result) const;
     107             :   MOZ_MUST_USE bool ReadUInt32(PickleIterator* iter, uint32_t* result) const;
     108             :   MOZ_MUST_USE bool ReadInt64(PickleIterator* iter, int64_t* result) const;
     109             :   MOZ_MUST_USE bool ReadUInt64(PickleIterator* iter, uint64_t* result) const;
     110             :   MOZ_MUST_USE bool ReadDouble(PickleIterator* iter, double* result) const;
     111             :   MOZ_MUST_USE bool ReadIntPtr(PickleIterator* iter, intptr_t* result) const;
     112             :   MOZ_MUST_USE bool ReadUnsignedChar(PickleIterator* iter, unsigned char* result) const;
     113             :   MOZ_MUST_USE bool ReadString(PickleIterator* iter, std::string* result) const;
     114             :   MOZ_MUST_USE bool ReadWString(PickleIterator* iter, std::wstring* result) const;
     115             :   MOZ_MUST_USE bool ReadBytesInto(PickleIterator* iter, void* data, uint32_t length) const;
     116             :   MOZ_MUST_USE bool ExtractBuffers(PickleIterator* iter, size_t length, BufferList* buffers,
     117             :                                    uint32_t alignment = sizeof(memberAlignmentType)) const;
     118             : 
     119             :   // Safer version of ReadInt() checks for the result not being negative.
     120             :   // Use it for reading the object sizes.
     121             :   MOZ_MUST_USE bool ReadLength(PickleIterator* iter, int* result) const;
     122             : 
     123             :   MOZ_MUST_USE bool ReadSentinel(PickleIterator* iter, uint32_t sentinel) const
     124             : #ifdef MOZ_PICKLE_SENTINEL_CHECKING
     125             :     ;
     126             : #else
     127             :   {
     128             :     return true;
     129             :   }
     130             : #endif
     131             : 
     132             :   bool IgnoreSentinel(PickleIterator* iter) const
     133             : #ifdef MOZ_PICKLE_SENTINEL_CHECKING
     134             :     ;
     135             : #else
     136             :   {
     137             :     return true;
     138             :   }
     139             : #endif
     140             : 
     141             :   // NOTE: The message type optional parameter should _only_ be called from
     142             :   // generated IPDL code, as it is used to trigger the IPC_READ_LATENCY_MS
     143             :   // telemetry probe.
     144             :   void EndRead(PickleIterator& iter, uint32_t ipcMessageType = 0) const;
     145             : 
     146             :   // Methods for adding to the payload of the Pickle.  These values are
     147             :   // appended to the end of the Pickle's payload.  When reading values from a
     148             :   // Pickle, it is important to read them in the order in which they were added
     149             :   // to the Pickle.
     150       13778 :   bool WriteBool(bool value) {
     151             : #ifdef FUZZING
     152             :     Singleton<mozilla::ipc::Faulty>::get()->FuzzBool(&value);
     153             : #endif
     154       13778 :     return WriteInt(value ? 1 : 0);
     155             :   }
     156          19 :   bool WriteInt16(int16_t value) {
     157             : #ifdef FUZZING
     158             :     Singleton<mozilla::ipc::Faulty>::get()->FuzzInt16(&value);
     159             : #endif
     160          19 :     return WriteBytes(&value, sizeof(value));
     161             :   }
     162          29 :   bool WriteUInt16(uint16_t value) {
     163             : #ifdef FUZZING
     164             :     Singleton<mozilla::ipc::Faulty>::get()->FuzzUInt16(&value);
     165             : #endif
     166          29 :     return WriteBytes(&value, sizeof(value));
     167             :   }
     168       41570 :   bool WriteInt(int value) {
     169             : #ifdef FUZZING
     170             :     Singleton<mozilla::ipc::Faulty>::get()->FuzzInt(&value);
     171             : #endif
     172       41570 :     return WriteBytes(&value, sizeof(value));
     173             :   }
     174             :   bool WriteLong(long value) {
     175             :     // Always written as a 64-bit value since the size for this type can
     176             :     // differ between architectures.
     177             : #ifdef FUZZING
     178             :     Singleton<mozilla::ipc::Faulty>::get()->FuzzLong(&value);
     179             : #endif
     180             :     return WriteInt64(int64_t(value));
     181             :   }
     182           0 :   bool WriteULong(unsigned long value) {
     183             :     // Always written as a 64-bit value since the size for this type can
     184             :     // differ between architectures.
     185             : #ifdef FUZZING
     186             :     Singleton<mozilla::ipc::Faulty>::get()->FuzzULong(&value);
     187             : #endif
     188           0 :     return WriteUInt64(uint64_t(value));
     189             :   }
     190        1645 :   bool WriteSize(size_t value) {
     191             :     // Always written as a 64-bit value since the size for this type can
     192             :     // differ between architectures.
     193             : #ifdef FUZZING
     194             :     Singleton<mozilla::ipc::Faulty>::get()->FuzzSize(&value);
     195             : #endif
     196        1645 :     return WriteUInt64(uint64_t(value));
     197             :   }
     198             :   bool WriteInt32(int32_t value) {
     199             : #ifdef FUZZING
     200             :     Singleton<mozilla::ipc::Faulty>::get()->FuzzInt(&value);
     201             : #endif
     202             :     return WriteBytes(&value, sizeof(value));
     203             :   }
     204       83752 :   bool WriteUInt32(uint32_t value) {
     205             : #ifdef FUZZING
     206             :     Singleton<mozilla::ipc::Faulty>::get()->FuzzUInt32(&value);
     207             : #endif
     208       83752 :     return WriteBytes(&value, sizeof(value));
     209             :   }
     210          11 :   bool WriteInt64(int64_t value) {
     211             : #ifdef FUZZING
     212             :     Singleton<mozilla::ipc::Faulty>::get()->FuzzInt64(&value);
     213             : #endif
     214          11 :     return WriteBytes(&value, sizeof(value));
     215             :   }
     216        1645 :   bool WriteUInt64(uint64_t value) {
     217             : #ifdef FUZZING
     218             :     Singleton<mozilla::ipc::Faulty>::get()->FuzzUInt64(&value);
     219             : #endif
     220        1645 :     return WriteBytes(&value, sizeof(value));
     221             :   }
     222           2 :   bool WriteDouble(double value) {
     223             : #ifdef FUZZING
     224             :     Singleton<mozilla::ipc::Faulty>::get()->FuzzDouble(&value);
     225             : #endif
     226           2 :     return WriteBytes(&value, sizeof(value));
     227             :   }
     228             :   bool WriteIntPtr(intptr_t value) {
     229             :     // Always written as a 64-bit value since the size for this type can
     230             :     // differ between architectures.
     231             :     return WriteInt64(int64_t(value));
     232             :   }
     233             :   bool WriteUnsignedChar(unsigned char value) {
     234             : #ifdef FUZZING
     235             :     Singleton<mozilla::ipc::Faulty>::get()->FuzzUChar(&value);
     236             : #endif
     237             :     return WriteBytes(&value, sizeof(value));
     238             :   }
     239             :   bool WriteString(const std::string& value);
     240             :   bool WriteWString(const std::wstring& value);
     241             :   bool WriteData(const char* data, uint32_t length);
     242             :   bool WriteBytes(const void* data, uint32_t data_len,
     243             :                   uint32_t alignment = sizeof(memberAlignmentType));
     244             : 
     245             :   bool WriteSentinel(uint32_t sentinel)
     246             : #ifdef MOZ_PICKLE_SENTINEL_CHECKING
     247             :     ;
     248             : #else
     249             :   {
     250             :     return true;
     251             :   }
     252             : #endif
     253             : 
     254             :   int32_t* GetInt32PtrForTest(uint32_t offset);
     255             : 
     256             :   void InputBytes(const char* data, uint32_t length);
     257             : 
     258             :   // Payload follows after allocation of Header (header size is customizable).
     259             :   struct Header {
     260             :     uint32_t payload_size;  // Specifies the size of the payload.
     261             :   };
     262             : 
     263             :   // Returns the header, cast to a user-specified type T.  The type T must be a
     264             :   // subclass of Header and its size must correspond to the header_size passed
     265             :   // to the Pickle constructor.
     266             :   template <class T>
     267        4637 :   T* headerT() {
     268        4637 :     DCHECK(sizeof(T) == header_size_);
     269        4637 :     return static_cast<T*>(header_);
     270             :   }
     271             :   template <class T>
     272       20777 :   const T* headerT() const {
     273       20777 :     DCHECK(sizeof(T) == header_size_);
     274       20777 :     return static_cast<const T*>(header_);
     275             :   }
     276             : 
     277             :   typedef uint32_t memberAlignmentType;
     278             : 
     279             :  protected:
     280             :   uint32_t payload_size() const { return header_->payload_size; }
     281             : 
     282             :   // Resizes the buffer for use when writing the specified amount of data. The
     283             :   // location that the data should be written at is returned, or NULL if there
     284             :   // was an error. Call EndWrite with the returned offset and the given length
     285             :   // to pad out for the next write.
     286             :   void BeginWrite(uint32_t length, uint32_t alignment);
     287             : 
     288             :   // Completes the write operation by padding the data with NULL bytes until it
     289             :   // is padded. Should be paired with BeginWrite, but it does not necessarily
     290             :   // have to be called after the data is written.
     291             :   void EndWrite(uint32_t length);
     292             : 
     293             :   // Round 'bytes' up to the next multiple of 'alignment'.  'alignment' must be
     294             :   // a power of 2.
     295             :   template<uint32_t alignment> struct ConstantAligner {
     296      692435 :     static uint32_t align(int bytes) {
     297             :       static_assert((alignment & (alignment - 1)) == 0,
     298             :                     "alignment must be a power of two");
     299      692435 :       return (bytes + (alignment - 1)) & ~static_cast<uint32_t>(alignment - 1);
     300             :     }
     301             :   };
     302             : 
     303      692010 :   static uint32_t AlignInt(int bytes) {
     304      692010 :     return ConstantAligner<sizeof(memberAlignmentType)>::align(bytes);
     305             :   }
     306             : 
     307         388 :   static uint32_t AlignCapacity(int bytes) {
     308         388 :     return ConstantAligner<kSegmentAlignment>::align(bytes);
     309             :   }
     310             : 
     311             :   // Returns true if the given iterator could point to data with the given
     312             :   // length. If there is no room for the given data before the end of the
     313             :   // payload, returns false.
     314             :   bool IteratorHasRoomFor(const PickleIterator& iter, uint32_t len) const;
     315             : 
     316             :   // Moves the iterator by the given number of bytes, making sure it is aligned.
     317             :   // Pointer (iterator) is NOT aligned, but the change in the pointer
     318             :   // is guaranteed to be a multiple of sizeof(memberAlignmentType).
     319             :   void UpdateIter(PickleIterator* iter, uint32_t bytes) const;
     320             : 
     321             :   // Figure out how big the message starting at range_start is. Returns 0 if
     322             :   // there's no enough data to determine (i.e., if [range_start, range_end) does
     323             :   // not contain enough of the message header to know the size).
     324             :   static uint32_t MessageSize(uint32_t header_size,
     325             :                               const char* range_start,
     326             :                               const char* range_end);
     327             : 
     328             :   // Segments capacities are aligned to 8 bytes to ensure that all reads/writes
     329             :   // at 8-byte aligned offsets will be on 8-byte aligned pointers.
     330             :   static const uint32_t kSegmentAlignment = 8;
     331             : 
     332             :  private:
     333             :   friend class PickleIterator;
     334             : 
     335             :   BufferList buffers_;
     336             :   Header* header_;
     337             :   uint32_t header_size_;
     338             : };
     339             : 
     340             : #endif  // BASE_PICKLE_H__

Generated by: LCOV version 1.13