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