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_hdlc/decoder.h"
16
17 #include <array>
18 #include <cstddef>
19
20 #include "pw_bytes/array.h"
21 #include "pw_fuzzer/fuzztest.h"
22 #include "pw_hdlc/internal/protocol.h"
23 #include "pw_unit_test/framework.h"
24
25 namespace pw::hdlc {
26 namespace {
27
28 using std::byte;
29 using namespace fuzzer;
30
TEST(Frame,Fields)31 TEST(Frame, Fields) {
32 static constexpr auto kFrameData =
33 bytes::String("\x05\xab\x42\x24\xf9\x54\xfb\x3d");
34 auto result = Frame::Parse(kFrameData);
35 ASSERT_TRUE(result.ok());
36 Frame& frame = result.value();
37
38 EXPECT_EQ(frame.address(), 2u);
39 EXPECT_EQ(frame.control(), byte{0xab});
40
41 EXPECT_EQ(frame.data().size(), 2u);
42 EXPECT_EQ(frame.data()[0], byte{0x42});
43 EXPECT_EQ(frame.data()[1], byte{0x24});
44 }
45
TEST(Frame,MultibyteAddress)46 TEST(Frame, MultibyteAddress) {
47 static constexpr auto kFrameData =
48 bytes::String("\x2c\xd9\x33\x01\x02\xaf\xc8\x77\x48");
49 auto result = Frame::Parse(kFrameData);
50 ASSERT_TRUE(result.ok());
51 Frame& frame = result.value();
52
53 EXPECT_EQ(frame.address(), 0b11011000010110u);
54 EXPECT_EQ(frame.control(), byte{0x33});
55
56 EXPECT_EQ(frame.data().size(), 2u);
57 EXPECT_EQ(frame.data()[0], byte{0x01});
58 EXPECT_EQ(frame.data()[1], byte{0x02});
59 }
60
TEST(Frame,MultibyteAddressTooLong)61 TEST(Frame, MultibyteAddressTooLong) {
62 // 11-byte encoded address.
63 constexpr auto kLongAddress =
64 bytes::String("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01");
65 static constexpr auto kFrameData = bytes::Concat(
66 kLongAddress, bytes::String("\x33\x01\x02\xaf\xc8\x77\x48"));
67 auto result = Frame::Parse(kFrameData);
68 EXPECT_EQ(result.status(), Status::DataLoss());
69 }
70
TEST(Decoder,Clear)71 TEST(Decoder, Clear) {
72 DecoderBuffer<8> decoder;
73
74 // Process a partial packet
75 decoder.Process(bytes::String("~1234abcd"),
76 [](const Result<Frame>&) { FAIL(); });
77
78 decoder.Clear();
79 Status status = Status::Unknown();
80
81 decoder.Process(
82 bytes::String("~1234\xa3\xe0\xe3\x9b~"),
83 [&status](const Result<Frame>& result) { status = result.status(); });
84
85 EXPECT_EQ(OkStatus(), status);
86 }
87
TEST(Decoder,ExactFit)88 TEST(Decoder, ExactFit) {
89 DecoderBuffer<8> decoder;
90
91 for (byte b : bytes::String("~1234\xa3\xe0\xe3\x9b")) {
92 EXPECT_EQ(Status::Unavailable(), decoder.Process(b).status());
93 }
94 auto result = decoder.Process(kFlag);
95 ASSERT_EQ(OkStatus(), result.status());
96 ASSERT_EQ(result.value().data().size(), 2u);
97 ASSERT_EQ(result.value().data()[0], byte{'3'});
98 ASSERT_EQ(result.value().data()[1], byte{'4'});
99 }
100
TEST(Decoder,MinimumSizedBuffer)101 TEST(Decoder, MinimumSizedBuffer) {
102 DecoderBuffer<6> decoder;
103
104 for (byte b : bytes::String("~12\xcd\x44\x53\x4f")) {
105 EXPECT_EQ(Status::Unavailable(), decoder.Process(b).status());
106 }
107
108 auto result = decoder.Process(kFlag);
109 ASSERT_EQ(OkStatus(), result.status());
110 EXPECT_EQ(result.value().data().size(), 0u);
111 }
112
TEST(Decoder,TooLargeForBuffer_ReportsResourceExhausted)113 TEST(Decoder, TooLargeForBuffer_ReportsResourceExhausted) {
114 DecoderBuffer<8> decoder;
115
116 for (byte b : bytes::String("~12345\x1c\x3a\xf5\xcb")) {
117 EXPECT_EQ(Status::Unavailable(), decoder.Process(b).status());
118 }
119 EXPECT_EQ(Status::ResourceExhausted(), decoder.Process(kFlag).status());
120
121 for (byte b : bytes::String("~12345678901234567890\xf2\x19\x63\x90")) {
122 EXPECT_EQ(Status::Unavailable(), decoder.Process(b).status());
123 }
124 EXPECT_EQ(Status::ResourceExhausted(), decoder.Process(kFlag).status());
125 }
126
TEST(Decoder,TooLargeForBuffer_StaysWithinBufferBoundaries)127 TEST(Decoder, TooLargeForBuffer_StaysWithinBufferBoundaries) {
128 std::array<byte, 16> buffer = bytes::Initialized<16>('?');
129
130 Decoder decoder(span(buffer.data(), 8));
131
132 for (byte b : bytes::String("~12345678901234567890\xf2\x19\x63\x90")) {
133 EXPECT_EQ(Status::Unavailable(), decoder.Process(b).status());
134 }
135
136 for (size_t i = 8; i < buffer.size(); ++i) {
137 ASSERT_EQ(byte{'?'}, buffer[i]);
138 }
139
140 EXPECT_EQ(Status::ResourceExhausted(), decoder.Process(kFlag).status());
141 }
142
TEST(Decoder,TooLargeForBuffer_DecodesNextFrame)143 TEST(Decoder, TooLargeForBuffer_DecodesNextFrame) {
144 DecoderBuffer<8> decoder;
145
146 for (byte b : bytes::String("~12345678901234567890\xf2\x19\x63\x90")) {
147 EXPECT_EQ(Status::Unavailable(), decoder.Process(b).status());
148 }
149 EXPECT_EQ(Status::ResourceExhausted(), decoder.Process(kFlag).status());
150
151 for (byte b : bytes::String("1234\xa3\xe0\xe3\x9b")) {
152 EXPECT_EQ(Status::Unavailable(), decoder.Process(b).status());
153 }
154 EXPECT_EQ(OkStatus(), decoder.Process(kFlag).status());
155 }
156
ProcessNeverCrashes(ConstByteSpan data)157 void ProcessNeverCrashes(ConstByteSpan data) {
158 DecoderBuffer<1024> decoder;
159 for (byte b : data) {
160 if (decoder.Process(b).status() != Status::Unavailable()) {
161 decoder.Clear();
162 }
163 }
164 }
165
166 FUZZ_TEST(Decoder, ProcessNeverCrashes)
167 .WithDomains(VectorOf<1024>(Arbitrary<byte>()));
168
169 } // namespace
170 } // namespace pw::hdlc
171