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