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 : #include "base/pickle.h"
8 :
9 : #include "mozilla/Alignment.h"
10 : #include "mozilla/CheckedInt.h"
11 : #include "mozilla/EndianUtils.h"
12 : #include "mozilla/TypeTraits.h"
13 : #include "mozilla/Telemetry.h"
14 : #include "mozilla/ipc/ProtocolUtils.h"
15 :
16 : #include <stdlib.h>
17 :
18 : #include <limits>
19 : #include <string>
20 : #include <algorithm>
21 :
22 : #include "nsDebug.h"
23 :
24 : //------------------------------------------------------------------------------
25 :
26 : static_assert(MOZ_ALIGNOF(Pickle::memberAlignmentType) >= MOZ_ALIGNOF(uint32_t),
27 : "Insufficient alignment");
28 :
29 : #ifndef MOZ_TASK_TRACER
30 : static const uint32_t kHeaderSegmentCapacity = 64;
31 : #else
32 : // TaskTracer would add extra fields to the header to carry task ID and
33 : // other information.
34 : // \see class Message::HeaderTaskTracer
35 : static const uint32_t kHeaderSegmentCapacity = 128;
36 : #endif
37 :
38 : static const uint32_t kDefaultSegmentCapacity = 4096;
39 :
40 : static const char kBytePaddingMarker = char(0xbf);
41 :
42 : // Note: we round the time to the nearest millisecond. So a min value of 1 ms
43 : // actually captures from 500us and above.
44 : static const uint32_t kMinTelemetryIPCReadLatencyMs = 1;
45 :
46 : namespace {
47 :
48 : // We want to copy data to our payload as efficiently as possible.
49 : // memcpy fits the bill for copying, but not all compilers or
50 : // architectures support inlining memcpy from void*, which has unknown
51 : // static alignment. However, we know that all the members of our
52 : // payload will be aligned on memberAlignmentType boundaries. We
53 : // therefore use that knowledge to construct a copier that will copy
54 : // efficiently (via standard C++ assignment mechanisms) if the datatype
55 : // needs that alignment or less, and memcpy otherwise. (The compiler
56 : // may still inline memcpy, of course.)
57 :
58 : template<typename T, size_t size, bool hasSufficientAlignment>
59 : struct Copier
60 : {
61 1657 : static void Copy(T* dest, const char* iter) {
62 1657 : memcpy(dest, iter, sizeof(T));
63 1657 : }
64 : };
65 :
66 : // Copying 64-bit quantities happens often enough and can easily be made
67 : // worthwhile on 32-bit platforms, so handle it specially. Only do it
68 : // if 64-bit types aren't sufficiently aligned; the alignment
69 : // requirements for them vary between 32-bit platforms.
70 : #ifndef HAVE_64BIT_BUILD
71 : template<typename T>
72 : struct Copier<T, sizeof(uint64_t), false>
73 : {
74 : static void Copy(T* dest, const char* iter) {
75 : #if MOZ_LITTLE_ENDIAN
76 : static const int loIndex = 0, hiIndex = 1;
77 : #else
78 : static const int loIndex = 1, hiIndex = 0;
79 : #endif
80 : static_assert(MOZ_ALIGNOF(uint32_t*) == MOZ_ALIGNOF(void*),
81 : "Pointers have different alignments");
82 : const uint32_t* src = reinterpret_cast<const uint32_t*>(iter);
83 : uint32_t* uint32dest = reinterpret_cast<uint32_t*>(dest);
84 : uint32dest[loIndex] = src[loIndex];
85 : uint32dest[hiIndex] = src[hiIndex];
86 : }
87 : };
88 : #endif
89 :
90 : template<typename T, size_t size>
91 : struct Copier<T, size, true>
92 : {
93 124728 : static void Copy(T* dest, const char* iter) {
94 124728 : *dest = *reinterpret_cast<const T*>(iter);
95 124728 : }
96 : };
97 :
98 : } // anonymous namespace
99 :
100 550 : PickleIterator::PickleIterator(const Pickle& pickle)
101 550 : : iter_(pickle.buffers_.Iter())
102 550 : , start_(mozilla::TimeStamp::Now()) {
103 550 : iter_.Advance(pickle.buffers_, pickle.header_size_);
104 550 : }
105 :
106 : template<typename T>
107 : void
108 126384 : PickleIterator::CopyInto(T* dest) {
109 : static_assert(mozilla::IsPod<T>::value, "Copied type must be a POD type");
110 126384 : Copier<T, sizeof(T), (MOZ_ALIGNOF(T) <= sizeof(Pickle::memberAlignmentType))>::Copy(dest, iter_.Data());
111 126385 : }
112 :
113 126384 : bool Pickle::IteratorHasRoomFor(const PickleIterator& iter, uint32_t len) const {
114 : // Make sure we don't get into trouble where AlignInt(len) == 0.
115 126384 : MOZ_RELEASE_ASSERT(len < 64);
116 :
117 126384 : return iter.iter_.HasRoomFor(AlignInt(len));
118 : }
119 :
120 126385 : void Pickle::UpdateIter(PickleIterator* iter, uint32_t bytes) const {
121 : // Make sure we don't get into trouble where AlignInt(bytes) == 0.
122 126385 : MOZ_RELEASE_ASSERT(bytes < 64);
123 :
124 126385 : iter->iter_.Advance(buffers_, AlignInt(bytes));
125 126385 : }
126 :
127 : // Payload is sizeof(Pickle::memberAlignmentType) aligned.
128 :
129 570 : Pickle::Pickle(uint32_t header_size, size_t segment_capacity)
130 570 : : buffers_(AlignInt(header_size),
131 : segment_capacity ? segment_capacity : kHeaderSegmentCapacity,
132 : segment_capacity ? segment_capacity : kDefaultSegmentCapacity),
133 : header_(nullptr),
134 1140 : header_size_(AlignInt(header_size)) {
135 570 : DCHECK(static_cast<memberAlignmentType>(header_size) >= sizeof(Header));
136 570 : DCHECK(header_size_ <= kHeaderSegmentCapacity);
137 570 : header_ = reinterpret_cast<Header*>(buffers_.Start());
138 570 : header_->payload_size = 0;
139 570 : }
140 :
141 388 : Pickle::Pickle(uint32_t header_size, const char* data, uint32_t length)
142 388 : : buffers_(length, AlignCapacity(length), kDefaultSegmentCapacity),
143 : header_(nullptr),
144 388 : header_size_(AlignInt(header_size)) {
145 388 : DCHECK(static_cast<memberAlignmentType>(header_size) >= sizeof(Header));
146 388 : DCHECK(header_size <= kHeaderSegmentCapacity);
147 388 : MOZ_RELEASE_ASSERT(header_size <= length);
148 :
149 388 : header_ = reinterpret_cast<Header*>(buffers_.Start());
150 388 : memcpy(header_, data, length);
151 388 : }
152 :
153 476 : Pickle::Pickle(Pickle&& other)
154 476 : : buffers_(mozilla::Move(other.buffers_)),
155 476 : header_(other.header_),
156 952 : header_size_(other.header_size_) {
157 476 : other.header_ = nullptr;
158 476 : }
159 :
160 1418 : Pickle::~Pickle() {
161 1418 : }
162 :
163 56 : Pickle& Pickle::operator=(Pickle&& other) {
164 112 : BufferList tmp = mozilla::Move(other.buffers_);
165 56 : other.buffers_ = mozilla::Move(buffers_);
166 56 : buffers_ = mozilla::Move(tmp);
167 :
168 : //std::swap(buffers_, other.buffers_);
169 56 : std::swap(header_, other.header_);
170 56 : std::swap(header_size_, other.header_size_);
171 112 : return *this;
172 : }
173 :
174 13711 : bool Pickle::ReadBool(PickleIterator* iter, bool* result) const {
175 13711 : DCHECK(iter);
176 :
177 : int tmp;
178 13711 : if (!ReadInt(iter, &tmp))
179 0 : return false;
180 13711 : DCHECK(0 == tmp || 1 == tmp);
181 13711 : *result = tmp ? true : false;
182 13711 : return true;
183 : }
184 :
185 19 : bool Pickle::ReadInt16(PickleIterator* iter, int16_t* result) const {
186 19 : DCHECK(iter);
187 :
188 19 : if (!IteratorHasRoomFor(*iter, sizeof(*result)))
189 0 : return ReadBytesInto(iter, result, sizeof(*result));
190 :
191 19 : iter->CopyInto(result);
192 :
193 19 : UpdateIter(iter, sizeof(*result));
194 19 : return true;
195 : }
196 :
197 29 : bool Pickle::ReadUInt16(PickleIterator* iter, uint16_t* result) const {
198 29 : DCHECK(iter);
199 :
200 29 : if (!IteratorHasRoomFor(*iter, sizeof(*result)))
201 0 : return ReadBytesInto(iter, result, sizeof(*result));
202 :
203 29 : iter->CopyInto(result);
204 :
205 29 : UpdateIter(iter, sizeof(*result));
206 29 : return true;
207 : }
208 :
209 41500 : bool Pickle::ReadInt(PickleIterator* iter, int* result) const {
210 41500 : DCHECK(iter);
211 :
212 41500 : if (!IteratorHasRoomFor(*iter, sizeof(*result)))
213 0 : return ReadBytesInto(iter, result, sizeof(*result));
214 :
215 41500 : iter->CopyInto(result);
216 :
217 41500 : UpdateIter(iter, sizeof(*result));
218 41500 : return true;
219 : }
220 :
221 : // Always written as a 64-bit value since the size for this type can
222 : // differ between architectures.
223 0 : bool Pickle::ReadLong(PickleIterator* iter, long* result) const {
224 0 : DCHECK(iter);
225 :
226 0 : int64_t big_result = 0;
227 0 : if (IteratorHasRoomFor(*iter, sizeof(big_result))) {
228 0 : iter->CopyInto(&big_result);
229 0 : UpdateIter(iter, sizeof(big_result));
230 : } else {
231 0 : if (!ReadBytesInto(iter, &big_result, sizeof(big_result))) {
232 0 : return false;
233 : }
234 : }
235 : DCHECK(big_result <= LONG_MAX && big_result >= LONG_MIN);
236 0 : *result = static_cast<long>(big_result);
237 :
238 0 : return true;
239 : }
240 :
241 : // Always written as a 64-bit value since the size for this type can
242 : // differ between architectures.
243 0 : bool Pickle::ReadULong(PickleIterator* iter, unsigned long* result) const {
244 0 : DCHECK(iter);
245 :
246 0 : uint64_t big_result = 0;
247 0 : if (IteratorHasRoomFor(*iter, sizeof(big_result))) {
248 0 : iter->CopyInto(&big_result);
249 0 : UpdateIter(iter, sizeof(big_result));
250 : } else {
251 0 : if (!ReadBytesInto(iter, &big_result, sizeof(big_result))) {
252 0 : return false;
253 : }
254 : }
255 : DCHECK(big_result <= ULONG_MAX);
256 0 : *result = static_cast<unsigned long>(big_result);
257 :
258 0 : return true;
259 : }
260 :
261 0 : bool Pickle::ReadLength(PickleIterator* iter, int* result) const {
262 0 : if (!ReadInt(iter, result))
263 0 : return false;
264 0 : return ((*result) >= 0);
265 : }
266 :
267 : // Always written as a 64-bit value since the size for this type can
268 : // differ between architectures.
269 1644 : bool Pickle::ReadSize(PickleIterator* iter, size_t* result) const {
270 1644 : DCHECK(iter);
271 :
272 1644 : uint64_t big_result = 0;
273 1644 : if (IteratorHasRoomFor(*iter, sizeof(big_result))) {
274 1644 : iter->CopyInto(&big_result);
275 1644 : UpdateIter(iter, sizeof(big_result));
276 : } else {
277 0 : if (!ReadBytesInto(iter, &big_result, sizeof(big_result))) {
278 0 : return false;
279 : }
280 : }
281 1644 : DCHECK(big_result <= std::numeric_limits<size_t>::max());
282 1644 : *result = static_cast<size_t>(big_result);
283 :
284 1644 : return true;
285 : }
286 :
287 0 : bool Pickle::ReadInt32(PickleIterator* iter, int32_t* result) const {
288 0 : DCHECK(iter);
289 :
290 0 : if (!IteratorHasRoomFor(*iter, sizeof(*result)))
291 0 : return ReadBytesInto(iter, result, sizeof(*result));
292 :
293 0 : iter->CopyInto(result);
294 :
295 0 : UpdateIter(iter, sizeof(*result));
296 0 : return true;
297 : }
298 :
299 83179 : bool Pickle::ReadUInt32(PickleIterator* iter, uint32_t* result) const {
300 83179 : DCHECK(iter);
301 :
302 83179 : if (!IteratorHasRoomFor(*iter, sizeof(*result)))
303 0 : return ReadBytesInto(iter, result, sizeof(*result));
304 :
305 83179 : iter->CopyInto(result);
306 :
307 83180 : UpdateIter(iter, sizeof(*result));
308 83180 : return true;
309 : }
310 :
311 11 : bool Pickle::ReadInt64(PickleIterator* iter, int64_t* result) const {
312 11 : DCHECK(iter);
313 :
314 11 : if (!IteratorHasRoomFor(*iter, sizeof(*result)))
315 0 : return ReadBytesInto(iter, result, sizeof(*result));
316 :
317 11 : iter->CopyInto(result);
318 :
319 11 : UpdateIter(iter, sizeof(*result));
320 11 : return true;
321 : }
322 :
323 0 : bool Pickle::ReadUInt64(PickleIterator* iter, uint64_t* result) const {
324 0 : DCHECK(iter);
325 :
326 0 : if (!IteratorHasRoomFor(*iter, sizeof(*result)))
327 0 : return ReadBytesInto(iter, result, sizeof(*result));
328 :
329 0 : iter->CopyInto(result);
330 :
331 0 : UpdateIter(iter, sizeof(*result));
332 0 : return true;
333 : }
334 :
335 2 : bool Pickle::ReadDouble(PickleIterator* iter, double* result) const {
336 2 : DCHECK(iter);
337 :
338 2 : if (!IteratorHasRoomFor(*iter, sizeof(*result)))
339 0 : return ReadBytesInto(iter, result, sizeof(*result));
340 :
341 2 : iter->CopyInto(result);
342 :
343 2 : UpdateIter(iter, sizeof(*result));
344 2 : return true;
345 : }
346 :
347 : // Always written as a 64-bit value since the size for this type can
348 : // differ between architectures.
349 0 : bool Pickle::ReadIntPtr(PickleIterator* iter, intptr_t* result) const {
350 0 : DCHECK(iter);
351 :
352 0 : int64_t big_result = 0;
353 0 : if (IteratorHasRoomFor(*iter, sizeof(big_result))) {
354 0 : iter->CopyInto(&big_result);
355 0 : UpdateIter(iter, sizeof(big_result));
356 : } else {
357 0 : if (!ReadBytesInto(iter, &big_result, sizeof(big_result))) {
358 0 : return false;
359 : }
360 : }
361 :
362 0 : DCHECK(big_result <= std::numeric_limits<intptr_t>::max() && big_result >= std::numeric_limits<intptr_t>::min());
363 0 : *result = static_cast<intptr_t>(big_result);
364 :
365 0 : return true;
366 : }
367 :
368 0 : bool Pickle::ReadUnsignedChar(PickleIterator* iter, unsigned char* result) const {
369 0 : DCHECK(iter);
370 :
371 0 : if (!IteratorHasRoomFor(*iter, sizeof(*result)))
372 0 : return ReadBytesInto(iter, result, sizeof(*result));
373 :
374 0 : iter->CopyInto(result);
375 :
376 0 : UpdateIter(iter, sizeof(*result));
377 0 : return true;
378 : }
379 :
380 0 : bool Pickle::ReadString(PickleIterator* iter, std::string* result) const {
381 0 : DCHECK(iter);
382 :
383 : int len;
384 0 : if (!ReadLength(iter, &len))
385 0 : return false;
386 :
387 0 : auto chars = mozilla::MakeUnique<char[]>(len);
388 0 : if (!ReadBytesInto(iter, chars.get(), len)) {
389 0 : return false;
390 : }
391 0 : result->assign(chars.get(), len);
392 :
393 0 : return true;
394 : }
395 :
396 0 : bool Pickle::ReadWString(PickleIterator* iter, std::wstring* result) const {
397 0 : DCHECK(iter);
398 :
399 : int len;
400 0 : if (!ReadLength(iter, &len))
401 0 : return false;
402 : // Avoid integer multiplication overflow.
403 0 : if (len > INT_MAX / static_cast<int>(sizeof(wchar_t)))
404 0 : return false;
405 :
406 0 : auto chars = mozilla::MakeUnique<wchar_t[]>(len);
407 0 : if (!ReadBytesInto(iter, chars.get(), len * sizeof(wchar_t))) {
408 0 : return false;
409 : }
410 0 : result->assign(chars.get(), len);
411 :
412 0 : return true;
413 : }
414 :
415 40 : bool Pickle::ExtractBuffers(PickleIterator* iter, size_t length, BufferList* buffers,
416 : uint32_t alignment) const
417 : {
418 40 : DCHECK(iter);
419 40 : DCHECK(buffers);
420 40 : DCHECK(alignment == 4 || alignment == 8);
421 40 : DCHECK(intptr_t(header_) % alignment == 0);
422 :
423 40 : if (AlignInt(length) < length) {
424 0 : return false;
425 : }
426 :
427 40 : uint32_t padding_len = intptr_t(iter->iter_.Data()) % alignment;
428 40 : if (!iter->iter_.AdvanceAcrossSegments(buffers_, padding_len)) {
429 0 : return false;
430 : }
431 :
432 : bool success;
433 40 : *buffers = const_cast<BufferList*>(&buffers_)->Extract(iter->iter_, length, &success);
434 40 : if (!success) {
435 0 : return false;
436 : }
437 :
438 40 : return iter->iter_.AdvanceAcrossSegments(buffers_, AlignInt(length) - length);
439 : }
440 :
441 11278 : bool Pickle::ReadBytesInto(PickleIterator* iter, void* data, uint32_t length) const {
442 11278 : if (AlignInt(length) < length) {
443 0 : return false;
444 : }
445 :
446 11278 : if (!buffers_.ReadBytes(iter->iter_, reinterpret_cast<char*>(data), length)) {
447 0 : return false;
448 : }
449 :
450 11278 : return iter->iter_.AdvanceAcrossSegments(buffers_, AlignInt(length) - length);
451 : }
452 :
453 : #ifdef MOZ_PICKLE_SENTINEL_CHECKING
454 70354 : bool Pickle::ReadSentinel(PickleIterator* iter, uint32_t sentinel) const {
455 : uint32_t found;
456 70354 : if (!ReadUInt32(iter, &found)) {
457 0 : return false;
458 : }
459 70354 : return found == sentinel;
460 : }
461 :
462 2 : bool Pickle::IgnoreSentinel(PickleIterator* iter) const {
463 : uint32_t found;
464 2 : return ReadUInt32(iter, &found);
465 : }
466 :
467 70459 : bool Pickle::WriteSentinel(uint32_t sentinel) {
468 70459 : return WriteUInt32(sentinel);
469 : }
470 : #endif
471 :
472 435 : void Pickle::EndRead(PickleIterator& iter, uint32_t ipcMsgType) const {
473 435 : DCHECK(iter.iter_.Done());
474 :
475 435 : if (NS_IsMainThread() && ipcMsgType != 0) {
476 272 : uint32_t latencyMs = round((mozilla::TimeStamp::Now() - iter.start_).ToMilliseconds());
477 272 : if (latencyMs >= kMinTelemetryIPCReadLatencyMs) {
478 : mozilla::Telemetry::Accumulate(mozilla::Telemetry::IPC_READ_MAIN_THREAD_LATENCY_MS,
479 8 : nsDependentCString(mozilla::ipc::StringFromIPCMessageType(ipcMsgType)),
480 4 : latencyMs);
481 : }
482 : }
483 435 : }
484 :
485 138415 : void Pickle::BeginWrite(uint32_t length, uint32_t alignment) {
486 138415 : DCHECK(alignment % 4 == 0) << "Must be at least 32-bit aligned!";
487 :
488 : // write at an alignment-aligned offset from the beginning of the header
489 138415 : uint32_t offset = AlignInt(header_->payload_size);
490 138415 : uint32_t padding = (header_size_ + offset) % alignment;
491 138415 : uint32_t new_size = offset + padding + AlignInt(length);
492 138415 : MOZ_RELEASE_ASSERT(new_size >= header_->payload_size);
493 :
494 138415 : DCHECK(intptr_t(header_) % alignment == 0);
495 :
496 : #ifdef ARCH_CPU_64_BITS
497 138415 : DCHECK_LE(length, std::numeric_limits<uint32_t>::max());
498 : #endif
499 :
500 138415 : if (padding) {
501 15 : MOZ_RELEASE_ASSERT(padding <= 8);
502 : static const char padding_data[8] = {
503 : kBytePaddingMarker, kBytePaddingMarker, kBytePaddingMarker, kBytePaddingMarker,
504 : kBytePaddingMarker, kBytePaddingMarker, kBytePaddingMarker, kBytePaddingMarker,
505 : };
506 15 : buffers_.WriteBytes(padding_data, padding);
507 : }
508 :
509 138415 : DCHECK((header_size_ + header_->payload_size + padding) % alignment == 0);
510 :
511 138415 : header_->payload_size = new_size;
512 138415 : }
513 :
514 138414 : void Pickle::EndWrite(uint32_t length) {
515 : // Zero-pad to keep tools like purify from complaining about uninitialized
516 : // memory.
517 138414 : uint32_t padding = AlignInt(length) - length;
518 138414 : if (padding) {
519 6841 : MOZ_RELEASE_ASSERT(padding <= 4);
520 : static const char padding_data[4] = {
521 : kBytePaddingMarker, kBytePaddingMarker, kBytePaddingMarker, kBytePaddingMarker,
522 : };
523 6841 : buffers_.WriteBytes(padding_data, padding);
524 : }
525 138414 : }
526 :
527 138415 : bool Pickle::WriteBytes(const void* data, uint32_t data_len, uint32_t alignment) {
528 138415 : DCHECK(alignment == 4 || alignment == 8);
529 138415 : DCHECK(intptr_t(header_) % alignment == 0);
530 :
531 138415 : BeginWrite(data_len, alignment);
532 :
533 138415 : buffers_.WriteBytes(reinterpret_cast<const char*>(data), data_len);
534 :
535 138414 : EndWrite(data_len);
536 138414 : return true;
537 : }
538 :
539 0 : bool Pickle::WriteString(const std::string& value) {
540 : #ifdef FUZZING
541 : std::string v(value);
542 : Singleton<mozilla::ipc::Faulty>::get()->FuzzString(v);
543 : if (!WriteInt(static_cast<int>(v.size())))
544 : return false;
545 :
546 : return WriteBytes(v.data(), static_cast<int>(v.size()));
547 : #else
548 0 : if (!WriteInt(static_cast<int>(value.size())))
549 0 : return false;
550 :
551 0 : return WriteBytes(value.data(), static_cast<int>(value.size()));
552 : #endif
553 : }
554 :
555 0 : bool Pickle::WriteWString(const std::wstring& value) {
556 : #ifdef FUZZING
557 : std::wstring v(value);
558 : Singleton<mozilla::ipc::Faulty>::get()->FuzzWString(v);
559 : if (!WriteInt(static_cast<int>(v.size())))
560 : return false;
561 :
562 : return WriteBytes(v.data(),
563 : static_cast<int>(v.size() * sizeof(wchar_t)));
564 : #else
565 0 : if (!WriteInt(static_cast<int>(value.size())))
566 0 : return false;
567 :
568 0 : return WriteBytes(value.data(),
569 0 : static_cast<int>(value.size() * sizeof(wchar_t)));
570 : #endif
571 : }
572 :
573 0 : bool Pickle::WriteData(const char* data, uint32_t length) {
574 : #ifdef FUZZING
575 : std::string v(data, length);
576 : Singleton<mozilla::ipc::Faulty>::get()->FuzzData(v, v.size());
577 : return WriteInt(v.size()) && WriteBytes(v.data(), v.size());
578 : #else
579 0 : return WriteInt(length) && WriteBytes(data, length);
580 : #endif
581 : }
582 :
583 419 : void Pickle::InputBytes(const char* data, uint32_t length) {
584 419 : buffers_.WriteBytes(data, length);
585 419 : }
586 :
587 0 : int32_t* Pickle::GetInt32PtrForTest(uint32_t offset) {
588 0 : size_t pos = buffers_.Size() - offset;
589 0 : BufferList::IterImpl iter(buffers_);
590 0 : MOZ_RELEASE_ASSERT(iter.AdvanceAcrossSegments(buffers_, pos));
591 0 : return reinterpret_cast<int32_t*>(iter.Data());
592 : }
593 :
594 : // static
595 388 : uint32_t Pickle::MessageSize(uint32_t header_size,
596 : const char* start,
597 : const char* end) {
598 388 : DCHECK(header_size == AlignInt(header_size));
599 388 : DCHECK(header_size <= static_cast<memberAlignmentType>(kHeaderSegmentCapacity));
600 :
601 388 : if (end < start)
602 0 : return 0;
603 388 : size_t length = static_cast<size_t>(end - start);
604 388 : if (length < sizeof(Header))
605 0 : return 0;
606 :
607 388 : const Header* hdr = reinterpret_cast<const Header*>(start);
608 388 : if (length < header_size)
609 0 : return 0;
610 :
611 388 : mozilla::CheckedInt<uint32_t> sum(header_size);
612 388 : sum += hdr->payload_size;
613 :
614 388 : if (!sum.isValid())
615 0 : return 0;
616 :
617 388 : return sum.value();
618 : }
|