• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <string>
9 
10 #include "base/base_export.h"
11 #include "base/basictypes.h"
12 #include "base/compiler_specific.h"
13 #include "base/gtest_prod_util.h"
14 #include "base/logging.h"
15 #include "base/strings/string16.h"
16 
17 class Pickle;
18 
19 // PickleIterator reads data from a Pickle. The Pickle object must remain valid
20 // while the PickleIterator object is in use.
21 class BASE_EXPORT PickleIterator {
22  public:
PickleIterator()23   PickleIterator() : read_ptr_(NULL), read_end_ptr_(NULL) {}
24   explicit PickleIterator(const Pickle& pickle);
25 
26   // Methods for reading the payload of the Pickle. To read from the start of
27   // the Pickle, create a PickleIterator from a Pickle. If successful, these
28   // methods return true. Otherwise, false is returned to indicate that the
29   // result could not be extracted.
30   bool ReadBool(bool* result) WARN_UNUSED_RESULT;
31   bool ReadInt(int* result) WARN_UNUSED_RESULT;
32   bool ReadLong(long* result) WARN_UNUSED_RESULT;
33   bool ReadUInt16(uint16* result) WARN_UNUSED_RESULT;
34   bool ReadUInt32(uint32* result) WARN_UNUSED_RESULT;
35   bool ReadInt64(int64* result) WARN_UNUSED_RESULT;
36   bool ReadUInt64(uint64* result) WARN_UNUSED_RESULT;
37   bool ReadFloat(float* result) WARN_UNUSED_RESULT;
38   bool ReadString(std::string* result) WARN_UNUSED_RESULT;
39   bool ReadWString(std::wstring* result) WARN_UNUSED_RESULT;
40   bool ReadString16(base::string16* result) WARN_UNUSED_RESULT;
41   bool ReadData(const char** data, int* length) WARN_UNUSED_RESULT;
42   bool ReadBytes(const char** data, int length) WARN_UNUSED_RESULT;
43 
44   // Safer version of ReadInt() checks for the result not being negative.
45   // Use it for reading the object sizes.
ReadLength(int * result)46   bool ReadLength(int* result) WARN_UNUSED_RESULT {
47     return ReadInt(result) && *result >= 0;
48   }
49 
50   // Skips bytes in the read buffer and returns true if there are at least
51   // num_bytes available. Otherwise, does nothing and returns false.
SkipBytes(int num_bytes)52   bool SkipBytes(int num_bytes) WARN_UNUSED_RESULT {
53     return !!GetReadPointerAndAdvance(num_bytes);
54   }
55 
56  private:
57   // Aligns 'i' by rounding it up to the next multiple of 'alignment'
AlignInt(size_t i,int alignment)58   static size_t AlignInt(size_t i, int alignment) {
59     return i + (alignment - (i % alignment)) % alignment;
60   }
61 
62   // Read Type from Pickle.
63   template <typename Type>
64   inline bool ReadBuiltinType(Type* result);
65 
66   // Get read pointer for Type and advance read pointer.
67   template<typename Type>
68   inline const char* GetReadPointerAndAdvance();
69 
70   // Get read pointer for |num_bytes| and advance read pointer. This method
71   // checks num_bytes for negativity and wrapping.
72   const char* GetReadPointerAndAdvance(int num_bytes);
73 
74   // Get read pointer for (num_elements * size_element) bytes and advance read
75   // pointer. This method checks for int overflow, negativity and wrapping.
76   inline const char* GetReadPointerAndAdvance(int num_elements,
77                                               size_t size_element);
78 
79   // Pointers to the Pickle data.
80   const char* read_ptr_;
81   const char* read_end_ptr_;
82 
83   FRIEND_TEST_ALL_PREFIXES(PickleTest, GetReadPointerAndAdvance);
84 };
85 
86 // This class provides facilities for basic binary value packing and unpacking.
87 //
88 // The Pickle class supports appending primitive values (ints, strings, etc.)
89 // to a pickle instance.  The Pickle instance grows its internal memory buffer
90 // dynamically to hold the sequence of primitive values.   The internal memory
91 // buffer is exposed as the "data" of the Pickle.  This "data" can be passed
92 // to a Pickle object to initialize it for reading.
93 //
94 // When reading from a Pickle object, it is important for the consumer to know
95 // what value types to read and in what order to read them as the Pickle does
96 // not keep track of the type of data written to it.
97 //
98 // The Pickle's data has a header which contains the size of the Pickle's
99 // payload.  It can optionally support additional space in the header.  That
100 // space is controlled by the header_size parameter passed to the Pickle
101 // constructor.
102 //
103 class BASE_EXPORT Pickle {
104  public:
105   // Initialize a Pickle object using the default header size.
106   Pickle();
107 
108   // Initialize a Pickle object with the specified header size in bytes, which
109   // must be greater-than-or-equal-to sizeof(Pickle::Header).  The header size
110   // will be rounded up to ensure that the header size is 32bit-aligned.
111   explicit Pickle(int header_size);
112 
113   // Initializes a Pickle from a const block of data.  The data is not copied;
114   // instead the data is merely referenced by this Pickle.  Only const methods
115   // should be used on the Pickle when initialized this way.  The header
116   // padding size is deduced from the data length.
117   Pickle(const char* data, int data_len);
118 
119   // Initializes a Pickle as a deep copy of another Pickle.
120   Pickle(const Pickle& other);
121 
122   // Note: There are no virtual methods in this class.  This destructor is
123   // virtual as an element of defensive coding.  Other classes have derived from
124   // this class, and there is a *chance* that they will cast into this base
125   // class before destruction.  At least one such class does have a virtual
126   // destructor, suggesting at least some need to call more derived destructors.
127   virtual ~Pickle();
128 
129   // Performs a deep copy.
130   Pickle& operator=(const Pickle& other);
131 
132   // Returns the size of the Pickle's data.
size()133   size_t size() const { return header_size_ + header_->payload_size; }
134 
135   // Returns the data for this Pickle.
data()136   const void* data() const { return header_; }
137 
138   // For compatibility, these older style read methods pass through to the
139   // PickleIterator methods.
140   // TODO(jbates) Remove these methods.
ReadBool(PickleIterator * iter,bool * result)141   bool ReadBool(PickleIterator* iter,
142                 bool* result) const WARN_UNUSED_RESULT {
143     return iter->ReadBool(result);
144   }
ReadInt(PickleIterator * iter,int * result)145   bool ReadInt(PickleIterator* iter,
146                int* result) const WARN_UNUSED_RESULT {
147     return iter->ReadInt(result);
148   }
ReadLong(PickleIterator * iter,long * result)149   bool ReadLong(PickleIterator* iter,
150                 long* result) const WARN_UNUSED_RESULT {
151     return iter->ReadLong(result);
152   }
ReadUInt16(PickleIterator * iter,uint16 * result)153   bool ReadUInt16(PickleIterator* iter,
154                   uint16* result) const WARN_UNUSED_RESULT {
155     return iter->ReadUInt16(result);
156   }
ReadUInt32(PickleIterator * iter,uint32 * result)157   bool ReadUInt32(PickleIterator* iter,
158                   uint32* result) const WARN_UNUSED_RESULT {
159     return iter->ReadUInt32(result);
160   }
ReadInt64(PickleIterator * iter,int64 * result)161   bool ReadInt64(PickleIterator* iter,
162                  int64* result) const WARN_UNUSED_RESULT {
163     return iter->ReadInt64(result);
164   }
ReadUInt64(PickleIterator * iter,uint64 * result)165   bool ReadUInt64(PickleIterator* iter,
166                   uint64* result) const WARN_UNUSED_RESULT {
167     return iter->ReadUInt64(result);
168   }
ReadFloat(PickleIterator * iter,float * result)169   bool ReadFloat(PickleIterator* iter,
170                  float* result) const WARN_UNUSED_RESULT {
171     return iter->ReadFloat(result);
172   }
ReadString(PickleIterator * iter,std::string * result)173   bool ReadString(PickleIterator* iter,
174                   std::string* result) const WARN_UNUSED_RESULT {
175     return iter->ReadString(result);
176   }
ReadWString(PickleIterator * iter,std::wstring * result)177   bool ReadWString(PickleIterator* iter,
178                    std::wstring* result) const WARN_UNUSED_RESULT {
179     return iter->ReadWString(result);
180   }
ReadString16(PickleIterator * iter,base::string16 * result)181   bool ReadString16(PickleIterator* iter,
182                     base::string16* result) const WARN_UNUSED_RESULT {
183     return iter->ReadString16(result);
184   }
185   // A pointer to the data will be placed in *data, and the length will be
186   // placed in *length. This buffer will be into the message's buffer so will
187   // be scoped to the lifetime of the message (or until the message data is
188   // mutated).
ReadData(PickleIterator * iter,const char ** data,int * length)189   bool ReadData(PickleIterator* iter,
190                 const char** data,
191                 int* length) const WARN_UNUSED_RESULT {
192     return iter->ReadData(data, length);
193   }
194   // A pointer to the data will be placed in *data. The caller specifies the
195   // number of bytes to read, and ReadBytes will validate this length. The
196   // returned buffer will be into the message's buffer so will be scoped to the
197   // lifetime of the message (or until the message data is mutated).
ReadBytes(PickleIterator * iter,const char ** data,int length)198   bool ReadBytes(PickleIterator* iter,
199                  const char** data,
200                  int length) const WARN_UNUSED_RESULT {
201     return iter->ReadBytes(data, length);
202   }
203 
204   // Safer version of ReadInt() checks for the result not being negative.
205   // Use it for reading the object sizes.
ReadLength(PickleIterator * iter,int * result)206   bool ReadLength(PickleIterator* iter,
207                   int* result) const  WARN_UNUSED_RESULT {
208     return iter->ReadLength(result);
209   }
210 
211   // Methods for adding to the payload of the Pickle.  These values are
212   // appended to the end of the Pickle's payload.  When reading values from a
213   // Pickle, it is important to read them in the order in which they were added
214   // to the Pickle.
WriteBool(bool value)215   bool WriteBool(bool value) {
216     return WriteInt(value ? 1 : 0);
217   }
WriteInt(int value)218   bool WriteInt(int value) {
219     return WritePOD(value);
220   }
221   // WARNING: DO NOT USE THIS METHOD IF PICKLES ARE PERSISTED IN ANY WAY.
222   // It will write whatever a "long" is on this architecture. On 32-bit
223   // platforms, it is 32 bits. On 64-bit platforms, it is 64 bits. If persisted
224   // pickles are still around after upgrading to 64-bit, or if they are copied
225   // between dissimilar systems, YOUR PICKLES WILL HAVE GONE BAD.
WriteLongUsingDangerousNonPortableLessPersistableForm(long value)226   bool WriteLongUsingDangerousNonPortableLessPersistableForm(long value) {
227     return WritePOD(value);
228   }
WriteUInt16(uint16 value)229   bool WriteUInt16(uint16 value) {
230     return WritePOD(value);
231   }
WriteUInt32(uint32 value)232   bool WriteUInt32(uint32 value) {
233     return WritePOD(value);
234   }
WriteInt64(int64 value)235   bool WriteInt64(int64 value) {
236     return WritePOD(value);
237   }
WriteUInt64(uint64 value)238   bool WriteUInt64(uint64 value) {
239     return WritePOD(value);
240   }
WriteFloat(float value)241   bool WriteFloat(float value) {
242     return WritePOD(value);
243   }
244   bool WriteString(const std::string& value);
245   bool WriteWString(const std::wstring& value);
246   bool WriteString16(const base::string16& value);
247   // "Data" is a blob with a length. When you read it out you will be given the
248   // length. See also WriteBytes.
249   bool WriteData(const char* data, int length);
250   // "Bytes" is a blob with no length. The caller must specify the length both
251   // when reading and writing. It is normally used to serialize PoD types of a
252   // known size. See also WriteData.
253   bool WriteBytes(const void* data, int length);
254 
255   // Reserves space for upcoming writes when multiple writes will be made and
256   // their sizes are computed in advance. It can be significantly faster to call
257   // Reserve() before calling WriteFoo() multiple times.
258   void Reserve(size_t additional_capacity);
259 
260   // Payload follows after allocation of Header (header size is customizable).
261   struct Header {
262     uint32 payload_size;  // Specifies the size of the payload.
263   };
264 
265   // Returns the header, cast to a user-specified type T.  The type T must be a
266   // subclass of Header and its size must correspond to the header_size passed
267   // to the Pickle constructor.
268   template <class T>
headerT()269   T* headerT() {
270     DCHECK_EQ(header_size_, sizeof(T));
271     return static_cast<T*>(header_);
272   }
273   template <class T>
headerT()274   const T* headerT() const {
275     DCHECK_EQ(header_size_, sizeof(T));
276     return static_cast<const T*>(header_);
277   }
278 
279   // The payload is the pickle data immediately following the header.
payload_size()280   size_t payload_size() const { return header_->payload_size; }
281 
payload()282   const char* payload() const {
283     return reinterpret_cast<const char*>(header_) + header_size_;
284   }
285 
286   // Returns the address of the byte immediately following the currently valid
287   // header + payload.
end_of_payload()288   const char* end_of_payload() const {
289     // This object may be invalid.
290     return header_ ? payload() + payload_size() : NULL;
291   }
292 
293  protected:
mutable_payload()294   char* mutable_payload() {
295     return reinterpret_cast<char*>(header_) + header_size_;
296   }
297 
capacity_after_header()298   size_t capacity_after_header() const {
299     return capacity_after_header_;
300   }
301 
302   // Resize the capacity, note that the input value should not include the size
303   // of the header.
304   void Resize(size_t new_capacity);
305 
306   // Aligns 'i' by rounding it up to the next multiple of 'alignment'
AlignInt(size_t i,int alignment)307   static size_t AlignInt(size_t i, int alignment) {
308     return i + (alignment - (i % alignment)) % alignment;
309   }
310 
311   // Find the end of the pickled data that starts at range_start.  Returns NULL
312   // if the entire Pickle is not found in the given data range.
313   static const char* FindNext(size_t header_size,
314                               const char* range_start,
315                               const char* range_end);
316 
317   // The allocation granularity of the payload.
318   static const int kPayloadUnit;
319 
320  private:
321   friend class PickleIterator;
322 
323   Header* header_;
324   size_t header_size_;  // Supports extra data between header and payload.
325   // Allocation size of payload (or -1 if allocation is const). Note: this
326   // doesn't count the header.
327   size_t capacity_after_header_;
328   // The offset at which we will write the next field. Note: this doesn't count
329   // the header.
330   size_t write_offset_;
331 
332   // Just like WriteBytes, but with a compile-time size, for performance.
333   template<size_t length> void WriteBytesStatic(const void* data);
334 
335   // Writes a POD by copying its bytes.
WritePOD(const T & data)336   template <typename T> bool WritePOD(const T& data) {
337     WriteBytesStatic<sizeof(data)>(&data);
338     return true;
339   }
340   inline void WriteBytesCommon(const void* data, size_t length);
341 
342   FRIEND_TEST_ALL_PREFIXES(PickleTest, Resize);
343   FRIEND_TEST_ALL_PREFIXES(PickleTest, FindNext);
344   FRIEND_TEST_ALL_PREFIXES(PickleTest, FindNextWithIncompleteHeader);
345   FRIEND_TEST_ALL_PREFIXES(PickleTest, FindNextOverflow);
346 };
347 
348 #endif  // BASE_PICKLE_H__
349