diff options
Diffstat (limited to 'src/tools/fuzzing/random.h')
-rw-r--r-- | src/tools/fuzzing/random.h | 90 |
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 |