blob: 6488057b28562383824d05d7ffe9134db680731f [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.
[email protected]d26cd5272008-08-07 13:40:164
danakj51d26a42024-04-25 14:23:565#ifdef UNSAFE_BUFFERS_BUILD
6// TODO(crbug.com/40284755): Remove this and spanify to fix the errors.
7#pragma allow_unsafe_buffers
8#endif
9
dcheng093de9b2016-04-04 21:25:5110#include "base/pickle.h"
11
avi9b6f42932015-12-26 22:15:1412#include <limits.h>
13#include <stddef.h>
14#include <stdint.h>
15
dcheng093de9b2016-04-04 21:25:5116#include <memory>
[email protected]d26cd5272008-08-07 13:40:1617#include <string>
Helmut Januschka1dce9dc2024-06-11 13:05:3518#include <string_view>
Avi Drissman933398e2022-01-22 00:55:4219#include <tuple>
initial.commitd7cae122008-07-26 21:49:3820
HuanPo Lin27731ca2024-04-16 14:57:3021#include "base/containers/heap_array.h"
Avi Drissman516e1922024-03-21 18:11:2822#include "base/containers/span.h"
pkasting89a19f142014-10-02 03:01:0423#include "base/strings/utf_string_conversions.h"
Daniel Chengf45f47602022-02-28 22:38:3224#include "build/build_config.h"
Matt Menke4e486db2025-04-07 13:51:4325#include "testing/gmock/include/gmock/gmock.h"
initial.commitd7cae122008-07-26 21:49:3826#include "testing/gtest/include/gtest/gtest.h"
27
brettw05cfd8ddb2015-06-02 07:02:4728namespace base {
[email protected]476dafb2013-12-03 00:39:2629
initial.commitd7cae122008-07-26 21:49:3830namespace {
31
initial.commitd7cae122008-07-26 21:49:3832const bool testbool1 = false;
33const bool testbool2 = true;
Peter Kastinge72b278b2018-01-17 05:29:0934const int testint = 2'093'847'192;
35const long testlong = 1'093'847'192;
avi9b6f42932015-12-26 22:15:1436const uint16_t testuint16 = 32123;
37const uint32_t testuint32 = 1593847192;
Peter Kastinge72b278b2018-01-17 05:29:0938const int64_t testint64 = -0x7E8CA925'3104BDFCLL;
39const uint64_t testuint64 = 0xCE8CA925'3104BDF7ULL;
[email protected]b1f61b032012-11-28 15:40:5840const float testfloat = 3.1415926935f;
[email protected]915cc7d2014-07-14 22:50:3241const double testdouble = 2.71828182845904523;
pkasting89a19f142014-10-02 03:01:0442const std::string teststring("Hello world"); // note non-aligned string length
Will Harris3542dc42025-01-30 22:13:3543const std::string testemptystring("");
pkasting89a19f142014-10-02 03:01:0444const std::wstring testwstring(L"Hello, world");
Jan Wilken Dörriec92a6d7242021-03-23 17:43:4845const std::u16string teststring16(u"Hello, world");
Peter Kasting134ef9af2024-12-28 02:30:0946const char testrawstring[] = "Hello new world"; // Test raw string writing
Jan Wilken Dörrie677e0c872021-03-10 10:04:3847// Test raw char16_t writing, assumes UTF16 encoding is ANSI for alpha chars.
48const char16_t testrawstring16[] = {'A', 'l', 'o', 'h', 'a', 0};
pkasting89a19f142014-10-02 03:01:0449const char testdata[] = "AAA\0BBB\0";
Peter Kasting28b51cf2022-06-28 15:02:4350const size_t testdatalen = std::size(testdata) - 1;
initial.commitd7cae122008-07-26 21:49:3851
brucedawsoneaa38962015-03-10 01:46:5052// checks that the results can be read correctly from the Pickle
initial.commitd7cae122008-07-26 21:49:3853void VerifyResult(const Pickle& pickle) {
[email protected]ce208f872012-03-07 20:42:5654 PickleIterator iter(pickle);
initial.commitd7cae122008-07-26 21:49:3855
initial.commitd7cae122008-07-26 21:49:3856 bool outbool;
avi48fc13b2014-12-28 23:31:4857 EXPECT_TRUE(iter.ReadBool(&outbool));
[email protected]18853692013-01-03 12:30:5258 EXPECT_FALSE(outbool);
avi48fc13b2014-12-28 23:31:4859 EXPECT_TRUE(iter.ReadBool(&outbool));
[email protected]18853692013-01-03 12:30:5260 EXPECT_TRUE(outbool);
initial.commitd7cae122008-07-26 21:49:3861
pkasting89a19f142014-10-02 03:01:0462 int outint;
avi48fc13b2014-12-28 23:31:4863 EXPECT_TRUE(iter.ReadInt(&outint));
pkasting89a19f142014-10-02 03:01:0464 EXPECT_EQ(testint, outint);
65
66 long outlong;
avi48fc13b2014-12-28 23:31:4867 EXPECT_TRUE(iter.ReadLong(&outlong));
pkasting89a19f142014-10-02 03:01:0468 EXPECT_EQ(testlong, outlong);
69
avi9b6f42932015-12-26 22:15:1470 uint16_t outuint16;
avi48fc13b2014-12-28 23:31:4871 EXPECT_TRUE(iter.ReadUInt16(&outuint16));
[email protected]6d81b482011-02-22 19:47:1972 EXPECT_EQ(testuint16, outuint16);
73
avi9b6f42932015-12-26 22:15:1474 uint32_t outuint32;
avi48fc13b2014-12-28 23:31:4875 EXPECT_TRUE(iter.ReadUInt32(&outuint32));
pkasting89a19f142014-10-02 03:01:0476 EXPECT_EQ(testuint32, outuint32);
77
avi9b6f42932015-12-26 22:15:1478 int64_t outint64;
avi48fc13b2014-12-28 23:31:4879 EXPECT_TRUE(iter.ReadInt64(&outint64));
pkasting89a19f142014-10-02 03:01:0480 EXPECT_EQ(testint64, outint64);
81
avi9b6f42932015-12-26 22:15:1482 uint64_t outuint64;
avi48fc13b2014-12-28 23:31:4883 EXPECT_TRUE(iter.ReadUInt64(&outuint64));
pkasting89a19f142014-10-02 03:01:0484 EXPECT_EQ(testuint64, outuint64);
85
[email protected]b1f61b032012-11-28 15:40:5886 float outfloat;
avi48fc13b2014-12-28 23:31:4887 EXPECT_TRUE(iter.ReadFloat(&outfloat));
[email protected]b1f61b032012-11-28 15:40:5888 EXPECT_EQ(testfloat, outfloat);
89
[email protected]915cc7d2014-07-14 22:50:3290 double outdouble;
avi48fc13b2014-12-28 23:31:4891 EXPECT_TRUE(iter.ReadDouble(&outdouble));
[email protected]915cc7d2014-07-14 22:50:3292 EXPECT_EQ(testdouble, outdouble);
93
pkasting89a19f142014-10-02 03:01:0494 std::string outstring;
avi48fc13b2014-12-28 23:31:4895 EXPECT_TRUE(iter.ReadString(&outstring));
pkasting89a19f142014-10-02 03:01:0496 EXPECT_EQ(teststring, outstring);
97
Will Harris3542dc42025-01-30 22:13:3598 std::string outstring2;
99 EXPECT_TRUE(iter.ReadString(&outstring2));
100 EXPECT_EQ(testemptystring, outstring2);
101
Jan Wilken Dörrie085b2aa2021-03-12 16:26:57102 std::u16string outstring16;
avi48fc13b2014-12-28 23:31:48103 EXPECT_TRUE(iter.ReadString16(&outstring16));
pkasting89a19f142014-10-02 03:01:04104 EXPECT_EQ(teststring16, outstring16);
105
Helmut Januschka1dce9dc2024-06-11 13:05:35106 std::string_view outstringpiece;
brucedawsoneaa38962015-03-10 01:46:50107 EXPECT_TRUE(iter.ReadStringPiece(&outstringpiece));
108 EXPECT_EQ(testrawstring, outstringpiece);
109
Helmut Januschka1dce9dc2024-06-11 13:05:35110 std::u16string_view outstringpiece16;
brucedawsoneaa38962015-03-10 01:46:50111 EXPECT_TRUE(iter.ReadStringPiece16(&outstringpiece16));
112 EXPECT_EQ(testrawstring16, outstringpiece16);
113
initial.commitd7cae122008-07-26 21:49:38114 const char* outdata;
Peter Kasting28b51cf2022-06-28 15:02:43115 size_t outdatalen;
avi48fc13b2014-12-28 23:31:48116 EXPECT_TRUE(iter.ReadData(&outdata, &outdatalen));
initial.commitd7cae122008-07-26 21:49:38117 EXPECT_EQ(testdatalen, outdatalen);
118 EXPECT_EQ(memcmp(testdata, outdata, outdatalen), 0);
119
initial.commitd7cae122008-07-26 21:49:38120 // reads past the end should fail
avi48fc13b2014-12-28 23:31:48121 EXPECT_FALSE(iter.ReadInt(&outint));
initial.commitd7cae122008-07-26 21:49:38122}
123
124} // namespace
125
Avi Drissman516e1922024-03-21 18:11:28126TEST(PickleTest, UnownedVsOwned) {
127 const uint8_t buffer[1] = {0x00};
128
129 Pickle unowned_pickle = Pickle::WithUnownedBuffer(buffer);
130 EXPECT_EQ(unowned_pickle.GetTotalAllocatedSize(), 0u);
131
132 Pickle owned_pickle = Pickle::WithData(buffer);
133 EXPECT_GE(unowned_pickle.GetTotalAllocatedSize(), 0u);
134}
135
initial.commitd7cae122008-07-26 21:49:38136TEST(PickleTest, EncodeDecode) {
137 Pickle pickle;
138
Daniel Cheng0d89f9222017-09-22 05:05:07139 pickle.WriteBool(testbool1);
140 pickle.WriteBool(testbool2);
141 pickle.WriteInt(testint);
142 pickle.WriteLong(testlong);
143 pickle.WriteUInt16(testuint16);
144 pickle.WriteUInt32(testuint32);
145 pickle.WriteInt64(testint64);
146 pickle.WriteUInt64(testuint64);
147 pickle.WriteFloat(testfloat);
148 pickle.WriteDouble(testdouble);
149 pickle.WriteString(teststring);
Will Harris3542dc42025-01-30 22:13:35150 pickle.WriteString(testemptystring);
Daniel Cheng0d89f9222017-09-22 05:05:07151 pickle.WriteString16(teststring16);
152 pickle.WriteString(testrawstring);
153 pickle.WriteString16(testrawstring16);
Austin Sullivan31fcd06b2024-01-10 22:18:29154 pickle.WriteData(std::string_view(testdata, testdatalen));
initial.commitd7cae122008-07-26 21:49:38155 VerifyResult(pickle);
156
157 // test copy constructor
158 Pickle pickle2(pickle);
159 VerifyResult(pickle2);
160
161 // test operator=
162 Pickle pickle3;
163 pickle3 = pickle;
164 VerifyResult(pickle3);
165}
166
jam03d8a782016-02-10 20:13:39167// Tests that reading/writing a long works correctly when the source process
pkasting89a19f142014-10-02 03:01:04168// is 64-bit. We rely on having both 32- and 64-bit trybots to validate both
169// arms of the conditional in this test.
jam03d8a782016-02-10 20:13:39170TEST(PickleTest, LongFrom64Bit) {
pkasting89a19f142014-10-02 03:01:04171 Pickle pickle;
jam03d8a782016-02-10 20:13:39172 // Under the hood long is always written as a 64-bit value, so simulate a
173 // 64-bit long even on 32-bit architectures by explicitly writing an int64_t.
Daniel Cheng0d89f9222017-09-22 05:05:07174 pickle.WriteInt64(testint64);
pkasting89a19f142014-10-02 03:01:04175
176 PickleIterator iter(pickle);
jam03d8a782016-02-10 20:13:39177 long outlong;
178 if (sizeof(long) < sizeof(int64_t)) {
179 // ReadLong() should return false when the original written value can't be
180 // represented as a long.
Maksim Ivanov88edf972022-10-21 17:58:16181 EXPECT_FALSE(iter.ReadLong(&outlong));
pkasting89a19f142014-10-02 03:01:04182 } else {
jam03d8a782016-02-10 20:13:39183 EXPECT_TRUE(iter.ReadLong(&outlong));
184 EXPECT_EQ(testint64, outlong);
pkasting89a19f142014-10-02 03:01:04185 }
186}
187
[email protected]d87f8e6f2010-11-15 19:31:23188// Tests that we can handle really small buffers.
189TEST(PickleTest, SmallBuffer) {
Avi Drissman516e1922024-03-21 18:11:28190 const uint8_t buffer[] = {0x00};
[email protected]d87f8e6f2010-11-15 19:31:23191
192 // We should not touch the buffer.
Avi Drissman516e1922024-03-21 18:11:28193 Pickle pickle = Pickle::WithUnownedBuffer(buffer);
[email protected]d87f8e6f2010-11-15 19:31:23194
[email protected]ce208f872012-03-07 20:42:56195 PickleIterator iter(pickle);
[email protected]d87f8e6f2010-11-15 19:31:23196 int data;
avi48fc13b2014-12-28 23:31:48197 EXPECT_FALSE(iter.ReadInt(&data));
[email protected]d87f8e6f2010-11-15 19:31:23198}
199
200// Tests that we can handle improper headers.
201TEST(PickleTest, BigSize) {
Avi Drissman516e1922024-03-21 18:11:28202 const int buffer[4] = {0x56035200, 25, 40, 50};
[email protected]d87f8e6f2010-11-15 19:31:23203
Avi Drissman516e1922024-03-21 18:11:28204 Pickle pickle = Pickle::WithUnownedBuffer(as_byte_span(buffer));
David Sanders42527592021-06-16 07:20:38205 EXPECT_EQ(0U, pickle.size());
[email protected]d87f8e6f2010-11-15 19:31:23206
[email protected]ce208f872012-03-07 20:42:56207 PickleIterator iter(pickle);
[email protected]d87f8e6f2010-11-15 19:31:23208 int data;
avi48fc13b2014-12-28 23:31:48209 EXPECT_FALSE(iter.ReadInt(&data));
[email protected]d87f8e6f2010-11-15 19:31:23210}
211
Nick Diego Yamane7676c802022-01-19 19:02:51212// Tests that instances constructed with invalid parameter combinations can be
213// properly copied. Regression test for https://crbug.com/1271311.
214TEST(PickleTest, CopyWithInvalidHeader) {
215 // 1. Actual header size (calculated based on the input buffer) > passed in
216 // buffer size. Which results in Pickle's internal |header_| = null.
217 {
218 Pickle::Header header = {.payload_size = 100};
Avi Drissman516e1922024-03-21 18:11:28219 const Pickle pickle = Pickle::WithUnownedBuffer(byte_span_from_ref(header));
Nick Diego Yamane7676c802022-01-19 19:02:51220
221 EXPECT_EQ(0U, pickle.size());
222 EXPECT_FALSE(pickle.data());
223
224 Pickle copy_built_with_op = pickle;
225 EXPECT_EQ(0U, copy_built_with_op.size());
226 EXPECT_FALSE(copy_built_with_op.data());
227
228 Pickle copy_built_with_ctor(pickle);
229 EXPECT_EQ(0U, copy_built_with_ctor.size());
230 EXPECT_FALSE(copy_built_with_ctor.data());
231 }
232 // 2. Input buffer's size < sizeof(Pickle::Header). Which must also result in
233 // Pickle's internal |header_| = null.
234 {
Avi Drissman516e1922024-03-21 18:11:28235 const uint8_t data[] = {0x00, 0x00};
236 const Pickle pickle = Pickle::WithUnownedBuffer(data);
Nick Diego Yamane7676c802022-01-19 19:02:51237 static_assert(sizeof(Pickle::Header) > sizeof(data));
238
239 EXPECT_EQ(0U, pickle.size());
240 EXPECT_FALSE(pickle.data());
241
242 Pickle copy_built_with_op = pickle;
243 EXPECT_EQ(0U, copy_built_with_op.size());
244 EXPECT_FALSE(copy_built_with_op.data());
245
246 Pickle copy_built_with_ctor(pickle);
247 EXPECT_EQ(0U, copy_built_with_ctor.size());
248 EXPECT_FALSE(copy_built_with_ctor.data());
249 }
250}
251
[email protected]d87f8e6f2010-11-15 19:31:23252TEST(PickleTest, UnalignedSize) {
Peter Kasting134ef9af2024-12-28 02:30:09253 int buffer[] = {10, 25, 40, 50};
[email protected]d87f8e6f2010-11-15 19:31:23254
Avi Drissman516e1922024-03-21 18:11:28255 Pickle pickle = Pickle::WithUnownedBuffer(as_byte_span(buffer));
[email protected]d87f8e6f2010-11-15 19:31:23256
[email protected]ce208f872012-03-07 20:42:56257 PickleIterator iter(pickle);
[email protected]d87f8e6f2010-11-15 19:31:23258 int data;
avi48fc13b2014-12-28 23:31:48259 EXPECT_FALSE(iter.ReadInt(&data));
[email protected]d87f8e6f2010-11-15 19:31:23260}
261
initial.commitd7cae122008-07-26 21:49:38262TEST(PickleTest, ZeroLenStr) {
263 Pickle pickle;
Daniel Cheng0d89f9222017-09-22 05:05:07264 pickle.WriteString(std::string());
initial.commitd7cae122008-07-26 21:49:38265
[email protected]ce208f872012-03-07 20:42:56266 PickleIterator iter(pickle);
initial.commitd7cae122008-07-26 21:49:38267 std::string outstr;
avi48fc13b2014-12-28 23:31:48268 EXPECT_TRUE(iter.ReadString(&outstr));
initial.commitd7cae122008-07-26 21:49:38269 EXPECT_EQ("", outstr);
270}
271
thestigf84f17f2015-03-11 20:41:55272TEST(PickleTest, ZeroLenStr16) {
initial.commitd7cae122008-07-26 21:49:38273 Pickle pickle;
Jan Wilken Dörrie085b2aa2021-03-12 16:26:57274 pickle.WriteString16(std::u16string());
initial.commitd7cae122008-07-26 21:49:38275
[email protected]ce208f872012-03-07 20:42:56276 PickleIterator iter(pickle);
initial.commitd7cae122008-07-26 21:49:38277 std::string outstr;
avi48fc13b2014-12-28 23:31:48278 EXPECT_TRUE(iter.ReadString(&outstr));
initial.commitd7cae122008-07-26 21:49:38279 EXPECT_EQ("", outstr);
280}
281
282TEST(PickleTest, BadLenStr) {
283 Pickle pickle;
Daniel Cheng0d89f9222017-09-22 05:05:07284 pickle.WriteInt(-2);
initial.commitd7cae122008-07-26 21:49:38285
[email protected]ce208f872012-03-07 20:42:56286 PickleIterator iter(pickle);
initial.commitd7cae122008-07-26 21:49:38287 std::string outstr;
avi48fc13b2014-12-28 23:31:48288 EXPECT_FALSE(iter.ReadString(&outstr));
initial.commitd7cae122008-07-26 21:49:38289}
290
thestigf84f17f2015-03-11 20:41:55291TEST(PickleTest, BadLenStr16) {
initial.commitd7cae122008-07-26 21:49:38292 Pickle pickle;
Daniel Cheng0d89f9222017-09-22 05:05:07293 pickle.WriteInt(-1);
initial.commitd7cae122008-07-26 21:49:38294
[email protected]ce208f872012-03-07 20:42:56295 PickleIterator iter(pickle);
Jan Wilken Dörrie085b2aa2021-03-12 16:26:57296 std::u16string outstr;
thestigf84f17f2015-03-11 20:41:55297 EXPECT_FALSE(iter.ReadString16(&outstr));
initial.commitd7cae122008-07-26 21:49:38298}
299
dskiba6f3790a2015-09-30 17:24:30300TEST(PickleTest, PeekNext) {
301 struct CustomHeader : base::Pickle::Header {
302 int cookies[10];
303 };
304
305 Pickle pickle(sizeof(CustomHeader));
306
Daniel Cheng0d89f9222017-09-22 05:05:07307 pickle.WriteString("Goooooooooooogle");
dskiba6f3790a2015-09-30 17:24:30308
Claudio DeSouzac537f85d2023-03-02 18:42:52309 const char* pickle_data = pickle.data_as_char();
dskiba6f3790a2015-09-30 17:24:30310
311 size_t pickle_size;
312
313 // Data range doesn't contain header
Peter Kasting134ef9af2024-12-28 02:30:09314 EXPECT_FALSE(Pickle::PeekNext(sizeof(CustomHeader), pickle_data,
315 pickle_data + sizeof(CustomHeader) - 1,
316 &pickle_size));
dskiba6f3790a2015-09-30 17:24:30317
318 // Data range contains header
Peter Kasting134ef9af2024-12-28 02:30:09319 EXPECT_TRUE(Pickle::PeekNext(sizeof(CustomHeader), pickle_data,
320 pickle_data + sizeof(CustomHeader),
321 &pickle_size));
dskiba6f3790a2015-09-30 17:24:30322 EXPECT_EQ(pickle_size, pickle.size());
323
324 // Data range contains header and some other data
Peter Kasting134ef9af2024-12-28 02:30:09325 EXPECT_TRUE(Pickle::PeekNext(sizeof(CustomHeader), pickle_data,
326 pickle_data + sizeof(CustomHeader) + 1,
327 &pickle_size));
dskiba6f3790a2015-09-30 17:24:30328 EXPECT_EQ(pickle_size, pickle.size());
329
330 // Data range contains full pickle
Peter Kasting134ef9af2024-12-28 02:30:09331 EXPECT_TRUE(Pickle::PeekNext(sizeof(CustomHeader), pickle_data,
332 pickle_data + pickle.size(), &pickle_size));
dskiba6f3790a2015-09-30 17:24:30333 EXPECT_EQ(pickle_size, pickle.size());
334}
335
336TEST(PickleTest, PeekNextOverflow) {
337 struct CustomHeader : base::Pickle::Header {
338 int cookies[10];
339 };
340
341 CustomHeader header;
342
343 // Check if we can wrap around at all
Peter Kasting134ef9af2024-12-28 02:30:09344 if (sizeof(size_t) > sizeof(header.payload_size)) {
dskiba6f3790a2015-09-30 17:24:30345 return;
Peter Kasting134ef9af2024-12-28 02:30:09346 }
dskiba6f3790a2015-09-30 17:24:30347
348 const char* pickle_data = reinterpret_cast<const char*>(&header);
349
350 size_t pickle_size;
351
352 // Wrapping around is detected and reported as maximum size_t value
Peter Kasting134ef9af2024-12-28 02:30:09353 header.payload_size =
354 static_cast<uint32_t>(1 - static_cast<int32_t>(sizeof(CustomHeader)));
355 EXPECT_TRUE(Pickle::PeekNext(sizeof(CustomHeader), pickle_data,
356 pickle_data + sizeof(CustomHeader),
357 &pickle_size));
dskiba6f3790a2015-09-30 17:24:30358 EXPECT_EQ(pickle_size, std::numeric_limits<size_t>::max());
359
360 // Ridiculous pickle sizes are fine (callers are supposed to
361 // verify them)
362 header.payload_size =
363 std::numeric_limits<uint32_t>::max() / 2 - sizeof(CustomHeader);
Peter Kasting134ef9af2024-12-28 02:30:09364 EXPECT_TRUE(Pickle::PeekNext(sizeof(CustomHeader), pickle_data,
365 pickle_data + sizeof(CustomHeader),
366 &pickle_size));
dskiba6f3790a2015-09-30 17:24:30367 EXPECT_EQ(pickle_size, std::numeric_limits<uint32_t>::max() / 2);
368}
369
initial.commitd7cae122008-07-26 21:49:38370TEST(PickleTest, FindNext) {
371 Pickle pickle;
Daniel Cheng0d89f9222017-09-22 05:05:07372 pickle.WriteInt(1);
373 pickle.WriteString("Domo");
initial.commitd7cae122008-07-26 21:49:38374
375 const char* start = reinterpret_cast<const char*>(pickle.data());
376 const char* end = start + pickle.size();
377
Ivan Kotenkova16212a52017-11-08 12:37:33378 EXPECT_EQ(end, Pickle::FindNext(pickle.header_size_, start, end));
379 EXPECT_EQ(nullptr, Pickle::FindNext(pickle.header_size_, start, end - 1));
380 EXPECT_EQ(end, Pickle::FindNext(pickle.header_size_, start, end + 1));
initial.commitd7cae122008-07-26 21:49:38381}
382
[email protected]137d2372011-01-26 13:02:27383TEST(PickleTest, FindNextWithIncompleteHeader) {
384 size_t header_size = sizeof(Pickle::Header);
HuanPo Lin27731ca2024-04-16 14:57:30385 auto buffer = base::HeapArray<char>::Uninit(header_size - 1);
386 memset(buffer.data(), 0x1, header_size - 1);
[email protected]137d2372011-01-26 13:02:27387
HuanPo Lin27731ca2024-04-16 14:57:30388 const char* start = buffer.data();
[email protected]137d2372011-01-26 13:02:27389 const char* end = start + header_size - 1;
390
Ivan Kotenkova16212a52017-11-08 12:37:33391 EXPECT_EQ(nullptr, Pickle::FindNext(header_size, start, end));
[email protected]137d2372011-01-26 13:02:27392}
393
[email protected]9dbfa9842013-11-01 09:43:45394#if defined(COMPILER_MSVC)
395#pragma warning(push)
Peter Kasting134ef9af2024-12-28 02:30:09396#pragma warning(disable : 4146)
[email protected]9dbfa9842013-11-01 09:43:45397#endif
[email protected]33a38dd2013-11-01 09:06:26398TEST(PickleTest, FindNextOverflow) {
399 size_t header_size = sizeof(Pickle::Header);
400 size_t header_size2 = 2 * header_size;
401 size_t payload_received = 100;
HuanPo Lin27731ca2024-04-16 14:57:30402 auto buffer = base::HeapArray<char>::Uninit(header_size2 + payload_received);
403 const char* start = buffer.data();
404 Pickle::Header* header = reinterpret_cast<Pickle::Header*>(buffer.data());
[email protected]33a38dd2013-11-01 09:06:26405 const char* end = start + header_size2 + payload_received;
406 // It is impossible to construct an overflow test otherwise.
407 if (sizeof(size_t) > sizeof(header->payload_size) ||
Peter Kasting134ef9af2024-12-28 02:30:09408 sizeof(uintptr_t) > sizeof(header->payload_size)) {
[email protected]33a38dd2013-11-01 09:06:26409 return;
Peter Kasting134ef9af2024-12-28 02:30:09410 }
[email protected]33a38dd2013-11-01 09:06:26411
412 header->payload_size = -(reinterpret_cast<uintptr_t>(start) + header_size2);
Ivan Kotenkova16212a52017-11-08 12:37:33413 EXPECT_EQ(nullptr, Pickle::FindNext(header_size2, start, end));
[email protected]33a38dd2013-11-01 09:06:26414
415 header->payload_size = -header_size2;
Ivan Kotenkova16212a52017-11-08 12:37:33416 EXPECT_EQ(nullptr, Pickle::FindNext(header_size2, start, end));
[email protected]33a38dd2013-11-01 09:06:26417
418 header->payload_size = 0;
419 end = start + header_size;
Ivan Kotenkova16212a52017-11-08 12:37:33420 EXPECT_EQ(nullptr, Pickle::FindNext(header_size2, start, end));
[email protected]33a38dd2013-11-01 09:06:26421}
[email protected]9dbfa9842013-11-01 09:43:45422#if defined(COMPILER_MSVC)
423#pragma warning(pop)
424#endif
[email protected]33a38dd2013-11-01 09:06:26425
[email protected]ce208f872012-03-07 20:42:56426TEST(PickleTest, GetReadPointerAndAdvance) {
initial.commitd7cae122008-07-26 21:49:38427 Pickle pickle;
[email protected]ce208f872012-03-07 20:42:56428
429 PickleIterator iter(pickle);
430 EXPECT_FALSE(iter.GetReadPointerAndAdvance(1));
431
Daniel Cheng0d89f9222017-09-22 05:05:07432 pickle.WriteInt(1);
433 pickle.WriteInt(2);
[email protected]ce208f872012-03-07 20:42:56434 int bytes = sizeof(int) * 2;
initial.commitd7cae122008-07-26 21:49:38435
[email protected]ce208f872012-03-07 20:42:56436 EXPECT_TRUE(PickleIterator(pickle).GetReadPointerAndAdvance(0));
437 EXPECT_TRUE(PickleIterator(pickle).GetReadPointerAndAdvance(1));
438 EXPECT_FALSE(PickleIterator(pickle).GetReadPointerAndAdvance(-1));
439 EXPECT_TRUE(PickleIterator(pickle).GetReadPointerAndAdvance(bytes));
440 EXPECT_FALSE(PickleIterator(pickle).GetReadPointerAndAdvance(bytes + 1));
441 EXPECT_FALSE(PickleIterator(pickle).GetReadPointerAndAdvance(INT_MAX));
442 EXPECT_FALSE(PickleIterator(pickle).GetReadPointerAndAdvance(INT_MIN));
initial.commitd7cae122008-07-26 21:49:38443}
444
445TEST(PickleTest, Resize) {
[email protected]44a1cbfa2008-08-15 01:05:11446 size_t unit = Pickle::kPayloadUnit;
HuanPo Lin27731ca2024-04-16 14:57:30447 auto data = base::HeapArray<char>::Uninit(unit);
448 char* data_ptr = data.data();
Peter Kasting134ef9af2024-12-28 02:30:09449 for (size_t i = 0; i < unit; i++) {
initial.commitd7cae122008-07-26 21:49:38450 data_ptr[i] = 'G';
Peter Kasting134ef9af2024-12-28 02:30:09451 }
initial.commitd7cae122008-07-26 21:49:38452
453 // construct a message that will be exactly the size of one payload unit,
454 // note that any data will have a 4-byte header indicating the size
avi9b6f42932015-12-26 22:15:14455 const size_t payload_size_after_header = unit - sizeof(uint32_t);
initial.commitd7cae122008-07-26 21:49:38456 Pickle pickle;
Austin Sullivan31fcd06b2024-01-10 22:18:29457 pickle.WriteData(
458 std::string_view(data_ptr, payload_size_after_header - sizeof(uint32_t)));
[email protected]44a1cbfa2008-08-15 01:05:11459 size_t cur_payload = payload_size_after_header;
initial.commitd7cae122008-07-26 21:49:38460
[email protected]2de46262009-03-16 20:21:57461 // note: we assume 'unit' is a power of 2
[email protected]d1b319fc2013-10-31 04:03:02462 EXPECT_EQ(unit, pickle.capacity_after_header());
initial.commitd7cae122008-07-26 21:49:38463 EXPECT_EQ(pickle.payload_size(), payload_size_after_header);
464
465 // fill out a full page (noting data header)
Austin Sullivan31fcd06b2024-01-10 22:18:29466 pickle.WriteData(std::string_view(data_ptr, unit - sizeof(uint32_t)));
initial.commitd7cae122008-07-26 21:49:38467 cur_payload += unit;
[email protected]d1b319fc2013-10-31 04:03:02468 EXPECT_EQ(unit * 2, pickle.capacity_after_header());
initial.commitd7cae122008-07-26 21:49:38469 EXPECT_EQ(cur_payload, pickle.payload_size());
470
[email protected]2de46262009-03-16 20:21:57471 // one more byte should double the capacity
Austin Sullivan31fcd06b2024-01-10 22:18:29472 pickle.WriteData(std::string_view(data_ptr, 1u));
[email protected]a15016f2014-06-02 23:23:49473 cur_payload += 8;
[email protected]d1b319fc2013-10-31 04:03:02474 EXPECT_EQ(unit * 4, pickle.capacity_after_header());
initial.commitd7cae122008-07-26 21:49:38475 EXPECT_EQ(cur_payload, pickle.payload_size());
476}
477
[email protected]d26cd5272008-08-07 13:40:16478namespace {
initial.commitd7cae122008-07-26 21:49:38479
[email protected]d26cd5272008-08-07 13:40:16480struct CustomHeader : Pickle::Header {
481 int blah;
482};
483
484} // namespace
485
486TEST(PickleTest, HeaderPadding) {
avi9b6f42932015-12-26 22:15:14487 const uint32_t kMagic = 0x12345678;
initial.commitd7cae122008-07-26 21:49:38488
489 Pickle pickle(sizeof(CustomHeader));
490 pickle.WriteInt(kMagic);
491
492 // this should not overwrite the 'int' payload
493 pickle.headerT<CustomHeader>()->blah = 10;
494
[email protected]ce208f872012-03-07 20:42:56495 PickleIterator iter(pickle);
initial.commitd7cae122008-07-26 21:49:38496 int result;
avi48fc13b2014-12-28 23:31:48497 ASSERT_TRUE(iter.ReadInt(&result));
initial.commitd7cae122008-07-26 21:49:38498
avi9b6f42932015-12-26 22:15:14499 EXPECT_EQ(static_cast<uint32_t>(result), kMagic);
initial.commitd7cae122008-07-26 21:49:38500}
501
502TEST(PickleTest, EqualsOperator) {
503 Pickle source;
504 source.WriteInt(1);
505
Avi Drissman516e1922024-03-21 18:11:28506 Pickle copy_refs_source_buffer = Pickle::WithUnownedBuffer(source);
initial.commitd7cae122008-07-26 21:49:38507 Pickle copy;
508 copy = copy_refs_source_buffer;
509 ASSERT_EQ(source.size(), copy.size());
[email protected]d26cd5272008-08-07 13:40:16510}
[email protected]87665562009-06-25 16:54:02511
512TEST(PickleTest, EvilLengths) {
513 Pickle source;
[email protected]b235357d2009-06-25 17:23:49514 std::string str(100000, 'A');
Austin Sullivan31fcd06b2024-01-10 22:18:29515 source.WriteData(std::string_view(str.c_str(), 100000u));
[email protected]87665562009-06-25 16:54:02516 // ReadString16 used to have its read buffer length calculation wrong leading
517 // to out-of-bounds reading.
[email protected]ce208f872012-03-07 20:42:56518 PickleIterator iter(source);
Jan Wilken Dörrie085b2aa2021-03-12 16:26:57519 std::u16string str16;
avi48fc13b2014-12-28 23:31:48520 EXPECT_FALSE(iter.ReadString16(&str16));
[email protected]87665562009-06-25 16:54:02521
522 // And check we didn't break ReadString16.
Avi Drissman516e1922024-03-21 18:11:28523 str16 = u"A";
[email protected]87665562009-06-25 16:54:02524 Pickle str16_pickle;
Daniel Cheng0d89f9222017-09-22 05:05:07525 str16_pickle.WriteString16(str16);
[email protected]ce208f872012-03-07 20:42:56526 iter = PickleIterator(str16_pickle);
avi48fc13b2014-12-28 23:31:48527 EXPECT_TRUE(iter.ReadString16(&str16));
[email protected]87665562009-06-25 16:54:02528 EXPECT_EQ(1U, str16.length());
529
[email protected]ce208f872012-03-07 20:42:56530 // Check we don't fail in a length check with invalid String16 size.
Jan Wilken Dörrie677e0c872021-03-10 10:04:38531 // (1<<31) * sizeof(char16_t) == 0, so this is particularly evil.
[email protected]ce208f872012-03-07 20:42:56532 Pickle bad_len;
Daniel Cheng0d89f9222017-09-22 05:05:07533 bad_len.WriteInt(1 << 31);
[email protected]ce208f872012-03-07 20:42:56534 iter = PickleIterator(bad_len);
avi48fc13b2014-12-28 23:31:48535 EXPECT_FALSE(iter.ReadString16(&str16));
[email protected]87665562009-06-25 16:54:02536}
537
[email protected]e64ff5e2009-07-28 21:00:03538// Check we can write zero bytes of data and 'data' can be NULL.
539TEST(PickleTest, ZeroLength) {
540 Pickle pickle;
Austin Sullivan31fcd06b2024-01-10 22:18:29541 pickle.WriteData(std::string_view());
[email protected]e64ff5e2009-07-28 21:00:03542
[email protected]ce208f872012-03-07 20:42:56543 PickleIterator iter(pickle);
[email protected]e64ff5e2009-07-28 21:00:03544 const char* outdata;
Peter Kasting28b51cf2022-06-28 15:02:43545 size_t outdatalen;
avi48fc13b2014-12-28 23:31:48546 EXPECT_TRUE(iter.ReadData(&outdata, &outdatalen));
Peter Kasting28b51cf2022-06-28 15:02:43547 EXPECT_EQ(0u, outdatalen);
[email protected]e64ff5e2009-07-28 21:00:03548 // We can't assert that outdata is NULL.
549}
550
[email protected]26d2f472010-03-30 23:52:24551// Check that ReadBytes works properly with an iterator initialized to NULL.
552TEST(PickleTest, ReadBytes) {
553 Pickle pickle;
554 int data = 0x7abcd;
Daniel Cheng0d89f9222017-09-22 05:05:07555 pickle.WriteBytes(&data, sizeof(data));
[email protected]26d2f472010-03-30 23:52:24556
[email protected]ce208f872012-03-07 20:42:56557 PickleIterator iter(pickle);
Ivan Kotenkova16212a52017-11-08 12:37:33558 const char* outdata_char = nullptr;
avi48fc13b2014-12-28 23:31:48559 EXPECT_TRUE(iter.ReadBytes(&outdata_char, sizeof(data)));
[email protected]26d2f472010-03-30 23:52:24560
561 int outdata;
562 memcpy(&outdata, outdata_char, sizeof(outdata));
563 EXPECT_EQ(data, outdata);
564}
brettw05cfd8ddb2015-06-02 07:02:47565
erikchenf9ca8f5f02015-09-08 23:36:29566// Checks that when a pickle is deep-copied, the result is not larger than
567// needed.
568TEST(PickleTest, DeepCopyResize) {
569 Pickle pickle;
Peter Kasting134ef9af2024-12-28 02:30:09570 while (pickle.capacity_after_header() != pickle.payload_size()) {
erikchenf9ca8f5f02015-09-08 23:36:29571 pickle.WriteBool(true);
Peter Kasting134ef9af2024-12-28 02:30:09572 }
erikchenf9ca8f5f02015-09-08 23:36:29573
574 // Make a deep copy.
575 Pickle pickle2(pickle);
576
577 // Check that there isn't any extraneous capacity.
578 EXPECT_EQ(pickle.capacity_after_header(), pickle2.capacity_after_header());
579}
580
rockot0776a502015-12-17 06:19:49581namespace {
582
583// Publicly exposes the ClaimBytes interface for testing.
584class TestingPickle : public Pickle {
585 public:
Chris Watkinsbb7211c2017-11-29 07:16:38586 TestingPickle() = default;
rockot0776a502015-12-17 06:19:49587
588 void* ClaimBytes(size_t num_bytes) { return Pickle::ClaimBytes(num_bytes); }
589};
590
591} // namespace
592
593// Checks that claimed bytes are zero-initialized.
594TEST(PickleTest, ClaimBytesInitialization) {
595 static const int kChunkSize = 64;
596 TestingPickle pickle;
597 const char* bytes = static_cast<const char*>(pickle.ClaimBytes(kChunkSize));
598 for (size_t i = 0; i < kChunkSize; ++i) {
599 EXPECT_EQ(0, bytes[i]);
600 }
601}
602
603// Checks that ClaimBytes properly advances the write offset.
604TEST(PickleTest, ClaimBytes) {
605 std::string data("Hello, world!");
606
607 TestingPickle pickle;
jam03d8a782016-02-10 20:13:39608 pickle.WriteUInt32(data.size());
rockot0776a502015-12-17 06:19:49609 void* bytes = pickle.ClaimBytes(data.size());
610 pickle.WriteInt(42);
611 memcpy(bytes, data.data(), data.size());
612
613 PickleIterator iter(pickle);
jam03d8a782016-02-10 20:13:39614 uint32_t out_data_length;
615 EXPECT_TRUE(iter.ReadUInt32(&out_data_length));
rockot0776a502015-12-17 06:19:49616 EXPECT_EQ(data.size(), out_data_length);
617
618 const char* out_data = nullptr;
619 EXPECT_TRUE(iter.ReadBytes(&out_data, out_data_length));
620 EXPECT_EQ(data, std::string(out_data, out_data_length));
621
622 int out_value;
623 EXPECT_TRUE(iter.ReadInt(&out_value));
624 EXPECT_EQ(42, out_value);
625}
626
Daniel Chengea877be2020-03-06 22:56:31627TEST(PickleTest, ReachedEnd) {
628 Pickle pickle;
629 pickle.WriteInt(1);
630 pickle.WriteInt(2);
631 pickle.WriteInt(3);
632
633 PickleIterator iter(pickle);
634 int out;
635
636 EXPECT_FALSE(iter.ReachedEnd());
637 EXPECT_TRUE(iter.ReadInt(&out));
638 EXPECT_EQ(1, out);
639
640 EXPECT_FALSE(iter.ReachedEnd());
641 EXPECT_TRUE(iter.ReadInt(&out));
642 EXPECT_EQ(2, out);
643
644 EXPECT_FALSE(iter.ReachedEnd());
645 EXPECT_TRUE(iter.ReadInt(&out));
646 EXPECT_EQ(3, out);
647
648 EXPECT_TRUE(iter.ReachedEnd());
649 EXPECT_FALSE(iter.ReadInt(&out));
650 EXPECT_TRUE(iter.ReachedEnd());
651}
652
David Benjamin5746c532023-10-25 15:16:10653// Test that reading a value other than 0 or 1 as a bool does not trigger
654// UBSan.
655TEST(PickleTest, NonCanonicalBool) {
656 Pickle pickle;
657 pickle.WriteInt(0xff);
658
659 PickleIterator iter(pickle);
660 bool b;
661 ASSERT_TRUE(iter.ReadBool(&b));
662 EXPECT_TRUE(b);
663}
664
Matt Menke4e486db2025-04-07 13:51:43665// Tests the ReadData() overload that returns a span.
666TEST(PickleTest, ReadDataAsSpan) {
667 constexpr auto kWriteData =
668 std::to_array<uint8_t>({0x01, 0x02, 0x03, 0x61, 0x62, 0x63});
669
670 Pickle pickle;
671 pickle.WriteData(kWriteData);
672 pickle.WriteData(base::span<const uint8_t>());
673
674 PickleIterator iter(pickle);
675 EXPECT_THAT(iter.ReadData(), testing::Optional(kWriteData));
676 EXPECT_THAT(iter.ReadData(), testing::Optional(base::span<const uint8_t>()));
677 EXPECT_FALSE(iter.ReadData());
678}
679
680// Tests the ReadBytes() overload that returns a span.
681TEST(PickleTest, ReadBytesAsSpan) {
682 constexpr auto kWriteData =
683 std::to_array<uint8_t>({0x01, 0x02, 0x03, 0x61, 0x62, 0x63});
684
685 Pickle pickle;
686 pickle.WriteBytes(kWriteData);
687
688 PickleIterator iter(pickle);
689 EXPECT_THAT(iter.ReadBytes(kWriteData.size()), testing::Optional(kWriteData));
690 EXPECT_FALSE(iter.ReadBytes(kWriteData.size()));
691}
692
brettw05cfd8ddb2015-06-02 07:02:47693} // namespace base