747c31e296
Moves the (SkRect + flags) struct into SkImageFilter_Base with protected access only. Base constructor and all src/effects/imagefilters Make functions now take a "const SkRect*" instead. CropRect is still what's stored and used by filter implementations during filterImage(), but it's no longer publicly available. The SkImageFilters factory implementations now can go straight to the Make functions in src/effects/imagefilters instead of wrapping its "const SkRect*" in an SkImageFilter::CropRect. Bug: skia:9296, skia:11230 Change-Id: I2c62f42031910ec405623d4519c8a434cd2b3bdd Reviewed-on: https://skia-review.googlesource.com/c/skia/+/361496 Commit-Queue: Michael Ludwig <michaelludwig@google.com> Reviewed-by: Florin Malita <fmalita@chromium.org> Reviewed-by: Mike Reed <reed@google.com> Auto-Submit: Michael Ludwig <michaelludwig@google.com>
143 lines
4.2 KiB
C++
143 lines
4.2 KiB
C++
/*
|
|
* Copyright 2016 Google Inc.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
* found in the LICENSE file.
|
|
*/
|
|
|
|
#ifndef Fuzz_DEFINED
|
|
#define Fuzz_DEFINED
|
|
|
|
#include "include/core/SkData.h"
|
|
#include "include/core/SkImageFilter.h"
|
|
#include "include/core/SkRegion.h"
|
|
#include "include/core/SkTypes.h"
|
|
#include "include/private/SkMalloc.h"
|
|
#include "include/private/SkTFitsIn.h"
|
|
#include "tools/Registry.h"
|
|
|
|
#include <limits>
|
|
#include <cmath>
|
|
#include <signal.h>
|
|
#include <limits>
|
|
|
|
class Fuzz : SkNoncopyable {
|
|
public:
|
|
explicit Fuzz(sk_sp<SkData> bytes) : fBytes(bytes), fNextByte(0) {}
|
|
|
|
// Returns the total number of "random" bytes available.
|
|
size_t size() { return fBytes->size(); }
|
|
// Returns if there are no bytes remaining for fuzzing.
|
|
bool exhausted() {
|
|
return fBytes->size() == fNextByte;
|
|
}
|
|
|
|
size_t remaining() {
|
|
return fBytes->size() - fNextByte;
|
|
}
|
|
|
|
void deplete() {
|
|
fNextByte = fBytes->size();
|
|
}
|
|
|
|
// next() loads fuzzed bytes into the variable passed in by pointer.
|
|
// We use this approach instead of T next() because different compilers
|
|
// evaluate function parameters in different orders. If fuzz->next()
|
|
// returned 5 and then 7, foo(fuzz->next(), fuzz->next()) would be
|
|
// foo(5, 7) when compiled on GCC and foo(7, 5) when compiled on Clang.
|
|
// By requiring params to be passed in, we avoid the temptation to call
|
|
// next() in a way that does not consume fuzzed bytes in a single
|
|
// platform-independent order.
|
|
template <typename T>
|
|
void next(T* t) { this->nextBytes(t, sizeof(T)); }
|
|
|
|
// This is a convenient way to initialize more than one argument at a time.
|
|
template <typename Arg, typename... Args>
|
|
void next(Arg* first, Args... rest);
|
|
|
|
// nextRange returns values only in [min, max].
|
|
template <typename T, typename Min, typename Max>
|
|
void nextRange(T*, Min, Max);
|
|
|
|
// nextEnum is a wrapper around nextRange for enums.
|
|
template <typename T>
|
|
void nextEnum(T* ptr, T max);
|
|
|
|
// nextN loads n * sizeof(T) bytes into ptr
|
|
template <typename T>
|
|
void nextN(T* ptr, int n);
|
|
|
|
void signalBug(){
|
|
// Tell the fuzzer that these inputs found a bug.
|
|
SkDebugf("Signal bug\n");
|
|
raise(SIGSEGV);
|
|
}
|
|
|
|
// Specialized versions for when true random doesn't quite make sense
|
|
void next(bool* b);
|
|
void next(SkRegion* region);
|
|
|
|
void nextRange(float* f, float min, float max);
|
|
|
|
private:
|
|
template <typename T>
|
|
T nextT();
|
|
|
|
sk_sp<SkData> fBytes;
|
|
size_t fNextByte;
|
|
friend void fuzz__MakeEncoderCorpus(Fuzz*);
|
|
|
|
void nextBytes(void* ptr, size_t size);
|
|
};
|
|
|
|
template <typename Arg, typename... Args>
|
|
inline void Fuzz::next(Arg* first, Args... rest) {
|
|
this->next(first);
|
|
this->next(rest...);
|
|
}
|
|
|
|
template <typename T, typename Min, typename Max>
|
|
inline void Fuzz::nextRange(T* value, Min min, Max max) {
|
|
// UBSAN worries if we make an enum with out of range values, even temporarily.
|
|
using Raw = typename sk_strip_enum<T>::type;
|
|
Raw raw;
|
|
this->next(&raw);
|
|
|
|
if (raw < (Raw)min) { raw = (Raw)min; }
|
|
if (raw > (Raw)max) { raw = (Raw)max; }
|
|
*value = (T)raw;
|
|
}
|
|
|
|
template <typename T>
|
|
inline void Fuzz::nextEnum(T* value, T max) {
|
|
// This works around the fact that UBSAN will assert if we put an invalid
|
|
// value into an enum. We might see issues with enums being represented
|
|
// on Windows differently than Linux, but that's not a thing we can fix here.
|
|
using U = typename std::underlying_type<T>::type;
|
|
U v;
|
|
this->next(&v);
|
|
if (v < (U)0) { *value = (T)0; return;}
|
|
if (v > (U)max) { *value = (T)max; return;}
|
|
*value = (T)v;
|
|
}
|
|
|
|
template <typename T>
|
|
inline void Fuzz::nextN(T* ptr, int n) {
|
|
for (int i = 0; i < n; i++) {
|
|
this->next(ptr+i);
|
|
}
|
|
}
|
|
|
|
struct Fuzzable {
|
|
const char* name;
|
|
void (*fn)(Fuzz*);
|
|
};
|
|
|
|
// Not static so that we can link these into oss-fuzz harnesses if we like.
|
|
#define DEF_FUZZ(name, f) \
|
|
void fuzz_##name(Fuzz*); \
|
|
sk_tools::Registry<Fuzzable> register_##name({#name, fuzz_##name}); \
|
|
void fuzz_##name(Fuzz* f)
|
|
|
|
#endif//Fuzz_DEFINED
|