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