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