1*1a96fba6SXin Li // Copyright 2019 The Chromium OS Authors. All rights reserved.
2*1a96fba6SXin Li // Use of this source code is governed by a BSD-style license that can be
3*1a96fba6SXin Li // found in the LICENSE file.
4*1a96fba6SXin Li
5*1a96fba6SXin Li #include <cmath>
6*1a96fba6SXin Li #include <cstddef>
7*1a96fba6SXin Li #include <cstdint>
8*1a96fba6SXin Li #include <map>
9*1a96fba6SXin Li #include <string>
10*1a96fba6SXin Li #include <utility>
11*1a96fba6SXin Li #include <vector>
12*1a96fba6SXin Li
13*1a96fba6SXin Li #include <base/logging.h>
14*1a96fba6SXin Li #include <base/strings/string_util.h>
15*1a96fba6SXin Li #include <brillo/dbus/data_serialization.h>
16*1a96fba6SXin Li #include <dbus/string_util.h>
17*1a96fba6SXin Li #include <fuzzer/FuzzedDataProvider.h>
18*1a96fba6SXin Li
19*1a96fba6SXin Li namespace {
20*1a96fba6SXin Li constexpr int kRandomMaxContainerSize = 8;
21*1a96fba6SXin Li constexpr int kRandomMaxDataLength = 128;
22*1a96fba6SXin Li
23*1a96fba6SXin Li typedef enum DataType {
24*1a96fba6SXin Li kUint8 = 0,
25*1a96fba6SXin Li kUint16,
26*1a96fba6SXin Li kUint32,
27*1a96fba6SXin Li kUint64,
28*1a96fba6SXin Li kInt16,
29*1a96fba6SXin Li kInt32,
30*1a96fba6SXin Li kInt64,
31*1a96fba6SXin Li kBool,
32*1a96fba6SXin Li kDouble,
33*1a96fba6SXin Li kString,
34*1a96fba6SXin Li kObjectPath,
35*1a96fba6SXin Li // A couple vector types.
36*1a96fba6SXin Li kVectorInt16,
37*1a96fba6SXin Li kVectorString,
38*1a96fba6SXin Li // A couple pair types.
39*1a96fba6SXin Li kPairBoolInt64,
40*1a96fba6SXin Li kPairUint32String,
41*1a96fba6SXin Li // A couple tuple types.
42*1a96fba6SXin Li kTupleUint16StringBool,
43*1a96fba6SXin Li kTupleDoubleInt32ObjectPath,
44*1a96fba6SXin Li // A couple map types.
45*1a96fba6SXin Li kMapInt32String,
46*1a96fba6SXin Li kMapDoubleBool,
47*1a96fba6SXin Li kMaxValue = kMapDoubleBool,
48*1a96fba6SXin Li } DataType;
49*1a96fba6SXin Li
50*1a96fba6SXin Li template <typename T>
AppendValue(dbus::MessageWriter * writer,bool variant,const T & value)51*1a96fba6SXin Li void AppendValue(dbus::MessageWriter* writer, bool variant, const T& value) {
52*1a96fba6SXin Li if (variant)
53*1a96fba6SXin Li brillo::dbus_utils::AppendValueToWriterAsVariant(writer, value);
54*1a96fba6SXin Li else
55*1a96fba6SXin Li brillo::dbus_utils::AppendValueToWriter(writer, value);
56*1a96fba6SXin Li }
57*1a96fba6SXin Li
58*1a96fba6SXin Li template <typename T>
GenerateIntAndAppendValue(FuzzedDataProvider * data_provider,dbus::MessageWriter * writer,bool variant)59*1a96fba6SXin Li void GenerateIntAndAppendValue(FuzzedDataProvider* data_provider,
60*1a96fba6SXin Li dbus::MessageWriter* writer,
61*1a96fba6SXin Li bool variant) {
62*1a96fba6SXin Li AppendValue(writer, variant, data_provider->ConsumeIntegral<T>());
63*1a96fba6SXin Li }
64*1a96fba6SXin Li
65*1a96fba6SXin Li template <typename T>
PopValue(dbus::MessageReader * reader,bool variant,T * value)66*1a96fba6SXin Li void PopValue(dbus::MessageReader* reader, bool variant, T* value) {
67*1a96fba6SXin Li if (variant)
68*1a96fba6SXin Li brillo::dbus_utils::PopVariantValueFromReader(reader, value);
69*1a96fba6SXin Li else
70*1a96fba6SXin Li brillo::dbus_utils::PopValueFromReader(reader, value);
71*1a96fba6SXin Li }
72*1a96fba6SXin Li
GenerateValidUTF8(FuzzedDataProvider * data_provider)73*1a96fba6SXin Li std::string GenerateValidUTF8(FuzzedDataProvider* data_provider) {
74*1a96fba6SXin Li // >= 0x80
75*1a96fba6SXin Li // Generates a random string and returns it if it is valid UTF8, if it is not
76*1a96fba6SXin Li // then it will strip it down to all the 7-bit ASCII chars and just return
77*1a96fba6SXin Li // that string.
78*1a96fba6SXin Li std::string str =
79*1a96fba6SXin Li data_provider->ConsumeRandomLengthString(kRandomMaxDataLength);
80*1a96fba6SXin Li if (base::IsStringUTF8(str))
81*1a96fba6SXin Li return str;
82*1a96fba6SXin Li for (auto it = str.begin(); it != str.end(); it++) {
83*1a96fba6SXin Li if (static_cast<uint8_t>(*it) >= 0x80) {
84*1a96fba6SXin Li // Might be invalid, remove it.
85*1a96fba6SXin Li it = str.erase(it);
86*1a96fba6SXin Li it--;
87*1a96fba6SXin Li }
88*1a96fba6SXin Li }
89*1a96fba6SXin Li return str;
90*1a96fba6SXin Li }
91*1a96fba6SXin Li
92*1a96fba6SXin Li } // namespace
93*1a96fba6SXin Li
94*1a96fba6SXin Li class Environment {
95*1a96fba6SXin Li public:
Environment()96*1a96fba6SXin Li Environment() {
97*1a96fba6SXin Li // Disable logging.
98*1a96fba6SXin Li logging::SetMinLogLevel(logging::LOG_FATAL);
99*1a96fba6SXin Li }
100*1a96fba6SXin Li };
101*1a96fba6SXin Li
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)102*1a96fba6SXin Li extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
103*1a96fba6SXin Li static Environment env;
104*1a96fba6SXin Li FuzzedDataProvider data_provider(data, size);
105*1a96fba6SXin Li // Consume a random fraction of our data writing random things to a D-Bus
106*1a96fba6SXin Li // message, and then consume the remaining data reading randomly from that
107*1a96fba6SXin Li // same D-Bus message. Given the templated nature of these functions and that
108*1a96fba6SXin Li // they support essentially an infinite amount of types, we are constraining
109*1a96fba6SXin Li // this to a fixed set of types defined above.
110*1a96fba6SXin Li std::unique_ptr<dbus::Response> message = dbus::Response::CreateEmpty();
111*1a96fba6SXin Li dbus::MessageWriter writer(message.get());
112*1a96fba6SXin Li
113*1a96fba6SXin Li int bytes_left_for_read =
114*1a96fba6SXin Li static_cast<int>(data_provider.ConsumeProbability<float>() * size);
115*1a96fba6SXin Li while (data_provider.remaining_bytes() > bytes_left_for_read) {
116*1a96fba6SXin Li DataType curr_type = data_provider.ConsumeEnum<DataType>();
117*1a96fba6SXin Li bool variant = data_provider.ConsumeBool();
118*1a96fba6SXin Li switch (curr_type) {
119*1a96fba6SXin Li case kUint8:
120*1a96fba6SXin Li GenerateIntAndAppendValue<uint8_t>(&data_provider, &writer, variant);
121*1a96fba6SXin Li break;
122*1a96fba6SXin Li case kUint16:
123*1a96fba6SXin Li GenerateIntAndAppendValue<uint16_t>(&data_provider, &writer, variant);
124*1a96fba6SXin Li break;
125*1a96fba6SXin Li case kUint32:
126*1a96fba6SXin Li GenerateIntAndAppendValue<uint32_t>(&data_provider, &writer, variant);
127*1a96fba6SXin Li break;
128*1a96fba6SXin Li case kUint64:
129*1a96fba6SXin Li GenerateIntAndAppendValue<uint64_t>(&data_provider, &writer, variant);
130*1a96fba6SXin Li break;
131*1a96fba6SXin Li case kInt16:
132*1a96fba6SXin Li GenerateIntAndAppendValue<int16_t>(&data_provider, &writer, variant);
133*1a96fba6SXin Li break;
134*1a96fba6SXin Li case kInt32:
135*1a96fba6SXin Li GenerateIntAndAppendValue<int32_t>(&data_provider, &writer, variant);
136*1a96fba6SXin Li break;
137*1a96fba6SXin Li case kInt64:
138*1a96fba6SXin Li GenerateIntAndAppendValue<int64_t>(&data_provider, &writer, variant);
139*1a96fba6SXin Li break;
140*1a96fba6SXin Li case kBool:
141*1a96fba6SXin Li AppendValue(&writer, variant, data_provider.ConsumeBool());
142*1a96fba6SXin Li break;
143*1a96fba6SXin Li case kDouble:
144*1a96fba6SXin Li AppendValue(&writer, variant,
145*1a96fba6SXin Li data_provider.ConsumeProbability<double>());
146*1a96fba6SXin Li break;
147*1a96fba6SXin Li case kString:
148*1a96fba6SXin Li AppendValue(&writer, variant, GenerateValidUTF8(&data_provider));
149*1a96fba6SXin Li break;
150*1a96fba6SXin Li case kObjectPath: {
151*1a96fba6SXin Li std::string object_path =
152*1a96fba6SXin Li data_provider.ConsumeRandomLengthString(kRandomMaxDataLength);
153*1a96fba6SXin Li // If this isn't valid we'll hit a CHECK failure.
154*1a96fba6SXin Li if (dbus::IsValidObjectPath(object_path))
155*1a96fba6SXin Li AppendValue(&writer, variant, dbus::ObjectPath(object_path));
156*1a96fba6SXin Li break;
157*1a96fba6SXin Li }
158*1a96fba6SXin Li case kVectorInt16: {
159*1a96fba6SXin Li int vec_size = data_provider.ConsumeIntegralInRange<int>(
160*1a96fba6SXin Li 0, kRandomMaxContainerSize);
161*1a96fba6SXin Li std::vector<int16_t> vec(vec_size);
162*1a96fba6SXin Li for (int i = 0; i < vec_size; i++)
163*1a96fba6SXin Li vec[i] = data_provider.ConsumeIntegral<int16_t>();
164*1a96fba6SXin Li AppendValue(&writer, variant, vec);
165*1a96fba6SXin Li break;
166*1a96fba6SXin Li }
167*1a96fba6SXin Li case kVectorString: {
168*1a96fba6SXin Li int vec_size = data_provider.ConsumeIntegralInRange<int>(
169*1a96fba6SXin Li 0, kRandomMaxContainerSize);
170*1a96fba6SXin Li std::vector<std::string> vec(vec_size);
171*1a96fba6SXin Li for (int i = 0; i < vec_size; i++)
172*1a96fba6SXin Li vec[i] = GenerateValidUTF8(&data_provider);
173*1a96fba6SXin Li AppendValue(&writer, variant, vec);
174*1a96fba6SXin Li break;
175*1a96fba6SXin Li }
176*1a96fba6SXin Li case kPairBoolInt64:
177*1a96fba6SXin Li AppendValue(
178*1a96fba6SXin Li &writer, variant,
179*1a96fba6SXin Li std::pair<bool, int64_t>{data_provider.ConsumeBool(),
180*1a96fba6SXin Li data_provider.ConsumeIntegral<int64_t>()});
181*1a96fba6SXin Li break;
182*1a96fba6SXin Li case kPairUint32String:
183*1a96fba6SXin Li AppendValue(&writer, variant,
184*1a96fba6SXin Li std::pair<uint32_t, std::string>{
185*1a96fba6SXin Li data_provider.ConsumeIntegral<uint32_t>(),
186*1a96fba6SXin Li GenerateValidUTF8(&data_provider)});
187*1a96fba6SXin Li break;
188*1a96fba6SXin Li case kTupleUint16StringBool:
189*1a96fba6SXin Li AppendValue(&writer, variant,
190*1a96fba6SXin Li std::tuple<uint32_t, std::string, bool>{
191*1a96fba6SXin Li data_provider.ConsumeIntegral<uint32_t>(),
192*1a96fba6SXin Li GenerateValidUTF8(&data_provider),
193*1a96fba6SXin Li data_provider.ConsumeBool()});
194*1a96fba6SXin Li break;
195*1a96fba6SXin Li case kTupleDoubleInt32ObjectPath: {
196*1a96fba6SXin Li std::string object_path =
197*1a96fba6SXin Li data_provider.ConsumeRandomLengthString(kRandomMaxDataLength);
198*1a96fba6SXin Li // If this isn't valid we'll hit a CHECK failure.
199*1a96fba6SXin Li if (dbus::IsValidObjectPath(object_path)) {
200*1a96fba6SXin Li AppendValue(&writer, variant,
201*1a96fba6SXin Li std::tuple<double, int32_t, dbus::ObjectPath>{
202*1a96fba6SXin Li data_provider.ConsumeProbability<double>(),
203*1a96fba6SXin Li data_provider.ConsumeIntegral<int32_t>(),
204*1a96fba6SXin Li dbus::ObjectPath(object_path)});
205*1a96fba6SXin Li }
206*1a96fba6SXin Li break;
207*1a96fba6SXin Li }
208*1a96fba6SXin Li case kMapInt32String: {
209*1a96fba6SXin Li int map_size = data_provider.ConsumeIntegralInRange<int>(
210*1a96fba6SXin Li 0, kRandomMaxContainerSize);
211*1a96fba6SXin Li std::map<int32_t, std::string> map;
212*1a96fba6SXin Li for (int i = 0; i < map_size; i++)
213*1a96fba6SXin Li map[data_provider.ConsumeIntegral<int32_t>()] =
214*1a96fba6SXin Li GenerateValidUTF8(&data_provider);
215*1a96fba6SXin Li AppendValue(&writer, variant, map);
216*1a96fba6SXin Li break;
217*1a96fba6SXin Li }
218*1a96fba6SXin Li case kMapDoubleBool: {
219*1a96fba6SXin Li int map_size = data_provider.ConsumeIntegralInRange<int>(
220*1a96fba6SXin Li 0, kRandomMaxContainerSize);
221*1a96fba6SXin Li std::map<double, bool> map;
222*1a96fba6SXin Li for (int i = 0; i < map_size; i++)
223*1a96fba6SXin Li map[data_provider.ConsumeProbability<double>()] =
224*1a96fba6SXin Li data_provider.ConsumeBool();
225*1a96fba6SXin Li AppendValue(&writer, variant, map);
226*1a96fba6SXin Li break;
227*1a96fba6SXin Li }
228*1a96fba6SXin Li }
229*1a96fba6SXin Li }
230*1a96fba6SXin Li
231*1a96fba6SXin Li dbus::MessageReader reader(message.get());
232*1a96fba6SXin Li while (data_provider.remaining_bytes()) {
233*1a96fba6SXin Li DataType curr_type = data_provider.ConsumeEnum<DataType>();
234*1a96fba6SXin Li bool variant = data_provider.ConsumeBool();
235*1a96fba6SXin Li switch (curr_type) {
236*1a96fba6SXin Li case kUint8: {
237*1a96fba6SXin Li uint8_t value;
238*1a96fba6SXin Li PopValue(&reader, variant, &value);
239*1a96fba6SXin Li break;
240*1a96fba6SXin Li }
241*1a96fba6SXin Li case kUint16: {
242*1a96fba6SXin Li uint16_t value;
243*1a96fba6SXin Li PopValue(&reader, variant, &value);
244*1a96fba6SXin Li break;
245*1a96fba6SXin Li }
246*1a96fba6SXin Li case kUint32: {
247*1a96fba6SXin Li uint32_t value;
248*1a96fba6SXin Li PopValue(&reader, variant, &value);
249*1a96fba6SXin Li break;
250*1a96fba6SXin Li }
251*1a96fba6SXin Li case kUint64: {
252*1a96fba6SXin Li uint64_t value;
253*1a96fba6SXin Li PopValue(&reader, variant, &value);
254*1a96fba6SXin Li break;
255*1a96fba6SXin Li }
256*1a96fba6SXin Li case kInt16: {
257*1a96fba6SXin Li int16_t value;
258*1a96fba6SXin Li PopValue(&reader, variant, &value);
259*1a96fba6SXin Li break;
260*1a96fba6SXin Li }
261*1a96fba6SXin Li case kInt32: {
262*1a96fba6SXin Li int32_t value;
263*1a96fba6SXin Li PopValue(&reader, variant, &value);
264*1a96fba6SXin Li break;
265*1a96fba6SXin Li }
266*1a96fba6SXin Li case kInt64: {
267*1a96fba6SXin Li int64_t value;
268*1a96fba6SXin Li PopValue(&reader, variant, &value);
269*1a96fba6SXin Li break;
270*1a96fba6SXin Li }
271*1a96fba6SXin Li case kBool: {
272*1a96fba6SXin Li bool value;
273*1a96fba6SXin Li PopValue(&reader, variant, &value);
274*1a96fba6SXin Li break;
275*1a96fba6SXin Li }
276*1a96fba6SXin Li case kDouble: {
277*1a96fba6SXin Li double value;
278*1a96fba6SXin Li PopValue(&reader, variant, &value);
279*1a96fba6SXin Li break;
280*1a96fba6SXin Li }
281*1a96fba6SXin Li case kString: {
282*1a96fba6SXin Li std::string value;
283*1a96fba6SXin Li PopValue(&reader, variant, &value);
284*1a96fba6SXin Li break;
285*1a96fba6SXin Li }
286*1a96fba6SXin Li case kObjectPath: {
287*1a96fba6SXin Li dbus::ObjectPath value;
288*1a96fba6SXin Li PopValue(&reader, variant, &value);
289*1a96fba6SXin Li break;
290*1a96fba6SXin Li }
291*1a96fba6SXin Li case kVectorInt16: {
292*1a96fba6SXin Li std::vector<int16_t> value;
293*1a96fba6SXin Li PopValue(&reader, variant, &value);
294*1a96fba6SXin Li break;
295*1a96fba6SXin Li }
296*1a96fba6SXin Li case kVectorString: {
297*1a96fba6SXin Li std::vector<std::string> value;
298*1a96fba6SXin Li PopValue(&reader, variant, &value);
299*1a96fba6SXin Li break;
300*1a96fba6SXin Li }
301*1a96fba6SXin Li case kPairBoolInt64: {
302*1a96fba6SXin Li std::pair<bool, int64_t> value;
303*1a96fba6SXin Li PopValue(&reader, variant, &value);
304*1a96fba6SXin Li break;
305*1a96fba6SXin Li }
306*1a96fba6SXin Li case kPairUint32String: {
307*1a96fba6SXin Li std::pair<uint32_t, std::string> value;
308*1a96fba6SXin Li PopValue(&reader, variant, &value);
309*1a96fba6SXin Li break;
310*1a96fba6SXin Li }
311*1a96fba6SXin Li case kTupleUint16StringBool: {
312*1a96fba6SXin Li std::tuple<uint16_t, std::string, bool> value;
313*1a96fba6SXin Li break;
314*1a96fba6SXin Li }
315*1a96fba6SXin Li case kTupleDoubleInt32ObjectPath: {
316*1a96fba6SXin Li std::tuple<double, int32_t, dbus::ObjectPath> value;
317*1a96fba6SXin Li PopValue(&reader, variant, &value);
318*1a96fba6SXin Li break;
319*1a96fba6SXin Li }
320*1a96fba6SXin Li case kMapInt32String: {
321*1a96fba6SXin Li std::map<int32_t, std::string> value;
322*1a96fba6SXin Li PopValue(&reader, variant, &value);
323*1a96fba6SXin Li break;
324*1a96fba6SXin Li }
325*1a96fba6SXin Li case kMapDoubleBool: {
326*1a96fba6SXin Li std::map<double, bool> value;
327*1a96fba6SXin Li PopValue(&reader, variant, &value);
328*1a96fba6SXin Li break;
329*1a96fba6SXin Li }
330*1a96fba6SXin Li }
331*1a96fba6SXin Li }
332*1a96fba6SXin Li
333*1a96fba6SXin Li return 0;
334*1a96fba6SXin Li }
335