Coverage Report

Created: 2024-07-09 06:09

/proc/self/cwd/pw_protobuf/decoder_fuzzer.cc
Line
Count
Source (jump to first uncovered line)
1
// Copyright 2022 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 <algorithm>
16
#include <cstddef>
17
#include <cstdint>
18
#include <cstring>
19
#include <vector>
20
21
#include "fuzz.h"
22
#include "pw_fuzzer/fuzzed_data_provider.h"
23
#include "pw_protobuf/stream_decoder.h"
24
#include "pw_span/span.h"
25
#include "pw_status/status.h"
26
#include "pw_status/status_with_size.h"
27
#include "pw_stream/memory_stream.h"
28
#include "pw_stream/stream.h"
29
30
namespace pw::protobuf::fuzz {
31
namespace {
32
33
void RecursiveFuzzedDecode(FuzzedDataProvider& provider,
34
                           StreamDecoder& decoder,
35
5.54k
                           uint32_t depth = 0) {
36
5.54k
  constexpr size_t kMaxRepeatedRead = 256;
37
5.54k
  constexpr size_t kMaxDepth = 3;
38
39
5.54k
  if (depth > kMaxDepth) {
40
791
    return;
41
791
  }
42
16.1k
  while (provider.remaining_bytes() != 0 && decoder.Next().ok()) {
43
13.0k
    FieldType field_type = provider.ConsumeEnum<FieldType>();
44
13.0k
    switch (field_type) {
45
448
      case kUint32:
46
448
        if (!decoder.ReadUint32().status().ok()) {
47
160
          return;
48
160
        }
49
288
        break;
50
477
      case kPackedUint32: {
51
477
        uint32_t packed[kMaxRepeatedRead] = {0};
52
477
        if (!decoder.ReadPackedUint32(packed).status().ok()) {
53
121
          return;
54
121
        }
55
477
      } break;
56
356
      case kUint64:
57
227
        if (!decoder.ReadUint64().status().ok()) {
58
29
          return;
59
29
        }
60
198
        break;
61
370
      case kPackedUint64: {
62
370
        uint64_t packed[kMaxRepeatedRead] = {0};
63
370
        if (!decoder.ReadPackedUint64(packed).status().ok()) {
64
75
          return;
65
75
        }
66
370
      } break;
67
485
      case kInt32:
68
485
        if (!decoder.ReadInt32().status().ok()) {
69
194
          return;
70
194
        }
71
291
        break;
72
330
      case kPackedInt32: {
73
330
        int32_t packed[kMaxRepeatedRead] = {0};
74
330
        if (!decoder.ReadPackedInt32(packed).status().ok()) {
75
53
          return;
76
53
        }
77
330
      } break;
78
277
      case kInt64:
79
225
        if (!decoder.ReadInt64().status().ok()) {
80
28
          return;
81
28
        }
82
197
        break;
83
317
      case kPackedInt64: {
84
317
        int64_t packed[kMaxRepeatedRead] = {0};
85
317
        if (!decoder.ReadPackedInt64(packed).status().ok()) {
86
49
          return;
87
49
        }
88
317
      } break;
89
440
      case kSint32:
90
440
        if (!decoder.ReadSint32().status().ok()) {
91
146
          return;
92
146
        }
93
294
        break;
94
439
      case kPackedSint32: {
95
439
        int32_t packed[kMaxRepeatedRead] = {0};
96
439
        if (!decoder.ReadPackedSint32(packed).status().ok()) {
97
138
          return;
98
138
        }
99
439
      } break;
100
301
      case kSint64:
101
240
        if (!decoder.ReadSint64().status().ok()) {
102
39
          return;
103
39
        }
104
201
        break;
105
313
      case kPackedSint64: {
106
313
        int64_t packed[kMaxRepeatedRead] = {0};
107
313
        if (!decoder.ReadPackedSint64(packed).status().ok()) {
108
38
          return;
109
38
        }
110
313
      } break;
111
275
      case kBool:
112
272
        if (!decoder.ReadBool().status().ok()) {
113
175
          return;
114
175
        }
115
97
        break;
116
372
      case kFixed32:
117
372
        if (!decoder.ReadFixed32().status().ok()) {
118
7
          return;
119
7
        }
120
365
        break;
121
365
      case kPackedFixed32: {
122
362
        uint32_t packed[kMaxRepeatedRead] = {0};
123
362
        if (!decoder.ReadPackedFixed32(packed).status().ok()) {
124
31
          return;
125
31
        }
126
362
      } break;
127
331
      case kFixed64:
128
209
        if (!decoder.ReadFixed64().status().ok()) {
129
10
          return;
130
10
        }
131
199
        break;
132
754
      case kPackedFixed64: {
133
754
        uint64_t packed[kMaxRepeatedRead] = {0};
134
754
        if (!decoder.ReadPackedFixed64(packed).status().ok()) {
135
42
          return;
136
42
        }
137
754
      } break;
138
712
      case kSfixed32:
139
396
        if (!decoder.ReadSfixed32().status().ok()) {
140
8
          return;
141
8
        }
142
388
        break;
143
388
      case kPackedSfixed32: {
144
343
        int32_t packed[kMaxRepeatedRead] = {0};
145
343
        if (!decoder.ReadPackedSfixed32(packed).status().ok()) {
146
38
          return;
147
38
        }
148
343
      } break;
149
305
      case kSfixed64:
150
210
        if (!decoder.ReadSfixed64().status().ok()) {
151
8
          return;
152
8
        }
153
202
        break;
154
458
      case kPackedSfixed64: {
155
458
        int64_t packed[kMaxRepeatedRead] = {0};
156
458
        if (!decoder.ReadPackedSfixed64(packed).status().ok()) {
157
36
          return;
158
36
        }
159
458
      } break;
160
422
      case kFloat:
161
254
        if (!decoder.ReadFloat().status().ok()) {
162
14
          return;
163
14
        }
164
240
        break;
165
387
      case kPackedFloat: {
166
387
        float packed[kMaxRepeatedRead] = {0};
167
387
        if (!decoder.ReadPackedFloat(packed).status().ok()) {
168
44
          return;
169
44
        }
170
387
      } break;
171
343
      case kDouble:
172
206
        if (!decoder.ReadDouble().status().ok()) {
173
7
          return;
174
7
        }
175
199
        break;
176
308
      case kPackedDouble: {
177
308
        double packed[kMaxRepeatedRead] = {0};
178
308
        if (!decoder.ReadPackedDouble(packed).status().ok()) {
179
30
          return;
180
30
        }
181
308
      } break;
182
512
      case kBytes: {
183
512
        std::byte bytes[kMaxRepeatedRead] = {std::byte{0}};
184
512
        if (!decoder.ReadBytes(bytes).status().ok()) {
185
72
          return;
186
72
        }
187
512
      } break;
188
551
      case kString: {
189
551
        char str[kMaxRepeatedRead] = {0};
190
551
        if (!decoder.ReadString(str).status().ok()) {
191
70
          return;
192
70
        }
193
551
      } break;
194
3.12k
      case kPush: {
195
3.12k
        StreamDecoder nested_decoder = decoder.GetNestedDecoder();
196
3.12k
        RecursiveFuzzedDecode(provider, nested_decoder, depth + 1);
197
3.12k
      } break;
198
0
      case kPop:
199
0
        if (depth > 0) {
200
          // Special "field". The marks the end of a nested message.
201
0
          return;
202
0
        }
203
13.0k
    }
204
13.0k
  }
205
4.75k
}
206
207
2.41k
void TestOneInput(FuzzedDataProvider& provider) {
208
2.41k
  constexpr size_t kMaxFuzzedProtoSize = 4096;
209
2.41k
  std::vector<std::byte> proto_message_data = provider.ConsumeBytes<std::byte>(
210
2.41k
      provider.ConsumeIntegralInRange<size_t>(0, kMaxFuzzedProtoSize));
211
2.41k
  stream::MemoryReader memory_reader(proto_message_data);
212
2.41k
  StreamDecoder decoder(memory_reader);
213
2.41k
  RecursiveFuzzedDecode(provider, decoder);
214
2.41k
}
215
216
}  // namespace
217
}  // namespace pw::protobuf::fuzz
218
219
6.89k
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
220
6.89k
  FuzzedDataProvider provider(data, size);
221
6.89k
  pw::protobuf::fuzz::TestOneInput(provider);
222
6.89k
  return 0;
223
6.89k
}