xref: /aosp_15_r20/external/pigweed/pw_hdlc/decoder_test.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
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