1 // Copyright (c) 2019, Paul Dreik
2 // For the license information refer to format.h.
3
4 #include <cstdint>
5 #include <exception>
6 #include <string>
7 #include <fmt/format.h>
8
9 #include "fuzzer-common.h"
10
11 template <typename Item1, typename Item2>
invoke_fmt(const uint8_t * data,size_t size)12 void invoke_fmt(const uint8_t* data, size_t size) {
13 static_assert(sizeof(Item1) <= fixed_size, "size1 exceeded");
14 static_assert(sizeof(Item2) <= fixed_size, "size2 exceeded");
15 if (size <= fixed_size + fixed_size) return;
16
17 const Item1 item1 = assign_from_buf<Item1>(data);
18 data += fixed_size;
19 size -= fixed_size;
20
21 const Item2 item2 = assign_from_buf<Item2>(data);
22 data += fixed_size;
23 size -= fixed_size;
24
25 auto format_str = fmt::string_view(as_chars(data), size);
26 #if FMT_FUZZ_FORMAT_TO_STRING
27 std::string message = fmt::format(format_str, item1, item2);
28 #else
29 fmt::memory_buffer message;
30 fmt::format_to(message, format_str, item1, item2);
31 #endif
32 }
33
34 // For dynamic dispatching to an explicit instantiation.
invoke(int index,Callback callback)35 template <typename Callback> void invoke(int index, Callback callback) {
36 switch (index) {
37 case 0:
38 callback(bool());
39 break;
40 case 1:
41 callback(char());
42 break;
43 case 2:
44 using sc = signed char;
45 callback(sc());
46 break;
47 case 3:
48 using uc = unsigned char;
49 callback(uc());
50 break;
51 case 4:
52 callback(short());
53 break;
54 case 5:
55 using us = unsigned short;
56 callback(us());
57 break;
58 case 6:
59 callback(int());
60 break;
61 case 7:
62 callback(unsigned());
63 break;
64 case 8:
65 callback(long());
66 break;
67 case 9:
68 using ul = unsigned long;
69 callback(ul());
70 break;
71 case 10:
72 callback(float());
73 break;
74 case 11:
75 callback(double());
76 break;
77 case 12:
78 using LD = long double;
79 callback(LD());
80 break;
81 case 13:
82 using ptr = void*;
83 callback(ptr());
84 break;
85 }
86 }
87
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)88 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
89 if (size <= 3) return 0;
90
91 // Switch types depending on the first byte of the input.
92 const auto type1 = data[0] & 0x0F;
93 const auto type2 = (data[0] & 0xF0) >> 4;
94 data++;
95 size--;
96 try {
97 invoke(type1, [=](auto param1) {
98 invoke(type2, [=](auto param2) {
99 invoke_fmt<decltype(param1), decltype(param2)>(data, size);
100 });
101 });
102 } catch (std::exception&) {
103 }
104 return 0;
105 }
106