Mercurial > hg
annotate contrib/fuzz/FuzzedDataProvider.h @ 43813:5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
This is taken from the (improved since we started fuzzing) guide on ideal
integrations. Rather than have our own wonky targets for building outside the
fuzzer universe, we have a driver program we carry along and use when we're
not using LibFuzzer. This will let us jettison a fair amount of goo.
contrib/fuzz/standalone_fuzz_target_runner.cc is
https://github.com/google/oss-fuzz/ file
projects/example/my-api-repo/standalone from git revision
c4579d9358a73ea5dbcc99cb985de1f2bf76dcf7, reformatted with out
clang-format settings and a no-check-code comment added. It allows
running a single test input through a fuzzer, rather than performing
ongoing fuzzing as libfuzzer would.
contrib/fuzz/FuzzedDataProvider.h is
https://github.com/llvm/llvm-project/ file
/compiler-rt/include/fuzzer/FuzzedDataProvider.h from git revision
a44ef027ebca1598892ea9b104d6189aeb3bc2f0, reformatted with our
clang-format settings and a no-check-code comment added. We can
discard this if we instead want to add an hghave check for a new
enough llvm that includes FuzzedDataProvder.h in the fuzzer headers.
Differential Revision: https://phab.mercurial-scm.org/D7564
author | Augie Fackler <augie@google.com> |
---|---|
date | Fri, 06 Dec 2019 15:19:47 -0500 |
parents | |
children |
rev | line source |
---|---|
43813
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
1 //===- FuzzedDataProvider.h - Utility header for fuzz targets ---*- C++ -* ===// |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
2 // |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
4 // See https://llvm.org/LICENSE.txt for license information. |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
6 // |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
7 //===----------------------------------------------------------------------===// |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
8 // A single header library providing an utility class to break up an array of |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
9 // bytes. Whenever run on the same input, provides the same output, as long as |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
10 // its methods are called in the same order, with the same arguments. |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
11 //===----------------------------------------------------------------------===// |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
12 |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
13 #ifndef LLVM_FUZZER_FUZZED_DATA_PROVIDER_H_ |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
14 #define LLVM_FUZZER_FUZZED_DATA_PROVIDER_H_ |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
15 |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
16 #include <algorithm> |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
17 #include <climits> |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
18 #include <cstddef> |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
19 #include <cstdint> |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
20 #include <cstring> |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
21 #include <initializer_list> |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
22 #include <string> |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
23 #include <type_traits> |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
24 #include <utility> |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
25 #include <vector> |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
26 |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
27 // In addition to the comments below, the API is also briefly documented at |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
28 // https://github.com/google/fuzzing/blob/master/docs/split-inputs.md#fuzzed-data-provider |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
29 class FuzzedDataProvider |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
30 { |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
31 public: |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
32 // |data| is an array of length |size| that the FuzzedDataProvider wraps |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
33 // to provide more granular access. |data| must outlive the |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
34 // FuzzedDataProvider. |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
35 FuzzedDataProvider(const uint8_t *data, size_t size) |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
36 : data_ptr_(data), remaining_bytes_(size) |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
37 { |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
38 } |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
39 ~FuzzedDataProvider() = default; |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
40 |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
41 // Returns a std::vector containing |num_bytes| of input data. If fewer |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
42 // than |num_bytes| of data remain, returns a shorter std::vector |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
43 // containing all of the data that's left. Can be used with any byte |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
44 // sized type, such as char, unsigned char, uint8_t, etc. |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
45 template <typename T> std::vector<T> ConsumeBytes(size_t num_bytes) |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
46 { |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
47 num_bytes = std::min(num_bytes, remaining_bytes_); |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
48 return ConsumeBytes<T>(num_bytes, num_bytes); |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
49 } |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
50 |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
51 // Similar to |ConsumeBytes|, but also appends the terminator value at |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
52 // the end of the resulting vector. Useful, when a mutable |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
53 // null-terminated C-string is needed, for example. But that is a rare |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
54 // case. Better avoid it, if possible, and prefer using |ConsumeBytes| |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
55 // or |ConsumeBytesAsString| methods. |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
56 template <typename T> |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
57 std::vector<T> ConsumeBytesWithTerminator(size_t num_bytes, |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
58 T terminator = 0) |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
59 { |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
60 num_bytes = std::min(num_bytes, remaining_bytes_); |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
61 std::vector<T> result = |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
62 ConsumeBytes<T>(num_bytes + 1, num_bytes); |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
63 result.back() = terminator; |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
64 return result; |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
65 } |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
66 |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
67 // Returns a std::string containing |num_bytes| of input data. Using |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
68 // this and |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
69 // |.c_str()| on the resulting string is the best way to get an |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
70 // immutable null-terminated C string. If fewer than |num_bytes| of data |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
71 // remain, returns a shorter std::string containing all of the data |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
72 // that's left. |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
73 std::string ConsumeBytesAsString(size_t num_bytes) |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
74 { |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
75 static_assert(sizeof(std::string::value_type) == |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
76 sizeof(uint8_t), |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
77 "ConsumeBytesAsString cannot convert the data to " |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
78 "a string."); |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
79 |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
80 num_bytes = std::min(num_bytes, remaining_bytes_); |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
81 std::string result( |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
82 reinterpret_cast<const std::string::value_type *>( |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
83 data_ptr_), |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
84 num_bytes); |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
85 Advance(num_bytes); |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
86 return result; |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
87 } |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
88 |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
89 // Returns a number in the range [min, max] by consuming bytes from the |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
90 // input data. The value might not be uniformly distributed in the given |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
91 // range. If there's no input data left, always returns |min|. |min| |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
92 // must be less than or equal to |max|. |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
93 template <typename T> T ConsumeIntegralInRange(T min, T max) |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
94 { |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
95 static_assert(std::is_integral<T>::value, |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
96 "An integral type is required."); |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
97 static_assert(sizeof(T) <= sizeof(uint64_t), |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
98 "Unsupported integral type."); |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
99 |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
100 if (min > max) |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
101 abort(); |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
102 |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
103 // Use the biggest type possible to hold the range and the |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
104 // result. |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
105 uint64_t range = static_cast<uint64_t>(max) - min; |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
106 uint64_t result = 0; |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
107 size_t offset = 0; |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
108 |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
109 while (offset < sizeof(T) * CHAR_BIT && (range >> offset) > 0 && |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
110 remaining_bytes_ != 0) { |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
111 // Pull bytes off the end of the seed data. |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
112 // Experimentally, this seems to allow the fuzzer to |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
113 // more easily explore the input space. This makes |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
114 // sense, since it works by modifying inputs that caused |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
115 // new code to run, and this data is often used to |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
116 // encode length of data read by |ConsumeBytes|. |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
117 // Separating out read lengths makes it easier modify |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
118 // the contents of the data that is actually read. |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
119 --remaining_bytes_; |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
120 result = |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
121 (result << CHAR_BIT) | data_ptr_[remaining_bytes_]; |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
122 offset += CHAR_BIT; |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
123 } |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
124 |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
125 // Avoid division by 0, in case |range + 1| results in overflow. |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
126 if (range != std::numeric_limits<decltype(range)>::max()) |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
127 result = result % (range + 1); |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
128 |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
129 return static_cast<T>(min + result); |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
130 } |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
131 |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
132 // Returns a std::string of length from 0 to |max_length|. When it runs |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
133 // out of input data, returns what remains of the input. Designed to be |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
134 // more stable with respect to a fuzzer inserting characters than just |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
135 // picking a random length and then consuming that many bytes with |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
136 // |ConsumeBytes|. |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
137 std::string ConsumeRandomLengthString(size_t max_length) |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
138 { |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
139 // Reads bytes from the start of |data_ptr_|. Maps "\\" to "\", |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
140 // and maps "\" followed by anything else to the end of the |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
141 // string. As a result of this logic, a fuzzer can insert |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
142 // characters into the string, and the string will be lengthened |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
143 // to include those new characters, resulting in a more stable |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
144 // fuzzer than picking the length of a string independently from |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
145 // picking its contents. |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
146 std::string result; |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
147 |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
148 // Reserve the anticipated capaticity to prevent several |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
149 // reallocations. |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
150 result.reserve(std::min(max_length, remaining_bytes_)); |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
151 for (size_t i = 0; i < max_length && remaining_bytes_ != 0; |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
152 ++i) { |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
153 char next = ConvertUnsignedToSigned<char>(data_ptr_[0]); |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
154 Advance(1); |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
155 if (next == '\\' && remaining_bytes_ != 0) { |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
156 next = |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
157 ConvertUnsignedToSigned<char>(data_ptr_[0]); |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
158 Advance(1); |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
159 if (next != '\\') |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
160 break; |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
161 } |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
162 result += next; |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
163 } |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
164 |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
165 result.shrink_to_fit(); |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
166 return result; |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
167 } |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
168 |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
169 // Returns a std::vector containing all remaining bytes of the input |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
170 // data. |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
171 template <typename T> std::vector<T> ConsumeRemainingBytes() |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
172 { |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
173 return ConsumeBytes<T>(remaining_bytes_); |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
174 } |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
175 |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
176 // Returns a std::string containing all remaining bytes of the input |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
177 // data. Prefer using |ConsumeRemainingBytes| unless you actually need a |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
178 // std::string object. |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
179 std::string ConsumeRemainingBytesAsString() |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
180 { |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
181 return ConsumeBytesAsString(remaining_bytes_); |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
182 } |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
183 |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
184 // Returns a number in the range [Type's min, Type's max]. The value |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
185 // might not be uniformly distributed in the given range. If there's no |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
186 // input data left, always returns |min|. |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
187 template <typename T> T ConsumeIntegral() |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
188 { |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
189 return ConsumeIntegralInRange(std::numeric_limits<T>::min(), |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
190 std::numeric_limits<T>::max()); |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
191 } |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
192 |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
193 // Reads one byte and returns a bool, or false when no data remains. |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
194 bool ConsumeBool() |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
195 { |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
196 return 1 & ConsumeIntegral<uint8_t>(); |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
197 } |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
198 |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
199 // Returns a copy of the value selected from the given fixed-size |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
200 // |array|. |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
201 template <typename T, size_t size> |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
202 T PickValueInArray(const T (&array)[size]) |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
203 { |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
204 static_assert(size > 0, "The array must be non empty."); |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
205 return array[ConsumeIntegralInRange<size_t>(0, size - 1)]; |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
206 } |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
207 |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
208 template <typename T> |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
209 T PickValueInArray(std::initializer_list<const T> list) |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
210 { |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
211 // TODO(Dor1s): switch to static_assert once C++14 is allowed. |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
212 if (!list.size()) |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
213 abort(); |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
214 |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
215 return *(list.begin() + |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
216 ConsumeIntegralInRange<size_t>(0, list.size() - 1)); |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
217 } |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
218 |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
219 // Returns an enum value. The enum must start at 0 and be contiguous. It |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
220 // must also contain |kMaxValue| aliased to its largest (inclusive) |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
221 // value. Such as: enum class Foo { SomeValue, OtherValue, kMaxValue = |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
222 // OtherValue }; |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
223 template <typename T> T ConsumeEnum() |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
224 { |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
225 static_assert(std::is_enum<T>::value, |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
226 "|T| must be an enum type."); |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
227 return static_cast<T>(ConsumeIntegralInRange<uint32_t>( |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
228 0, static_cast<uint32_t>(T::kMaxValue))); |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
229 } |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
230 |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
231 // Returns a floating point number in the range [0.0, 1.0]. If there's |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
232 // no input data left, always returns 0. |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
233 template <typename T> T ConsumeProbability() |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
234 { |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
235 static_assert(std::is_floating_point<T>::value, |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
236 "A floating point type is required."); |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
237 |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
238 // Use different integral types for different floating point |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
239 // types in order to provide better density of the resulting |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
240 // values. |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
241 using IntegralType = |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
242 typename std::conditional<(sizeof(T) <= sizeof(uint32_t)), |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
243 uint32_t, uint64_t>::type; |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
244 |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
245 T result = static_cast<T>(ConsumeIntegral<IntegralType>()); |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
246 result /= |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
247 static_cast<T>(std::numeric_limits<IntegralType>::max()); |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
248 return result; |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
249 } |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
250 |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
251 // Returns a floating point value in the range [Type's lowest, Type's |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
252 // max] by consuming bytes from the input data. If there's no input data |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
253 // left, always returns approximately 0. |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
254 template <typename T> T ConsumeFloatingPoint() |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
255 { |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
256 return ConsumeFloatingPointInRange<T>( |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
257 std::numeric_limits<T>::lowest(), |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
258 std::numeric_limits<T>::max()); |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
259 } |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
260 |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
261 // Returns a floating point value in the given range by consuming bytes |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
262 // from the input data. If there's no input data left, returns |min|. |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
263 // Note that |min| must be less than or equal to |max|. |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
264 template <typename T> T ConsumeFloatingPointInRange(T min, T max) |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
265 { |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
266 if (min > max) |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
267 abort(); |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
268 |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
269 T range = .0; |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
270 T result = min; |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
271 constexpr T zero(.0); |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
272 if (max > zero && min < zero && |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
273 max > min + std::numeric_limits<T>::max()) { |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
274 // The diff |max - min| would overflow the given |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
275 // floating point type. Use the half of the diff as the |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
276 // range and consume a bool to decide whether the result |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
277 // is in the first of the second part of the diff. |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
278 range = (max / 2.0) - (min / 2.0); |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
279 if (ConsumeBool()) { |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
280 result += range; |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
281 } |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
282 } else { |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
283 range = max - min; |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
284 } |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
285 |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
286 return result + range * ConsumeProbability<T>(); |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
287 } |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
288 |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
289 // Reports the remaining bytes available for fuzzed input. |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
290 size_t remaining_bytes() |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
291 { |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
292 return remaining_bytes_; |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
293 } |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
294 |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
295 private: |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
296 FuzzedDataProvider(const FuzzedDataProvider &) = delete; |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
297 FuzzedDataProvider &operator=(const FuzzedDataProvider &) = delete; |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
298 |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
299 void Advance(size_t num_bytes) |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
300 { |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
301 if (num_bytes > remaining_bytes_) |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
302 abort(); |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
303 |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
304 data_ptr_ += num_bytes; |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
305 remaining_bytes_ -= num_bytes; |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
306 } |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
307 |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
308 template <typename T> |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
309 std::vector<T> ConsumeBytes(size_t size, size_t num_bytes_to_consume) |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
310 { |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
311 static_assert(sizeof(T) == sizeof(uint8_t), |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
312 "Incompatible data type."); |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
313 |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
314 // The point of using the size-based constructor below is to |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
315 // increase the odds of having a vector object with capacity |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
316 // being equal to the length. That part is always implementation |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
317 // specific, but at least both libc++ and libstdc++ allocate the |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
318 // requested number of bytes in that constructor, which seems to |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
319 // be a natural choice for other implementations as well. To |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
320 // increase the odds even more, we also call |shrink_to_fit| |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
321 // below. |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
322 std::vector<T> result(size); |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
323 if (size == 0) { |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
324 if (num_bytes_to_consume != 0) |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
325 abort(); |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
326 return result; |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
327 } |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
328 |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
329 std::memcpy(result.data(), data_ptr_, num_bytes_to_consume); |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
330 Advance(num_bytes_to_consume); |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
331 |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
332 // Even though |shrink_to_fit| is also implementation specific, |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
333 // we expect it to provide an additional assurance in case |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
334 // vector's constructor allocated a buffer which is larger than |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
335 // the actual amount of data we put inside it. |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
336 result.shrink_to_fit(); |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
337 return result; |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
338 } |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
339 |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
340 template <typename TS, typename TU> TS ConvertUnsignedToSigned(TU value) |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
341 { |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
342 static_assert(sizeof(TS) == sizeof(TU), |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
343 "Incompatible data types."); |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
344 static_assert(!std::numeric_limits<TU>::is_signed, |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
345 "Source type must be unsigned."); |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
346 |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
347 // TODO(Dor1s): change to `if constexpr` once C++17 becomes |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
348 // mainstream. |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
349 if (std::numeric_limits<TS>::is_modulo) |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
350 return static_cast<TS>(value); |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
351 |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
352 // Avoid using implementation-defined unsigned to signer |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
353 // conversions. To learn more, see |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
354 // https://stackoverflow.com/questions/13150449. |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
355 if (value <= std::numeric_limits<TS>::max()) { |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
356 return static_cast<TS>(value); |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
357 } else { |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
358 constexpr auto TS_min = std::numeric_limits<TS>::min(); |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
359 return TS_min + static_cast<char>(value - TS_min); |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
360 } |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
361 } |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
362 |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
363 const uint8_t *data_ptr_; |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
364 size_t remaining_bytes_; |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
365 }; |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
366 |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
367 #endif // LLVM_FUZZER_FUZZED_DATA_PROVIDER_H_ |
5a9e2ae9899b
fuzz: use a more standard approach to allow local builds of fuzzers
Augie Fackler <augie@google.com>
parents:
diff
changeset
|
368 // no-check-code since this is from a third party |