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