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