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