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