• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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