1 // Copyright 2021 Google LLC
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 "dice/cbor_writer.h"
16 #include "fuzzer/FuzzedDataProvider.h"
17
18 namespace {
19
20 enum CborWriterFunction {
21 WriteInt,
22 WriteUint,
23 WriteBstr,
24 AllocBstr,
25 WriteTstr,
26 AllocTstr,
27 WriteArray,
28 WriteMap,
29 WriteTag,
30 WriteFalse,
31 WriteTrue,
32 WriteNull,
33 kMaxValue = WriteNull,
34 };
35
36 // Use data sizes that exceed the 16-bit range without being excessive.
37 constexpr size_t kMaxDataSize = 0xffff + 0x5000;
38 constexpr size_t kMaxBufferSize = kMaxDataSize * 3;
39 constexpr size_t kIterations = CborWriterFunction::kMaxValue * 2;
40
41 } // namespace
42
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)43 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
44 FuzzedDataProvider fdp(data, size);
45
46 auto buffer_size = fdp.ConsumeIntegralInRange<size_t>(0, kMaxBufferSize);
47 std::vector<uint8_t> buffer(buffer_size);
48 CborOut out;
49 CborOutInit(buffer.data(), buffer.size(), &out);
50
51 for (size_t i = 0; i < kIterations; i++) {
52 switch (fdp.ConsumeEnum<CborWriterFunction>()) {
53 case WriteInt:
54 CborWriteInt(fdp.ConsumeIntegral<int64_t>(), &out);
55 break;
56 case WriteUint:
57 CborWriteUint(fdp.ConsumeIntegral<uint64_t>(), &out);
58 break;
59 case WriteBstr: {
60 auto bstr_data_size =
61 fdp.ConsumeIntegralInRange<size_t>(0, kMaxDataSize);
62 std::vector<uint8_t> bstr_data(bstr_data_size);
63 CborWriteBstr(bstr_data.size(), bstr_data.data(), &out);
64 break;
65 }
66 case AllocBstr: {
67 auto bstr_data_size =
68 fdp.ConsumeIntegralInRange<size_t>(0, kMaxDataSize);
69 uint8_t* ptr = CborAllocBstr(bstr_data_size, &out);
70 if (ptr) {
71 memset(ptr, 0x5a, bstr_data_size);
72 }
73 break;
74 }
75 case WriteTstr: {
76 auto tstr_data_size =
77 fdp.ConsumeIntegralInRange<size_t>(0, kMaxDataSize);
78 std::string str(tstr_data_size, 'a');
79 CborWriteTstr(str.c_str(), &out);
80 break;
81 }
82 case AllocTstr: {
83 auto tstr_data_size =
84 fdp.ConsumeIntegralInRange<size_t>(0, kMaxDataSize);
85 char* str = CborAllocTstr(tstr_data_size, &out);
86 if (str) {
87 memset(str, 'q', tstr_data_size);
88 }
89 break;
90 }
91 case WriteArray: {
92 auto num_elements = fdp.ConsumeIntegral<size_t>();
93 CborWriteArray(num_elements, &out);
94 break;
95 }
96 case WriteMap: {
97 auto num_pairs = fdp.ConsumeIntegral<size_t>();
98 CborWriteMap(num_pairs, &out);
99 break;
100 }
101 case WriteTag: {
102 auto tag = fdp.ConsumeIntegral<uint64_t>();
103 CborWriteTag(tag, &out);
104 break;
105 }
106 case WriteFalse:
107 CborWriteNull(&out);
108 break;
109 case WriteTrue:
110 CborWriteNull(&out);
111 break;
112 case WriteNull:
113 CborWriteNull(&out);
114 break;
115 }
116 }
117
118 return 0;
119 }
120