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