diff options
Diffstat (limited to 'fuzz/Fuzz.h')
-rw-r--r-- | fuzz/Fuzz.h | 98 |
1 files changed, 58 insertions, 40 deletions
diff --git a/fuzz/Fuzz.h b/fuzz/Fuzz.h index 43918f4a94..17d75f4d34 100644 --- a/fuzz/Fuzz.h +++ b/fuzz/Fuzz.h @@ -12,7 +12,7 @@ #include "SkTRegistry.h" #include "SkTypes.h" -#include <vector> +#include <cmath> class Fuzz : SkNoncopyable { public: @@ -20,60 +20,78 @@ public: // Returns the total number of "random" bytes available. size_t size(); - // Returns the total number of "random" bytes remaining for randomness. - size_t remaining(); + // Returns if there are no bytes remaining for fuzzing. + bool exhausted(); template <typename T> - bool SK_WARN_UNUSED_RESULT next(T* n); + T next(); - // UBSAN reminds us that bool can only legally hold 0 or 1. - bool SK_WARN_UNUSED_RESULT next(bool* b) { - uint8_t byte; - if (!this->next(&byte)) { - return false; - } - *b = (byte & 1) == 1; - return true; - } + // nextRange returns values only in [min, max]. + template <typename T> + T nextRange(T min, T max); - // The nextFoo methods are deprecated. - // TODO(kjlubick): replace existing uses with next() and remove these. - bool nextBool(); - uint8_t nextB(); - uint32_t nextU(); - // This can be nan, +- infinity, 0, anything. - float nextF(); - // Returns a float between [0..1) as a IEEE float - float nextF1(); - - // Return the next fuzzed value [min, max) as an unsigned 32bit integer. - uint32_t nextRangeU(uint32_t min, uint32_t max); - /** - * Returns next fuzzed value [min...max) as a float. - * Will not be Infinity or NaN. - */ - float nextRangeF(float min, float max); - - void signalBug (); // Tell afl-fuzz these inputs found a bug. - void signalBoring(); // Tell afl-fuzz these inputs are not worth testing. + void signalBug(); // Tell afl-fuzz these inputs found a bug. private: template <typename T> T nextT(); sk_sp<SkData> fBytes; - int fNextByte; + size_t fNextByte; }; +// UBSAN reminds us that bool can only legally hold 0 or 1. +template <> +inline bool Fuzz::next<bool>() { + return (this->next<uint8_t>() & 1) == 1; +} + template <typename T> -bool Fuzz::next(T* n) { - if (fNextByte + sizeof(T) > fBytes->size()) { - return false; +T Fuzz::next() { + if ((fNextByte + sizeof(T)) > fBytes->size()) { + T n = 0; + memcpy(&n, fBytes->bytes() + fNextByte, fBytes->size() - fNextByte); + fNextByte = fBytes->size(); + return n; } - - memcpy(n, fBytes->bytes() + fNextByte, sizeof(T)); + T n; + memcpy(&n, fBytes->bytes() + fNextByte, sizeof(T)); fNextByte += sizeof(T); - return true; + return n; +} + +template <> +inline float Fuzz::nextRange(float min, float max) { + if (min > max) { + SkDebugf("Check mins and maxes (%f, %f)\n", min, max); + this->signalBug(); + } + float f = this->next<float>(); + if (!std::isnormal(f) && f != 0.0f) { + // Don't deal with infinity or other strange floats. + return max; + } + return min + std::fmod(std::abs(f), (max - min + 1)); +} + +template <typename T> +T Fuzz::nextRange(T min, T max) { + if (min > max) { + SkDebugf("Check mins and maxes (%d, %d)\n", min, max); + this->signalBug(); + } + T n = this->next<T>(); + T range = max - min + 1; + if (0 == range) { + return n; + } else { + n = abs(n); + if (n < 0) { + // abs(INT_MIN) = INT_MIN, so we check this to avoid accidental negatives. + return min; + } + return min + n % range; + } } struct Fuzzable { |