xref: /aosp_15_r20/external/cronet/base/pickle_fuzzer.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2018 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <fuzzer/FuzzedDataProvider.h>
6 
7 #include <tuple>
8 
9 #include "base/containers/span.h"
10 #include "base/pickle.h"
11 
12 namespace {
13 constexpr int kIterations = 16;
14 constexpr int kReadControlBytes = 32;
15 constexpr int kReadDataTypes = 17;
16 constexpr int kMaxReadLength = 1024;
17 constexpr int kMaxSkipBytes = 1024;
18 }  // namespace
19 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)20 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
21   if (size < kReadControlBytes) {
22     return 0;
23   }
24   // Use the first kReadControlBytes bytes of the fuzzer input to control how
25   // the pickled data is read.
26   FuzzedDataProvider data_provider(data, kReadControlBytes);
27   data += kReadControlBytes;
28   size -= kReadControlBytes;
29 
30   base::Pickle pickle =
31       base::Pickle::WithUnownedBuffer(UNSAFE_BUFFERS(base::span(data, size)));
32   base::PickleIterator iter(pickle);
33   for (int i = 0; i < kIterations; i++) {
34     uint8_t read_type = data_provider.ConsumeIntegral<uint8_t>();
35     switch (read_type % kReadDataTypes) {
36       case 0: {
37         bool result = 0;
38         std::ignore = iter.ReadBool(&result);
39         break;
40       }
41       case 1: {
42         int result = 0;
43         std::ignore = iter.ReadInt(&result);
44         break;
45       }
46       case 2: {
47         long result = 0;
48         std::ignore = iter.ReadLong(&result);
49         break;
50       }
51       case 3: {
52         uint16_t result = 0;
53         std::ignore = iter.ReadUInt16(&result);
54         break;
55       }
56       case 4: {
57         uint32_t result = 0;
58         std::ignore = iter.ReadUInt32(&result);
59         break;
60       }
61       case 5: {
62         int64_t result = 0;
63         std::ignore = iter.ReadInt64(&result);
64         break;
65       }
66       case 6: {
67         uint64_t result = 0;
68         std::ignore = iter.ReadUInt64(&result);
69         break;
70       }
71       case 7: {
72         float result = 0;
73         std::ignore = iter.ReadFloat(&result);
74         break;
75       }
76       case 8: {
77         double result = 0;
78         std::ignore = iter.ReadDouble(&result);
79         break;
80       }
81       case 9: {
82         std::string result;
83         std::ignore = iter.ReadString(&result);
84         break;
85       }
86       case 10: {
87         base::StringPiece result;
88         std::ignore = iter.ReadStringPiece(&result);
89         break;
90       }
91       case 11: {
92         std::u16string result;
93         std::ignore = iter.ReadString16(&result);
94         break;
95       }
96       case 12: {
97         base::StringPiece16 result;
98         std::ignore = iter.ReadStringPiece16(&result);
99         break;
100       }
101       case 13: {
102         const char* data_result = nullptr;
103         size_t length_result = 0;
104         std::ignore = iter.ReadData(&data_result, &length_result);
105         break;
106       }
107       case 14: {
108         const char* data_result = nullptr;
109         int read_length =
110             data_provider.ConsumeIntegralInRange(0, kMaxReadLength);
111         std::ignore =
112             iter.ReadBytes(&data_result, static_cast<size_t>(read_length));
113         break;
114       }
115       case 15: {
116         size_t result = 0;
117         std::ignore = iter.ReadLength(&result);
118         break;
119       }
120       case 16: {
121         std::ignore = iter.SkipBytes(static_cast<size_t>(
122             data_provider.ConsumeIntegralInRange(0, kMaxSkipBytes)));
123         break;
124       }
125     }
126   }
127 
128   return 0;
129 }
130