Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Fuzz.h
Go to the documentation of this file.
1/*
2 * Copyright 2016 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef Fuzz_DEFINED
9#define Fuzz_DEFINED
10
11#include "include/core/SkData.h"
17#include "tools/Registry.h"
18
19#include <limits>
20#include <cmath>
21#include <signal.h>
22#include <limits>
23
24class Fuzz {
25public:
26 explicit Fuzz(const uint8_t* data, size_t size) : fData(data), fSize(size), fNextByte(0) {}
27 Fuzz() = delete;
28
29 // Make noncopyable
30 Fuzz(Fuzz&) = delete;
31 Fuzz& operator=(Fuzz&) = delete;
32
33 // Returns the total number of "random" bytes available.
34 size_t size() const {
35 return fSize;
36 }
37
38 // Returns if there are no bytes remaining for fuzzing.
39 bool exhausted() const {
40 return fSize == fNextByte;
41 }
42
43 void deplete() {
44 fNextByte = fSize;
45 }
46
47 size_t remainingSize() const {
48 return fSize - fNextByte;
49 }
50
51 const uint8_t *remainingData() const {
52 return fData + fNextByte;
53 }
54
55 // next() loads fuzzed bytes into the variable passed in by pointer.
56 // We use this approach instead of T next() because different compilers
57 // evaluate function parameters in different orders. If fuzz->next()
58 // returned 5 and then 7, foo(fuzz->next(), fuzz->next()) would be
59 // foo(5, 7) when compiled on GCC and foo(7, 5) when compiled on Clang.
60 // By requiring params to be passed in, we avoid the temptation to call
61 // next() in a way that does not consume fuzzed bytes in a single
62 // platform-independent order.
63 template <typename T>
64 void next(T* t) { this->nextBytes(t, sizeof(T)); }
65
66 // This is a convenient way to initialize more than one argument at a time.
67 template <typename Arg, typename... Args>
68 void next(Arg* first, Args... rest);
69
70 // nextRange returns values only in [min, max].
71 template <typename T, typename Min, typename Max>
72 void nextRange(T*, Min, Max);
73
74 // nextEnum is a wrapper around nextRange for enums.
75 template <typename T>
76 void nextEnum(T* ptr, T max);
77
78 // nextN loads n * sizeof(T) bytes into ptr
79 template <typename T>
80 void nextN(T* ptr, int n);
81
82 void signalBug() {
83 // Tell the fuzzer that these inputs found a bug.
84 SkDebugf("Signal bug\n");
85 raise(SIGSEGV);
86 }
87
88 // Specialized versions for when true random doesn't quite make sense
89 void next(bool* b);
90 void next(SkRegion* region);
91
92 bool nextBool() {
93 bool b;
94 this->next(&b);
95 return b;
96 }
97
98 void nextRange(float* f, float min, float max);
99
100private:
101 template <typename T>
102 T nextT();
103
104 const uint8_t *fData;
105 size_t fSize;
106 size_t fNextByte;
108
109 void nextBytes(void* ptr, size_t size);
110};
111
112template <typename Arg, typename... Args>
113inline void Fuzz::next(Arg* first, Args... rest) {
114 this->next(first);
115 this->next(rest...);
116}
117
118template <typename T, typename Min, typename Max>
119inline void Fuzz::nextRange(T* value, Min min, Max max) {
120 // UBSAN worries if we make an enum with out of range values, even temporarily.
121 using Raw = typename sk_strip_enum<T>::type;
122 Raw raw;
123 this->next(&raw);
124
125 if (raw < (Raw)min) { raw = (Raw)min; }
126 if (raw > (Raw)max) { raw = (Raw)max; }
127 *value = (T)raw;
128}
129
130template <typename T>
131inline void Fuzz::nextEnum(T* value, T max) {
132 // This works around the fact that UBSAN will assert if we put an invalid
133 // value into an enum. We might see issues with enums being represented
134 // on Windows differently than Linux, but that's not a thing we can fix here.
135 using U = typename std::underlying_type<T>::type;
136 U v;
137 this->next(&v);
138 if (v < (U)0) { *value = (T)0; return;}
139 if (v > (U)max) { *value = (T)max; return;}
140 *value = (T)v;
141}
142
143template <typename T>
144inline void Fuzz::nextN(T* ptr, int n) {
145 for (int i = 0; i < n; i++) {
146 this->next(ptr+i);
147 }
148}
149
150struct Fuzzable {
151 const char* name;
152 void (*fn)(Fuzz*);
153};
154
155// Not static so that we can link these into oss-fuzz harnesses if we like.
156#define DEF_FUZZ(name, f) \
157 void fuzz_##name(Fuzz*); \
158 sk_tools::Registry<Fuzzable> register_##name({#name, fuzz_##name}); \
159 void fuzz_##name(Fuzz* f)
160
161#endif // Fuzz_DEFINED
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
Definition Fuzz.h:24
void next(T *t)
Definition Fuzz.h:64
Fuzz & operator=(Fuzz &)=delete
void signalBug()
Definition Fuzz.h:82
size_t remainingSize() const
Definition Fuzz.h:47
size_t size() const
Definition Fuzz.h:34
const uint8_t * remainingData() const
Definition Fuzz.h:51
void nextRange(T *, Min, Max)
Definition Fuzz.h:119
bool nextBool()
Definition Fuzz.h:92
void deplete()
Definition Fuzz.h:43
bool exhausted() const
Definition Fuzz.h:39
friend void fuzz__MakeEncoderCorpus(Fuzz *)
Fuzz(Fuzz &)=delete
void nextEnum(T *ptr, T max)
Definition Fuzz.h:131
Fuzz()=delete
Fuzz(const uint8_t *data, size_t size)
Definition Fuzz.h:26
void nextN(T *ptr, int n)
Definition Fuzz.h:144
static bool b
uint8_t value
static float max(float r, float g, float b)
Definition hsl.cpp:49
static float min(float r, float g, float b)
Definition hsl.cpp:48
#define T
const char * name
Definition Fuzz.h:151
void(* fn)(Fuzz *)
Definition Fuzz.h:152