• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2019, Paul Dreik
2 // For the license information refer to format.h.
3 
4 #include <cstdint>
5 #include <fmt/chrono.h>
6 
7 #include "fuzzer-common.h"
8 
9 template <typename Period, typename Rep>
invoke_inner(fmt::string_view format_str,Rep rep)10 void invoke_inner(fmt::string_view format_str, Rep rep) {
11   auto value = std::chrono::duration<Rep, Period>(rep);
12   try {
13 #if FMT_FUZZ_FORMAT_TO_STRING
14     std::string message = fmt::format(format_str, value);
15 #else
16     fmt::memory_buffer buf;
17     fmt::format_to(buf, format_str, value);
18 #endif
19   } catch (std::exception&) {
20   }
21 }
22 
23 // Rep is a duration's representation type.
24 template <typename Rep>
invoke_outer(const uint8_t * data,size_t size,int period)25 void invoke_outer(const uint8_t* data, size_t size, int period) {
26   // Always use a fixed location of the data.
27   static_assert(sizeof(Rep) <= fixed_size, "fixed size is too small");
28   if (size <= fixed_size + 1) return;
29 
30   const Rep rep = assign_from_buf<Rep>(data);
31   data += fixed_size;
32   size -= fixed_size;
33 
34   // data is already allocated separately in libFuzzer so reading past the end
35   // will most likely be detected anyway.
36   const auto format_str = fmt::string_view(as_chars(data), size);
37 
38   // yocto, zepto, zetta and yotta are not handled.
39   switch (period) {
40   case 1:
41     invoke_inner<std::atto>(format_str, rep);
42     break;
43   case 2:
44     invoke_inner<std::femto>(format_str, rep);
45     break;
46   case 3:
47     invoke_inner<std::pico>(format_str, rep);
48     break;
49   case 4:
50     invoke_inner<std::nano>(format_str, rep);
51     break;
52   case 5:
53     invoke_inner<std::micro>(format_str, rep);
54     break;
55   case 6:
56     invoke_inner<std::milli>(format_str, rep);
57     break;
58   case 7:
59     invoke_inner<std::centi>(format_str, rep);
60     break;
61   case 8:
62     invoke_inner<std::deci>(format_str, rep);
63     break;
64   case 9:
65     invoke_inner<std::deca>(format_str, rep);
66     break;
67   case 10:
68     invoke_inner<std::kilo>(format_str, rep);
69     break;
70   case 11:
71     invoke_inner<std::mega>(format_str, rep);
72     break;
73   case 12:
74     invoke_inner<std::giga>(format_str, rep);
75     break;
76   case 13:
77     invoke_inner<std::tera>(format_str, rep);
78     break;
79   case 14:
80     invoke_inner<std::peta>(format_str, rep);
81     break;
82   case 15:
83     invoke_inner<std::exa>(format_str, rep);
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 <= 4)  return 0;
90 
91   const auto representation = data[0];
92   const auto period = data[1];
93   data += 2;
94   size -= 2;
95 
96   switch (representation) {
97   case 1:
98     invoke_outer<char>(data, size, period);
99     break;
100   case 2:
101     invoke_outer<signed char>(data, size, period);
102     break;
103   case 3:
104     invoke_outer<unsigned char>(data, size, period);
105     break;
106   case 4:
107     invoke_outer<short>(data, size, period);
108     break;
109   case 5:
110     invoke_outer<unsigned short>(data, size, period);
111     break;
112   case 6:
113     invoke_outer<int>(data, size, period);
114     break;
115   case 7:
116     invoke_outer<unsigned int>(data, size, period);
117     break;
118   case 8:
119     invoke_outer<long>(data, size, period);
120     break;
121   case 9:
122     invoke_outer<unsigned long>(data, size, period);
123     break;
124   case 10:
125     invoke_outer<float>(data, size, period);
126     break;
127   case 11:
128     invoke_outer<double>(data, size, period);
129     break;
130   case 12:
131     invoke_outer<long double>(data, size, period);
132     break;
133   }
134   return 0;
135 }
136