| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2016 Google Inc. | 2 * Copyright 2016 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #ifndef Fuzz_DEFINED | 8 #ifndef Fuzz_DEFINED |
| 9 #define Fuzz_DEFINED | 9 #define Fuzz_DEFINED |
| 10 | 10 |
| 11 #include "SkData.h" | 11 #include "SkData.h" |
| 12 #include "SkTRegistry.h" | 12 #include "SkTRegistry.h" |
| 13 #include "SkTypes.h" | 13 #include "SkTypes.h" |
| 14 | 14 |
| 15 #include <cmath> | 15 #include <cmath> |
| 16 | 16 |
| 17 class Fuzz : SkNoncopyable { | 17 class Fuzz : SkNoncopyable { |
| 18 public: | 18 public: |
| 19 explicit Fuzz(sk_sp<SkData>); | 19 explicit Fuzz(sk_sp<SkData>); |
| 20 | 20 |
| 21 // Returns the total number of "random" bytes available. | 21 // Returns the total number of "random" bytes available. |
| 22 size_t size(); | 22 size_t size(); |
| 23 // Returns if there are no bytes remaining for fuzzing. | 23 // Returns if there are no bytes remaining for fuzzing. |
| 24 bool exhausted(); | 24 bool exhausted(); |
| 25 | 25 |
| 26 // next() loads fuzzed bytes into the variable passed in by pointer. |
| 27 // We use this approach instead of T next() because different compilers |
| 28 // evaluate function parameters in different orders. If fuzz->next() |
| 29 // returned 5 and then 7, foo(fuzz->next(), fuzz->next()) would be |
| 30 // foo(5, 7) when compiled on GCC and foo(7, 5) when compiled on Clang. |
| 31 // By requiring params to be passed in, we avoid any problems with |
| 32 // non-determinism. |
| 26 template <typename T> | 33 template <typename T> |
| 27 T next(); | 34 void next(T* t); |
| 35 |
| 36 // This is a convenient way to initialize more than one argument at a time. |
| 37 template <typename Arg, typename... Args> |
| 38 void next(Arg* first, Args... rest); |
| 28 | 39 |
| 29 // nextRange returns values only in [min, max]. | 40 // nextRange returns values only in [min, max]. |
| 30 template <typename T> | 41 template <typename T> |
| 31 T nextRange(T min, T max); | 42 void nextRange(T* n, T min, T max); |
| 32 | 43 |
| 33 void signalBug(); // Tell afl-fuzz these inputs found a bug. | 44 void signalBug(); // Tell afl-fuzz these inputs found a bug. |
| 34 | 45 |
| 35 private: | 46 private: |
| 36 template <typename T> | 47 template <typename T> |
| 37 T nextT(); | 48 T nextT(); |
| 38 | 49 |
| 39 sk_sp<SkData> fBytes; | 50 sk_sp<SkData> fBytes; |
| 40 size_t fNextByte; | 51 size_t fNextByte; |
| 41 }; | 52 }; |
| 42 | 53 |
| 43 // UBSAN reminds us that bool can only legally hold 0 or 1. | 54 // UBSAN reminds us that bool can only legally hold 0 or 1. |
| 44 template <> | 55 template <> |
| 45 inline bool Fuzz::next<bool>() { | 56 inline void Fuzz::next(bool* b) { |
| 46 return (this->next<uint8_t>() & 1) == 1; | 57 uint8_t n; |
| 58 this->next(&n); |
| 59 *b = (n & 1) == 1; |
| 47 } | 60 } |
| 48 | 61 |
| 49 template <typename T> | 62 template <typename T> |
| 50 T Fuzz::next() { | 63 void Fuzz::next(T* n) { |
| 51 if ((fNextByte + sizeof(T)) > fBytes->size()) { | 64 if ((fNextByte + sizeof(T)) > fBytes->size()) { |
| 52 T n = 0; | 65 *n = 0; |
| 53 memcpy(&n, fBytes->bytes() + fNextByte, fBytes->size() - fNextByte); | 66 memcpy(n, fBytes->bytes() + fNextByte, fBytes->size() - fNextByte); |
| 54 fNextByte = fBytes->size(); | 67 fNextByte = fBytes->size(); |
| 55 return n; | 68 return; |
| 56 } | 69 } |
| 57 T n; | 70 memcpy(n, fBytes->bytes() + fNextByte, sizeof(T)); |
| 58 memcpy(&n, fBytes->bytes() + fNextByte, sizeof(T)); | |
| 59 fNextByte += sizeof(T); | 71 fNextByte += sizeof(T); |
| 60 return n; | 72 } |
| 73 |
| 74 template <typename Arg, typename... Args> |
| 75 void Fuzz::next(Arg* first, Args... rest) { |
| 76 this->next(first); |
| 77 this->next(rest...); |
| 61 } | 78 } |
| 62 | 79 |
| 63 template <> | 80 template <> |
| 64 inline float Fuzz::nextRange(float min, float max) { | 81 inline void Fuzz::nextRange(float* f, float min, float max) { |
| 65 if (min > max) { | 82 if (min > max) { |
| 66 SkDebugf("Check mins and maxes (%f, %f)\n", min, max); | 83 SkDebugf("Check mins and maxes (%f, %f)\n", min, max); |
| 67 this->signalBug(); | 84 this->signalBug(); |
| 68 } | 85 } |
| 69 float f = this->next<float>(); | 86 this->next<float>(f); |
| 70 if (!std::isnormal(f) && f != 0.0f) { | 87 if (!std::isnormal(*f) && *f != 0.0f) { |
| 71 // Don't deal with infinity or other strange floats. | 88 // Don't deal with infinity or other strange floats. |
| 72 return max; | 89 *f = max; |
| 73 } | 90 } |
| 74 return min + std::fmod(std::abs(f), (max - min + 1)); | 91 *f = min + std::fmod(std::abs(*f), (max - min + 1)); |
| 75 } | 92 } |
| 76 | 93 |
| 77 template <typename T> | 94 template <typename T> |
| 78 T Fuzz::nextRange(T min, T max) { | 95 void Fuzz::nextRange(T* n, T min, T max) { |
| 79 if (min > max) { | 96 if (min > max) { |
| 80 SkDebugf("Check mins and maxes (%d, %d)\n", min, max); | 97 SkDebugf("Check mins and maxes (%d, %d)\n", min, max); |
| 81 this->signalBug(); | 98 this->signalBug(); |
| 82 } | 99 } |
| 83 T n = this->next<T>(); | 100 this->next<T>(n); |
| 84 T range = max - min + 1; | 101 T range = max - min + 1; |
| 85 if (0 == range) { | 102 if (0 == range) { |
| 86 return n; | 103 return; |
| 87 } else { | 104 } else { |
| 88 n = abs(n); | 105 *n = abs(*n); |
| 89 if (n < 0) { | 106 if (*n < 0) { |
| 90 // abs(INT_MIN) = INT_MIN, so we check this to avoid accidental negati
ves. | 107 // abs(INT_MIN) = INT_MIN, so we check this to avoid accidental negati
ves. |
| 91 return min; | 108 *n = min; |
| 109 return; |
| 92 } | 110 } |
| 93 return min + n % range; | 111 *n = min + *n % range; |
| 94 } | 112 } |
| 95 } | 113 } |
| 96 | 114 |
| 97 struct Fuzzable { | 115 struct Fuzzable { |
| 98 const char* name; | 116 const char* name; |
| 99 void (*fn)(Fuzz*); | 117 void (*fn)(Fuzz*); |
| 100 }; | 118 }; |
| 101 | 119 |
| 102 #define DEF_FUZZ(name, f) \ | 120 #define DEF_FUZZ(name, f) \ |
| 103 static void fuzz_##name(Fuzz*); \ | 121 static void fuzz_##name(Fuzz*); \ |
| 104 SkTRegistry<Fuzzable> register_##name({#name, fuzz_##name}); \ | 122 SkTRegistry<Fuzzable> register_##name({#name, fuzz_##name}); \ |
| 105 static void fuzz_##name(Fuzz* f) | 123 static void fuzz_##name(Fuzz* f) |
| 106 | 124 |
| 107 #endif//Fuzz_DEFINED | 125 #endif//Fuzz_DEFINED |
| OLD | NEW |