xref: /aosp_15_r20/external/libchrome/base/pickle.cc (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
1*635a8641SAndroid Build Coastguard Worker // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file.
4*635a8641SAndroid Build Coastguard Worker 
5*635a8641SAndroid Build Coastguard Worker #include "base/pickle.h"
6*635a8641SAndroid Build Coastguard Worker 
7*635a8641SAndroid Build Coastguard Worker #include <stdlib.h>
8*635a8641SAndroid Build Coastguard Worker 
9*635a8641SAndroid Build Coastguard Worker #include <algorithm>  // for max()
10*635a8641SAndroid Build Coastguard Worker #include <limits>
11*635a8641SAndroid Build Coastguard Worker 
12*635a8641SAndroid Build Coastguard Worker #include "base/bits.h"
13*635a8641SAndroid Build Coastguard Worker #include "base/macros.h"
14*635a8641SAndroid Build Coastguard Worker #include "base/numerics/safe_conversions.h"
15*635a8641SAndroid Build Coastguard Worker #include "base/numerics/safe_math.h"
16*635a8641SAndroid Build Coastguard Worker #include "build/build_config.h"
17*635a8641SAndroid Build Coastguard Worker 
18*635a8641SAndroid Build Coastguard Worker namespace base {
19*635a8641SAndroid Build Coastguard Worker 
20*635a8641SAndroid Build Coastguard Worker // static
21*635a8641SAndroid Build Coastguard Worker const int Pickle::kPayloadUnit = 64;
22*635a8641SAndroid Build Coastguard Worker 
23*635a8641SAndroid Build Coastguard Worker static const size_t kCapacityReadOnly = static_cast<size_t>(-1);
24*635a8641SAndroid Build Coastguard Worker 
PickleIterator(const Pickle & pickle)25*635a8641SAndroid Build Coastguard Worker PickleIterator::PickleIterator(const Pickle& pickle)
26*635a8641SAndroid Build Coastguard Worker     : payload_(pickle.payload()),
27*635a8641SAndroid Build Coastguard Worker       read_index_(0),
28*635a8641SAndroid Build Coastguard Worker       end_index_(pickle.payload_size()) {
29*635a8641SAndroid Build Coastguard Worker }
30*635a8641SAndroid Build Coastguard Worker 
31*635a8641SAndroid Build Coastguard Worker template <typename Type>
ReadBuiltinType(Type * result)32*635a8641SAndroid Build Coastguard Worker inline bool PickleIterator::ReadBuiltinType(Type* result) {
33*635a8641SAndroid Build Coastguard Worker   const char* read_from = GetReadPointerAndAdvance<Type>();
34*635a8641SAndroid Build Coastguard Worker   if (!read_from)
35*635a8641SAndroid Build Coastguard Worker     return false;
36*635a8641SAndroid Build Coastguard Worker   if (sizeof(Type) > sizeof(uint32_t))
37*635a8641SAndroid Build Coastguard Worker     memcpy(result, read_from, sizeof(*result));
38*635a8641SAndroid Build Coastguard Worker   else
39*635a8641SAndroid Build Coastguard Worker     *result = *reinterpret_cast<const Type*>(read_from);
40*635a8641SAndroid Build Coastguard Worker   return true;
41*635a8641SAndroid Build Coastguard Worker }
42*635a8641SAndroid Build Coastguard Worker 
Advance(size_t size)43*635a8641SAndroid Build Coastguard Worker inline void PickleIterator::Advance(size_t size) {
44*635a8641SAndroid Build Coastguard Worker   size_t aligned_size = bits::Align(size, sizeof(uint32_t));
45*635a8641SAndroid Build Coastguard Worker   if (end_index_ - read_index_ < aligned_size) {
46*635a8641SAndroid Build Coastguard Worker     read_index_ = end_index_;
47*635a8641SAndroid Build Coastguard Worker   } else {
48*635a8641SAndroid Build Coastguard Worker     read_index_ += aligned_size;
49*635a8641SAndroid Build Coastguard Worker   }
50*635a8641SAndroid Build Coastguard Worker }
51*635a8641SAndroid Build Coastguard Worker 
52*635a8641SAndroid Build Coastguard Worker template<typename Type>
GetReadPointerAndAdvance()53*635a8641SAndroid Build Coastguard Worker inline const char* PickleIterator::GetReadPointerAndAdvance() {
54*635a8641SAndroid Build Coastguard Worker   if (sizeof(Type) > end_index_ - read_index_) {
55*635a8641SAndroid Build Coastguard Worker     read_index_ = end_index_;
56*635a8641SAndroid Build Coastguard Worker     return nullptr;
57*635a8641SAndroid Build Coastguard Worker   }
58*635a8641SAndroid Build Coastguard Worker   const char* current_read_ptr = payload_ + read_index_;
59*635a8641SAndroid Build Coastguard Worker   Advance(sizeof(Type));
60*635a8641SAndroid Build Coastguard Worker   return current_read_ptr;
61*635a8641SAndroid Build Coastguard Worker }
62*635a8641SAndroid Build Coastguard Worker 
GetReadPointerAndAdvance(int num_bytes)63*635a8641SAndroid Build Coastguard Worker const char* PickleIterator::GetReadPointerAndAdvance(int num_bytes) {
64*635a8641SAndroid Build Coastguard Worker   if (num_bytes < 0 ||
65*635a8641SAndroid Build Coastguard Worker       end_index_ - read_index_ < static_cast<size_t>(num_bytes)) {
66*635a8641SAndroid Build Coastguard Worker     read_index_ = end_index_;
67*635a8641SAndroid Build Coastguard Worker     return nullptr;
68*635a8641SAndroid Build Coastguard Worker   }
69*635a8641SAndroid Build Coastguard Worker   const char* current_read_ptr = payload_ + read_index_;
70*635a8641SAndroid Build Coastguard Worker   Advance(num_bytes);
71*635a8641SAndroid Build Coastguard Worker   return current_read_ptr;
72*635a8641SAndroid Build Coastguard Worker }
73*635a8641SAndroid Build Coastguard Worker 
GetReadPointerAndAdvance(int num_elements,size_t size_element)74*635a8641SAndroid Build Coastguard Worker inline const char* PickleIterator::GetReadPointerAndAdvance(
75*635a8641SAndroid Build Coastguard Worker     int num_elements,
76*635a8641SAndroid Build Coastguard Worker     size_t size_element) {
77*635a8641SAndroid Build Coastguard Worker   // Check for int32_t overflow.
78*635a8641SAndroid Build Coastguard Worker   int num_bytes;
79*635a8641SAndroid Build Coastguard Worker   if (!CheckMul(num_elements, size_element).AssignIfValid(&num_bytes))
80*635a8641SAndroid Build Coastguard Worker     return nullptr;
81*635a8641SAndroid Build Coastguard Worker   return GetReadPointerAndAdvance(num_bytes);
82*635a8641SAndroid Build Coastguard Worker }
83*635a8641SAndroid Build Coastguard Worker 
ReadBool(bool * result)84*635a8641SAndroid Build Coastguard Worker bool PickleIterator::ReadBool(bool* result) {
85*635a8641SAndroid Build Coastguard Worker   return ReadBuiltinType(result);
86*635a8641SAndroid Build Coastguard Worker }
87*635a8641SAndroid Build Coastguard Worker 
ReadInt(int * result)88*635a8641SAndroid Build Coastguard Worker bool PickleIterator::ReadInt(int* result) {
89*635a8641SAndroid Build Coastguard Worker   return ReadBuiltinType(result);
90*635a8641SAndroid Build Coastguard Worker }
91*635a8641SAndroid Build Coastguard Worker 
ReadLong(long * result)92*635a8641SAndroid Build Coastguard Worker bool PickleIterator::ReadLong(long* result) {
93*635a8641SAndroid Build Coastguard Worker   // Always read long as a 64-bit value to ensure compatibility between 32-bit
94*635a8641SAndroid Build Coastguard Worker   // and 64-bit processes.
95*635a8641SAndroid Build Coastguard Worker   int64_t result_int64 = 0;
96*635a8641SAndroid Build Coastguard Worker   if (!ReadBuiltinType(&result_int64))
97*635a8641SAndroid Build Coastguard Worker     return false;
98*635a8641SAndroid Build Coastguard Worker   // CHECK if the cast truncates the value so that we know to change this IPC
99*635a8641SAndroid Build Coastguard Worker   // parameter to use int64_t.
100*635a8641SAndroid Build Coastguard Worker   *result = base::checked_cast<long>(result_int64);
101*635a8641SAndroid Build Coastguard Worker   return true;
102*635a8641SAndroid Build Coastguard Worker }
103*635a8641SAndroid Build Coastguard Worker 
ReadUInt16(uint16_t * result)104*635a8641SAndroid Build Coastguard Worker bool PickleIterator::ReadUInt16(uint16_t* result) {
105*635a8641SAndroid Build Coastguard Worker   return ReadBuiltinType(result);
106*635a8641SAndroid Build Coastguard Worker }
107*635a8641SAndroid Build Coastguard Worker 
ReadUInt32(uint32_t * result)108*635a8641SAndroid Build Coastguard Worker bool PickleIterator::ReadUInt32(uint32_t* result) {
109*635a8641SAndroid Build Coastguard Worker   return ReadBuiltinType(result);
110*635a8641SAndroid Build Coastguard Worker }
111*635a8641SAndroid Build Coastguard Worker 
ReadInt64(int64_t * result)112*635a8641SAndroid Build Coastguard Worker bool PickleIterator::ReadInt64(int64_t* result) {
113*635a8641SAndroid Build Coastguard Worker   return ReadBuiltinType(result);
114*635a8641SAndroid Build Coastguard Worker }
115*635a8641SAndroid Build Coastguard Worker 
ReadUInt64(uint64_t * result)116*635a8641SAndroid Build Coastguard Worker bool PickleIterator::ReadUInt64(uint64_t* result) {
117*635a8641SAndroid Build Coastguard Worker   return ReadBuiltinType(result);
118*635a8641SAndroid Build Coastguard Worker }
119*635a8641SAndroid Build Coastguard Worker 
ReadFloat(float * result)120*635a8641SAndroid Build Coastguard Worker bool PickleIterator::ReadFloat(float* result) {
121*635a8641SAndroid Build Coastguard Worker   // crbug.com/315213
122*635a8641SAndroid Build Coastguard Worker   // The source data may not be properly aligned, and unaligned float reads
123*635a8641SAndroid Build Coastguard Worker   // cause SIGBUS on some ARM platforms, so force using memcpy to copy the data
124*635a8641SAndroid Build Coastguard Worker   // into the result.
125*635a8641SAndroid Build Coastguard Worker   const char* read_from = GetReadPointerAndAdvance<float>();
126*635a8641SAndroid Build Coastguard Worker   if (!read_from)
127*635a8641SAndroid Build Coastguard Worker     return false;
128*635a8641SAndroid Build Coastguard Worker   memcpy(result, read_from, sizeof(*result));
129*635a8641SAndroid Build Coastguard Worker   return true;
130*635a8641SAndroid Build Coastguard Worker }
131*635a8641SAndroid Build Coastguard Worker 
ReadDouble(double * result)132*635a8641SAndroid Build Coastguard Worker bool PickleIterator::ReadDouble(double* result) {
133*635a8641SAndroid Build Coastguard Worker   // crbug.com/315213
134*635a8641SAndroid Build Coastguard Worker   // The source data may not be properly aligned, and unaligned double reads
135*635a8641SAndroid Build Coastguard Worker   // cause SIGBUS on some ARM platforms, so force using memcpy to copy the data
136*635a8641SAndroid Build Coastguard Worker   // into the result.
137*635a8641SAndroid Build Coastguard Worker   const char* read_from = GetReadPointerAndAdvance<double>();
138*635a8641SAndroid Build Coastguard Worker   if (!read_from)
139*635a8641SAndroid Build Coastguard Worker     return false;
140*635a8641SAndroid Build Coastguard Worker   memcpy(result, read_from, sizeof(*result));
141*635a8641SAndroid Build Coastguard Worker   return true;
142*635a8641SAndroid Build Coastguard Worker }
143*635a8641SAndroid Build Coastguard Worker 
ReadString(std::string * result)144*635a8641SAndroid Build Coastguard Worker bool PickleIterator::ReadString(std::string* result) {
145*635a8641SAndroid Build Coastguard Worker   int len;
146*635a8641SAndroid Build Coastguard Worker   if (!ReadInt(&len))
147*635a8641SAndroid Build Coastguard Worker     return false;
148*635a8641SAndroid Build Coastguard Worker   const char* read_from = GetReadPointerAndAdvance(len);
149*635a8641SAndroid Build Coastguard Worker   if (!read_from)
150*635a8641SAndroid Build Coastguard Worker     return false;
151*635a8641SAndroid Build Coastguard Worker 
152*635a8641SAndroid Build Coastguard Worker   result->assign(read_from, len);
153*635a8641SAndroid Build Coastguard Worker   return true;
154*635a8641SAndroid Build Coastguard Worker }
155*635a8641SAndroid Build Coastguard Worker 
ReadStringPiece(StringPiece * result)156*635a8641SAndroid Build Coastguard Worker bool PickleIterator::ReadStringPiece(StringPiece* result) {
157*635a8641SAndroid Build Coastguard Worker   int len;
158*635a8641SAndroid Build Coastguard Worker   if (!ReadInt(&len))
159*635a8641SAndroid Build Coastguard Worker     return false;
160*635a8641SAndroid Build Coastguard Worker   const char* read_from = GetReadPointerAndAdvance(len);
161*635a8641SAndroid Build Coastguard Worker   if (!read_from)
162*635a8641SAndroid Build Coastguard Worker     return false;
163*635a8641SAndroid Build Coastguard Worker 
164*635a8641SAndroid Build Coastguard Worker   *result = StringPiece(read_from, len);
165*635a8641SAndroid Build Coastguard Worker   return true;
166*635a8641SAndroid Build Coastguard Worker }
167*635a8641SAndroid Build Coastguard Worker 
ReadString16(string16 * result)168*635a8641SAndroid Build Coastguard Worker bool PickleIterator::ReadString16(string16* result) {
169*635a8641SAndroid Build Coastguard Worker   int len;
170*635a8641SAndroid Build Coastguard Worker   if (!ReadInt(&len))
171*635a8641SAndroid Build Coastguard Worker     return false;
172*635a8641SAndroid Build Coastguard Worker   const char* read_from = GetReadPointerAndAdvance(len, sizeof(char16));
173*635a8641SAndroid Build Coastguard Worker   if (!read_from)
174*635a8641SAndroid Build Coastguard Worker     return false;
175*635a8641SAndroid Build Coastguard Worker 
176*635a8641SAndroid Build Coastguard Worker   result->assign(reinterpret_cast<const char16*>(read_from), len);
177*635a8641SAndroid Build Coastguard Worker   return true;
178*635a8641SAndroid Build Coastguard Worker }
179*635a8641SAndroid Build Coastguard Worker 
ReadStringPiece16(StringPiece16 * result)180*635a8641SAndroid Build Coastguard Worker bool PickleIterator::ReadStringPiece16(StringPiece16* result) {
181*635a8641SAndroid Build Coastguard Worker   int len;
182*635a8641SAndroid Build Coastguard Worker   if (!ReadInt(&len))
183*635a8641SAndroid Build Coastguard Worker     return false;
184*635a8641SAndroid Build Coastguard Worker   const char* read_from = GetReadPointerAndAdvance(len, sizeof(char16));
185*635a8641SAndroid Build Coastguard Worker   if (!read_from)
186*635a8641SAndroid Build Coastguard Worker     return false;
187*635a8641SAndroid Build Coastguard Worker 
188*635a8641SAndroid Build Coastguard Worker   *result = StringPiece16(reinterpret_cast<const char16*>(read_from), len);
189*635a8641SAndroid Build Coastguard Worker   return true;
190*635a8641SAndroid Build Coastguard Worker }
191*635a8641SAndroid Build Coastguard Worker 
ReadData(const char ** data,int * length)192*635a8641SAndroid Build Coastguard Worker bool PickleIterator::ReadData(const char** data, int* length) {
193*635a8641SAndroid Build Coastguard Worker   *length = 0;
194*635a8641SAndroid Build Coastguard Worker   *data = nullptr;
195*635a8641SAndroid Build Coastguard Worker 
196*635a8641SAndroid Build Coastguard Worker   if (!ReadInt(length))
197*635a8641SAndroid Build Coastguard Worker     return false;
198*635a8641SAndroid Build Coastguard Worker 
199*635a8641SAndroid Build Coastguard Worker   return ReadBytes(data, *length);
200*635a8641SAndroid Build Coastguard Worker }
201*635a8641SAndroid Build Coastguard Worker 
ReadBytes(const char ** data,int length)202*635a8641SAndroid Build Coastguard Worker bool PickleIterator::ReadBytes(const char** data, int length) {
203*635a8641SAndroid Build Coastguard Worker   const char* read_from = GetReadPointerAndAdvance(length);
204*635a8641SAndroid Build Coastguard Worker   if (!read_from)
205*635a8641SAndroid Build Coastguard Worker     return false;
206*635a8641SAndroid Build Coastguard Worker   *data = read_from;
207*635a8641SAndroid Build Coastguard Worker   return true;
208*635a8641SAndroid Build Coastguard Worker }
209*635a8641SAndroid Build Coastguard Worker 
210*635a8641SAndroid Build Coastguard Worker Pickle::Attachment::Attachment() = default;
211*635a8641SAndroid Build Coastguard Worker 
212*635a8641SAndroid Build Coastguard Worker Pickle::Attachment::~Attachment() = default;
213*635a8641SAndroid Build Coastguard Worker 
214*635a8641SAndroid Build Coastguard Worker // Payload is uint32_t aligned.
215*635a8641SAndroid Build Coastguard Worker 
Pickle()216*635a8641SAndroid Build Coastguard Worker Pickle::Pickle()
217*635a8641SAndroid Build Coastguard Worker     : header_(nullptr),
218*635a8641SAndroid Build Coastguard Worker       header_size_(sizeof(Header)),
219*635a8641SAndroid Build Coastguard Worker       capacity_after_header_(0),
220*635a8641SAndroid Build Coastguard Worker       write_offset_(0) {
221*635a8641SAndroid Build Coastguard Worker   static_assert((Pickle::kPayloadUnit & (Pickle::kPayloadUnit - 1)) == 0,
222*635a8641SAndroid Build Coastguard Worker                 "Pickle::kPayloadUnit must be a power of two");
223*635a8641SAndroid Build Coastguard Worker   Resize(kPayloadUnit);
224*635a8641SAndroid Build Coastguard Worker   header_->payload_size = 0;
225*635a8641SAndroid Build Coastguard Worker }
226*635a8641SAndroid Build Coastguard Worker 
Pickle(int header_size)227*635a8641SAndroid Build Coastguard Worker Pickle::Pickle(int header_size)
228*635a8641SAndroid Build Coastguard Worker     : header_(nullptr),
229*635a8641SAndroid Build Coastguard Worker       header_size_(bits::Align(header_size, sizeof(uint32_t))),
230*635a8641SAndroid Build Coastguard Worker       capacity_after_header_(0),
231*635a8641SAndroid Build Coastguard Worker       write_offset_(0) {
232*635a8641SAndroid Build Coastguard Worker   DCHECK_GE(static_cast<size_t>(header_size), sizeof(Header));
233*635a8641SAndroid Build Coastguard Worker   DCHECK_LE(header_size, kPayloadUnit);
234*635a8641SAndroid Build Coastguard Worker   Resize(kPayloadUnit);
235*635a8641SAndroid Build Coastguard Worker   header_->payload_size = 0;
236*635a8641SAndroid Build Coastguard Worker }
237*635a8641SAndroid Build Coastguard Worker 
Pickle(const char * data,int data_len)238*635a8641SAndroid Build Coastguard Worker Pickle::Pickle(const char* data, int data_len)
239*635a8641SAndroid Build Coastguard Worker     : header_(reinterpret_cast<Header*>(const_cast<char*>(data))),
240*635a8641SAndroid Build Coastguard Worker       header_size_(0),
241*635a8641SAndroid Build Coastguard Worker       capacity_after_header_(kCapacityReadOnly),
242*635a8641SAndroid Build Coastguard Worker       write_offset_(0) {
243*635a8641SAndroid Build Coastguard Worker   if (data_len >= static_cast<int>(sizeof(Header)))
244*635a8641SAndroid Build Coastguard Worker     header_size_ = data_len - header_->payload_size;
245*635a8641SAndroid Build Coastguard Worker 
246*635a8641SAndroid Build Coastguard Worker   if (header_size_ > static_cast<unsigned int>(data_len))
247*635a8641SAndroid Build Coastguard Worker     header_size_ = 0;
248*635a8641SAndroid Build Coastguard Worker 
249*635a8641SAndroid Build Coastguard Worker   if (header_size_ != bits::Align(header_size_, sizeof(uint32_t)))
250*635a8641SAndroid Build Coastguard Worker     header_size_ = 0;
251*635a8641SAndroid Build Coastguard Worker 
252*635a8641SAndroid Build Coastguard Worker   // If there is anything wrong with the data, we're not going to use it.
253*635a8641SAndroid Build Coastguard Worker   if (!header_size_)
254*635a8641SAndroid Build Coastguard Worker     header_ = nullptr;
255*635a8641SAndroid Build Coastguard Worker }
256*635a8641SAndroid Build Coastguard Worker 
Pickle(const Pickle & other)257*635a8641SAndroid Build Coastguard Worker Pickle::Pickle(const Pickle& other)
258*635a8641SAndroid Build Coastguard Worker     : header_(nullptr),
259*635a8641SAndroid Build Coastguard Worker       header_size_(other.header_size_),
260*635a8641SAndroid Build Coastguard Worker       capacity_after_header_(0),
261*635a8641SAndroid Build Coastguard Worker       write_offset_(other.write_offset_) {
262*635a8641SAndroid Build Coastguard Worker   Resize(other.header_->payload_size);
263*635a8641SAndroid Build Coastguard Worker   memcpy(header_, other.header_, header_size_ + other.header_->payload_size);
264*635a8641SAndroid Build Coastguard Worker }
265*635a8641SAndroid Build Coastguard Worker 
~Pickle()266*635a8641SAndroid Build Coastguard Worker Pickle::~Pickle() {
267*635a8641SAndroid Build Coastguard Worker   if (capacity_after_header_ != kCapacityReadOnly)
268*635a8641SAndroid Build Coastguard Worker     free(header_);
269*635a8641SAndroid Build Coastguard Worker }
270*635a8641SAndroid Build Coastguard Worker 
operator =(const Pickle & other)271*635a8641SAndroid Build Coastguard Worker Pickle& Pickle::operator=(const Pickle& other) {
272*635a8641SAndroid Build Coastguard Worker   if (this == &other) {
273*635a8641SAndroid Build Coastguard Worker     return *this;
274*635a8641SAndroid Build Coastguard Worker   }
275*635a8641SAndroid Build Coastguard Worker   if (capacity_after_header_ == kCapacityReadOnly) {
276*635a8641SAndroid Build Coastguard Worker     header_ = nullptr;
277*635a8641SAndroid Build Coastguard Worker     capacity_after_header_ = 0;
278*635a8641SAndroid Build Coastguard Worker   }
279*635a8641SAndroid Build Coastguard Worker   if (header_size_ != other.header_size_) {
280*635a8641SAndroid Build Coastguard Worker     free(header_);
281*635a8641SAndroid Build Coastguard Worker     header_ = nullptr;
282*635a8641SAndroid Build Coastguard Worker     header_size_ = other.header_size_;
283*635a8641SAndroid Build Coastguard Worker   }
284*635a8641SAndroid Build Coastguard Worker   Resize(other.header_->payload_size);
285*635a8641SAndroid Build Coastguard Worker   memcpy(header_, other.header_,
286*635a8641SAndroid Build Coastguard Worker          other.header_size_ + other.header_->payload_size);
287*635a8641SAndroid Build Coastguard Worker   write_offset_ = other.write_offset_;
288*635a8641SAndroid Build Coastguard Worker   return *this;
289*635a8641SAndroid Build Coastguard Worker }
290*635a8641SAndroid Build Coastguard Worker 
WriteString(const StringPiece & value)291*635a8641SAndroid Build Coastguard Worker void Pickle::WriteString(const StringPiece& value) {
292*635a8641SAndroid Build Coastguard Worker   WriteInt(static_cast<int>(value.size()));
293*635a8641SAndroid Build Coastguard Worker   WriteBytes(value.data(), static_cast<int>(value.size()));
294*635a8641SAndroid Build Coastguard Worker }
295*635a8641SAndroid Build Coastguard Worker 
WriteString16(const StringPiece16 & value)296*635a8641SAndroid Build Coastguard Worker void Pickle::WriteString16(const StringPiece16& value) {
297*635a8641SAndroid Build Coastguard Worker   WriteInt(static_cast<int>(value.size()));
298*635a8641SAndroid Build Coastguard Worker   WriteBytes(value.data(), static_cast<int>(value.size()) * sizeof(char16));
299*635a8641SAndroid Build Coastguard Worker }
300*635a8641SAndroid Build Coastguard Worker 
WriteData(const char * data,int length)301*635a8641SAndroid Build Coastguard Worker void Pickle::WriteData(const char* data, int length) {
302*635a8641SAndroid Build Coastguard Worker   DCHECK_GE(length, 0);
303*635a8641SAndroid Build Coastguard Worker   WriteInt(length);
304*635a8641SAndroid Build Coastguard Worker   WriteBytes(data, length);
305*635a8641SAndroid Build Coastguard Worker }
306*635a8641SAndroid Build Coastguard Worker 
WriteBytes(const void * data,int length)307*635a8641SAndroid Build Coastguard Worker void Pickle::WriteBytes(const void* data, int length) {
308*635a8641SAndroid Build Coastguard Worker   WriteBytesCommon(data, length);
309*635a8641SAndroid Build Coastguard Worker }
310*635a8641SAndroid Build Coastguard Worker 
Reserve(size_t length)311*635a8641SAndroid Build Coastguard Worker void Pickle::Reserve(size_t length) {
312*635a8641SAndroid Build Coastguard Worker   size_t data_len = bits::Align(length, sizeof(uint32_t));
313*635a8641SAndroid Build Coastguard Worker   DCHECK_GE(data_len, length);
314*635a8641SAndroid Build Coastguard Worker #ifdef ARCH_CPU_64_BITS
315*635a8641SAndroid Build Coastguard Worker   DCHECK_LE(data_len, std::numeric_limits<uint32_t>::max());
316*635a8641SAndroid Build Coastguard Worker #endif
317*635a8641SAndroid Build Coastguard Worker   DCHECK_LE(write_offset_, std::numeric_limits<uint32_t>::max() - data_len);
318*635a8641SAndroid Build Coastguard Worker   size_t new_size = write_offset_ + data_len;
319*635a8641SAndroid Build Coastguard Worker   if (new_size > capacity_after_header_)
320*635a8641SAndroid Build Coastguard Worker     Resize(capacity_after_header_ * 2 + new_size);
321*635a8641SAndroid Build Coastguard Worker }
322*635a8641SAndroid Build Coastguard Worker 
WriteAttachment(scoped_refptr<Attachment> attachment)323*635a8641SAndroid Build Coastguard Worker bool Pickle::WriteAttachment(scoped_refptr<Attachment> attachment) {
324*635a8641SAndroid Build Coastguard Worker   return false;
325*635a8641SAndroid Build Coastguard Worker }
326*635a8641SAndroid Build Coastguard Worker 
ReadAttachment(base::PickleIterator * iter,scoped_refptr<Attachment> * attachment) const327*635a8641SAndroid Build Coastguard Worker bool Pickle::ReadAttachment(base::PickleIterator* iter,
328*635a8641SAndroid Build Coastguard Worker                             scoped_refptr<Attachment>* attachment) const {
329*635a8641SAndroid Build Coastguard Worker   return false;
330*635a8641SAndroid Build Coastguard Worker }
331*635a8641SAndroid Build Coastguard Worker 
HasAttachments() const332*635a8641SAndroid Build Coastguard Worker bool Pickle::HasAttachments() const {
333*635a8641SAndroid Build Coastguard Worker   return false;
334*635a8641SAndroid Build Coastguard Worker }
335*635a8641SAndroid Build Coastguard Worker 
Resize(size_t new_capacity)336*635a8641SAndroid Build Coastguard Worker void Pickle::Resize(size_t new_capacity) {
337*635a8641SAndroid Build Coastguard Worker   CHECK_NE(capacity_after_header_, kCapacityReadOnly);
338*635a8641SAndroid Build Coastguard Worker   capacity_after_header_ = bits::Align(new_capacity, kPayloadUnit);
339*635a8641SAndroid Build Coastguard Worker   void* p = realloc(header_, GetTotalAllocatedSize());
340*635a8641SAndroid Build Coastguard Worker   CHECK(p);
341*635a8641SAndroid Build Coastguard Worker   header_ = reinterpret_cast<Header*>(p);
342*635a8641SAndroid Build Coastguard Worker }
343*635a8641SAndroid Build Coastguard Worker 
ClaimBytes(size_t num_bytes)344*635a8641SAndroid Build Coastguard Worker void* Pickle::ClaimBytes(size_t num_bytes) {
345*635a8641SAndroid Build Coastguard Worker   void* p = ClaimUninitializedBytesInternal(num_bytes);
346*635a8641SAndroid Build Coastguard Worker   CHECK(p);
347*635a8641SAndroid Build Coastguard Worker   memset(p, 0, num_bytes);
348*635a8641SAndroid Build Coastguard Worker   return p;
349*635a8641SAndroid Build Coastguard Worker }
350*635a8641SAndroid Build Coastguard Worker 
GetTotalAllocatedSize() const351*635a8641SAndroid Build Coastguard Worker size_t Pickle::GetTotalAllocatedSize() const {
352*635a8641SAndroid Build Coastguard Worker   if (capacity_after_header_ == kCapacityReadOnly)
353*635a8641SAndroid Build Coastguard Worker     return 0;
354*635a8641SAndroid Build Coastguard Worker   return header_size_ + capacity_after_header_;
355*635a8641SAndroid Build Coastguard Worker }
356*635a8641SAndroid Build Coastguard Worker 
357*635a8641SAndroid Build Coastguard Worker // static
FindNext(size_t header_size,const char * start,const char * end)358*635a8641SAndroid Build Coastguard Worker const char* Pickle::FindNext(size_t header_size,
359*635a8641SAndroid Build Coastguard Worker                              const char* start,
360*635a8641SAndroid Build Coastguard Worker                              const char* end) {
361*635a8641SAndroid Build Coastguard Worker   size_t pickle_size = 0;
362*635a8641SAndroid Build Coastguard Worker   if (!PeekNext(header_size, start, end, &pickle_size))
363*635a8641SAndroid Build Coastguard Worker     return nullptr;
364*635a8641SAndroid Build Coastguard Worker 
365*635a8641SAndroid Build Coastguard Worker   if (pickle_size > static_cast<size_t>(end - start))
366*635a8641SAndroid Build Coastguard Worker     return nullptr;
367*635a8641SAndroid Build Coastguard Worker 
368*635a8641SAndroid Build Coastguard Worker   return start + pickle_size;
369*635a8641SAndroid Build Coastguard Worker }
370*635a8641SAndroid Build Coastguard Worker 
371*635a8641SAndroid Build Coastguard Worker // static
PeekNext(size_t header_size,const char * start,const char * end,size_t * pickle_size)372*635a8641SAndroid Build Coastguard Worker bool Pickle::PeekNext(size_t header_size,
373*635a8641SAndroid Build Coastguard Worker                       const char* start,
374*635a8641SAndroid Build Coastguard Worker                       const char* end,
375*635a8641SAndroid Build Coastguard Worker                       size_t* pickle_size) {
376*635a8641SAndroid Build Coastguard Worker   DCHECK_EQ(header_size, bits::Align(header_size, sizeof(uint32_t)));
377*635a8641SAndroid Build Coastguard Worker   DCHECK_GE(header_size, sizeof(Header));
378*635a8641SAndroid Build Coastguard Worker   DCHECK_LE(header_size, static_cast<size_t>(kPayloadUnit));
379*635a8641SAndroid Build Coastguard Worker 
380*635a8641SAndroid Build Coastguard Worker   size_t length = static_cast<size_t>(end - start);
381*635a8641SAndroid Build Coastguard Worker   if (length < sizeof(Header))
382*635a8641SAndroid Build Coastguard Worker     return false;
383*635a8641SAndroid Build Coastguard Worker 
384*635a8641SAndroid Build Coastguard Worker   const Header* hdr = reinterpret_cast<const Header*>(start);
385*635a8641SAndroid Build Coastguard Worker   if (length < header_size)
386*635a8641SAndroid Build Coastguard Worker     return false;
387*635a8641SAndroid Build Coastguard Worker 
388*635a8641SAndroid Build Coastguard Worker   // If payload_size causes an overflow, we return maximum possible
389*635a8641SAndroid Build Coastguard Worker   // pickle size to indicate that.
390*635a8641SAndroid Build Coastguard Worker   *pickle_size = ClampAdd(header_size, hdr->payload_size);
391*635a8641SAndroid Build Coastguard Worker   return true;
392*635a8641SAndroid Build Coastguard Worker }
393*635a8641SAndroid Build Coastguard Worker 
WriteBytesStatic(const void * data)394*635a8641SAndroid Build Coastguard Worker template <size_t length> void Pickle::WriteBytesStatic(const void* data) {
395*635a8641SAndroid Build Coastguard Worker   WriteBytesCommon(data, length);
396*635a8641SAndroid Build Coastguard Worker }
397*635a8641SAndroid Build Coastguard Worker 
398*635a8641SAndroid Build Coastguard Worker template void Pickle::WriteBytesStatic<2>(const void* data);
399*635a8641SAndroid Build Coastguard Worker template void Pickle::WriteBytesStatic<4>(const void* data);
400*635a8641SAndroid Build Coastguard Worker template void Pickle::WriteBytesStatic<8>(const void* data);
401*635a8641SAndroid Build Coastguard Worker 
ClaimUninitializedBytesInternal(size_t length)402*635a8641SAndroid Build Coastguard Worker inline void* Pickle::ClaimUninitializedBytesInternal(size_t length) {
403*635a8641SAndroid Build Coastguard Worker   DCHECK_NE(kCapacityReadOnly, capacity_after_header_)
404*635a8641SAndroid Build Coastguard Worker       << "oops: pickle is readonly";
405*635a8641SAndroid Build Coastguard Worker   size_t data_len = bits::Align(length, sizeof(uint32_t));
406*635a8641SAndroid Build Coastguard Worker   DCHECK_GE(data_len, length);
407*635a8641SAndroid Build Coastguard Worker #ifdef ARCH_CPU_64_BITS
408*635a8641SAndroid Build Coastguard Worker   DCHECK_LE(data_len, std::numeric_limits<uint32_t>::max());
409*635a8641SAndroid Build Coastguard Worker #endif
410*635a8641SAndroid Build Coastguard Worker   DCHECK_LE(write_offset_, std::numeric_limits<uint32_t>::max() - data_len);
411*635a8641SAndroid Build Coastguard Worker   size_t new_size = write_offset_ + data_len;
412*635a8641SAndroid Build Coastguard Worker   if (new_size > capacity_after_header_) {
413*635a8641SAndroid Build Coastguard Worker     size_t new_capacity = capacity_after_header_ * 2;
414*635a8641SAndroid Build Coastguard Worker     const size_t kPickleHeapAlign = 4096;
415*635a8641SAndroid Build Coastguard Worker     if (new_capacity > kPickleHeapAlign)
416*635a8641SAndroid Build Coastguard Worker       new_capacity = bits::Align(new_capacity, kPickleHeapAlign) - kPayloadUnit;
417*635a8641SAndroid Build Coastguard Worker     Resize(std::max(new_capacity, new_size));
418*635a8641SAndroid Build Coastguard Worker   }
419*635a8641SAndroid Build Coastguard Worker 
420*635a8641SAndroid Build Coastguard Worker   char* write = mutable_payload() + write_offset_;
421*635a8641SAndroid Build Coastguard Worker   memset(write + length, 0, data_len - length);  // Always initialize padding
422*635a8641SAndroid Build Coastguard Worker   header_->payload_size = static_cast<uint32_t>(new_size);
423*635a8641SAndroid Build Coastguard Worker   write_offset_ = new_size;
424*635a8641SAndroid Build Coastguard Worker   return write;
425*635a8641SAndroid Build Coastguard Worker }
426*635a8641SAndroid Build Coastguard Worker 
WriteBytesCommon(const void * data,size_t length)427*635a8641SAndroid Build Coastguard Worker inline void Pickle::WriteBytesCommon(const void* data, size_t length) {
428*635a8641SAndroid Build Coastguard Worker   DCHECK_NE(kCapacityReadOnly, capacity_after_header_)
429*635a8641SAndroid Build Coastguard Worker       << "oops: pickle is readonly";
430*635a8641SAndroid Build Coastguard Worker   MSAN_CHECK_MEM_IS_INITIALIZED(data, length);
431*635a8641SAndroid Build Coastguard Worker   void* write = ClaimUninitializedBytesInternal(length);
432*635a8641SAndroid Build Coastguard Worker   memcpy(write, data, length);
433*635a8641SAndroid Build Coastguard Worker }
434*635a8641SAndroid Build Coastguard Worker 
435*635a8641SAndroid Build Coastguard Worker }  // namespace base
436