ZeroErr
载入中...
搜索中...
未找到
fuzztest.h
浏览该文件的文档.
1#pragma once
2
4#include "zeroerr/unittest.h"
5
12
13
14#include <exception>
15#include <functional>
16#include <string>
17#include <tuple>
18#include <type_traits>
19#include <vector>
20
22
23#define ZEROERR_CREATE_FUZZ_TEST_FUNC(function, name, ...) \
24 static void function(zeroerr::TestContext*); \
25 static zeroerr::detail::regTest ZEROERR_NAMEGEN(_zeroerr_reg)( \
26 {name, __FILE__, __LINE__, function, {__VA_ARGS__}}, zeroerr::TestType::fuzz_test); \
27 static void function(ZEROERR_UNUSED(zeroerr::TestContext* _ZEROERR_TEST_CONTEXT))
28
29#define FUZZ_TEST_CASE(...) \
30 ZEROERR_SUPPRESS_COMMON_WARNINGS_PUSH \
31 ZEROERR_CREATE_FUZZ_TEST_FUNC(ZEROERR_NAMEGEN(_zeroerr_testcase), __VA_ARGS__) \
32 ZEROERR_SUPPRESS_COMMON_WARNINGS_POP
33
34#define FUZZ_FUNC(func) zeroerr::FuzzFunction(func, _ZEROERR_TEST_CONTEXT)
35
36
37namespace zeroerr {
38
39namespace detail {
40
45template <typename... Args>
47 static constexpr size_t numOfArgs = sizeof...(Args);
48 using ValueType = std::tuple<Args...>;
49};
50
51template <typename... Args>
53 void (*)(Args...));
54
55template <typename... Args>
57 std::function<void(Args...)>);
58
59
60template <typename T>
62 using type = void;
63};
64
65template <typename Ret, typename Class, typename... Args>
66struct memfun_type<Ret (Class::*)(Args...) const> {
68};
69
70template <typename F>
71typename memfun_type<decltype(&F::operator())>::ret_type FunctionDecompositionImpl(F);
72
73
74template <typename T>
75using FunctionDecompositionT = decltype(FunctionDecompositionImpl(std::declval<T>()));
76
77} // namespace detail
78
79
85template <typename TargetFunction,
87struct FuzzTest;
88
89template <typename TargetFunction, typename FuncType, typename Domain,
92
93struct IFuzzTest {
94 virtual void Run(int count = 1000, int seed = 0) = 0;
95 virtual void RunOneTime(const uint8_t* data, size_t size) = 0;
96 virtual std::string MutateData(const uint8_t* data, size_t size, size_t max_size,
97 unsigned int seed) = 0;
98
99 int count = 0, max_count = 0;
100 bool should_stop() { return count == max_count; }
101};
102
103class FuzzFinishedException : public std::exception {
104public:
105 virtual const char* what() const throw() { return "Fuzzing finished"; }
106};
107
108// The details are described in the declaration of the class.
109template <typename TargetFunction, typename FuncType>
111 using ValueType = typename FuncType::ValueType;
113 FuzzTest(const FuzzTest& other)
114 : func(other.func), context(other.context), seeds(other.seeds) {}
115
116 template <typename... T>
118 FuzzTestWithDomain<TargetFunction, FuncType,
119 AggregateOf<std::tuple<typename T::ValueType...>, T...>>;
120
124 template <typename... T>
126 AggregateOf<std::tuple<typename T::ValueType...>, T...> domain) {
127 return FuzzTestWithDomainType<T...>(*this, domain);
128 }
129
135 template <typename... T>
136 FuzzTestWithDomainType<T...> WithDomains(T&&... domains) {
137 return WithDomains(TupleOf(std::forward<T>(domains)...));
138 }
139
140 FuzzTest& WithSeeds(std::vector<ValueType> _seeds) {
141 this->seeds.insert(this->seeds.end(), _seeds.begin(), _seeds.end());
142 return *this;
143 }
144
145 // This should create default domains
146 virtual void Run(int = 1000, int = 0) {}
147 virtual void RunOneTime(const uint8_t*, size_t) {}
148 virtual std::string MutateData(const uint8_t*, size_t, size_t, unsigned int) { return ""; }
149
150 TargetFunction func;
152 std::vector<ValueType> seeds;
153};
154
155extern void RunFuzzTest(IFuzzTest& fuzz_test, int seed = 0, int runs = 1000, int max_len = 0,
156 int timeout = 1200, int len_control = 100);
157
158
166template <typename TargetFunction, typename FuncType, typename Domain, typename Base>
167struct FuzzTestWithDomain : public Base {
168 FuzzTestWithDomain(const Base& ft, const Domain& domain) : Base(ft), m_domain(domain) {}
169
170 virtual void Run(int _count = 1000, int _seed = 0) override {
171 Base::count = 1;
172 Base::max_count = _count;
173 m_rng = new Rng(_seed);
174 RunFuzzTest(*this, _seed, _count, 500, 1200, 1);
175 delete m_rng;
176 m_rng = nullptr;
177 }
178
179 typename Domain::CorpusType GetRandomCorpus() {
180 Rng& rng = *this->m_rng;
181 if (Base::seeds.size() > 0 && rng.bounded(2) == 0) {
182 return m_domain.FromValue(Base::seeds[rng() % Base::seeds.size()]);
183 }
184 return m_domain.GetRandomCorpus(rng);
185 }
186
187 typename Domain::CorpusType TryParse(const std::string& input) {
188 try {
189 IRObject obj = IRObject::FromString(input);
191 return m_domain.ParseCorpus(obj);
192 } catch (...) {
193 return GetRandomCorpus();
194 }
195 }
196
197 template <typename T, unsigned... I>
198 void apply(T args, detail::seq<I...>) {
199 this->func(std::get<I>(args)...);
200 }
201
202 virtual void RunOneTime(const uint8_t* data, size_t size) override {
203 Base::count++;
204 std::string input = std::string((const char*)data, size);
205 typename Domain::CorpusType corpus = TryParse(input);
206 typename Domain::ValueType value = m_domain.GetValue(corpus);
207 apply(value, detail::gen_seq<std::tuple_size<typename Domain::ValueType>::value>{});
208 }
209
210 virtual std::string MutateData(const uint8_t* data, size_t size, size_t max_size,
211 unsigned int seed) override {
212 Rng rng(seed);
213 std::string input = std::string((const char*)data, size);
214 typename Domain::CorpusType corpus = TryParse(input);
215 m_domain.Mutate(rng, corpus, false);
216 IRObject mutated_obj = m_domain.SerializeCorpus(corpus);
217 return IRObject::ToString(mutated_obj);
218 }
219
222};
223
224
225template <typename T>
227 return FuzzTest<T>(func, context);
228}
229
230template <typename T>
231std::vector<T> ReadCorpusFromDir(std::string dir);
232
233
234} // namespace zeroerr
235
236
AggregateOf is a domain that combines multiple inner domains into a tuple or aggregate type
Definition aggregate_of.h:41
Domain class for generating random values of a specific type.
Definition domain.h:21
virtual ValueType GetValue(const CorpusType &v) const =0
virtual void Mutate(Rng &rng, CorpusType &v, bool only_shrink=false) const =0
virtual CorpusType GetRandomCorpus(Rng &rng) const =0
virtual IRObject SerializeCorpus(const CorpusType &v) const
Definition domain.h:32
virtual CorpusType FromValue(const ValueType &v) const =0
virtual CorpusType ParseCorpus(IRObject v) const
Definition domain.h:31
Definition fuzztest.h:103
virtual const char * what() const
Definition fuzztest.h:105
Definition rng.h:30
uint32_t bounded(uint32_t range) noexcept
Definition rng.h:126
TestContext is a class that holds the test results and reporter context. There are 8 different matric...
Definition unittest.h:77
#define ZEROERR_SUPPRESS_COMMON_WARNINGS_POP
Definition config.h:268
#define ZEROERR_SUPPRESS_COMMON_WARNINGS_PUSH
Definition config.h:220
decltype(FunctionDecompositionImpl(std::declval< T >())) FunctionDecompositionT
Definition fuzztest.h:75
FunctionDecomposition< typename std::decay< Args >::type... > FunctionDecompositionImpl(void(*)(Args...))
Definition benchmark.cpp:17
void RunFuzzTest(IFuzzTest &fuzz_test, int seed, int runs, int max_len, int timeout, int len_control)
Definition fuzztest.cpp:32
AggregateOf< std::tuple< typename Inner::ValueType... >, Inner... > TupleOf(Inner &&... inner)
Definition aggregate_of.h:107
@ fuzz_test
Definition unittest.h:274
Decorator * timeout(float timeout)
Definition unittest.cpp:853
std::vector< T > ReadCorpusFromDir(std::string dir)
FuzzTest< T > FuzzFunction(T func, TestContext *context)
Definition fuzztest.h:226
FuzzTestWithDomain implements the Base class with the domain passed into.
Definition fuzztest.h:167
Domain m_domain
Definition fuzztest.h:220
FuzzTestWithDomain(const Base &ft, const Domain &domain)
Definition fuzztest.h:168
Domain::CorpusType GetRandomCorpus()
Definition fuzztest.h:179
virtual void RunOneTime(const uint8_t *data, size_t size) override
Definition fuzztest.h:202
void apply(T args, detail::seq< I... >)
Definition fuzztest.h:198
virtual std::string MutateData(const uint8_t *data, size_t size, size_t max_size, unsigned int seed) override
Definition fuzztest.h:210
Rng * m_rng
Definition fuzztest.h:221
virtual void Run(int _count=1000, int _seed=0) override
Definition fuzztest.h:170
Domain::CorpusType TryParse(const std::string &input)
Definition fuzztest.h:187
FuzzTest is a template class to create a fuzz test for the target function.
Definition fuzztest.h:110
TargetFunction func
Definition fuzztest.h:150
FuzzTest(TargetFunction func, TestContext *context)
Definition fuzztest.h:112
std::vector< ValueType > seeds
Definition fuzztest.h:152
TestContext * context
Definition fuzztest.h:151
FuzzTestWithDomainType< T... > WithDomains(T &&... domains)
Definition fuzztest.h:136
virtual void Run(int=1000, int=0)
Definition fuzztest.h:146
virtual void RunOneTime(const uint8_t *, size_t)
Definition fuzztest.h:147
typename FuncType::ValueType ValueType
Definition fuzztest.h:111
FuzzTest & WithSeeds(std::vector< ValueType > _seeds)
Definition fuzztest.h:140
FuzzTest(const FuzzTest &other)
Definition fuzztest.h:113
virtual std::string MutateData(const uint8_t *, size_t, size_t, unsigned int)
Definition fuzztest.h:148
FuzzTestWithDomainType< T... > WithDomains(AggregateOf< std::tuple< typename T::ValueType... >, T... > domain)
Definition fuzztest.h:125
Definition fuzztest.h:93
virtual void RunOneTime(const uint8_t *data, size_t size)=0
virtual std::string MutateData(const uint8_t *data, size_t size, size_t max_size, unsigned int seed)=0
virtual void Run(int count=1000, int seed=0)=0
bool should_stop()
Definition fuzztest.h:100
int max_count
Definition fuzztest.h:99
int count
Definition fuzztest.h:99
Interface for serializable objects
Definition serialization.h:43
unsigned char type
Definition serialization.h:68
static std::string ToString(IRObject obj)
Definition serialization.cpp:135
static IRObject FromString(std::string str)
Definition serialization.cpp:141
@ Undefined
Definition serialization.h:58
FunctionDecomposition is a meta function to decompose the function type. The ValueType and numOfArgs ...
Definition fuzztest.h:46
std::tuple< Args... > ValueType
Definition fuzztest.h:48
static constexpr size_t numOfArgs
Definition fuzztest.h:47
Definition typetraits.h:63
Definition fuzztest.h:61
void type
Definition fuzztest.h:62
Definition typetraits.h:60