13
13
#ifndef LLVM_FUZZER_FUZZED_DATA_PROVIDER_H_
14
14
#define LLVM_FUZZER_FUZZED_DATA_PROVIDER_H_
15
15
16
- #include < limits.h>
17
- #include < stddef.h>
18
- #include < stdint.h>
19
-
20
16
#include < algorithm>
17
+ #include < climits>
18
+ #include < cstddef>
19
+ #include < cstdint>
21
20
#include < cstring>
22
21
#include < initializer_list>
23
22
#include < string>
24
23
#include < type_traits>
25
24
#include < utility>
26
25
#include < vector>
27
26
27
+ // In addition to the comments below, the API is also briefly documented at
28
+ // https://github.com/google/fuzzing/blob/master/docs/split-inputs.md#fuzzed-data-provider
28
29
class FuzzedDataProvider {
29
- public:
30
+ public:
30
31
// |data| is an array of length |size| that the FuzzedDataProvider wraps to
31
32
// provide more granular access. |data| must outlive the FuzzedDataProvider.
32
33
FuzzedDataProvider (const uint8_t *data, size_t size)
@@ -143,9 +144,9 @@ class FuzzedDataProvider {
143
144
return ConsumeBytes<T>(remaining_bytes_);
144
145
}
145
146
147
+ // Returns a std::string containing all remaining bytes of the input data.
146
148
// Prefer using |ConsumeRemainingBytes| unless you actually need a std::string
147
149
// object.
148
- // Returns a std::vector containing all remaining bytes of the input data.
149
150
std::string ConsumeRemainingBytesAsString () {
150
151
return ConsumeBytesAsString (remaining_bytes_);
151
152
}
@@ -161,7 +162,7 @@ class FuzzedDataProvider {
161
162
// Reads one byte and returns a bool, or false when no data remains.
162
163
bool ConsumeBool () { return 1 & ConsumeIntegral<uint8_t >(); }
163
164
164
- // Returns a copy of a value selected from a fixed-size |array|.
165
+ // Returns a copy of the value selected from the given fixed-size |array|.
165
166
template <typename T, size_t size>
166
167
T PickValueInArray (const T (&array)[size]) {
167
168
static_assert (size > 0 , " The array must be non empty." );
@@ -170,11 +171,14 @@ class FuzzedDataProvider {
170
171
171
172
template <typename T>
172
173
T PickValueInArray (std::initializer_list<const T> list) {
173
- // static_assert(list.size() > 0, "The array must be non empty.");
174
+ // TODO(Dor1s): switch to static_assert once C++14 is allowed.
175
+ if (!list.size ())
176
+ abort ();
177
+
174
178
return *(list.begin () + ConsumeIntegralInRange<size_t >(0 , list.size () - 1 ));
175
179
}
176
180
177
- // Return an enum value. The enum must start at 0 and be contiguous. It must
181
+ // Returns an enum value. The enum must start at 0 and be contiguous. It must
178
182
// also contain |kMaxValue| aliased to its largest (inclusive) value. Such as:
179
183
// enum class Foo { SomeValue, OtherValue, kMaxValue = OtherValue };
180
184
template <typename T> T ConsumeEnum () {
@@ -183,10 +187,60 @@ class FuzzedDataProvider {
183
187
0 , static_cast <uint32_t >(T::kMaxValue )));
184
188
}
185
189
190
+ // Returns a floating point number in the range [0.0, 1.0]. If there's no
191
+ // input data left, always returns 0.
192
+ template <typename T> T ConsumeProbability () {
193
+ static_assert (std::is_floating_point<T>::value,
194
+ " A floating point type is required." );
195
+
196
+ // Use different integral types for different floating point types in order
197
+ // to provide better density of the resulting values.
198
+ using IntegralType =
199
+ typename std::conditional<(sizeof (T) <= sizeof (uint32_t )), uint32_t ,
200
+ uint64_t >::type;
201
+
202
+ T result = static_cast <T>(ConsumeIntegral<IntegralType>());
203
+ result /= static_cast <T>(std::numeric_limits<IntegralType>::max ());
204
+ return result;
205
+ }
206
+
207
+ // Returns a floating point value in the range [Type's lowest, Type's max] by
208
+ // consuming bytes from the input data. If there's no input data left, always
209
+ // returns approximately 0.
210
+ template <typename T> T ConsumeFloatingPoint () {
211
+ return ConsumeFloatingPointInRange<T>(std::numeric_limits<T>::lowest (),
212
+ std::numeric_limits<T>::max ());
213
+ }
214
+
215
+ // Returns a floating point value in the given range by consuming bytes from
216
+ // the input data. If there's no input data left, returns |min|. Note that
217
+ // |min| must be less than or equal to |max|.
218
+ template <typename T> T ConsumeFloatingPointInRange (T min, T max) {
219
+ if (min > max)
220
+ abort ();
221
+
222
+ T range = .0 ;
223
+ T result = min;
224
+ constexpr T zero (.0 );
225
+ if (max > zero && min < zero && max > min + std::numeric_limits<T>::max ()) {
226
+ // The diff |max - min| would overflow the given floating point type. Use
227
+ // the half of the diff as the range and consume a bool to decide whether
228
+ // the result is in the first of the second part of the diff.
229
+ range = (max / 2.0 ) - (min / 2.0 );
230
+ if (ConsumeBool ()) {
231
+ result += range;
232
+ }
233
+ } else {
234
+ range = max - min;
235
+ }
236
+
237
+ return result + range * ConsumeProbability<T>();
238
+ }
239
+
186
240
// Reports the remaining bytes available for fuzzed input.
187
241
size_t remaining_bytes () { return remaining_bytes_; }
188
242
189
- private:
243
+ private:
190
244
FuzzedDataProvider (const FuzzedDataProvider &) = delete;
191
245
FuzzedDataProvider &operator =(const FuzzedDataProvider &) = delete;
192
246
@@ -209,6 +263,12 @@ class FuzzedDataProvider {
209
263
// which seems to be a natural choice for other implementations as well.
210
264
// To increase the odds even more, we also call |shrink_to_fit| below.
211
265
std::vector<T> result (size);
266
+ if (size == 0 ) {
267
+ if (num_bytes_to_consume != 0 )
268
+ abort ();
269
+ return result;
270
+ }
271
+
212
272
std::memcpy (result.data (), data_ptr_, num_bytes_to_consume);
213
273
Advance (num_bytes_to_consume);
214
274
@@ -230,9 +290,9 @@ class FuzzedDataProvider {
230
290
231
291
// Avoid using implementation-defined unsigned to signer conversions.
232
292
// To learn more, see https://stackoverflow.com/questions/13150449.
233
- if (value <= std::numeric_limits<TS>::max ())
293
+ if (value <= std::numeric_limits<TS>::max ()) {
234
294
return static_cast <TS>(value);
235
- else {
295
+ } else {
236
296
constexpr auto TS_min = std::numeric_limits<TS>::min ();
237
297
return TS_min + static_cast <char >(value - TS_min);
238
298
}
0 commit comments