xref: /aosp_15_r20/external/pigweed/pw_protobuf/encoder_fuzzer.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1*61c4878aSAndroid Build Coastguard Worker // Copyright 2019 The Pigweed Authors
2*61c4878aSAndroid Build Coastguard Worker //
3*61c4878aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4*61c4878aSAndroid Build Coastguard Worker // use this file except in compliance with the License. You may obtain a copy of
5*61c4878aSAndroid Build Coastguard Worker // the License at
6*61c4878aSAndroid Build Coastguard Worker //
7*61c4878aSAndroid Build Coastguard Worker //     https://www.apache.org/licenses/LICENSE-2.0
8*61c4878aSAndroid Build Coastguard Worker //
9*61c4878aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*61c4878aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11*61c4878aSAndroid Build Coastguard Worker // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12*61c4878aSAndroid Build Coastguard Worker // License for the specific language governing permissions and limitations under
13*61c4878aSAndroid Build Coastguard Worker // the License.
14*61c4878aSAndroid Build Coastguard Worker 
15*61c4878aSAndroid Build Coastguard Worker #include <cstddef>
16*61c4878aSAndroid Build Coastguard Worker #include <cstdint>
17*61c4878aSAndroid Build Coastguard Worker #include <cstring>
18*61c4878aSAndroid Build Coastguard Worker #include <vector>
19*61c4878aSAndroid Build Coastguard Worker 
20*61c4878aSAndroid Build Coastguard Worker #include "fuzz.h"
21*61c4878aSAndroid Build Coastguard Worker #include "pw_fuzzer/asan_interface.h"
22*61c4878aSAndroid Build Coastguard Worker #include "pw_fuzzer/fuzzed_data_provider.h"
23*61c4878aSAndroid Build Coastguard Worker #include "pw_protobuf/encoder.h"
24*61c4878aSAndroid Build Coastguard Worker #include "pw_span/span.h"
25*61c4878aSAndroid Build Coastguard Worker 
26*61c4878aSAndroid Build Coastguard Worker namespace pw::protobuf::fuzz {
27*61c4878aSAndroid Build Coastguard Worker namespace {
28*61c4878aSAndroid Build Coastguard Worker 
29*61c4878aSAndroid Build Coastguard Worker // TODO: b/235289495 - Move this to pw_fuzzer/fuzzed_data_provider.h
30*61c4878aSAndroid Build Coastguard Worker 
31*61c4878aSAndroid Build Coastguard Worker // Uses the given |provider| to pick and return a number between 0 and the
32*61c4878aSAndroid Build Coastguard Worker // maximum numbers of T that can be generated from the remaining input data.
33*61c4878aSAndroid Build Coastguard Worker template <typename T>
ConsumeSize(FuzzedDataProvider & provider)34*61c4878aSAndroid Build Coastguard Worker size_t ConsumeSize(FuzzedDataProvider& provider) {
35*61c4878aSAndroid Build Coastguard Worker   size_t max = provider.remaining_bytes() / sizeof(T);
36*61c4878aSAndroid Build Coastguard Worker   return provider.ConsumeIntegralInRange<size_t>(0, max);
37*61c4878aSAndroid Build Coastguard Worker }
38*61c4878aSAndroid Build Coastguard Worker 
39*61c4878aSAndroid Build Coastguard Worker // Uses the given |provider| to generate several instances of T, store them in
40*61c4878aSAndroid Build Coastguard Worker // |data|, and then return a span to them. It is the caller's responsbility
41*61c4878aSAndroid Build Coastguard Worker // to ensure |data| remains in scope as long as the returned span.
42*61c4878aSAndroid Build Coastguard Worker template <typename T>
ConsumeSpan(FuzzedDataProvider & provider,std::vector<T> * data)43*61c4878aSAndroid Build Coastguard Worker span<const T> ConsumeSpan(FuzzedDataProvider& provider, std::vector<T>* data) {
44*61c4878aSAndroid Build Coastguard Worker   size_t num = ConsumeSize<T>(provider);
45*61c4878aSAndroid Build Coastguard Worker   size_t off = data->size();
46*61c4878aSAndroid Build Coastguard Worker   if (num == 0) {
47*61c4878aSAndroid Build Coastguard Worker     return span<const T>();
48*61c4878aSAndroid Build Coastguard Worker   }
49*61c4878aSAndroid Build Coastguard Worker 
50*61c4878aSAndroid Build Coastguard Worker   data->reserve(off + num);
51*61c4878aSAndroid Build Coastguard Worker   for (size_t i = 0; i < num; ++i) {
52*61c4878aSAndroid Build Coastguard Worker     if constexpr (std::is_floating_point<T>::value) {
53*61c4878aSAndroid Build Coastguard Worker       data->push_back(provider.ConsumeFloatingPoint<T>());
54*61c4878aSAndroid Build Coastguard Worker     } else {
55*61c4878aSAndroid Build Coastguard Worker       data->push_back(provider.ConsumeIntegral<T>());
56*61c4878aSAndroid Build Coastguard Worker     }
57*61c4878aSAndroid Build Coastguard Worker   }
58*61c4878aSAndroid Build Coastguard Worker   return span(&((*data)[off]), num);
59*61c4878aSAndroid Build Coastguard Worker }
60*61c4878aSAndroid Build Coastguard Worker 
61*61c4878aSAndroid Build Coastguard Worker // Uses the given |provider| to generate a string, store it in |data|, and
62*61c4878aSAndroid Build Coastguard Worker // return a C-style representation. It is the caller's responsbility to
63*61c4878aSAndroid Build Coastguard Worker // ensure |data| remains in scope as long as the returned char*.
ConsumeString(FuzzedDataProvider & provider,std::vector<std::string> * data)64*61c4878aSAndroid Build Coastguard Worker const char* ConsumeString(FuzzedDataProvider& provider,
65*61c4878aSAndroid Build Coastguard Worker                           std::vector<std::string>* data) {
66*61c4878aSAndroid Build Coastguard Worker   size_t off = data->size();
67*61c4878aSAndroid Build Coastguard Worker   // OSS-Fuzz's clang doesn't have the zero-parameter version of
68*61c4878aSAndroid Build Coastguard Worker   // ConsumeRandomLengthString yet.
69*61c4878aSAndroid Build Coastguard Worker   size_t max_length = std::numeric_limits<size_t>::max();
70*61c4878aSAndroid Build Coastguard Worker   data->push_back(provider.ConsumeRandomLengthString(max_length));
71*61c4878aSAndroid Build Coastguard Worker   return (*data)[off].c_str();
72*61c4878aSAndroid Build Coastguard Worker }
73*61c4878aSAndroid Build Coastguard Worker 
74*61c4878aSAndroid Build Coastguard Worker // Uses the given |provider| to generate non-arithmetic bytes, store them in
75*61c4878aSAndroid Build Coastguard Worker // |data|, and return a span to them. It is the caller's responsbility to
76*61c4878aSAndroid Build Coastguard Worker // ensure |data| remains in scope as long as the returned span.
ConsumeBytes(FuzzedDataProvider & provider,std::vector<std::byte> * data)77*61c4878aSAndroid Build Coastguard Worker span<const std::byte> ConsumeBytes(FuzzedDataProvider& provider,
78*61c4878aSAndroid Build Coastguard Worker                                    std::vector<std::byte>* data) {
79*61c4878aSAndroid Build Coastguard Worker   size_t num = ConsumeSize<std::byte>(provider);
80*61c4878aSAndroid Build Coastguard Worker   auto added = provider.ConsumeBytes<std::byte>(num);
81*61c4878aSAndroid Build Coastguard Worker   size_t off = data->size();
82*61c4878aSAndroid Build Coastguard Worker   num = added.size();
83*61c4878aSAndroid Build Coastguard Worker   data->insert(data->end(), added.begin(), added.end());
84*61c4878aSAndroid Build Coastguard Worker   // It's possible nothing was added, and the vector was empty to begin with.
85*61c4878aSAndroid Build Coastguard Worker   if (data->empty()) {
86*61c4878aSAndroid Build Coastguard Worker     return span<const std::byte>();
87*61c4878aSAndroid Build Coastguard Worker   }
88*61c4878aSAndroid Build Coastguard Worker   return span(&((*data)[off]), num);
89*61c4878aSAndroid Build Coastguard Worker }
90*61c4878aSAndroid Build Coastguard Worker 
RecursiveFuzzedEncode(FuzzedDataProvider & provider,StreamEncoder & encoder,uint32_t depth=0)91*61c4878aSAndroid Build Coastguard Worker void RecursiveFuzzedEncode(FuzzedDataProvider& provider,
92*61c4878aSAndroid Build Coastguard Worker                            StreamEncoder& encoder,
93*61c4878aSAndroid Build Coastguard Worker                            uint32_t depth = 0) {
94*61c4878aSAndroid Build Coastguard Worker   constexpr size_t kMaxDepth = 256;
95*61c4878aSAndroid Build Coastguard Worker   if (depth > kMaxDepth) {
96*61c4878aSAndroid Build Coastguard Worker     return;
97*61c4878aSAndroid Build Coastguard Worker   }
98*61c4878aSAndroid Build Coastguard Worker 
99*61c4878aSAndroid Build Coastguard Worker   // Storage for generated spans
100*61c4878aSAndroid Build Coastguard Worker   std::vector<uint32_t> u32s;
101*61c4878aSAndroid Build Coastguard Worker   std::vector<uint64_t> u64s;
102*61c4878aSAndroid Build Coastguard Worker   std::vector<int32_t> s32s;
103*61c4878aSAndroid Build Coastguard Worker   std::vector<int64_t> s64s;
104*61c4878aSAndroid Build Coastguard Worker   std::vector<float> floats;
105*61c4878aSAndroid Build Coastguard Worker   std::vector<double> doubles;
106*61c4878aSAndroid Build Coastguard Worker   std::vector<std::string> strings;
107*61c4878aSAndroid Build Coastguard Worker   std::vector<std::byte> bytes;
108*61c4878aSAndroid Build Coastguard Worker 
109*61c4878aSAndroid Build Coastguard Worker   // Consume the fuzzing input, using it to generate a sequence of fields to
110*61c4878aSAndroid Build Coastguard Worker   // encode. Both the uint32_t field IDs and the fields values are generated.
111*61c4878aSAndroid Build Coastguard Worker   // Don't try to detect errors, ensures pushes and pops are balanced, or
112*61c4878aSAndroid Build Coastguard Worker   // otherwise hold the interface correctly. Instead, fuzz the widest possbile
113*61c4878aSAndroid Build Coastguard Worker   // set of inputs to the encoder to ensure it doesn't misbehave.
114*61c4878aSAndroid Build Coastguard Worker   while (provider.remaining_bytes() != 0) {
115*61c4878aSAndroid Build Coastguard Worker     switch (provider.ConsumeEnum<FieldType>()) {
116*61c4878aSAndroid Build Coastguard Worker       case kUint32:
117*61c4878aSAndroid Build Coastguard Worker         encoder
118*61c4878aSAndroid Build Coastguard Worker             .WriteUint32(provider.ConsumeIntegral<uint32_t>(),
119*61c4878aSAndroid Build Coastguard Worker                          provider.ConsumeIntegral<uint32_t>())
120*61c4878aSAndroid Build Coastguard Worker             .IgnoreError();
121*61c4878aSAndroid Build Coastguard Worker         break;
122*61c4878aSAndroid Build Coastguard Worker       case kPackedUint32:
123*61c4878aSAndroid Build Coastguard Worker         encoder
124*61c4878aSAndroid Build Coastguard Worker             .WritePackedUint32(provider.ConsumeIntegral<uint32_t>(),
125*61c4878aSAndroid Build Coastguard Worker                                ConsumeSpan<uint32_t>(provider, &u32s))
126*61c4878aSAndroid Build Coastguard Worker             .IgnoreError();
127*61c4878aSAndroid Build Coastguard Worker         break;
128*61c4878aSAndroid Build Coastguard Worker       case kUint64:
129*61c4878aSAndroid Build Coastguard Worker         encoder
130*61c4878aSAndroid Build Coastguard Worker             .WriteUint64(provider.ConsumeIntegral<uint32_t>(),
131*61c4878aSAndroid Build Coastguard Worker                          provider.ConsumeIntegral<uint64_t>())
132*61c4878aSAndroid Build Coastguard Worker             .IgnoreError();
133*61c4878aSAndroid Build Coastguard Worker         break;
134*61c4878aSAndroid Build Coastguard Worker       case kPackedUint64:
135*61c4878aSAndroid Build Coastguard Worker         encoder
136*61c4878aSAndroid Build Coastguard Worker             .WritePackedUint64(provider.ConsumeIntegral<uint32_t>(),
137*61c4878aSAndroid Build Coastguard Worker                                ConsumeSpan<uint64_t>(provider, &u64s))
138*61c4878aSAndroid Build Coastguard Worker             .IgnoreError();
139*61c4878aSAndroid Build Coastguard Worker         break;
140*61c4878aSAndroid Build Coastguard Worker       case kInt32:
141*61c4878aSAndroid Build Coastguard Worker         encoder
142*61c4878aSAndroid Build Coastguard Worker             .WriteInt32(provider.ConsumeIntegral<uint32_t>(),
143*61c4878aSAndroid Build Coastguard Worker                         provider.ConsumeIntegral<int32_t>())
144*61c4878aSAndroid Build Coastguard Worker             .IgnoreError();
145*61c4878aSAndroid Build Coastguard Worker         break;
146*61c4878aSAndroid Build Coastguard Worker       case kPackedInt32:
147*61c4878aSAndroid Build Coastguard Worker         encoder
148*61c4878aSAndroid Build Coastguard Worker             .WritePackedInt32(provider.ConsumeIntegral<uint32_t>(),
149*61c4878aSAndroid Build Coastguard Worker                               ConsumeSpan<int32_t>(provider, &s32s))
150*61c4878aSAndroid Build Coastguard Worker             .IgnoreError();
151*61c4878aSAndroid Build Coastguard Worker         break;
152*61c4878aSAndroid Build Coastguard Worker       case kInt64:
153*61c4878aSAndroid Build Coastguard Worker         encoder
154*61c4878aSAndroid Build Coastguard Worker             .WriteInt64(provider.ConsumeIntegral<uint32_t>(),
155*61c4878aSAndroid Build Coastguard Worker                         provider.ConsumeIntegral<int64_t>())
156*61c4878aSAndroid Build Coastguard Worker             .IgnoreError();
157*61c4878aSAndroid Build Coastguard Worker         break;
158*61c4878aSAndroid Build Coastguard Worker       case kPackedInt64:
159*61c4878aSAndroid Build Coastguard Worker         encoder
160*61c4878aSAndroid Build Coastguard Worker             .WritePackedInt64(provider.ConsumeIntegral<uint32_t>(),
161*61c4878aSAndroid Build Coastguard Worker                               ConsumeSpan<int64_t>(provider, &s64s))
162*61c4878aSAndroid Build Coastguard Worker             .IgnoreError();
163*61c4878aSAndroid Build Coastguard Worker         break;
164*61c4878aSAndroid Build Coastguard Worker       case kSint32:
165*61c4878aSAndroid Build Coastguard Worker         encoder
166*61c4878aSAndroid Build Coastguard Worker             .WriteSint32(provider.ConsumeIntegral<uint32_t>(),
167*61c4878aSAndroid Build Coastguard Worker                          provider.ConsumeIntegral<int32_t>())
168*61c4878aSAndroid Build Coastguard Worker             .IgnoreError();
169*61c4878aSAndroid Build Coastguard Worker         break;
170*61c4878aSAndroid Build Coastguard Worker       case kPackedSint32:
171*61c4878aSAndroid Build Coastguard Worker         encoder
172*61c4878aSAndroid Build Coastguard Worker             .WritePackedSint32(provider.ConsumeIntegral<uint32_t>(),
173*61c4878aSAndroid Build Coastguard Worker                                ConsumeSpan<int32_t>(provider, &s32s))
174*61c4878aSAndroid Build Coastguard Worker             .IgnoreError();
175*61c4878aSAndroid Build Coastguard Worker         break;
176*61c4878aSAndroid Build Coastguard Worker       case kSint64:
177*61c4878aSAndroid Build Coastguard Worker         encoder
178*61c4878aSAndroid Build Coastguard Worker             .WriteSint64(provider.ConsumeIntegral<uint32_t>(),
179*61c4878aSAndroid Build Coastguard Worker                          provider.ConsumeIntegral<int64_t>())
180*61c4878aSAndroid Build Coastguard Worker             .IgnoreError();
181*61c4878aSAndroid Build Coastguard Worker         break;
182*61c4878aSAndroid Build Coastguard Worker       case kPackedSint64:
183*61c4878aSAndroid Build Coastguard Worker         encoder
184*61c4878aSAndroid Build Coastguard Worker             .WritePackedSint64(provider.ConsumeIntegral<uint32_t>(),
185*61c4878aSAndroid Build Coastguard Worker                                ConsumeSpan<int64_t>(provider, &s64s))
186*61c4878aSAndroid Build Coastguard Worker             .IgnoreError();
187*61c4878aSAndroid Build Coastguard Worker         break;
188*61c4878aSAndroid Build Coastguard Worker       case kBool:
189*61c4878aSAndroid Build Coastguard Worker         encoder
190*61c4878aSAndroid Build Coastguard Worker             .WriteBool(provider.ConsumeIntegral<uint32_t>(),
191*61c4878aSAndroid Build Coastguard Worker                        provider.ConsumeBool())
192*61c4878aSAndroid Build Coastguard Worker             .IgnoreError();
193*61c4878aSAndroid Build Coastguard Worker         break;
194*61c4878aSAndroid Build Coastguard Worker       case kFixed32:
195*61c4878aSAndroid Build Coastguard Worker         encoder
196*61c4878aSAndroid Build Coastguard Worker             .WriteFixed32(provider.ConsumeIntegral<uint32_t>(),
197*61c4878aSAndroid Build Coastguard Worker                           provider.ConsumeIntegral<uint32_t>())
198*61c4878aSAndroid Build Coastguard Worker             .IgnoreError();
199*61c4878aSAndroid Build Coastguard Worker         break;
200*61c4878aSAndroid Build Coastguard Worker       case kPackedFixed32:
201*61c4878aSAndroid Build Coastguard Worker         encoder
202*61c4878aSAndroid Build Coastguard Worker             .WritePackedFixed32(provider.ConsumeIntegral<uint32_t>(),
203*61c4878aSAndroid Build Coastguard Worker                                 ConsumeSpan<uint32_t>(provider, &u32s))
204*61c4878aSAndroid Build Coastguard Worker             .IgnoreError();
205*61c4878aSAndroid Build Coastguard Worker         break;
206*61c4878aSAndroid Build Coastguard Worker       case kFixed64:
207*61c4878aSAndroid Build Coastguard Worker         encoder
208*61c4878aSAndroid Build Coastguard Worker             .WriteFixed64(provider.ConsumeIntegral<uint32_t>(),
209*61c4878aSAndroid Build Coastguard Worker                           provider.ConsumeIntegral<uint64_t>())
210*61c4878aSAndroid Build Coastguard Worker             .IgnoreError();
211*61c4878aSAndroid Build Coastguard Worker         break;
212*61c4878aSAndroid Build Coastguard Worker       case kPackedFixed64:
213*61c4878aSAndroid Build Coastguard Worker         encoder
214*61c4878aSAndroid Build Coastguard Worker             .WritePackedFixed64(provider.ConsumeIntegral<uint32_t>(),
215*61c4878aSAndroid Build Coastguard Worker                                 ConsumeSpan<uint64_t>(provider, &u64s))
216*61c4878aSAndroid Build Coastguard Worker             .IgnoreError();
217*61c4878aSAndroid Build Coastguard Worker         break;
218*61c4878aSAndroid Build Coastguard Worker       case kSfixed32:
219*61c4878aSAndroid Build Coastguard Worker         encoder
220*61c4878aSAndroid Build Coastguard Worker             .WriteSfixed32(provider.ConsumeIntegral<uint32_t>(),
221*61c4878aSAndroid Build Coastguard Worker                            provider.ConsumeIntegral<int32_t>())
222*61c4878aSAndroid Build Coastguard Worker             .IgnoreError();
223*61c4878aSAndroid Build Coastguard Worker         break;
224*61c4878aSAndroid Build Coastguard Worker       case kPackedSfixed32:
225*61c4878aSAndroid Build Coastguard Worker         encoder
226*61c4878aSAndroid Build Coastguard Worker             .WritePackedSfixed32(provider.ConsumeIntegral<uint32_t>(),
227*61c4878aSAndroid Build Coastguard Worker                                  ConsumeSpan<int32_t>(provider, &s32s))
228*61c4878aSAndroid Build Coastguard Worker             .IgnoreError();
229*61c4878aSAndroid Build Coastguard Worker         break;
230*61c4878aSAndroid Build Coastguard Worker       case kSfixed64:
231*61c4878aSAndroid Build Coastguard Worker         encoder
232*61c4878aSAndroid Build Coastguard Worker             .WriteSfixed64(provider.ConsumeIntegral<uint32_t>(),
233*61c4878aSAndroid Build Coastguard Worker                            provider.ConsumeIntegral<int64_t>())
234*61c4878aSAndroid Build Coastguard Worker             .IgnoreError();
235*61c4878aSAndroid Build Coastguard Worker         break;
236*61c4878aSAndroid Build Coastguard Worker       case kPackedSfixed64:
237*61c4878aSAndroid Build Coastguard Worker         encoder
238*61c4878aSAndroid Build Coastguard Worker             .WritePackedSfixed64(provider.ConsumeIntegral<uint32_t>(),
239*61c4878aSAndroid Build Coastguard Worker                                  ConsumeSpan<int64_t>(provider, &s64s))
240*61c4878aSAndroid Build Coastguard Worker             .IgnoreError();
241*61c4878aSAndroid Build Coastguard Worker         break;
242*61c4878aSAndroid Build Coastguard Worker       case kFloat:
243*61c4878aSAndroid Build Coastguard Worker         encoder
244*61c4878aSAndroid Build Coastguard Worker             .WriteFloat(provider.ConsumeIntegral<uint32_t>(),
245*61c4878aSAndroid Build Coastguard Worker                         provider.ConsumeFloatingPoint<float>())
246*61c4878aSAndroid Build Coastguard Worker             .IgnoreError();
247*61c4878aSAndroid Build Coastguard Worker         break;
248*61c4878aSAndroid Build Coastguard Worker       case kPackedFloat:
249*61c4878aSAndroid Build Coastguard Worker         encoder
250*61c4878aSAndroid Build Coastguard Worker             .WritePackedFloat(provider.ConsumeIntegral<uint32_t>(),
251*61c4878aSAndroid Build Coastguard Worker                               ConsumeSpan<float>(provider, &floats))
252*61c4878aSAndroid Build Coastguard Worker             .IgnoreError();
253*61c4878aSAndroid Build Coastguard Worker         break;
254*61c4878aSAndroid Build Coastguard Worker       case kDouble:
255*61c4878aSAndroid Build Coastguard Worker         encoder
256*61c4878aSAndroid Build Coastguard Worker             .WriteDouble(provider.ConsumeIntegral<uint32_t>(),
257*61c4878aSAndroid Build Coastguard Worker                          provider.ConsumeFloatingPoint<double>())
258*61c4878aSAndroid Build Coastguard Worker             .IgnoreError();
259*61c4878aSAndroid Build Coastguard Worker         break;
260*61c4878aSAndroid Build Coastguard Worker       case kPackedDouble:
261*61c4878aSAndroid Build Coastguard Worker         encoder
262*61c4878aSAndroid Build Coastguard Worker             .WritePackedDouble(provider.ConsumeIntegral<uint32_t>(),
263*61c4878aSAndroid Build Coastguard Worker                                ConsumeSpan<double>(provider, &doubles))
264*61c4878aSAndroid Build Coastguard Worker             .IgnoreError();
265*61c4878aSAndroid Build Coastguard Worker         break;
266*61c4878aSAndroid Build Coastguard Worker       case kBytes:
267*61c4878aSAndroid Build Coastguard Worker         encoder
268*61c4878aSAndroid Build Coastguard Worker             .WriteBytes(provider.ConsumeIntegral<uint32_t>(),
269*61c4878aSAndroid Build Coastguard Worker                         ConsumeBytes(provider, &bytes))
270*61c4878aSAndroid Build Coastguard Worker             .IgnoreError();
271*61c4878aSAndroid Build Coastguard Worker         break;
272*61c4878aSAndroid Build Coastguard Worker       case kString:
273*61c4878aSAndroid Build Coastguard Worker         encoder
274*61c4878aSAndroid Build Coastguard Worker             .WriteString(provider.ConsumeIntegral<uint32_t>(),
275*61c4878aSAndroid Build Coastguard Worker                          ConsumeString(provider, &strings))
276*61c4878aSAndroid Build Coastguard Worker             .IgnoreError();
277*61c4878aSAndroid Build Coastguard Worker         break;
278*61c4878aSAndroid Build Coastguard Worker       case kPush: {
279*61c4878aSAndroid Build Coastguard Worker         // Special "field". The marks the start of a nested message.
280*61c4878aSAndroid Build Coastguard Worker         StreamEncoder nested_encoder =
281*61c4878aSAndroid Build Coastguard Worker             encoder.GetNestedEncoder(provider.ConsumeIntegral<uint32_t>());
282*61c4878aSAndroid Build Coastguard Worker         RecursiveFuzzedEncode(provider, nested_encoder, depth + 1);
283*61c4878aSAndroid Build Coastguard Worker         break;
284*61c4878aSAndroid Build Coastguard Worker       }
285*61c4878aSAndroid Build Coastguard Worker       case kPop:
286*61c4878aSAndroid Build Coastguard Worker         if (depth > 0) {
287*61c4878aSAndroid Build Coastguard Worker           // Special "field". The marks the end of a nested message.
288*61c4878aSAndroid Build Coastguard Worker           return;
289*61c4878aSAndroid Build Coastguard Worker         }
290*61c4878aSAndroid Build Coastguard Worker     }
291*61c4878aSAndroid Build Coastguard Worker   }
292*61c4878aSAndroid Build Coastguard Worker }
293*61c4878aSAndroid Build Coastguard Worker 
TestOneInput(FuzzedDataProvider & provider)294*61c4878aSAndroid Build Coastguard Worker void TestOneInput(FuzzedDataProvider& provider) {
295*61c4878aSAndroid Build Coastguard Worker   static std::byte buffer[65536];
296*61c4878aSAndroid Build Coastguard Worker 
297*61c4878aSAndroid Build Coastguard Worker   // Pick a subset of the buffer that the fuzzer is allowed to use, and poison
298*61c4878aSAndroid Build Coastguard Worker   // the rest.
299*61c4878aSAndroid Build Coastguard Worker   size_t unpoisoned_length =
300*61c4878aSAndroid Build Coastguard Worker       provider.ConsumeIntegralInRange<size_t>(0, sizeof(buffer));
301*61c4878aSAndroid Build Coastguard Worker   ByteSpan unpoisoned(buffer, unpoisoned_length);
302*61c4878aSAndroid Build Coastguard Worker   void* poisoned = &buffer[unpoisoned_length];
303*61c4878aSAndroid Build Coastguard Worker   size_t poisoned_length = sizeof(buffer) - unpoisoned_length;
304*61c4878aSAndroid Build Coastguard Worker   ASAN_POISON_MEMORY_REGION(poisoned, poisoned_length);
305*61c4878aSAndroid Build Coastguard Worker 
306*61c4878aSAndroid Build Coastguard Worker   pw::protobuf::MemoryEncoder encoder(unpoisoned);
307*61c4878aSAndroid Build Coastguard Worker   RecursiveFuzzedEncode(provider, encoder);
308*61c4878aSAndroid Build Coastguard Worker 
309*61c4878aSAndroid Build Coastguard Worker   // Don't forget to unpoison for the next iteration!
310*61c4878aSAndroid Build Coastguard Worker   ASAN_UNPOISON_MEMORY_REGION(poisoned, poisoned_length);
311*61c4878aSAndroid Build Coastguard Worker }
312*61c4878aSAndroid Build Coastguard Worker 
313*61c4878aSAndroid Build Coastguard Worker }  // namespace
314*61c4878aSAndroid Build Coastguard Worker }  // namespace pw::protobuf::fuzz
315*61c4878aSAndroid Build Coastguard Worker 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)316*61c4878aSAndroid Build Coastguard Worker extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
317*61c4878aSAndroid Build Coastguard Worker   FuzzedDataProvider provider(data, size);
318*61c4878aSAndroid Build Coastguard Worker   pw::protobuf::fuzz::TestOneInput(provider);
319*61c4878aSAndroid Build Coastguard Worker   return 0;
320*61c4878aSAndroid Build Coastguard Worker }
321