[go: nahoru, domu]

blob: 711775e1446ab57234c84a8273ee75752ce57453 [file] [log] [blame]
Avi Drissmane4622aa2022-09-08 20:36:061// Copyright 2012 The Chromium Authors
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commitd7cae122008-07-26 21:49:384
initial.commitd7cae122008-07-26 21:49:385#include "base/pickle.h"
6
David Benjamin7d046122023-10-24 13:48:387#include <algorithm>
Avi Drissmanc73aa5d22023-12-07 17:24:228#include <bit>
Nick Diego Yamane7676c802022-01-19 19:02:519#include <cstdlib>
dskiba6f3790a2015-09-30 17:24:3010#include <limits>
Jean-Philippe Gravel47159f162022-11-27 20:32:5811#include <ostream>
David Benjamin5746c532023-10-25 15:16:1012#include <type_traits>
maruel@google.comc9046af2008-08-06 20:35:1713
primiano32a7f502015-07-24 20:13:3214#include "base/bits.h"
Austin Sullivan31fcd062024-01-10 22:18:2915#include "base/containers/span.h"
jam03d8a782016-02-10 20:13:3916#include "base/numerics/safe_conversions.h"
Justin Schuh91077eab2017-07-24 21:54:5617#include "base/numerics/safe_math.h"
avi9b6f42932015-12-26 22:15:1418#include "build/build_config.h"
primiano32a7f502015-07-24 20:13:3219
brettwa89dd422015-06-03 16:20:1420namespace base {
brettw@chromium.org476dafb2013-12-03 00:39:2621
initial.commitd7cae122008-07-26 21:49:3822// static
Peter Kasting28b51cf2022-06-28 15:02:4323const size_t Pickle::kPayloadUnit = 64;
initial.commitd7cae122008-07-26 21:49:3824
thestig@chromium.org9193d2f2011-10-10 22:20:3325static const size_t kCapacityReadOnly = static_cast<size_t>(-1);
deanm@google.com836061b2008-08-13 14:57:5126
jbates@chromium.orgce208f872012-03-07 20:42:5627PickleIterator::PickleIterator(const Pickle& pickle)
halyavin@google.coma15016f2014-06-02 23:23:4928 : payload_(pickle.payload()),
29 read_index_(0),
Nick Diego Yamane7676c802022-01-19 19:02:5130 end_index_(pickle.payload_size()) {}
jbates@chromium.orgce208f872012-03-07 20:42:5631
32template <typename Type>
33inline bool PickleIterator::ReadBuiltinType(Type* result) {
David Benjamin5746c532023-10-25 15:16:1034 static_assert(
35 std::is_integral_v<Type> && !std::is_same_v<Type, bool>,
36 "This method is only safe with to use with types without padding bits.");
jbates@chromium.orgce208f872012-03-07 20:42:5637 const char* read_from = GetReadPointerAndAdvance<Type>();
38 if (!read_from)
39 return false;
David Benjamin5746c532023-10-25 15:16:1040 memcpy(result, read_from, sizeof(*result));
jbates@chromium.orgce208f872012-03-07 20:42:5641 return true;
42}
43
halyavin@google.coma15016f2014-06-02 23:23:4944inline void PickleIterator::Advance(size_t size) {
Benoit Lize7b302c42021-02-04 11:20:3845 size_t aligned_size = bits::AlignUp(size, sizeof(uint32_t));
halyavin@google.coma15016f2014-06-02 23:23:4946 if (end_index_ - read_index_ < aligned_size) {
47 read_index_ = end_index_;
48 } else {
49 read_index_ += aligned_size;
50 }
51}
52
Nick Diego Yamane7676c802022-01-19 19:02:5153template <typename Type>
jbates@chromium.orgce208f872012-03-07 20:42:5654inline const char* PickleIterator::GetReadPointerAndAdvance() {
halyavin@google.coma15016f2014-06-02 23:23:4955 if (sizeof(Type) > end_index_ - read_index_) {
56 read_index_ = end_index_;
Ivan Kotenkova16212a52017-11-08 12:37:3357 return nullptr;
halyavin@google.coma15016f2014-06-02 23:23:4958 }
59 const char* current_read_ptr = payload_ + read_index_;
60 Advance(sizeof(Type));
jbates@chromium.orgce208f872012-03-07 20:42:5661 return current_read_ptr;
62}
63
Peter Kasting28b51cf2022-06-28 15:02:4364const char* PickleIterator::GetReadPointerAndAdvance(size_t num_bytes) {
65 if (num_bytes > end_index_ - read_index_) {
halyavin@google.coma15016f2014-06-02 23:23:4966 read_index_ = end_index_;
Ivan Kotenkova16212a52017-11-08 12:37:3367 return nullptr;
halyavin@google.coma15016f2014-06-02 23:23:4968 }
69 const char* current_read_ptr = payload_ + read_index_;
70 Advance(num_bytes);
jbates@chromium.orgce208f872012-03-07 20:42:5671 return current_read_ptr;
72}
73
halyavin@google.coma15016f2014-06-02 23:23:4974inline const char* PickleIterator::GetReadPointerAndAdvance(
Peter Kasting28b51cf2022-06-28 15:02:4375 size_t num_elements,
halyavin@google.coma15016f2014-06-02 23:23:4976 size_t size_element) {
Peter Kasting28b51cf2022-06-28 15:02:4377 // Check for size_t overflow.
78 size_t num_bytes;
Justin Schuh91077eab2017-07-24 21:54:5679 if (!CheckMul(num_elements, size_element).AssignIfValid(&num_bytes))
Ivan Kotenkova16212a52017-11-08 12:37:3380 return nullptr;
Justin Schuh91077eab2017-07-24 21:54:5681 return GetReadPointerAndAdvance(num_bytes);
jbates@chromium.orgce208f872012-03-07 20:42:5682}
83
84bool PickleIterator::ReadBool(bool* result) {
David Benjamin5746c532023-10-25 15:16:1085 // Not all bit patterns are valid bools. Avoid undefined behavior by reading a
86 // type with no padding bits, then converting to bool.
87 uint8_t v;
88 if (!ReadBuiltinType(&v)) {
89 return false;
90 }
91 *result = v != 0;
92 return true;
jbates@chromium.orgce208f872012-03-07 20:42:5693}
94
95bool PickleIterator::ReadInt(int* result) {
96 return ReadBuiltinType(result);
97}
98
99bool PickleIterator::ReadLong(long* result) {
jam03d8a782016-02-10 20:13:39100 // Always read long as a 64-bit value to ensure compatibility between 32-bit
101 // and 64-bit processes.
102 int64_t result_int64 = 0;
103 if (!ReadBuiltinType(&result_int64))
104 return false;
Maksim Ivanov88edf972022-10-21 17:58:16105 if (!IsValueInRangeForNumericType<long>(result_int64))
106 return false;
107 *result = static_cast<long>(result_int64);
jam03d8a782016-02-10 20:13:39108 return true;
jbates@chromium.orgce208f872012-03-07 20:42:56109}
110
avic0279142015-12-04 22:38:52111bool PickleIterator::ReadUInt16(uint16_t* result) {
jbates@chromium.orgce208f872012-03-07 20:42:56112 return ReadBuiltinType(result);
113}
114
avic0279142015-12-04 22:38:52115bool PickleIterator::ReadUInt32(uint32_t* result) {
jbates@chromium.orgce208f872012-03-07 20:42:56116 return ReadBuiltinType(result);
117}
118
avic0279142015-12-04 22:38:52119bool PickleIterator::ReadInt64(int64_t* result) {
jbates@chromium.orgce208f872012-03-07 20:42:56120 return ReadBuiltinType(result);
121}
122
avic0279142015-12-04 22:38:52123bool PickleIterator::ReadUInt64(uint64_t* result) {
jbates@chromium.orgce208f872012-03-07 20:42:56124 return ReadBuiltinType(result);
125}
126
rbyers@chromium.orgb1f61b032012-11-28 15:40:58127bool PickleIterator::ReadFloat(float* result) {
piman@chromium.org522fbea2013-11-18 00:50:25128 // crbug.com/315213
129 // The source data may not be properly aligned, and unaligned float reads
130 // cause SIGBUS on some ARM platforms, so force using memcpy to copy the data
131 // into the result.
132 const char* read_from = GetReadPointerAndAdvance<float>();
133 if (!read_from)
134 return false;
135 memcpy(result, read_from, sizeof(*result));
136 return true;
rbyers@chromium.orgb1f61b032012-11-28 15:40:58137}
138
mostynb@opera.com915cc7d2014-07-14 22:50:32139bool PickleIterator::ReadDouble(double* result) {
140 // crbug.com/315213
141 // The source data may not be properly aligned, and unaligned double reads
142 // cause SIGBUS on some ARM platforms, so force using memcpy to copy the data
143 // into the result.
144 const char* read_from = GetReadPointerAndAdvance<double>();
145 if (!read_from)
146 return false;
147 memcpy(result, read_from, sizeof(*result));
148 return true;
149}
150
jbates@chromium.orgce208f872012-03-07 20:42:56151bool PickleIterator::ReadString(std::string* result) {
Peter Kasting28b51cf2022-06-28 15:02:43152 size_t len;
153 if (!ReadLength(&len))
jbates@chromium.orgce208f872012-03-07 20:42:56154 return false;
155 const char* read_from = GetReadPointerAndAdvance(len);
156 if (!read_from)
157 return false;
158
159 result->assign(read_from, len);
160 return true;
161}
162
brettwa89dd422015-06-03 16:20:14163bool PickleIterator::ReadStringPiece(StringPiece* result) {
Peter Kasting28b51cf2022-06-28 15:02:43164 size_t len;
165 if (!ReadLength(&len))
brucedawsoneaa38962015-03-10 01:46:50166 return false;
167 const char* read_from = GetReadPointerAndAdvance(len);
168 if (!read_from)
169 return false;
170
brettwa89dd422015-06-03 16:20:14171 *result = StringPiece(read_from, len);
brucedawsoneaa38962015-03-10 01:46:50172 return true;
173}
174
Jan Wilken Dörrie085b2aa2021-03-12 16:26:57175bool PickleIterator::ReadString16(std::u16string* result) {
Peter Kasting28b51cf2022-06-28 15:02:43176 size_t len;
177 if (!ReadLength(&len))
jbates@chromium.orgce208f872012-03-07 20:42:56178 return false;
Jan Wilken Dörrie677e0c872021-03-10 10:04:38179 const char* read_from = GetReadPointerAndAdvance(len, sizeof(char16_t));
jbates@chromium.orgce208f872012-03-07 20:42:56180 if (!read_from)
181 return false;
182
Jan Wilken Dörrie677e0c872021-03-10 10:04:38183 result->assign(reinterpret_cast<const char16_t*>(read_from), len);
jbates@chromium.orgce208f872012-03-07 20:42:56184 return true;
185}
186
brettwa89dd422015-06-03 16:20:14187bool PickleIterator::ReadStringPiece16(StringPiece16* result) {
Peter Kasting28b51cf2022-06-28 15:02:43188 size_t len;
189 if (!ReadLength(&len))
brucedawsoneaa38962015-03-10 01:46:50190 return false;
Jan Wilken Dörrie677e0c872021-03-10 10:04:38191 const char* read_from = GetReadPointerAndAdvance(len, sizeof(char16_t));
brucedawsoneaa38962015-03-10 01:46:50192 if (!read_from)
193 return false;
194
Jan Wilken Dörrie677e0c872021-03-10 10:04:38195 *result = StringPiece16(reinterpret_cast<const char16_t*>(read_from), len);
brucedawsoneaa38962015-03-10 01:46:50196 return true;
197}
198
Peter Kasting28b51cf2022-06-28 15:02:43199bool PickleIterator::ReadData(const char** data, size_t* length) {
jbates@chromium.orgce208f872012-03-07 20:42:56200 *length = 0;
Ivan Kotenkova16212a52017-11-08 12:37:33201 *data = nullptr;
jbates@chromium.orgce208f872012-03-07 20:42:56202
Peter Kasting28b51cf2022-06-28 15:02:43203 if (!ReadLength(length))
jbates@chromium.orgce208f872012-03-07 20:42:56204 return false;
205
206 return ReadBytes(data, *length);
207}
208
Claudio DeSouzac537f85d2023-03-02 18:42:52209absl::optional<base::span<const uint8_t>> PickleIterator::ReadData() {
Jeremy Roman2d8d7802020-06-11 22:08:20210 const char* ptr;
Peter Kasting28b51cf2022-06-28 15:02:43211 size_t length;
Jeremy Roman2d8d7802020-06-11 22:08:20212
213 if (!ReadData(&ptr, &length))
Claudio DeSouzac537f85d2023-03-02 18:42:52214 return absl::nullopt;
Jeremy Roman2d8d7802020-06-11 22:08:20215
Claudio DeSouzac537f85d2023-03-02 18:42:52216 return base::as_bytes(base::make_span(ptr, length));
Jeremy Roman2d8d7802020-06-11 22:08:20217}
218
Peter Kasting28b51cf2022-06-28 15:02:43219bool PickleIterator::ReadBytes(const char** data, size_t length) {
jbates@chromium.orgce208f872012-03-07 20:42:56220 const char* read_from = GetReadPointerAndAdvance(length);
221 if (!read_from)
222 return false;
223 *data = read_from;
224 return true;
225}
226
Chris Watkinsbb7211c2017-11-29 07:16:38227Pickle::Attachment::Attachment() = default;
rockot502c94f2016-02-03 20:20:16228
Chris Watkinsbb7211c2017-11-29 07:16:38229Pickle::Attachment::~Attachment() = default;
rockot502c94f2016-02-03 20:20:16230
avic0279142015-12-04 22:38:52231// Payload is uint32_t aligned.
initial.commitd7cae122008-07-26 21:49:38232
233Pickle::Pickle()
Ivan Kotenkova16212a52017-11-08 12:37:33234 : header_(nullptr),
initial.commitd7cae122008-07-26 21:49:38235 header_size_(sizeof(Header)),
piman@chromium.orgd1b319fc2013-10-31 04:03:02236 capacity_after_header_(0),
237 write_offset_(0) {
Avi Drissmanc73aa5d22023-12-07 17:24:22238 static_assert(std::has_single_bit(Pickle::kPayloadUnit),
primiano32a7f502015-07-24 20:13:32239 "Pickle::kPayloadUnit must be a power of two");
initial.commitd7cae122008-07-26 21:49:38240 Resize(kPayloadUnit);
241 header_->payload_size = 0;
242}
243
Peter Kasting28b51cf2022-06-28 15:02:43244Pickle::Pickle(size_t header_size)
Ivan Kotenkova16212a52017-11-08 12:37:33245 : header_(nullptr),
Benoit Lize7b302c42021-02-04 11:20:38246 header_size_(bits::AlignUp(header_size, sizeof(uint32_t))),
piman@chromium.orgd1b319fc2013-10-31 04:03:02247 capacity_after_header_(0),
248 write_offset_(0) {
Peter Kasting28b51cf2022-06-28 15:02:43249 DCHECK_GE(header_size, sizeof(Header));
kushi.p@gmail.comd7a93ad2011-04-22 13:13:07250 DCHECK_LE(header_size, kPayloadUnit);
initial.commitd7cae122008-07-26 21:49:38251 Resize(kPayloadUnit);
252 header_->payload_size = 0;
253}
254
Daniel Cheng122b6e9e2023-10-06 17:56:50255Pickle::Pickle(span<const uint8_t> data)
256 : Pickle(reinterpret_cast<const char*>(data.data()), data.size()) {}
257
Raul Tambref191b592019-01-21 23:56:29258Pickle::Pickle(const char* data, size_t data_len)
initial.commitd7cae122008-07-26 21:49:38259 : header_(reinterpret_cast<Header*>(const_cast<char*>(data))),
rvargas@google.comd87f8e62010-11-15 19:31:23260 header_size_(0),
piman@chromium.orgd1b319fc2013-10-31 04:03:02261 capacity_after_header_(kCapacityReadOnly),
262 write_offset_(0) {
Peter Kasting28b51cf2022-06-28 15:02:43263 if (data_len >= sizeof(Header))
rvargas@google.comd87f8e62010-11-15 19:31:23264 header_size_ = data_len - header_->payload_size;
265
Peter Kasting28b51cf2022-06-28 15:02:43266 if (header_size_ > data_len)
rvargas@google.comd87f8e62010-11-15 19:31:23267 header_size_ = 0;
268
Benoit Lize7b302c42021-02-04 11:20:38269 if (header_size_ != bits::AlignUp(header_size_, sizeof(uint32_t)))
rvargas@google.comd87f8e62010-11-15 19:31:23270 header_size_ = 0;
271
272 // If there is anything wrong with the data, we're not going to use it.
273 if (!header_size_)
Ivan Kotenkova16212a52017-11-08 12:37:33274 header_ = nullptr;
initial.commitd7cae122008-07-26 21:49:38275}
276
277Pickle::Pickle(const Pickle& other)
Ivan Kotenkova16212a52017-11-08 12:37:33278 : header_(nullptr),
initial.commitd7cae122008-07-26 21:49:38279 header_size_(other.header_size_),
piman@chromium.orgd1b319fc2013-10-31 04:03:02280 capacity_after_header_(0),
281 write_offset_(other.write_offset_) {
Nick Diego Yamane7676c802022-01-19 19:02:51282 if (other.header_) {
283 Resize(other.header_->payload_size);
284 memcpy(header_, other.header_, header_size_ + other.header_->payload_size);
285 }
initial.commitd7cae122008-07-26 21:49:38286}
287
288Pickle::~Pickle() {
piman@chromium.orgd1b319fc2013-10-31 04:03:02289 if (capacity_after_header_ != kCapacityReadOnly)
initial.commitd7cae122008-07-26 21:49:38290 free(header_);
291}
292
293Pickle& Pickle::operator=(const Pickle& other) {
jar@chromium.orgb944f612009-08-07 23:13:35294 if (this == &other) {
jar@chromium.orgb944f612009-08-07 23:13:35295 return *this;
296 }
piman@chromium.orgd1b319fc2013-10-31 04:03:02297 if (capacity_after_header_ == kCapacityReadOnly) {
Ivan Kotenkova16212a52017-11-08 12:37:33298 header_ = nullptr;
piman@chromium.orgd1b319fc2013-10-31 04:03:02299 capacity_after_header_ = 0;
jar@chromium.orgfb6ec9992009-08-03 07:01:47300 }
301 if (header_size_ != other.header_size_) {
initial.commitd7cae122008-07-26 21:49:38302 free(header_);
Ivan Kotenkova16212a52017-11-08 12:37:33303 header_ = nullptr;
initial.commitd7cae122008-07-26 21:49:38304 header_size_ = other.header_size_;
305 }
Nick Diego Yamane7676c802022-01-19 19:02:51306 if (other.header_) {
307 Resize(other.header_->payload_size);
308 memcpy(header_, other.header_,
309 other.header_size_ + other.header_->payload_size);
310 write_offset_ = other.write_offset_;
311 }
initial.commitd7cae122008-07-26 21:49:38312 return *this;
313}
314
Daniel Cheng0d89f9222017-09-22 05:05:07315void Pickle::WriteString(const StringPiece& value) {
Peter Kasting28b51cf2022-06-28 15:02:43316 WriteData(value.data(), value.size());
initial.commitd7cae122008-07-26 21:49:38317}
318
Daniel Cheng0d89f9222017-09-22 05:05:07319void Pickle::WriteString16(const StringPiece16& value) {
Peter Kasting28b51cf2022-06-28 15:02:43320 WriteInt(checked_cast<int>(value.size()));
321 WriteBytes(value.data(), value.size() * sizeof(char16_t));
initial.commitd7cae122008-07-26 21:49:38322}
323
Peter Kasting28b51cf2022-06-28 15:02:43324void Pickle::WriteData(const char* data, size_t length) {
Tom Sepez311d8782024-02-14 09:30:52325 WriteData(as_bytes(span(data, length)));
Austin Sullivan31fcd062024-01-10 22:18:29326}
327
328void Pickle::WriteData(std::string_view data) {
Tom Sepez311d8782024-02-14 09:30:52329 WriteData(as_byte_span(data));
330}
331
332void Pickle::WriteData(base::span<const uint8_t> data) {
Austin Sullivan31fcd062024-01-10 22:18:29333 WriteInt(checked_cast<int>(data.size()));
Tom Sepez311d8782024-02-14 09:30:52334 WriteBytes(data);
initial.commitd7cae122008-07-26 21:49:38335}
336
Peter Kasting28b51cf2022-06-28 15:02:43337void Pickle::WriteBytes(const void* data, size_t length) {
Tom Sepez30d68422024-01-24 19:55:09338 WriteBytesCommon(make_span(static_cast<const uint8_t*>(data), length));
Austin Sullivan31fcd062024-01-10 22:18:29339}
340
341void Pickle::WriteBytes(span<const uint8_t> data) {
342 WriteBytesCommon(data);
erg@google.com9989c9bb2011-01-07 20:23:43343}
344
piman@chromium.orgd1b319fc2013-10-31 04:03:02345void Pickle::Reserve(size_t length) {
Benoit Lize7b302c42021-02-04 11:20:38346 size_t data_len = bits::AlignUp(length, sizeof(uint32_t));
piman@chromium.orgd1b319fc2013-10-31 04:03:02347 DCHECK_GE(data_len, length);
erg@google.com9989c9bb2011-01-07 20:23:43348#ifdef ARCH_CPU_64_BITS
avic0279142015-12-04 22:38:52349 DCHECK_LE(data_len, std::numeric_limits<uint32_t>::max());
erg@google.com9989c9bb2011-01-07 20:23:43350#endif
avic0279142015-12-04 22:38:52351 DCHECK_LE(write_offset_, std::numeric_limits<uint32_t>::max() - data_len);
piman@chromium.orgd1b319fc2013-10-31 04:03:02352 size_t new_size = write_offset_ + data_len;
353 if (new_size > capacity_after_header_)
354 Resize(capacity_after_header_ * 2 + new_size);
erg@google.com9989c9bb2011-01-07 20:23:43355}
356
rockot502c94f2016-02-03 20:20:16357bool Pickle::WriteAttachment(scoped_refptr<Attachment> attachment) {
358 return false;
359}
360
361bool Pickle::ReadAttachment(base::PickleIterator* iter,
362 scoped_refptr<Attachment>* attachment) const {
363 return false;
364}
365
366bool Pickle::HasAttachments() const {
367 return false;
368}
369
piman@chromium.orgd1b319fc2013-10-31 04:03:02370void Pickle::Resize(size_t new_capacity) {
piman@chromium.orgd1b319fc2013-10-31 04:03:02371 CHECK_NE(capacity_after_header_, kCapacityReadOnly);
Benoit Lize7b302c42021-02-04 11:20:38372 capacity_after_header_ = bits::AlignUp(new_capacity, kPayloadUnit);
primiano9882cf342015-06-11 21:40:10373 void* p = realloc(header_, GetTotalAllocatedSize());
piman@chromium.orgd1b319fc2013-10-31 04:03:02374 CHECK(p);
initial.commitd7cae122008-07-26 21:49:38375 header_ = reinterpret_cast<Header*>(p);
primiano9882cf342015-06-11 21:40:10376}
377
rockot0776a502015-12-17 06:19:49378void* Pickle::ClaimBytes(size_t num_bytes) {
379 void* p = ClaimUninitializedBytesInternal(num_bytes);
380 CHECK(p);
381 memset(p, 0, num_bytes);
382 return p;
383}
384
primiano9882cf342015-06-11 21:40:10385size_t Pickle::GetTotalAllocatedSize() const {
386 if (capacity_after_header_ == kCapacityReadOnly)
387 return 0;
388 return header_size_ + capacity_after_header_;
initial.commitd7cae122008-07-26 21:49:38389}
390
391// static
392const char* Pickle::FindNext(size_t header_size,
393 const char* start,
394 const char* end) {
dskiba6f3790a2015-09-30 17:24:30395 size_t pickle_size = 0;
396 if (!PeekNext(header_size, start, end, &pickle_size))
Ivan Kotenkova16212a52017-11-08 12:37:33397 return nullptr;
dskiba6f3790a2015-09-30 17:24:30398
399 if (pickle_size > static_cast<size_t>(end - start))
Ivan Kotenkova16212a52017-11-08 12:37:33400 return nullptr;
dskiba6f3790a2015-09-30 17:24:30401
402 return start + pickle_size;
403}
404
405// static
406bool Pickle::PeekNext(size_t header_size,
407 const char* start,
408 const char* end,
409 size_t* pickle_size) {
Benoit Lize7b302c42021-02-04 11:20:38410 DCHECK_EQ(header_size, bits::AlignUp(header_size, sizeof(uint32_t)));
dskiba6f3790a2015-09-30 17:24:30411 DCHECK_GE(header_size, sizeof(Header));
kushi.p@gmail.comd7a93ad2011-04-22 13:13:07412 DCHECK_LE(header_size, static_cast<size_t>(kPayloadUnit));
initial.commitd7cae122008-07-26 21:49:38413
halyavin@google.com33a38dd2013-11-01 09:06:26414 size_t length = static_cast<size_t>(end - start);
415 if (length < sizeof(Header))
dskiba6f3790a2015-09-30 17:24:30416 return false;
glider@chromium.org137d2372011-01-26 13:02:27417
initial.commitd7cae122008-07-26 21:49:38418 const Header* hdr = reinterpret_cast<const Header*>(start);
dskiba6f3790a2015-09-30 17:24:30419 if (length < header_size)
420 return false;
421
Justin Schuh91077eab2017-07-24 21:54:56422 // If payload_size causes an overflow, we return maximum possible
423 // pickle size to indicate that.
424 *pickle_size = ClampAdd(header_size, hdr->payload_size);
dskiba6f3790a2015-09-30 17:24:30425 return true;
initial.commitd7cae122008-07-26 21:49:38426}
piman@chromium.orgd1b319fc2013-10-31 04:03:02427
Nick Diego Yamane7676c802022-01-19 19:02:51428template <size_t length>
429void Pickle::WriteBytesStatic(const void* data) {
Tom Sepez30d68422024-01-24 19:55:09430 WriteBytesCommon(make_span(static_cast<const uint8_t*>(data), length));
piman@chromium.orgd1b319fc2013-10-31 04:03:02431}
432
433template void Pickle::WriteBytesStatic<2>(const void* data);
434template void Pickle::WriteBytesStatic<4>(const void* data);
435template void Pickle::WriteBytesStatic<8>(const void* data);
436
rockot0776a502015-12-17 06:19:49437inline void* Pickle::ClaimUninitializedBytesInternal(size_t length) {
piman@chromium.orgd1b319fc2013-10-31 04:03:02438 DCHECK_NE(kCapacityReadOnly, capacity_after_header_)
439 << "oops: pickle is readonly";
Benoit Lize7b302c42021-02-04 11:20:38440 size_t data_len = bits::AlignUp(length, sizeof(uint32_t));
piman@chromium.orgd1b319fc2013-10-31 04:03:02441 DCHECK_GE(data_len, length);
442#ifdef ARCH_CPU_64_BITS
avic0279142015-12-04 22:38:52443 DCHECK_LE(data_len, std::numeric_limits<uint32_t>::max());
piman@chromium.orgd1b319fc2013-10-31 04:03:02444#endif
avic0279142015-12-04 22:38:52445 DCHECK_LE(write_offset_, std::numeric_limits<uint32_t>::max() - data_len);
piman@chromium.orgd1b319fc2013-10-31 04:03:02446 size_t new_size = write_offset_ + data_len;
447 if (new_size > capacity_after_header_) {
primiano32a7f502015-07-24 20:13:32448 size_t new_capacity = capacity_after_header_ * 2;
449 const size_t kPickleHeapAlign = 4096;
Benoit Lize7b302c42021-02-04 11:20:38450 if (new_capacity > kPickleHeapAlign) {
451 new_capacity =
452 bits::AlignUp(new_capacity, kPickleHeapAlign) - kPayloadUnit;
453 }
primiano32a7f502015-07-24 20:13:32454 Resize(std::max(new_capacity, new_size));
piman@chromium.orgd1b319fc2013-10-31 04:03:02455 }
456
457 char* write = mutable_payload() + write_offset_;
David Benjamin7d046122023-10-24 13:48:38458 std::fill(write + length, write + data_len, 0); // Always initialize padding
avic0279142015-12-04 22:38:52459 header_->payload_size = static_cast<uint32_t>(new_size);
piman@chromium.orgd1b319fc2013-10-31 04:03:02460 write_offset_ = new_size;
rockot0776a502015-12-17 06:19:49461 return write;
462}
463
Austin Sullivan31fcd062024-01-10 22:18:29464inline void Pickle::WriteBytesCommon(span<const uint8_t> data) {
rockot0776a502015-12-17 06:19:49465 DCHECK_NE(kCapacityReadOnly, capacity_after_header_)
466 << "oops: pickle is readonly";
Austin Sullivan31fcd062024-01-10 22:18:29467 MSAN_CHECK_MEM_IS_INITIALIZED(data.data(), data.size());
468 void* write = ClaimUninitializedBytesInternal(data.size());
469 std::copy(data.data(), data.data() + data.size(), static_cast<char*>(write));
piman@chromium.orgd1b319fc2013-10-31 04:03:02470}
brettwa89dd422015-06-03 16:20:14471
472} // namespace base