• 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/chrono.h>
5 #include <cstdint>
6 #include <limits>
7 #include <stdexcept>
8 #include <type_traits>
9 #include <vector>
10 #include "fuzzer_common.h"
11 
12 template <typename Item, typename Ratio>
invoke_inner(fmt::string_view formatstring,const Item item)13 void invoke_inner(fmt::string_view formatstring, const Item item) {
14   const std::chrono::duration<Item, Ratio> value(item);
15   try {
16 #if FMT_FUZZ_FORMAT_TO_STRING
17     std::string message = fmt::format(formatstring, value);
18 #else
19     fmt::memory_buffer buf;
20     fmt::format_to(buf, formatstring, value);
21 #endif
22   } catch (std::exception& /*e*/) {
23   }
24 }
25 
26 // Item is the underlying type for duration (int, long etc)
27 template <typename Item>
invoke_outer(const uint8_t * Data,std::size_t Size,const int scaling)28 void invoke_outer(const uint8_t* Data, std::size_t Size, const int scaling) {
29   // always use a fixed location of the data
30   using fmt_fuzzer::Nfixed;
31 
32   constexpr auto N = sizeof(Item);
33   static_assert(N <= Nfixed, "fixed size is too small");
34   if (Size <= Nfixed + 1) {
35     return;
36   }
37 
38   const Item item = fmt_fuzzer::assignFromBuf<Item>(Data);
39 
40   // fast forward
41   Data += Nfixed;
42   Size -= Nfixed;
43 
44   // Data is already allocated separately in libFuzzer so reading past
45   // the end will most likely be detected anyway
46   const auto formatstring = fmt::string_view(fmt_fuzzer::as_chars(Data), Size);
47 
48   // doit_impl<Item,std::yocto>(buf.data(),item);
49   // doit_impl<Item,std::zepto>(buf.data(),item);
50   switch (scaling) {
51   case 1:
52     invoke_inner<Item, std::atto>(formatstring, item);
53     break;
54   case 2:
55     invoke_inner<Item, std::femto>(formatstring, item);
56     break;
57   case 3:
58     invoke_inner<Item, std::pico>(formatstring, item);
59     break;
60   case 4:
61     invoke_inner<Item, std::nano>(formatstring, item);
62     break;
63   case 5:
64     invoke_inner<Item, std::micro>(formatstring, item);
65     break;
66   case 6:
67     invoke_inner<Item, std::milli>(formatstring, item);
68     break;
69   case 7:
70     invoke_inner<Item, std::centi>(formatstring, item);
71     break;
72   case 8:
73     invoke_inner<Item, std::deci>(formatstring, item);
74     break;
75   case 9:
76     invoke_inner<Item, std::deca>(formatstring, item);
77     break;
78   case 10:
79     invoke_inner<Item, std::kilo>(formatstring, item);
80     break;
81   case 11:
82     invoke_inner<Item, std::mega>(formatstring, item);
83     break;
84   case 12:
85     invoke_inner<Item, std::giga>(formatstring, item);
86     break;
87   case 13:
88     invoke_inner<Item, std::tera>(formatstring, item);
89     break;
90   case 14:
91     invoke_inner<Item, std::peta>(formatstring, item);
92     break;
93   case 15:
94     invoke_inner<Item, std::exa>(formatstring, item);
95   }
96   // doit_impl<Item,std::zeta>(buf.data(),item);
97   // doit_impl<Item,std::yotta>(buf.data(),item);
98 }
99 
LLVMFuzzerTestOneInput(const uint8_t * Data,std::size_t Size)100 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, std::size_t Size) {
101   if (Size <= 4) {
102     return 0;
103   }
104 
105   const auto representation = Data[0];
106   const auto scaling = Data[1];
107   Data += 2;
108   Size -= 2;
109 
110   switch (representation) {
111   case 1:
112     invoke_outer<char>(Data, Size, scaling);
113     break;
114   case 2:
115     invoke_outer<unsigned char>(Data, Size, scaling);
116     break;
117   case 3:
118     invoke_outer<signed char>(Data, Size, scaling);
119     break;
120   case 4:
121     invoke_outer<short>(Data, Size, scaling);
122     break;
123   case 5:
124     invoke_outer<unsigned short>(Data, Size, scaling);
125     break;
126   case 6:
127     invoke_outer<int>(Data, Size, scaling);
128     break;
129   case 7:
130     invoke_outer<unsigned int>(Data, Size, scaling);
131     break;
132   case 8:
133     invoke_outer<long>(Data, Size, scaling);
134     break;
135   case 9:
136     invoke_outer<unsigned long>(Data, Size, scaling);
137     break;
138   case 10:
139     invoke_outer<float>(Data, Size, scaling);
140     break;
141   case 11:
142     invoke_outer<double>(Data, Size, scaling);
143     break;
144   case 12:
145     invoke_outer<long double>(Data, Size, scaling);
146     break;
147   default:
148     break;
149   }
150 
151   return 0;
152 }
153