blob: bfee1b3b4c5370c627112bf9c9c2116e448ac36e [file] [log] [blame]
mtklein65e58242016-01-13 12:57:57 -08001/*
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
Hal Canaryfdcfb8b2018-06-13 09:42:32 -040011#include "../tools/Registry.h"
Hal Canaryc640d0d2018-06-13 09:59:02 -040012#include "SkData.h"
Kevin Lubickbc9a1a82018-09-17 14:46:57 -040013#include "SkImageFilter.h"
Herb Derbyb549cc32017-03-27 13:35:15 -040014#include "SkMalloc.h"
Kevin Lubickbc9a1a82018-09-17 14:46:57 -040015#include "SkRegion.h"
mtklein65e58242016-01-13 12:57:57 -080016#include "SkTypes.h"
mtklein65e58242016-01-13 12:57:57 -080017
Hal Canaryc640d0d2018-06-13 09:59:02 -040018#include <limits>
Kevin Lubick2f535ce2016-11-01 15:01:12 -040019#include <cmath>
Kevin Lubick2541edf2018-01-11 10:27:14 -050020#include <signal.h>
Mike Kleinbf45c702018-06-11 11:56:57 -040021#include <limits>
kjlubick840f12a2016-10-25 06:11:05 -070022
mtklein65e58242016-01-13 12:57:57 -080023class Fuzz : SkNoncopyable {
24public:
Kevin Lubick2541edf2018-01-11 10:27:14 -050025 explicit Fuzz(sk_sp<SkData> bytes) : fBytes(bytes), fNextByte(0) {}
mtklein65e58242016-01-13 12:57:57 -080026
kjlubicke5654502016-07-19 16:50:03 -070027 // Returns the total number of "random" bytes available.
Kevin Lubick2541edf2018-01-11 10:27:14 -050028 size_t size() { return fBytes->size(); }
Kevin Lubick2f535ce2016-11-01 15:01:12 -040029 // Returns if there are no bytes remaining for fuzzing.
Kevin Lubickf84ded22018-10-23 09:28:48 -040030 bool exhausted() {
Kevin Lubick2541edf2018-01-11 10:27:14 -050031 return fBytes->size() == fNextByte;
32 }
kjlubicke5654502016-07-19 16:50:03 -070033
Kevin Lubickf84ded22018-10-23 09:28:48 -040034 size_t remaining() {
35 return fBytes->size() - fNextByte;
36 }
37
38 void deplete() {
39 fNextByte = fBytes->size();
40 }
41
Kevin Lubick416b2482016-11-10 16:17:49 -050042 // next() loads fuzzed bytes into the variable passed in by pointer.
43 // We use this approach instead of T next() because different compilers
44 // evaluate function parameters in different orders. If fuzz->next()
45 // returned 5 and then 7, foo(fuzz->next(), fuzz->next()) would be
46 // foo(5, 7) when compiled on GCC and foo(7, 5) when compiled on Clang.
47 // By requiring params to be passed in, we avoid the temptation to call
48 // next() in a way that does not consume fuzzed bytes in a single
Yuqian Lia63d6902018-02-28 11:46:00 -050049 // platform-independent order.
kjlubicke5654502016-07-19 16:50:03 -070050 template <typename T>
Kevin Lubick416b2482016-11-10 16:17:49 -050051 void next(T* t);
52
53 // This is a convenient way to initialize more than one argument at a time.
54 template <typename Arg, typename... Args>
55 void next(Arg* first, Args... rest);
kjlubicke5654502016-07-19 16:50:03 -070056
Kevin Lubick2f535ce2016-11-01 15:01:12 -040057 // nextRange returns values only in [min, max].
Kevin Lubick416b2482016-11-10 16:17:49 -050058 template <typename T, typename Min, typename Max>
59 void nextRange(T*, Min, Max);
60
Kevin Lubickbc9a1a82018-09-17 14:46:57 -040061 // Explicit version of nextRange for enums.
62 // Again, values are in [min, max].
63 template <typename T, typename Min, typename Max>
64 void nextEnum(T*, Min, Max);
65
Kevin Lubick416b2482016-11-10 16:17:49 -050066 // nextN loads n * sizeof(T) bytes into ptr
Kevin Lubick2f535ce2016-11-01 15:01:12 -040067 template <typename T>
Kevin Lubick416b2482016-11-10 16:17:49 -050068 void nextN(T* ptr, int n);
kjlubick85d30172016-10-24 11:53:35 -070069
Kevin Lubick2541edf2018-01-11 10:27:14 -050070 void signalBug(){
71 // Tell the fuzzer that these inputs found a bug.
72 SkDebugf("Signal bug\n");
73 raise(SIGSEGV);
74 }
mtkleina1159422016-01-15 05:46:54 -080075
Kevin Lubickbc9a1a82018-09-17 14:46:57 -040076 // Specialized versions for when true random doesn't quite make sense
77 void next(bool* b);
78 void next(SkImageFilter::CropRect* cropRect);
79 void next(SkRegion* region);
80
81 void nextRange(float* f, float min, float max);
82
mtklein65e58242016-01-13 12:57:57 -080083private:
mtkleina1159422016-01-15 05:46:54 -080084 template <typename T>
85 T nextT();
86
bungemanffae30d2016-08-03 13:32:32 -070087 sk_sp<SkData> fBytes;
Kevin Lubick2f535ce2016-11-01 15:01:12 -040088 size_t fNextByte;
Kevin Lubicke4be55d2018-03-30 15:05:13 -040089 friend void fuzz__MakeEncoderCorpus(Fuzz*);
mtklein65e58242016-01-13 12:57:57 -080090};
91
Kevin Lubick2f535ce2016-11-01 15:01:12 -040092template <typename T>
Kevin Lubick416b2482016-11-10 16:17:49 -050093inline void Fuzz::next(T* n) {
Kevin Lubick2f535ce2016-11-01 15:01:12 -040094 if ((fNextByte + sizeof(T)) > fBytes->size()) {
Hal Canary24ac42b2017-02-14 13:35:14 -050095 sk_bzero(n, sizeof(T));
Kevin Lubick416b2482016-11-10 16:17:49 -050096 memcpy(n, fBytes->bytes() + fNextByte, fBytes->size() - fNextByte);
Kevin Lubick2f535ce2016-11-01 15:01:12 -040097 fNextByte = fBytes->size();
Kevin Lubick416b2482016-11-10 16:17:49 -050098 return;
Kevin Lubick2f535ce2016-11-01 15:01:12 -040099 }
Kevin Lubick416b2482016-11-10 16:17:49 -0500100 memcpy(n, fBytes->bytes() + fNextByte, sizeof(T));
kjlubicke5654502016-07-19 16:50:03 -0700101 fNextByte += sizeof(T);
Kevin Lubick416b2482016-11-10 16:17:49 -0500102}
103
104template <typename Arg, typename... Args>
105inline void Fuzz::next(Arg* first, Args... rest) {
106 this->next(first);
107 this->next(rest...);
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400108}
109
Kevin Lubick416b2482016-11-10 16:17:49 -0500110template <typename T, typename Min, typename Max>
111inline void Fuzz::nextRange(T* n, Min min, Max max) {
112 this->next<T>(n);
Kevin Lubickd1042662016-11-29 11:25:52 -0500113 if (min == max) {
114 *n = min;
115 return;
116 }
117 if (min > max) {
Kevin Lubickc9f0cc82016-11-15 16:07:02 -0500118 // Avoid misuse of nextRange
Kevin Lubick1991f552018-02-27 10:59:10 -0500119 SkDebugf("min > max (%d > %d) \n", min, max);
Kevin Lubickc9f0cc82016-11-15 16:07:02 -0500120 this->signalBug();
Kevin Lubick416b2482016-11-10 16:17:49 -0500121 }
Kevin Lubickc9f0cc82016-11-15 16:07:02 -0500122 if (*n < 0) { // Handle negatives
123 if (*n != std::numeric_limits<T>::lowest()) {
124 *n *= -1;
125 }
126 else {
127 *n = std::numeric_limits<T>::max();
128 }
129 }
130 *n = min + (*n % ((size_t)max - min + 1));
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400131}
132
Kevin Lubickbc9a1a82018-09-17 14:46:57 -0400133template <typename T, typename Min, typename Max>
134inline void Fuzz::nextEnum(T* value, Min rmin, Max rmax) {
Kevin Lubickf84ded22018-10-23 09:28:48 -0400135 this->nextRange((uint32_t*)value, (uint32_t)rmin, (uint32_t)rmax);
Kevin Lubickbc9a1a82018-09-17 14:46:57 -0400136}
137
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400138template <typename T>
Kevin Lubick416b2482016-11-10 16:17:49 -0500139inline void Fuzz::nextN(T* ptr, int n) {
140 for (int i = 0; i < n; i++) {
141 this->next(ptr+i);
142 }
kjlubicke5654502016-07-19 16:50:03 -0700143}
144
mtklein65e58242016-01-13 12:57:57 -0800145struct Fuzzable {
146 const char* name;
147 void (*fn)(Fuzz*);
148};
149
Kevin Lubickdb1e5c62018-02-27 08:30:43 -0500150// Not static so that we can link these into oss-fuzz harnesses if we like.
Mike Reedab273fa2017-01-11 13:58:55 -0500151#define DEF_FUZZ(name, f) \
Kevin Lubickdb1e5c62018-02-27 08:30:43 -0500152 void fuzz_##name(Fuzz*); \
Mike Reedab273fa2017-01-11 13:58:55 -0500153 sk_tools::Registry<Fuzzable> register_##name({#name, fuzz_##name}); \
Kevin Lubickdb1e5c62018-02-27 08:30:43 -0500154 void fuzz_##name(Fuzz* f)
mtklein65e58242016-01-13 12:57:57 -0800155
mtklein65e58242016-01-13 12:57:57 -0800156#endif//Fuzz_DEFINED