1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef BASE_PICKLE_H_
6#define BASE_PICKLE_H_
7
8#include <stddef.h>
9#include <stdint.h>
10
11#include <string>
12
13#include "base/base_export.h"
14#include "base/compiler_specific.h"
15#include "base/gtest_prod_util.h"
16#include "base/logging.h"
17#include "base/memory/ref_counted.h"
18#include "base/strings/string16.h"
19#include "base/strings/string_piece.h"
20
21#if defined(OS_POSIX)
22#include "base/files/file.h"
23#endif
24
25namespace base {
26
27class Pickle;
28
29// PickleIterator reads data from a Pickle. The Pickle object must remain valid
30// while the PickleIterator object is in use.
31class BASE_EXPORT PickleIterator {
32 public:
33  PickleIterator() : payload_(NULL), read_index_(0), end_index_(0) {}
34  explicit PickleIterator(const Pickle& pickle);
35
36  // Methods for reading the payload of the Pickle. To read from the start of
37  // the Pickle, create a PickleIterator from a Pickle. If successful, these
38  // methods return true. Otherwise, false is returned to indicate that the
39  // result could not be extracted. It is not possible to read from the iterator
40  // after that.
41  bool ReadBool(bool* result) WARN_UNUSED_RESULT;
42  bool ReadInt(int* result) WARN_UNUSED_RESULT;
43  bool ReadLong(long* result) WARN_UNUSED_RESULT;
44  bool ReadUInt16(uint16_t* result) WARN_UNUSED_RESULT;
45  bool ReadUInt32(uint32_t* result) WARN_UNUSED_RESULT;
46  bool ReadInt64(int64_t* result) WARN_UNUSED_RESULT;
47  bool ReadUInt64(uint64_t* result) WARN_UNUSED_RESULT;
48  bool ReadFloat(float* result) WARN_UNUSED_RESULT;
49  bool ReadDouble(double* result) WARN_UNUSED_RESULT;
50  bool ReadString(std::string* result) WARN_UNUSED_RESULT;
51  // The StringPiece data will only be valid for the lifetime of the message.
52  bool ReadStringPiece(StringPiece* result) WARN_UNUSED_RESULT;
53  bool ReadString16(string16* result) WARN_UNUSED_RESULT;
54  // The StringPiece16 data will only be valid for the lifetime of the message.
55  bool ReadStringPiece16(StringPiece16* result) WARN_UNUSED_RESULT;
56
57  // A pointer to the data will be placed in |*data|, and the length will be
58  // placed in |*length|. The pointer placed into |*data| points into the
59  // message's buffer so it will be scoped to the lifetime of the message (or
60  // until the message data is mutated). Do not keep the pointer around!
61  bool ReadData(const char** data, int* length) WARN_UNUSED_RESULT;
62
63  // A pointer to the data will be placed in |*data|. The caller specifies the
64  // number of bytes to read, and ReadBytes will validate this length. The
65  // pointer placed into |*data| points into the message's buffer so it will be
66  // scoped to the lifetime of the message (or until the message data is
67  // mutated). Do not keep the pointer around!
68  bool ReadBytes(const char** data, int length) WARN_UNUSED_RESULT;
69
70  // A safer version of ReadInt() that checks for the result not being negative.
71  // Use it for reading the object sizes.
72  bool ReadLength(int* result) WARN_UNUSED_RESULT {
73    return ReadInt(result) && *result >= 0;
74  }
75
76  // Skips bytes in the read buffer and returns true if there are at least
77  // num_bytes available. Otherwise, does nothing and returns false.
78  bool SkipBytes(int num_bytes) WARN_UNUSED_RESULT {
79    return !!GetReadPointerAndAdvance(num_bytes);
80  }
81
82 private:
83  // Read Type from Pickle.
84  template <typename Type>
85  bool ReadBuiltinType(Type* result);
86
87  // Advance read_index_ but do not allow it to exceed end_index_.
88  // Keeps read_index_ aligned.
89  void Advance(size_t size);
90
91  // Get read pointer for Type and advance read pointer.
92  template<typename Type>
93  const char* GetReadPointerAndAdvance();
94
95  // Get read pointer for |num_bytes| and advance read pointer. This method
96  // checks num_bytes for negativity and wrapping.
97  const char* GetReadPointerAndAdvance(int num_bytes);
98
99  // Get read pointer for (num_elements * size_element) bytes and advance read
100  // pointer. This method checks for int overflow, negativity and wrapping.
101  const char* GetReadPointerAndAdvance(int num_elements,
102                                       size_t size_element);
103
104  const char* payload_;  // Start of our pickle's payload.
105  size_t read_index_;  // Offset of the next readable byte in payload.
106  size_t end_index_;  // Payload size.
107
108  FRIEND_TEST_ALL_PREFIXES(PickleTest, GetReadPointerAndAdvance);
109};
110
111// This class provides an interface analogous to base::Pickle's WriteFoo()
112// methods and can be used to accurately compute the size of a hypothetical
113// Pickle's payload without having to reference the Pickle implementation.
114class BASE_EXPORT PickleSizer {
115 public:
116  PickleSizer();
117  ~PickleSizer();
118
119  // Returns the computed size of the payload.
120  size_t payload_size() const { return payload_size_; }
121
122  void AddBool() { return AddInt(); }
123  void AddInt() { AddPOD<int>(); }
124  void AddLong() { AddPOD<uint64_t>(); }
125  void AddUInt16() { return AddPOD<uint16_t>(); }
126  void AddUInt32() { return AddPOD<uint32_t>(); }
127  void AddInt64() { return AddPOD<int64_t>(); }
128  void AddUInt64() { return AddPOD<uint64_t>(); }
129  void AddFloat() { return AddPOD<float>(); }
130  void AddDouble() { return AddPOD<double>(); }
131  void AddString(const StringPiece& value);
132  void AddString16(const StringPiece16& value);
133  void AddData(int length);
134  void AddBytes(int length);
135  void AddAttachment();
136
137 private:
138  // Just like AddBytes() but with a compile-time size for performance.
139  template<size_t length> void BASE_EXPORT AddBytesStatic();
140
141  template <typename T>
142  void AddPOD() { AddBytesStatic<sizeof(T)>(); }
143
144  size_t payload_size_ = 0;
145};
146
147// This class provides facilities for basic binary value packing and unpacking.
148//
149// The Pickle class supports appending primitive values (ints, strings, etc.)
150// to a pickle instance.  The Pickle instance grows its internal memory buffer
151// dynamically to hold the sequence of primitive values.   The internal memory
152// buffer is exposed as the "data" of the Pickle.  This "data" can be passed
153// to a Pickle object to initialize it for reading.
154//
155// When reading from a Pickle object, it is important for the consumer to know
156// what value types to read and in what order to read them as the Pickle does
157// not keep track of the type of data written to it.
158//
159// The Pickle's data has a header which contains the size of the Pickle's
160// payload.  It can optionally support additional space in the header.  That
161// space is controlled by the header_size parameter passed to the Pickle
162// constructor.
163//
164class BASE_EXPORT Pickle {
165 public:
166  // Auxiliary data attached to a Pickle. Pickle must be subclassed along with
167  // this interface in order to provide a concrete implementation of support
168  // for attachments. The base Pickle implementation does not accept
169  // attachments.
170  class BASE_EXPORT Attachment : public RefCountedThreadSafe<Attachment> {
171   public:
172    Attachment();
173
174   protected:
175    friend class RefCountedThreadSafe<Attachment>;
176    virtual ~Attachment();
177
178    DISALLOW_COPY_AND_ASSIGN(Attachment);
179  };
180
181  // Initialize a Pickle object using the default header size.
182  Pickle();
183
184  // Initialize a Pickle object with the specified header size in bytes, which
185  // must be greater-than-or-equal-to sizeof(Pickle::Header).  The header size
186  // will be rounded up to ensure that the header size is 32bit-aligned.
187  explicit Pickle(int header_size);
188
189  // Initializes a Pickle from a const block of data.  The data is not copied;
190  // instead the data is merely referenced by this Pickle.  Only const methods
191  // should be used on the Pickle when initialized this way.  The header
192  // padding size is deduced from the data length.
193  Pickle(const char* data, int data_len);
194
195  // Initializes a Pickle as a deep copy of another Pickle.
196  Pickle(const Pickle& other);
197
198  // Note: There are no virtual methods in this class.  This destructor is
199  // virtual as an element of defensive coding.  Other classes have derived from
200  // this class, and there is a *chance* that they will cast into this base
201  // class before destruction.  At least one such class does have a virtual
202  // destructor, suggesting at least some need to call more derived destructors.
203  virtual ~Pickle();
204
205  // Performs a deep copy.
206  Pickle& operator=(const Pickle& other);
207
208  // Returns the number of bytes written in the Pickle, including the header.
209  size_t size() const { return header_size_ + header_->payload_size; }
210
211  // Returns the data for this Pickle.
212  const void* data() const { return header_; }
213
214  // Returns the effective memory capacity of this Pickle, that is, the total
215  // number of bytes currently dynamically allocated or 0 in the case of a
216  // read-only Pickle. This should be used only for diagnostic / profiling
217  // purposes.
218  size_t GetTotalAllocatedSize() const;
219
220  // Methods for adding to the payload of the Pickle.  These values are
221  // appended to the end of the Pickle's payload.  When reading values from a
222  // Pickle, it is important to read them in the order in which they were added
223  // to the Pickle.
224
225  bool WriteBool(bool value) {
226    return WriteInt(value ? 1 : 0);
227  }
228  bool WriteInt(int value) {
229    return WritePOD(value);
230  }
231  bool WriteLong(long value) {
232    // Always write long as a 64-bit value to ensure compatibility between
233    // 32-bit and 64-bit processes.
234    return WritePOD(static_cast<int64_t>(value));
235  }
236  bool WriteUInt16(uint16_t value) { return WritePOD(value); }
237  bool WriteUInt32(uint32_t value) { return WritePOD(value); }
238  bool WriteInt64(int64_t value) { return WritePOD(value); }
239  bool WriteUInt64(uint64_t value) { return WritePOD(value); }
240  bool WriteFloat(float value) {
241    return WritePOD(value);
242  }
243  bool WriteDouble(double value) {
244    return WritePOD(value);
245  }
246  bool WriteString(const StringPiece& value);
247  bool WriteString16(const StringPiece16& value);
248  // "Data" is a blob with a length. When you read it out you will be given the
249  // length. See also WriteBytes.
250  bool WriteData(const char* data, int length);
251  // "Bytes" is a blob with no length. The caller must specify the length both
252  // when reading and writing. It is normally used to serialize PoD types of a
253  // known size. See also WriteData.
254  bool WriteBytes(const void* data, int length);
255
256  // WriteAttachment appends |attachment| to the pickle. It returns
257  // false iff the set is full or if the Pickle implementation does not support
258  // attachments.
259  virtual bool WriteAttachment(scoped_refptr<Attachment> attachment);
260
261  // ReadAttachment parses an attachment given the parsing state |iter| and
262  // writes it to |*attachment|. It returns true on success.
263  virtual bool ReadAttachment(base::PickleIterator* iter,
264                              scoped_refptr<Attachment>* attachment) const;
265
266  // Indicates whether the pickle has any attachments.
267  virtual bool HasAttachments() const;
268
269  // Reserves space for upcoming writes when multiple writes will be made and
270  // their sizes are computed in advance. It can be significantly faster to call
271  // Reserve() before calling WriteFoo() multiple times.
272  void Reserve(size_t additional_capacity);
273
274  // Payload follows after allocation of Header (header size is customizable).
275  struct Header {
276    uint32_t payload_size;  // Specifies the size of the payload.
277  };
278
279  // Returns the header, cast to a user-specified type T.  The type T must be a
280  // subclass of Header and its size must correspond to the header_size passed
281  // to the Pickle constructor.
282  template <class T>
283  T* headerT() {
284    DCHECK_EQ(header_size_, sizeof(T));
285    return static_cast<T*>(header_);
286  }
287  template <class T>
288  const T* headerT() const {
289    DCHECK_EQ(header_size_, sizeof(T));
290    return static_cast<const T*>(header_);
291  }
292
293  // The payload is the pickle data immediately following the header.
294  size_t payload_size() const {
295    return header_ ? header_->payload_size : 0;
296  }
297
298  const char* payload() const {
299    return reinterpret_cast<const char*>(header_) + header_size_;
300  }
301
302  // Returns the address of the byte immediately following the currently valid
303  // header + payload.
304  const char* end_of_payload() const {
305    // This object may be invalid.
306    return header_ ? payload() + payload_size() : NULL;
307  }
308
309 protected:
310  char* mutable_payload() {
311    return reinterpret_cast<char*>(header_) + header_size_;
312  }
313
314  size_t capacity_after_header() const {
315    return capacity_after_header_;
316  }
317
318  // Resize the capacity, note that the input value should not include the size
319  // of the header.
320  void Resize(size_t new_capacity);
321
322  // Claims |num_bytes| bytes of payload. This is similar to Reserve() in that
323  // it may grow the capacity, but it also advances the write offset of the
324  // pickle by |num_bytes|. Claimed memory, including padding, is zeroed.
325  //
326  // Returns the address of the first byte claimed.
327  void* ClaimBytes(size_t num_bytes);
328
329  // Find the end of the pickled data that starts at range_start.  Returns NULL
330  // if the entire Pickle is not found in the given data range.
331  static const char* FindNext(size_t header_size,
332                              const char* range_start,
333                              const char* range_end);
334
335  // Parse pickle header and return total size of the pickle. Data range
336  // doesn't need to contain entire pickle.
337  // Returns true if pickle header was found and parsed. Callers must check
338  // returned |pickle_size| for sanity (against maximum message size, etc).
339  // NOTE: when function successfully parses a header, but encounters an
340  // overflow during pickle size calculation, it sets |pickle_size| to the
341  // maximum size_t value and returns true.
342  static bool PeekNext(size_t header_size,
343                       const char* range_start,
344                       const char* range_end,
345                       size_t* pickle_size);
346
347  // The allocation granularity of the payload.
348  static const int kPayloadUnit;
349
350 private:
351  friend class PickleIterator;
352
353  Header* header_;
354  size_t header_size_;  // Supports extra data between header and payload.
355  // Allocation size of payload (or -1 if allocation is const). Note: this
356  // doesn't count the header.
357  size_t capacity_after_header_;
358  // The offset at which we will write the next field. Note: this doesn't count
359  // the header.
360  size_t write_offset_;
361
362  // Just like WriteBytes, but with a compile-time size, for performance.
363  template<size_t length> void BASE_EXPORT WriteBytesStatic(const void* data);
364
365  // Writes a POD by copying its bytes.
366  template <typename T> bool WritePOD(const T& data) {
367    WriteBytesStatic<sizeof(data)>(&data);
368    return true;
369  }
370
371  inline void* ClaimUninitializedBytesInternal(size_t num_bytes);
372  inline void WriteBytesCommon(const void* data, size_t length);
373
374  FRIEND_TEST_ALL_PREFIXES(PickleTest, DeepCopyResize);
375  FRIEND_TEST_ALL_PREFIXES(PickleTest, Resize);
376  FRIEND_TEST_ALL_PREFIXES(PickleTest, PeekNext);
377  FRIEND_TEST_ALL_PREFIXES(PickleTest, PeekNextOverflow);
378  FRIEND_TEST_ALL_PREFIXES(PickleTest, FindNext);
379  FRIEND_TEST_ALL_PREFIXES(PickleTest, FindNextWithIncompleteHeader);
380  FRIEND_TEST_ALL_PREFIXES(PickleTest, FindNextOverflow);
381};
382
383}  // namespace base
384
385#endif  // BASE_PICKLE_H_
386