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