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