1 /*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "perfetto/protozero/proto_decoder.h"
18
19 #include "perfetto/ext/base/utils.h"
20 #include "perfetto/protozero/message.h"
21 #include "perfetto/protozero/proto_utils.h"
22 #include "perfetto/protozero/scattered_heap_buffer.h"
23 #include "perfetto/protozero/static_buffer.h"
24 #include "test/gtest_and_gmock.h"
25
26 #include "src/protozero/test/example_proto/test_messages.pb.h"
27 #include "src/protozero/test/example_proto/test_messages.pbzero.h"
28
29 // Generated by the protozero plugin.
30 namespace pbtest = protozero::test::protos::pbzero;
31
32 // Generated by the official protobuf compiler.
33 namespace pbgold = protozero::test::protos;
34
35 namespace protozero {
36 namespace {
37
38 using ::testing::_;
39 using ::testing::InSequence;
40 using ::testing::Invoke;
41 using namespace proto_utils;
42
TEST(ProtoDecoderTest,ReadString)43 TEST(ProtoDecoderTest, ReadString) {
44 HeapBuffered<Message> message;
45
46 static constexpr char kTestString[] = "test";
47 message->AppendString(1, kTestString);
48 std::vector<uint8_t> proto = message.SerializeAsArray();
49 TypedProtoDecoder<32, false> decoder(proto.data(), proto.size());
50
51 const auto& field = decoder.Get(1);
52 ASSERT_EQ(field.type(), ProtoWireType::kLengthDelimited);
53 ASSERT_EQ(field.size(), sizeof(kTestString) - 1);
54 for (size_t i = 0; i < sizeof(kTestString) - 1; i++) {
55 ASSERT_EQ(field.data()[i], kTestString[i]);
56 }
57 }
58
TEST(ProtoDecoderTest,SkipVeryLargeFields)59 TEST(ProtoDecoderTest, SkipVeryLargeFields) {
60 const size_t kPayloadSize = 257 * 1024 * 1024;
61 const uint64_t data_size = 4096 + kPayloadSize;
62 std::unique_ptr<uint8_t, perfetto::base::FreeDeleter> data(
63 static_cast<uint8_t*>(malloc(data_size)));
64
65 StaticBufferDelegate delegate(data.get(), data_size);
66 ScatteredStreamWriter writer(&delegate);
67 Message message;
68 message.Reset(&writer);
69
70 // Append a valid field.
71 message.AppendVarInt(/*field_id=*/1, 11);
72
73 // Append a very large field that will be skipped.
74 uint8_t raw[10];
75 uint8_t* wptr = raw;
76 wptr = WriteVarInt(MakeTagLengthDelimited(2), wptr);
77 wptr = WriteVarInt(kPayloadSize, wptr);
78 message.AppendRawProtoBytes(raw, static_cast<size_t>(wptr - raw));
79 const uint8_t padding[1024 * 128]{};
80 for (size_t i = 0; i < kPayloadSize / sizeof(padding); i++)
81 message.AppendRawProtoBytes(padding, sizeof(padding));
82
83 // Append another valid field.
84 message.AppendVarInt(/*field_id=*/3, 13);
85
86 ProtoDecoder decoder(data.get(), static_cast<size_t>(writer.written()));
87 Field field = decoder.ReadField();
88 ASSERT_EQ(1u, field.id());
89 ASSERT_EQ(11, field.as_int32());
90
91 field = decoder.ReadField();
92 ASSERT_EQ(3u, field.id());
93 ASSERT_EQ(13, field.as_int32());
94
95 field = decoder.ReadField();
96 ASSERT_FALSE(field.valid());
97 }
98
TEST(ProtoDecoderTest,SingleRepeatedField)99 TEST(ProtoDecoderTest, SingleRepeatedField) {
100 Message message;
101 ScatteredHeapBuffer delegate(512, 512);
102 ScatteredStreamWriter writer(&delegate);
103 delegate.set_writer(&writer);
104 message.Reset(&writer);
105 message.AppendVarInt(/*field_id=*/2, 10);
106 delegate.AdjustUsedSizeOfCurrentSlice();
107 auto used_range = delegate.slices()[0].GetUsedRange();
108
109 TypedProtoDecoder<2, true> tpd(used_range.begin, used_range.size());
110 auto it = tpd.GetRepeated<int32_t>(/*field_id=*/2);
111 EXPECT_TRUE(it);
112 EXPECT_EQ(it.field().as_int32(), 10);
113 EXPECT_EQ(*it, 10);
114 EXPECT_FALSE(++it);
115 }
116
TEST(ProtoDecoderTest,RepeatedVariableLengthField)117 TEST(ProtoDecoderTest, RepeatedVariableLengthField) {
118 HeapBuffered<Message> message;
119
120 static constexpr char kTestString[] = "test";
121 static constexpr char kTestString2[] = "honk honk";
122 message->AppendString(1, kTestString);
123 message->AppendString(1, kTestString2);
124 std::vector<uint8_t> proto = message.SerializeAsArray();
125 TypedProtoDecoder<32, false> decoder(proto.data(), proto.size());
126
127 auto it = decoder.GetRepeated<ConstChars>(1);
128 ASSERT_EQ(it->type(), ProtoWireType::kLengthDelimited);
129 ASSERT_EQ(it->size(), sizeof(kTestString) - 1);
130 ASSERT_EQ(it->as_std_string(), std::string(kTestString));
131 ASSERT_EQ((*it).ToStdString(), std::string(kTestString));
132 ++it;
133 ASSERT_EQ(it->type(), ProtoWireType::kLengthDelimited);
134 ASSERT_EQ(it->size(), sizeof(kTestString2) - 1);
135 ASSERT_EQ(it->as_std_string(), std::string(kTestString2));
136 ASSERT_EQ((*it).ToStdString(), std::string(kTestString2));
137 }
138
TEST(ProtoDecoderTest,SingleRepeatedFieldWithExpansion)139 TEST(ProtoDecoderTest, SingleRepeatedFieldWithExpansion) {
140 Message message;
141 ScatteredHeapBuffer delegate(512, 512);
142 ScatteredStreamWriter writer(&delegate);
143 delegate.set_writer(&writer);
144 message.Reset(&writer);
145 for (int i = 0; i < 2000; i++) {
146 message.AppendVarInt(/*field_id=*/2, i);
147 }
148 std::vector<uint8_t> data = delegate.StitchSlices();
149
150 TypedProtoDecoder<2, true> tpd(data.data(), data.size());
151 auto it = tpd.GetRepeated<int32_t>(/*field_id=*/2);
152 for (int i = 0; i < 2000; i++) {
153 EXPECT_TRUE(it);
154 EXPECT_EQ(*it, i);
155 ++it;
156 }
157 EXPECT_FALSE(it);
158 }
159
TEST(ProtoDecoderTest,NoRepeatedField)160 TEST(ProtoDecoderTest, NoRepeatedField) {
161 uint8_t buf[] = {0x01};
162 TypedProtoDecoder<2, true> tpd(buf, 1);
163 auto it = tpd.GetRepeated<int32_t>(/*field_id=*/1);
164 EXPECT_FALSE(it);
165 EXPECT_FALSE(tpd.Get(2).valid());
166 }
167
TEST(ProtoDecoderTest,RepeatedFields)168 TEST(ProtoDecoderTest, RepeatedFields) {
169 Message message;
170 ScatteredHeapBuffer delegate(512, 512);
171 ScatteredStreamWriter writer(&delegate);
172 delegate.set_writer(&writer);
173 message.Reset(&writer);
174
175 message.AppendVarInt(1, 10);
176 message.AppendVarInt(2, 20);
177 message.AppendVarInt(3, 30);
178
179 message.AppendVarInt(1, 11);
180 message.AppendVarInt(2, 21);
181 message.AppendVarInt(2, 22);
182
183 delegate.AdjustUsedSizeOfCurrentSlice();
184 auto used_range = delegate.slices()[0].GetUsedRange();
185
186 // When iterating with the simple decoder we should just see fields in parsing
187 // order.
188 ProtoDecoder decoder(used_range.begin, used_range.size());
189 std::string fields_seen;
190 for (auto fld = decoder.ReadField(); fld.valid(); fld = decoder.ReadField()) {
191 fields_seen +=
192 std::to_string(fld.id()) + ":" + std::to_string(fld.as_int32()) + ";";
193 }
194 EXPECT_EQ(fields_seen, "1:10;2:20;3:30;1:11;2:21;2:22;");
195
196 TypedProtoDecoder<4, true> tpd(used_range.begin, used_range.size());
197
198 // When parsing with the one-shot decoder and querying the single field id, we
199 // should see the last value for each of them, not the first one. This is the
200 // current behavior of Google protobuf's parser.
201 EXPECT_EQ(tpd.Get(1).as_int32(), 11);
202 EXPECT_EQ(tpd.Get(2).as_int32(), 22);
203 EXPECT_EQ(tpd.Get(3).as_int32(), 30);
204
205 // But when iterating we should see values in the original order.
206 auto it = tpd.GetRepeated<int32_t>(1);
207 EXPECT_EQ(*it, 10);
208 EXPECT_EQ(*++it, 11);
209 EXPECT_FALSE(++it);
210
211 it = tpd.GetRepeated<int32_t>(2);
212 EXPECT_EQ(*it++, 20);
213 EXPECT_EQ(*it++, 21);
214 EXPECT_EQ(*it++, 22);
215 EXPECT_FALSE(it);
216
217 it = tpd.GetRepeated<int32_t>(3);
218 EXPECT_EQ(*it, 30);
219 EXPECT_FALSE(++it);
220 }
221
TEST(ProtoDecoderTest,FixedData)222 TEST(ProtoDecoderTest, FixedData) {
223 struct FieldExpectation {
224 const char* encoded;
225 size_t encoded_size;
226 uint32_t id;
227 ProtoWireType type;
228 uint64_t int_value;
229 };
230
231 const FieldExpectation kFieldExpectations[] = {
232 {"\x08\x00", 2, 1, ProtoWireType::kVarInt, 0},
233 {"\x08\x01", 2, 1, ProtoWireType::kVarInt, 1},
234 {"\x08\x42", 2, 1, ProtoWireType::kVarInt, 0x42},
235 {"\xF8\x07\x42", 3, 127, ProtoWireType::kVarInt, 0x42},
236 {"\xB8\x3E\xFF\xFF\xFF\xFF\x0F", 7, 999, ProtoWireType::kVarInt,
237 0xFFFFFFFF},
238 {"\x7D\x42\x00\x00\x00", 5, 15, ProtoWireType::kFixed32, 0x42},
239 {"\xBD\x3E\x78\x56\x34\x12", 6, 999, ProtoWireType::kFixed32, 0x12345678},
240 {"\x79\x42\x00\x00\x00\x00\x00\x00\x00", 9, 15, ProtoWireType::kFixed64,
241 0x42},
242 {"\xB9\x3E\x08\x07\x06\x05\x04\x03\x02\x01", 10, 999,
243 ProtoWireType::kFixed64, 0x0102030405060708},
244 {"\x0A\x00", 2, 1, ProtoWireType::kLengthDelimited, 0},
245 {"\x0A\x04|abc", 6, 1, ProtoWireType::kLengthDelimited, 4},
246 {"\xBA\x3E\x04|abc", 7, 999, ProtoWireType::kLengthDelimited, 4},
247 {"\xBA\x3E\x83\x01|abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzab"
248 "cdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstu"
249 "vwx",
250 135, 999, ProtoWireType::kLengthDelimited, 131},
251 };
252
253 for (size_t i = 0; i < perfetto::base::ArraySize(kFieldExpectations); ++i) {
254 const FieldExpectation& exp = kFieldExpectations[i];
255 TypedProtoDecoder<999, 0> decoder(
256 reinterpret_cast<const uint8_t*>(exp.encoded), exp.encoded_size);
257
258 auto& field = decoder.Get(exp.id);
259 ASSERT_EQ(exp.type, field.type());
260
261 if (field.type() == ProtoWireType::kLengthDelimited) {
262 ASSERT_EQ(exp.int_value, field.size());
263 } else {
264 ASSERT_EQ(int64_t(exp.int_value), field.as_int64());
265 // Proto encodes booleans as varints of 0 or 1.
266 if (exp.int_value == 0 || exp.int_value == 1) {
267 ASSERT_EQ(int64_t(exp.int_value), field.as_bool());
268 }
269 }
270 }
271
272 // Test float and doubles decoding.
273 const char buf[] = "\x0d\x00\x00\xa0\x3f\x11\x00\x00\x00\x00\x00\x42\x8f\xc0";
274 TypedProtoDecoder<2, false> decoder(reinterpret_cast<const uint8_t*>(buf),
275 sizeof(buf));
276 EXPECT_FLOAT_EQ(decoder.Get(1).as_float(), 1.25f);
277 EXPECT_DOUBLE_EQ(decoder.Get(2).as_double(), -1000.25);
278 }
279
TEST(ProtoDecoderTest,FindField)280 TEST(ProtoDecoderTest, FindField) {
281 uint8_t buf[] = {0x08, 0x00}; // field_id 1, varint value 0.
282 ProtoDecoder pd(buf, 2);
283
284 auto field = pd.FindField(1);
285 ASSERT_TRUE(field);
286 EXPECT_EQ(field.as_int64(), 0);
287
288 auto field2 = pd.FindField(2);
289 EXPECT_FALSE(field2);
290 }
291
TEST(ProtoDecoderTest,MoveTypedDecoder)292 TEST(ProtoDecoderTest, MoveTypedDecoder) {
293 HeapBuffered<Message> message;
294 message->AppendVarInt(/*field_id=*/1, 10);
295 std::vector<uint8_t> proto = message.SerializeAsArray();
296
297 // Construct a decoder that uses inline storage (i.e., the fields are stored
298 // within the object itself).
299 using Decoder = TypedProtoDecoder<32, false>;
300 std::unique_ptr<Decoder> decoder(new Decoder(proto.data(), proto.size()));
301 ASSERT_GE(reinterpret_cast<uintptr_t>(&decoder->at<1>()),
302 reinterpret_cast<uintptr_t>(decoder.get()));
303 ASSERT_LT(reinterpret_cast<uintptr_t>(&decoder->at<1>()),
304 reinterpret_cast<uintptr_t>(decoder.get()) + sizeof(Decoder));
305
306 // Move the decoder into another object and deallocate the original object.
307 Decoder decoder2(std::move(*decoder));
308 decoder.reset();
309
310 // Check that the contents got moved correctly.
311 EXPECT_EQ(decoder2.Get(1).as_int32(), 10);
312 ASSERT_GE(reinterpret_cast<uintptr_t>(&decoder2.at<1>()),
313 reinterpret_cast<uintptr_t>(&decoder2));
314 ASSERT_LT(reinterpret_cast<uintptr_t>(&decoder2.at<1>()),
315 reinterpret_cast<uintptr_t>(&decoder2) + sizeof(Decoder));
316 }
317
TEST(ProtoDecoderTest,PackedRepeatedVarint)318 TEST(ProtoDecoderTest, PackedRepeatedVarint) {
319 std::vector<int32_t> values = {42, 255, 0, -1};
320
321 // serialize using protobuf library
322 pbgold::PackedRepeatedFields msg;
323 for (auto v : values)
324 msg.add_field_int32(v);
325 std::string serialized = msg.SerializeAsString();
326
327 // decode using TypedProtoDecoder directly
328 {
329 constexpr int kFieldId =
330 pbtest::PackedRepeatedFields::kFieldInt32FieldNumber;
331 TypedProtoDecoder<kFieldId, false> decoder(
332 reinterpret_cast<const uint8_t*>(serialized.data()), serialized.size());
333 ASSERT_TRUE(decoder.at<kFieldId>().valid());
334 bool parse_error = false;
335 auto packed_it =
336 decoder.GetPackedRepeated<proto_utils::ProtoWireType::kVarInt, int32_t>(
337 kFieldId, &parse_error);
338
339 std::vector<int32_t> decoded_values;
340 for (; packed_it; ++packed_it) {
341 auto v = *packed_it;
342 decoded_values.push_back(v);
343 }
344 ASSERT_EQ(values, decoded_values);
345 ASSERT_FALSE(parse_error);
346 }
347
348 // decode using plugin-generated accessor
349 {
350 auto decoder = pbtest::PackedRepeatedFields::Decoder(serialized);
351 ASSERT_TRUE(decoder.has_field_int32());
352
353 bool parse_error = false;
354 std::vector<int32_t> decoded_values;
355 for (auto packed_it = decoder.field_int32(&parse_error); packed_it;
356 ++packed_it) {
357 auto v = *packed_it;
358 decoded_values.push_back(v);
359 }
360 ASSERT_EQ(values, decoded_values);
361 ASSERT_FALSE(parse_error);
362 }
363
364 // unset field case
365 pbgold::PackedRepeatedFields empty_msg;
366 std::string empty_serialized = empty_msg.SerializeAsString();
367 auto decoder = pbtest::PackedRepeatedFields::Decoder(empty_serialized);
368 ASSERT_FALSE(decoder.has_field_int32());
369 bool parse_error = false;
370 auto packed_it = decoder.field_int32(&parse_error);
371 ASSERT_FALSE(bool(packed_it));
372 ASSERT_FALSE(parse_error);
373 }
374
TEST(ProtoDecoderTest,PackedRepeatedFixed32)375 TEST(ProtoDecoderTest, PackedRepeatedFixed32) {
376 std::vector<uint32_t> values = {42, 255, 0, 1};
377
378 // serialize using protobuf library
379 pbgold::PackedRepeatedFields msg;
380 for (auto v : values)
381 msg.add_field_fixed32(v);
382 std::string serialized = msg.SerializeAsString();
383
384 // decode using TypedProtoDecoder directly
385 {
386 constexpr int kFieldId =
387 pbtest::PackedRepeatedFields::kFieldFixed32FieldNumber;
388 TypedProtoDecoder<kFieldId, false> decoder(
389 reinterpret_cast<const uint8_t*>(serialized.data()), serialized.size());
390 bool parse_error = false;
391 auto packed_it =
392 decoder
393 .GetPackedRepeated<proto_utils::ProtoWireType::kFixed32, uint32_t>(
394 kFieldId, &parse_error);
395
396 std::vector<uint32_t> decoded_values;
397 for (; packed_it; ++packed_it) {
398 auto v = *packed_it;
399 decoded_values.push_back(v);
400 }
401 ASSERT_EQ(values, decoded_values);
402 ASSERT_FALSE(parse_error);
403 }
404
405 // decode using plugin-generated accessor
406 {
407 auto decoder = pbtest::PackedRepeatedFields::Decoder(serialized);
408 ASSERT_TRUE(decoder.has_field_fixed32());
409
410 bool parse_error = false;
411 std::vector<uint32_t> decoded_values;
412 for (auto packed_it = decoder.field_fixed32(&parse_error); packed_it;
413 packed_it++) {
414 auto v = *packed_it;
415 decoded_values.push_back(v);
416 }
417 ASSERT_EQ(values, decoded_values);
418 ASSERT_FALSE(parse_error);
419 }
420
421 // unset field case
422 pbgold::PackedRepeatedFields empty_msg;
423 std::string empty_serialized = empty_msg.SerializeAsString();
424 auto decoder = pbtest::PackedRepeatedFields::Decoder(empty_serialized);
425 ASSERT_FALSE(decoder.has_field_fixed32());
426 bool parse_error = false;
427 auto packed_it = decoder.field_fixed32(&parse_error);
428 ASSERT_FALSE(bool(packed_it));
429 ASSERT_FALSE(parse_error);
430 }
431
TEST(ProtoDecoderTest,PackedRepeatedFixed64)432 TEST(ProtoDecoderTest, PackedRepeatedFixed64) {
433 std::vector<int64_t> values = {42, 255, 0, -1};
434
435 // serialize using protobuf library
436 pbgold::PackedRepeatedFields msg;
437 for (auto v : values)
438 msg.add_field_sfixed64(v);
439 std::string serialized = msg.SerializeAsString();
440
441 // decode using TypedProtoDecoder directly
442 {
443 constexpr int kFieldId =
444 pbtest::PackedRepeatedFields::kFieldSfixed64FieldNumber;
445 TypedProtoDecoder<kFieldId, false> decoder(
446 reinterpret_cast<const uint8_t*>(serialized.data()), serialized.size());
447 bool parse_error = false;
448 auto packed_it =
449 decoder
450 .GetPackedRepeated<proto_utils::ProtoWireType::kFixed64, int64_t>(
451 kFieldId, &parse_error);
452
453 std::vector<int64_t> decoded_values;
454 for (; packed_it; ++packed_it) {
455 auto v = *packed_it;
456 decoded_values.push_back(v);
457 }
458 ASSERT_EQ(values, decoded_values);
459 ASSERT_FALSE(parse_error);
460 }
461
462 // decode using plugin-generated accessor
463 {
464 auto decoder = pbtest::PackedRepeatedFields::Decoder(serialized);
465 ASSERT_TRUE(decoder.has_field_sfixed64());
466
467 bool parse_error = false;
468 std::vector<int64_t> decoded_values;
469 for (auto packed_it = decoder.field_sfixed64(&parse_error); packed_it;
470 packed_it++) {
471 auto v = *packed_it;
472 decoded_values.push_back(v);
473 }
474 ASSERT_EQ(values, decoded_values);
475 ASSERT_FALSE(parse_error);
476 }
477
478 // unset field case
479 pbgold::PackedRepeatedFields empty_msg;
480 std::string empty_serialized = empty_msg.SerializeAsString();
481 auto decoder = pbtest::PackedRepeatedFields::Decoder(empty_serialized);
482 ASSERT_FALSE(decoder.has_field_sfixed64());
483 bool parse_error = false;
484 auto packed_it = decoder.field_sfixed64(&parse_error);
485 ASSERT_FALSE(bool(packed_it));
486 ASSERT_FALSE(parse_error);
487 }
488
TEST(ProtoDecoderTest,ZeroLengthPackedRepeatedField)489 TEST(ProtoDecoderTest, ZeroLengthPackedRepeatedField) {
490 HeapBuffered<pbtest::PackedRepeatedFields> msg;
491 PackedVarInt buf;
492 msg->set_field_int32(buf);
493 std::string serialized = msg.SerializeAsString();
494
495 // Encoded as 2 bytes: tag/field, and a length of zero.
496 EXPECT_EQ(2u, serialized.size());
497
498 // Appears empty when decoded.
499 auto decoder = pbtest::PackedRepeatedFields::Decoder(serialized);
500 ASSERT_TRUE(decoder.has_field_int32());
501 bool parse_error = false;
502 auto packed_it = decoder.field_int32(&parse_error);
503 ASSERT_FALSE(bool(packed_it));
504 ASSERT_FALSE(parse_error);
505 }
506
TEST(ProtoDecoderTest,MalformedPackedFixedBuffer)507 TEST(ProtoDecoderTest, MalformedPackedFixedBuffer) {
508 // Encode a fixed32 field where the length is not a multiple of 4 bytes.
509 HeapBuffered<pbtest::PackedRepeatedFields> msg;
510 PackedFixedSizeInt<uint32_t> buf;
511 buf.Append(1);
512 buf.Append(2);
513 buf.Append(3);
514 const uint8_t* data = buf.data();
515 size_t size = buf.size();
516 size_t invalid_size = size - 2;
517 constexpr int kFieldId =
518 pbtest::PackedRepeatedFields::kFieldFixed32FieldNumber;
519 msg->AppendBytes(kFieldId, data, invalid_size);
520 std::string serialized = msg.SerializeAsString();
521
522 // Iterator indicates parse error.
523 auto decoder = pbtest::PackedRepeatedFields::Decoder(serialized);
524 ASSERT_TRUE(decoder.has_field_fixed32());
525 bool parse_error = false;
526 for (auto packed_it = decoder.field_fixed32(&parse_error); packed_it;
527 packed_it++) {
528 }
529 ASSERT_TRUE(parse_error);
530 }
531
TEST(ProtoDecoderTest,MalformedPackedVarIntBuffer)532 TEST(ProtoDecoderTest, MalformedPackedVarIntBuffer) {
533 // Encode a varint field with the last varint chopped off partway.
534 HeapBuffered<pbtest::PackedRepeatedFields> msg;
535 PackedVarInt buf;
536 buf.Append(1024);
537 buf.Append(2048);
538 buf.Append(4096);
539 const uint8_t* data = buf.data();
540 size_t size = buf.size();
541 size_t invalid_size = size - 1;
542 constexpr int kFieldId = pbtest::PackedRepeatedFields::kFieldInt32FieldNumber;
543 msg->AppendBytes(kFieldId, data, invalid_size);
544 std::string serialized = msg.SerializeAsString();
545
546 // Iterator indicates parse error.
547 auto decoder = pbtest::PackedRepeatedFields::Decoder(serialized);
548 ASSERT_TRUE(decoder.has_field_int32());
549 bool parse_error = false;
550 for (auto packed_it = decoder.field_int32(&parse_error); packed_it;
551 packed_it++) {
552 }
553 ASSERT_TRUE(parse_error);
554 }
555
556 // Tests that big field ids (> 0xffff) are just skipped but don't fail parsing.
557 // This is a regression test for b/145339282 (DataSourceConfig.for_testing
558 // having a very large ID == 268435455 until Android R).
TEST(ProtoDecoderTest,SkipBigFieldIds)559 TEST(ProtoDecoderTest, SkipBigFieldIds) {
560 Message message;
561 ScatteredHeapBuffer delegate(512, 512);
562 ScatteredStreamWriter writer(&delegate);
563 delegate.set_writer(&writer);
564 message.Reset(&writer);
565 message.AppendVarInt(/*field_id=*/1, 11);
566 message.AppendVarInt(/*field_id=*/1000000, 0); // Will be skipped
567 message.AppendVarInt(/*field_id=*/65535, 99);
568 message.AppendVarInt(/*field_id=*/268435455, 0); // Will be skipped
569 message.AppendVarInt(/*field_id=*/2, 12);
570 message.AppendVarInt(/*field_id=*/2000000, 0); // Will be skipped
571 std::vector<uint8_t> data = delegate.StitchSlices();
572
573 // Check the iterator-based ProtoDecoder.
574 {
575 ProtoDecoder decoder(data.data(), data.size());
576 Field field = decoder.ReadField();
577 ASSERT_TRUE(field.valid());
578 ASSERT_EQ(field.id(), 1u);
579 ASSERT_EQ(field.as_int32(), 11);
580
581 field = decoder.ReadField();
582 ASSERT_TRUE(field.valid());
583 ASSERT_EQ(field.id(), 65535u);
584 ASSERT_EQ(field.as_int32(), 99);
585
586 field = decoder.ReadField();
587 ASSERT_TRUE(field.valid());
588 ASSERT_EQ(field.id(), 2u);
589 ASSERT_EQ(field.as_int32(), 12);
590
591 field = decoder.ReadField();
592 ASSERT_FALSE(field.valid());
593 }
594
595 // Test the one-shot-read TypedProtoDecoder.
596 // Note: field 65535 will be also skipped because this TypedProtoDecoder has
597 // a cap on MAX_FIELD_ID = 3.
598 {
599 TypedProtoDecoder<3, true> tpd(data.data(), data.size());
600 EXPECT_EQ(tpd.Get(1).as_int32(), 11);
601 EXPECT_EQ(tpd.Get(2).as_int32(), 12);
602 }
603 }
604
605 // Edge case for SkipBigFieldIds, the message contains only one field with a
606 // very big id. Test that we skip it and return an invalid field, instead of
607 // geetting stuck in some loop.
TEST(ProtoDecoderTest,OneBigFieldIdOnly)608 TEST(ProtoDecoderTest, OneBigFieldIdOnly) {
609 Message message;
610 ScatteredHeapBuffer delegate(512, 512);
611 ScatteredStreamWriter writer(&delegate);
612 delegate.set_writer(&writer);
613 message.Reset(&writer);
614 message.AppendVarInt(/*field_id=*/268435455, 0);
615 std::vector<uint8_t> data = delegate.StitchSlices();
616
617 // Check the iterator-based ProtoDecoder.
618 ProtoDecoder decoder(data.data(), data.size());
619 Field field = decoder.ReadField();
620 ASSERT_FALSE(field.valid());
621 }
622
623 } // namespace
624 } // namespace protozero
625