xref: /aosp_15_r20/external/fmtlib/test/fuzzing/named-arg.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 #include <type_traits>
8 #include <vector>
9 
10 #include "fuzzer-common.h"
11 
12 template <typename T>
invoke_fmt(const uint8_t * data,size_t size,unsigned arg_name_size)13 void invoke_fmt(const uint8_t* data, size_t size, unsigned arg_name_size) {
14   static_assert(sizeof(T) <= fixed_size, "fixed_size too small");
15   if (size <= fixed_size) return;
16   const T value = assign_from_buf<T>(data);
17   data += fixed_size;
18   size -= fixed_size;
19 
20   if (arg_name_size <= 0 || arg_name_size >= size) return;
21   data_to_string arg_name(data, arg_name_size, true);
22   data += arg_name_size;
23   size -= arg_name_size;
24 
25   data_to_string format_str(data, size);
26   try {
27 #if FMT_FUZZ_FORMAT_TO_STRING
28     std::string message =
29         fmt::format(format_str.get(), fmt::arg(arg_name.data(), value));
30 #else
31     fmt::memory_buffer out;
32     fmt::format_to(std::back_inserter(out), format_str.get(),
33                    fmt::arg(arg_name.data(), value));
34 #endif
35   } catch (std::exception&) {
36   }
37 }
38 
39 // For dynamic dispatching to an explicit instantiation.
invoke(int type,Callback callback)40 template <typename Callback> void invoke(int type, Callback callback) {
41   switch (type) {
42   case 0:
43     callback(bool());
44     break;
45   case 1:
46     callback(char());
47     break;
48   case 2:
49     using sc = signed char;
50     callback(sc());
51     break;
52   case 3:
53     using uc = unsigned char;
54     callback(uc());
55     break;
56   case 4:
57     callback(short());
58     break;
59   case 5:
60     using us = unsigned short;
61     callback(us());
62     break;
63   case 6:
64     callback(int());
65     break;
66   case 7:
67     callback(unsigned());
68     break;
69   case 8:
70     callback(long());
71     break;
72   case 9:
73     using ul = unsigned long;
74     callback(ul());
75     break;
76   case 10:
77     callback(float());
78     break;
79   case 11:
80     callback(double());
81     break;
82   case 12:
83     using LD = long double;
84     callback(LD());
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 <= 3) return 0;
91 
92   // Switch types depending on the first byte of the input.
93   const auto type = data[0] & 0x0F;
94   const unsigned arg_name_size = (data[0] & 0xF0) >> 4;
95   data++;
96   size--;
97 
98   invoke(type, [=](auto arg) {
99     invoke_fmt<decltype(arg)>(data, size, arg_name_size);
100   });
101   return 0;
102 }
103