1 //===- FuzzerAdapter.h - Arbitrary function Fuzzer adapter -------*- C++ -*===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // W A R N I N G : E X P E R I M E N T A L.
11 //
12 // Defines an adapter to fuzz functions with (almost) arbitrary signatures.
13 //===----------------------------------------------------------------------===//
14
15 #ifndef LLVM_FUZZER_ADAPTER_H
16 #define LLVM_FUZZER_ADAPTER_H
17
18 #include <stddef.h>
19 #include <stdint.h>
20
21 #include <algorithm>
22 #include <string>
23 #include <tuple>
24 #include <vector>
25
26 namespace fuzzer {
27
28 /// Unpacks bytes from \p Data according to \p F argument types
29 /// and calls the function.
30 /// Use to automatically adapt LLVMFuzzerTestOneInput interface to
31 /// a specific function.
32 /// Supported argument types: primitive types, std::vector<uint8_t>.
33 template <typename Fn> bool Adapt(Fn F, const uint8_t *Data, size_t Size);
34
35 // The implementation performs several steps:
36 // - function argument types are obtained (Args...)
37 // - data is unpacked into std::tuple<Args...> one by one
38 // - function is called with std::tuple<Args...> containing arguments.
39 namespace impl {
40
41 // Single argument unpacking.
42
43 template <typename T>
UnpackPrimitive(const uint8_t * Data,size_t Size,T * Value)44 size_t UnpackPrimitive(const uint8_t *Data, size_t Size, T *Value) {
45 if (Size < sizeof(T))
46 return Size;
47 *Value = *reinterpret_cast<const T *>(Data);
48 return Size - sizeof(T);
49 }
50
51 /// Unpacks into a given Value and returns the Size - num_consumed_bytes.
52 /// Return value equal to Size signals inability to unpack the data (typically
53 /// because there are not enough bytes).
54 template <typename T>
55 size_t UnpackSingle(const uint8_t *Data, size_t Size, T *Value);
56
57 #define UNPACK_SINGLE_PRIMITIVE(Type) \
58 template <> \
59 size_t UnpackSingle<Type>(const uint8_t *Data, size_t Size, Type *Value) { \
60 return UnpackPrimitive(Data, Size, Value); \
61 }
62
63 UNPACK_SINGLE_PRIMITIVE(char)
UNPACK_SINGLE_PRIMITIVE(signed char)64 UNPACK_SINGLE_PRIMITIVE(signed char)
65 UNPACK_SINGLE_PRIMITIVE(unsigned char)
66
67 UNPACK_SINGLE_PRIMITIVE(short int)
68 UNPACK_SINGLE_PRIMITIVE(unsigned short int)
69
70 UNPACK_SINGLE_PRIMITIVE(int)
71 UNPACK_SINGLE_PRIMITIVE(unsigned int)
72
73 UNPACK_SINGLE_PRIMITIVE(long int)
74 UNPACK_SINGLE_PRIMITIVE(unsigned long int)
75
76 UNPACK_SINGLE_PRIMITIVE(bool)
77 UNPACK_SINGLE_PRIMITIVE(wchar_t)
78
79 UNPACK_SINGLE_PRIMITIVE(float)
80 UNPACK_SINGLE_PRIMITIVE(double)
81 UNPACK_SINGLE_PRIMITIVE(long double)
82
83 #undef UNPACK_SINGLE_PRIMITIVE
84
85 template <>
86 size_t UnpackSingle<std::vector<uint8_t>>(const uint8_t *Data, size_t Size,
87 std::vector<uint8_t> *Value) {
88 if (Size < 1)
89 return Size;
90 size_t Len = std::min(static_cast<size_t>(*Data), Size - 1);
91 std::vector<uint8_t> V(Data + 1, Data + 1 + Len);
92 Value->swap(V);
93 return Size - Len - 1;
94 }
95
96 template <>
97 size_t UnpackSingle<std::string>(const uint8_t *Data, size_t Size,
98 std::string *Value) {
99 if (Size < 1)
100 return Size;
101 size_t Len = std::min(static_cast<size_t>(*Data), Size - 1);
102 std::string S(Data + 1, Data + 1 + Len);
103 Value->swap(S);
104 return Size - Len - 1;
105 }
106
107 // Unpacking into arbitrary tuple.
108
109 // Recursion guard.
110 template <int N, typename TupleT>
111 typename std::enable_if<N == std::tuple_size<TupleT>::value, bool>::type
UnpackImpl(const uint8_t * Data,size_t Size,TupleT * Tuple)112 UnpackImpl(const uint8_t *Data, size_t Size, TupleT *Tuple) {
113 return true;
114 }
115
116 // Unpack tuple elements starting from Nth.
117 template <int N, typename TupleT>
118 typename std::enable_if<N < std::tuple_size<TupleT>::value, bool>::type
119 UnpackImpl(const uint8_t *Data, size_t Size, TupleT *Tuple) {
120 size_t NewSize = UnpackSingle(Data, Size, &std::get<N>(*Tuple));
121 if (NewSize == Size) {
122 return false;
123 }
124
125 return UnpackImpl<N + 1, TupleT>(Data + (Size - NewSize), NewSize, Tuple);
126 }
127
128 // Unpacks into arbitrary tuple and returns true if successful.
129 template <typename... Args>
Unpack(const uint8_t * Data,size_t Size,std::tuple<Args...> * Tuple)130 bool Unpack(const uint8_t *Data, size_t Size, std::tuple<Args...> *Tuple) {
131 return UnpackImpl<0, std::tuple<Args...>>(Data, Size, Tuple);
132 }
133
134 // Helper integer sequence templates.
135
136 template <int...> struct Seq {};
137
138 template <int N, int... S> struct GenSeq : GenSeq<N - 1, N - 1, S...> {};
139
140 // GenSeq<N>::type is Seq<0, 1, ..., N-1>
141 template <int... S> struct GenSeq<0, S...> { typedef Seq<S...> type; };
142
143 // Function signature introspection.
144
145 template <typename T> struct FnTraits {};
146
147 template <typename ReturnType, typename... Args>
148 struct FnTraits<ReturnType (*)(Args...)> {
149 enum { Arity = sizeof...(Args) };
150 typedef std::tuple<Args...> ArgsTupleT;
151 };
152
153 // Calling a function with arguments in a tuple.
154
155 template <typename Fn, int... S>
156 void ApplyImpl(Fn F, const typename FnTraits<Fn>::ArgsTupleT &Params,
157 Seq<S...>) {
158 F(std::get<S>(Params)...);
159 }
160
161 template <typename Fn>
162 void Apply(Fn F, const typename FnTraits<Fn>::ArgsTupleT &Params) {
163 // S is Seq<0, ..., Arity-1>
164 auto S = typename GenSeq<FnTraits<Fn>::Arity>::type();
165 ApplyImpl(F, Params, S);
166 }
167
168 // Unpacking data into arguments tuple of correct type and calling the function.
169 template <typename Fn>
170 bool UnpackAndApply(Fn F, const uint8_t *Data, size_t Size) {
171 typename FnTraits<Fn>::ArgsTupleT Tuple;
172 if (!Unpack(Data, Size, &Tuple))
173 return false;
174
175 Apply(F, Tuple);
176 return true;
177 }
178
179 } // namespace impl
180
181 template <typename Fn> bool Adapt(Fn F, const uint8_t *Data, size_t Size) {
182 return impl::UnpackAndApply(F, Data, Size);
183 }
184
185 } // namespace fuzzer
186
187 #endif
188