• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2019, Paul Dreik
2 // License: see LICENSE.rst in the fmt root directory
3 
4 #include <fmt/core.h>
5 #include <cstdint>
6 #include <stdexcept>
7 #include <type_traits>
8 #include <vector>
9 
10 #include <fmt/chrono.h>
11 #include "fuzzer_common.h"
12 
13 using fmt_fuzzer::Nfixed;
14 
15 template <typename Item>
invoke_fmt(const uint8_t * Data,std::size_t Size)16 void invoke_fmt(const uint8_t* Data, std::size_t Size) {
17   constexpr auto N = sizeof(Item);
18   static_assert(N <= Nfixed, "Nfixed is too small");
19   if (Size <= Nfixed) {
20     return;
21   }
22   const Item item = fmt_fuzzer::assignFromBuf<Item>(Data);
23   Data += Nfixed;
24   Size -= Nfixed;
25 
26 #if FMT_FUZZ_SEPARATE_ALLOCATION
27   // allocates as tight as possible, making it easier to catch buffer overruns.
28   std::vector<char> fmtstringbuffer(Size);
29   std::memcpy(fmtstringbuffer.data(), Data, Size);
30   auto fmtstring = fmt::string_view(fmtstringbuffer.data(), Size);
31 #else
32   auto fmtstring = fmt::string_view(fmt_fuzzer::as_chars(Data), Size);
33 #endif
34 
35 #if FMT_FUZZ_FORMAT_TO_STRING
36   std::string message = fmt::format(fmtstring, item);
37 #else
38   fmt::memory_buffer message;
39   fmt::format_to(message, fmtstring, item);
40 #endif
41 }
42 
invoke_fmt_time(const uint8_t * Data,std::size_t Size)43 void invoke_fmt_time(const uint8_t* Data, std::size_t Size) {
44   using Item = std::time_t;
45   constexpr auto N = sizeof(Item);
46   static_assert(N <= Nfixed, "Nfixed too small");
47   if (Size <= Nfixed) {
48     return;
49   }
50   const Item item = fmt_fuzzer::assignFromBuf<Item>(Data);
51   Data += Nfixed;
52   Size -= Nfixed;
53 #if FMT_FUZZ_SEPARATE_ALLOCATION
54   // allocates as tight as possible, making it easier to catch buffer overruns.
55   std::vector<char> fmtstringbuffer(Size);
56   std::memcpy(fmtstringbuffer.data(), Data, Size);
57   auto fmtstring = fmt::string_view(fmtstringbuffer.data(), Size);
58 #else
59   auto fmtstring = fmt::string_view(fmt_fuzzer::as_chars(Data), Size);
60 #endif
61   auto* b = std::localtime(&item);
62   if (b) {
63 #if FMT_FUZZ_FORMAT_TO_STRING
64     std::string message = fmt::format(fmtstring, *b);
65 #else
66     fmt::memory_buffer message;
67     fmt::format_to(message, fmtstring, *b);
68 #endif
69   }
70 }
71 
LLVMFuzzerTestOneInput(const uint8_t * Data,std::size_t Size)72 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, std::size_t Size) {
73   if (Size <= 3) {
74     return 0;
75   }
76 
77   const auto first = Data[0];
78   Data++;
79   Size--;
80 
81   try {
82     switch (first) {
83     case 0:
84       invoke_fmt<bool>(Data, Size);
85       break;
86     case 1:
87       invoke_fmt<char>(Data, Size);
88       break;
89     case 2:
90       invoke_fmt<unsigned char>(Data, Size);
91       break;
92     case 3:
93       invoke_fmt<signed char>(Data, Size);
94       break;
95     case 4:
96       invoke_fmt<short>(Data, Size);
97       break;
98     case 5:
99       invoke_fmt<unsigned short>(Data, Size);
100       break;
101     case 6:
102       invoke_fmt<int>(Data, Size);
103       break;
104     case 7:
105       invoke_fmt<unsigned int>(Data, Size);
106       break;
107     case 8:
108       invoke_fmt<long>(Data, Size);
109       break;
110     case 9:
111       invoke_fmt<unsigned long>(Data, Size);
112       break;
113     case 10:
114       invoke_fmt<float>(Data, Size);
115       break;
116     case 11:
117       invoke_fmt<double>(Data, Size);
118       break;
119     case 12:
120       invoke_fmt<long double>(Data, Size);
121       break;
122     case 13:
123       invoke_fmt_time(Data, Size);
124       break;
125     default:
126       break;
127     }
128   } catch (std::exception& /*e*/) {
129   }
130   return 0;
131 }
132