• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 
15 #include "pw_protobuf/decoder.h"
16 
17 #include <cstring>
18 
19 #include "pw_fuzzer/asan_interface.h"
20 #include "pw_fuzzer/fuzztest.h"
21 #include "pw_preprocessor/util.h"
22 #include "pw_protobuf/wire_format.h"
23 #include "pw_unit_test/framework.h"
24 
25 namespace pw::protobuf {
26 namespace {
27 
28 class TestDecodeHandler : public DecodeHandler {
29  public:
ProcessField(CallbackDecoder & decoder,uint32_t field_number)30   Status ProcessField(CallbackDecoder& decoder,
31                       uint32_t field_number) override {
32     std::string_view str;
33 
34     switch (field_number) {
35       case 1:
36         EXPECT_EQ(OkStatus(), decoder.ReadInt32(&test_int32));
37         break;
38       case 2:
39         EXPECT_EQ(OkStatus(), decoder.ReadSint32(&test_sint32));
40         break;
41       case 3:
42         EXPECT_EQ(OkStatus(), decoder.ReadBool(&test_bool));
43         break;
44       case 4:
45         EXPECT_EQ(OkStatus(), decoder.ReadDouble(&test_double));
46         break;
47       case 5:
48         EXPECT_EQ(OkStatus(), decoder.ReadFixed32(&test_fixed32));
49         break;
50       case 6:
51         EXPECT_EQ(OkStatus(), decoder.ReadString(&str));
52         std::memcpy(test_string, str.data(), str.size());
53         test_string[str.size()] = '\0';
54         break;
55     }
56 
57     called = true;
58     return OkStatus();
59   }
60 
61   bool called = false;
62   int32_t test_int32 = 0;
63   int32_t test_sint32 = 0;
64   bool test_bool = true;
65   double test_double = 0;
66   uint32_t test_fixed32 = 0;
67   char test_string[16];
68 };
69 
TEST(Decoder,Decode)70 TEST(Decoder, Decode) {
71   // clang-format off
72   uint8_t encoded_proto[] = {
73     // type=int32, k=1, v=42
74     0x08, 0x2a,
75     // type=sint32, k=2, v=-13
76     0x10, 0x19,
77     // type=bool, k=3, v=false
78     0x18, 0x00,
79     // type=double, k=4, v=3.14159
80     0x21, 0x6e, 0x86, 0x1b, 0xf0, 0xf9, 0x21, 0x09, 0x40,
81     // type=fixed32, k=5, v=0xdeadbeef
82     0x2d, 0xef, 0xbe, 0xad, 0xde,
83     // type=string, k=6, v="Hello world"
84     0x32, 0x0b, 'H', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd',
85   };
86   // clang-format on
87 
88   Decoder decoder(as_bytes(span(encoded_proto)));
89 
90   int32_t v1 = 0;
91   EXPECT_EQ(decoder.Next(), OkStatus());
92   ASSERT_EQ(decoder.FieldNumber(), 1u);
93   EXPECT_EQ(decoder.ReadInt32(&v1), OkStatus());
94   EXPECT_EQ(v1, 42);
95 
96   int32_t v2 = 0;
97   EXPECT_EQ(decoder.Next(), OkStatus());
98   ASSERT_EQ(decoder.FieldNumber(), 2u);
99   EXPECT_EQ(decoder.ReadSint32(&v2), OkStatus());
100   EXPECT_EQ(v2, -13);
101 
102   bool v3 = true;
103   EXPECT_EQ(decoder.Next(), OkStatus());
104   ASSERT_EQ(decoder.FieldNumber(), 3u);
105   EXPECT_EQ(decoder.ReadBool(&v3), OkStatus());
106   EXPECT_FALSE(v3);
107 
108   double v4 = 0;
109   EXPECT_EQ(decoder.Next(), OkStatus());
110   ASSERT_EQ(decoder.FieldNumber(), 4u);
111   EXPECT_EQ(decoder.ReadDouble(&v4), OkStatus());
112   EXPECT_EQ(v4, 3.14159);
113 
114   uint32_t v5 = 0;
115   EXPECT_EQ(decoder.Next(), OkStatus());
116   ASSERT_EQ(decoder.FieldNumber(), 5u);
117   EXPECT_EQ(decoder.ReadFixed32(&v5), OkStatus());
118   EXPECT_EQ(v5, 0xdeadbeef);
119 
120   std::string_view v6;
121   char buffer[16];
122   EXPECT_EQ(decoder.Next(), OkStatus());
123   ASSERT_EQ(decoder.FieldNumber(), 6u);
124   EXPECT_EQ(decoder.ReadString(&v6), OkStatus());
125   std::memcpy(buffer, v6.data(), v6.size());
126   buffer[v6.size()] = '\0';
127   EXPECT_STREQ(buffer, "Hello world");
128 
129   EXPECT_EQ(decoder.Next(), Status::OutOfRange());
130 }
131 
TEST(Decoder,Decode_SkipsUnusedFields)132 TEST(Decoder, Decode_SkipsUnusedFields) {
133   // clang-format off
134   uint8_t encoded_proto[] = {
135     // type=int32, k=1, v=42
136     0x08, 0x2a,
137     // type=sint32, k=2, v=-13
138     0x10, 0x19,
139     // type=bool, k=3, v=false
140     0x18, 0x00,
141     // type=double, k=4, v=3.14159
142     0x21, 0x6e, 0x86, 0x1b, 0xf0, 0xf9, 0x21, 0x09, 0x40,
143     // type=fixed32, k=5, v=0xdeadbeef
144     0x2d, 0xef, 0xbe, 0xad, 0xde,
145     // type=string, k=6, v="Hello world"
146     0x32, 0x0b, 'H', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd',
147   };
148   // clang-format on
149 
150   Decoder decoder(as_bytes(span(encoded_proto)));
151 
152   // Don't process any fields except for the fourth. Next should still iterate
153   // correctly despite field values not being consumed.
154   EXPECT_EQ(decoder.Next(), OkStatus());
155   EXPECT_EQ(decoder.Next(), OkStatus());
156   EXPECT_EQ(decoder.Next(), OkStatus());
157   EXPECT_EQ(decoder.Next(), OkStatus());
158   ASSERT_EQ(decoder.FieldNumber(), 4u);
159   EXPECT_EQ(decoder.Next(), OkStatus());
160   EXPECT_EQ(decoder.Next(), OkStatus());
161   EXPECT_EQ(decoder.Next(), Status::OutOfRange());
162 }
163 
TEST(Decoder,Decode_BadFieldNumber)164 TEST(Decoder, Decode_BadFieldNumber) {
165   // clang-format off
166   constexpr uint8_t encoded_proto[] = {
167     // type=int32, k=1, v=42
168     0x08, 0x2a,
169     // type=int32, k=19001, v=42 (invalid field number)
170     0xc8, 0xa3, 0x09, 0x2a,
171     // type=bool, k=3, v=false
172     0x18, 0x00,
173   };
174   // clang-format on
175 
176   Decoder decoder(as_bytes(span(encoded_proto)));
177   int32_t value;
178 
179   EXPECT_EQ(decoder.Next(), OkStatus());
180   EXPECT_EQ(decoder.FieldNumber(), 1u);
181   ASSERT_EQ(decoder.ReadInt32(&value), OkStatus());
182   EXPECT_EQ(value, 42);
183 
184   // Bad field.
185   EXPECT_EQ(decoder.Next(), Status::DataLoss());
186   EXPECT_EQ(decoder.FieldNumber(), 0u);
187   EXPECT_EQ(decoder.ReadInt32(&value), Status::DataLoss());
188 }
189 
TEST(CallbackDecoder,Decode)190 TEST(CallbackDecoder, Decode) {
191   CallbackDecoder decoder;
192   TestDecodeHandler handler;
193 
194   // clang-format off
195   uint8_t encoded_proto[] = {
196     // type=int32, k=1, v=42
197     0x08, 0x2a,
198     // type=sint32, k=2, v=-13
199     0x10, 0x19,
200     // type=bool, k=3, v=false
201     0x18, 0x00,
202     // type=double, k=4, v=3.14159
203     0x21, 0x6e, 0x86, 0x1b, 0xf0, 0xf9, 0x21, 0x09, 0x40,
204     // type=fixed32, k=5, v=0xdeadbeef
205     0x2d, 0xef, 0xbe, 0xad, 0xde,
206     // type=string, k=6, v="Hello world"
207     0x32, 0x0b, 'H', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd',
208   };
209   // clang-format on
210 
211   decoder.set_handler(&handler);
212   EXPECT_EQ(decoder.Decode(as_bytes(span(encoded_proto))), OkStatus());
213   EXPECT_TRUE(handler.called);
214   EXPECT_EQ(handler.test_int32, 42);
215   EXPECT_EQ(handler.test_sint32, -13);
216   EXPECT_FALSE(handler.test_bool);
217   EXPECT_EQ(handler.test_double, 3.14159);
218   EXPECT_EQ(handler.test_fixed32, 0xdeadbeef);
219   EXPECT_STREQ(handler.test_string, "Hello world");
220 }
221 
TEST(CallbackDecoder,Decode_OverridesDuplicateFields)222 TEST(CallbackDecoder, Decode_OverridesDuplicateFields) {
223   CallbackDecoder decoder;
224   TestDecodeHandler handler;
225 
226   // clang-format off
227   uint8_t encoded_proto[] = {
228     // type=int32, k=1, v=42
229     0x08, 0x2a,
230     // type=int32, k=1, v=43
231     0x08, 0x2b,
232     // type=int32, k=1, v=44
233     0x08, 0x2c,
234   };
235   // clang-format on
236 
237   decoder.set_handler(&handler);
238   EXPECT_EQ(decoder.Decode(as_bytes(span(encoded_proto))), OkStatus());
239   EXPECT_TRUE(handler.called);
240   EXPECT_EQ(handler.test_int32, 44);
241 }
242 
TEST(CallbackDecoder,Decode_Empty)243 TEST(CallbackDecoder, Decode_Empty) {
244   CallbackDecoder decoder;
245   TestDecodeHandler handler;
246 
247   decoder.set_handler(&handler);
248   EXPECT_EQ(decoder.Decode(span<std::byte>()), OkStatus());
249   EXPECT_FALSE(handler.called);
250   EXPECT_EQ(handler.test_int32, 0);
251   EXPECT_EQ(handler.test_sint32, 0);
252 }
253 
TEST(CallbackDecoder,Decode_BadData)254 TEST(CallbackDecoder, Decode_BadData) {
255   CallbackDecoder decoder;
256   TestDecodeHandler handler;
257 
258   // Field key without a value.
259   uint8_t encoded_proto[] = {0x08};
260 
261   decoder.set_handler(&handler);
262   EXPECT_EQ(decoder.Decode(as_bytes(span(encoded_proto))), Status::DataLoss());
263 }
264 
265 // Only processes fields numbered 1 or 3.
266 class OneThreeDecodeHandler : public DecodeHandler {
267  public:
ProcessField(CallbackDecoder & decoder,uint32_t field_number)268   Status ProcessField(CallbackDecoder& decoder,
269                       uint32_t field_number) override {
270     switch (field_number) {
271       case 1:
272         EXPECT_EQ(decoder.ReadInt32(&field_one), OkStatus());
273         break;
274       case 3:
275         EXPECT_EQ(decoder.ReadInt32(&field_three), OkStatus());
276         break;
277       default:
278         // Do nothing.
279         break;
280     }
281 
282     called = true;
283     return OkStatus();
284   }
285 
286   bool called = false;
287   int32_t field_one = 0;
288   int32_t field_three = 0;
289 };
290 
TEST(CallbackDecoder,Decode_SkipsUnprocessedFields)291 TEST(CallbackDecoder, Decode_SkipsUnprocessedFields) {
292   CallbackDecoder decoder;
293   OneThreeDecodeHandler handler;
294 
295   // clang-format off
296   uint8_t encoded_proto[] = {
297     // type=int32, k=1, v=42
298     // Should be read.
299     0x08, 0x2a,
300     // type=sint32, k=2, v=-13
301     // Should be ignored.
302     0x10, 0x19,
303     // type=int32, k=2, v=3
304     // Should be ignored.
305     0x10, 0x03,
306     // type=int32, k=3, v=99
307     // Should be read.
308     0x18, 0x63,
309     // type=int32, k=4, v=16
310     // Should be ignored.
311     0x20, 0x10,
312   };
313   // clang-format on
314 
315   decoder.set_handler(&handler);
316   EXPECT_EQ(decoder.Decode(as_bytes(span(encoded_proto))), OkStatus());
317   EXPECT_TRUE(handler.called);
318   EXPECT_EQ(handler.field_one, 42);
319   EXPECT_EQ(handler.field_three, 99);
320 }
321 
322 // Only processes fields numbered 1 or 3, and stops the decode after hitting 1.
323 class ExitOnOneDecoder : public DecodeHandler {
324  public:
ProcessField(CallbackDecoder & decoder,uint32_t field_number)325   Status ProcessField(CallbackDecoder& decoder,
326                       uint32_t field_number) override {
327     switch (field_number) {
328       case 1:
329         EXPECT_EQ(decoder.ReadInt32(&field_one), OkStatus());
330         return Status::Cancelled();
331       case 3:
332         EXPECT_EQ(decoder.ReadInt32(&field_three), OkStatus());
333         break;
334       default:
335         // Do nothing.
336         break;
337     }
338 
339     return OkStatus();
340   }
341 
342   int32_t field_one = 0;
343   int32_t field_three = 1111;
344 };
345 
TEST(CallbackDecoder,Decode_StopsOnNonOkStatus)346 TEST(CallbackDecoder, Decode_StopsOnNonOkStatus) {
347   CallbackDecoder decoder;
348   ExitOnOneDecoder handler;
349 
350   // clang-format off
351   uint8_t encoded_proto[] = {
352     // type=int32, k=1, v=42
353     // Should be read.
354     0x08, 0x2a,
355     // type=int32, k=3, v=99
356     // Should be skipped.
357     0x18, 0x63,
358     // type=int32, k=2, v=16
359     // Should be skipped.
360     0x08, 0x10,
361   };
362   // clang-format on
363 
364   decoder.set_handler(&handler);
365   EXPECT_EQ(decoder.Decode(as_bytes(span(encoded_proto))), Status::Cancelled());
366   EXPECT_EQ(handler.field_one, 42);
367   EXPECT_EQ(handler.field_three, 1111);
368 }
369 
TEST(Decoder,DelimitedFieldSizeLargerThanRemainingSpan_ReturnsDataLoss)370 TEST(Decoder, DelimitedFieldSizeLargerThanRemainingSpan_ReturnsDataLoss) {
371   std::array<std::byte, 4> input = {
372       static_cast<std::byte>(
373           static_cast<uint32_t>(FieldKey(1, WireType::kDelimited))),
374       static_cast<std::byte>(3),  // Length longer than remaining subspan.
375       static_cast<std::byte>(172),
376       static_cast<std::byte>(193)};
377   // clang-format on
378   Decoder decoder(input);
379   EXPECT_EQ(decoder.Next(), Status::DataLoss());
380 }
381 
DoesNotCrash(ConstByteSpan buffer)382 void DoesNotCrash(ConstByteSpan buffer) {
383   // Place the input buffer in the middle of a poisoned memory region to catch
384   // if the decoder attempts to read beyond its bounds in either direction.
385   static std::array<std::byte, 2048> memory_region;
386   constexpr size_t kBufferOffset = 256;
387   ByteSpan input_buffer(memory_region.data() + kBufferOffset, buffer.size());
388 
389   ASAN_POISON_MEMORY_REGION(memory_region.data(), memory_region.size());
390   ASAN_UNPOISON_MEMORY_REGION(input_buffer.data(), input_buffer.size());
391 
392   std::memcpy(input_buffer.data(), buffer.data(), buffer.size());
393 
394   Decoder decoder(input_buffer);
395   for (int i = 0; i < 20; ++i) {
396     decoder.Next().IgnoreError();
397   }
398 
399   ASAN_UNPOISON_MEMORY_REGION(memory_region.data(), memory_region.size());
400 }
401 
402 FUZZ_TEST(Decoder, DoesNotCrash)
403     .WithDomains(fuzzer::VectorOf<64>(fuzztest::Arbitrary<std::byte>()));
404 
405 }  // namespace
406 }  // namespace pw::protobuf
407