summaryrefslogtreecommitdiff
path: root/src/tools/fuzzing/random.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/fuzzing/random.h')
-rw-r--r--src/tools/fuzzing/random.h90
1 files changed, 89 insertions, 1 deletions
diff --git a/src/tools/fuzzing/random.h b/src/tools/fuzzing/random.h
index 156f248ca..845aa2fa5 100644
--- a/src/tools/fuzzing/random.h
+++ b/src/tools/fuzzing/random.h
@@ -18,8 +18,11 @@
#define wasm_tools_fuzzing_random_h
#include <cstdint>
+#include <map>
#include <vector>
+#include "wasm-features.h"
+
namespace wasm {
class Random {
@@ -33,9 +36,13 @@ class Random {
// After we finish the input, we start going through it again, but xoring
// so it's not identical.
int xorFactor = 0;
+ // Features used for picking among FeatureOptions.
+ FeatureSet features;
public:
- Random(std::vector<char>&& bytes);
+ Random(std::vector<char>&& bytes, FeatureSet features);
+ Random(std::vector<char>&& bytes)
+ : Random(std::move(bytes), FeatureSet::All) {}
// Methods for getting random data.
int8_t get();
@@ -55,6 +62,87 @@ public:
uint32_t upToSquared(uint32_t x) { return upTo(upTo(x)); }
bool finished() { return finishedInput; }
+
+ // Pick from a vector-like container
+ template<typename T> const typename T::value_type& pick(const T& vec) {
+ assert(!vec.empty());
+ auto index = upTo(vec.size());
+ return vec[index];
+ }
+
+ // Pick from a fixed list
+ template<typename T, typename... Args> T pick(T first, Args... args) {
+ auto num = sizeof...(Args) + 1;
+ auto temp = upTo(num);
+ return pickGivenNum<T>(temp, first, args...);
+ }
+
+ template<typename T> T pickGivenNum(size_t num, T first) {
+ assert(num == 0);
+ return first;
+ }
+
+// Trick to avoid a bug in GCC 7.x.
+// Upstream bug report: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82800
+#define GCC_VERSION \
+ (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
+#if GCC_VERSION > 70000 && GCC_VERSION < 70300
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
+#endif
+
+ template<typename T, typename... Args>
+ T pickGivenNum(size_t num, T first, Args... args) {
+ if (num == 0) {
+ return first;
+ }
+ return pickGivenNum<T>(num - 1, args...);
+ }
+
+#if GCC_VERSION > 70000 && GCC_VERSION < 70300
+#pragma GCC diagnostic pop
+#endif
+
+ template<typename T> struct FeatureOptions {
+ template<typename... Ts>
+ FeatureOptions<T>& add(FeatureSet feature, T option, Ts... rest) {
+ options[feature].push_back(option);
+ return add(feature, rest...);
+ }
+
+ struct WeightedOption {
+ T option;
+ size_t weight;
+ };
+
+ template<typename... Ts>
+ FeatureOptions<T>&
+ add(FeatureSet feature, WeightedOption weightedOption, Ts... rest) {
+ for (size_t i = 0; i < weightedOption.weight; i++) {
+ options[feature].push_back(weightedOption.option);
+ }
+ return add(feature, rest...);
+ }
+
+ FeatureOptions<T>& add(FeatureSet feature) { return *this; }
+
+ std::map<FeatureSet, std::vector<T>> options;
+ };
+
+ template<typename T> std::vector<T> items(FeatureOptions<T>& picker) {
+ std::vector<T> matches;
+ for (const auto& item : picker.options) {
+ if (features.has(item.first)) {
+ matches.reserve(matches.size() + item.second.size());
+ matches.insert(matches.end(), item.second.begin(), item.second.end());
+ }
+ }
+ return matches;
+ }
+
+ template<typename T> const T pick(FeatureOptions<T>& picker) {
+ return pick(items(picker));
+ }
};
} // namespace wasm