Add Legacy fuzz reproducer

Make FuzzEnum always use uint32_t to make it consistent
(we were seeing some Windows setups have underlying type return
int and not unsigned int that we saw on Linux)

Bug: 897455
Change-Id: Ia8c97e59bb498d959a9a30abcb61731f4bd145cf
Reviewed-on: https://skia-review.googlesource.com/c/164240
Reviewed-by: Cary Clark <caryclark@google.com>
Commit-Queue: Kevin Lubick <kjlubick@google.com>
This commit is contained in:
Kevin Lubick 2018-10-23 09:28:48 -04:00 committed by Skia Commit-Bot
parent 00766bf8dd
commit f84ded269e
3 changed files with 98 additions and 4 deletions

View File

@ -27,10 +27,18 @@ public:
// 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(){
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()
@ -124,8 +132,7 @@ inline void Fuzz::nextRange(T* n, Min min, Max max) {
template <typename T, typename Min, typename Max>
inline void Fuzz::nextEnum(T* value, Min rmin, Max rmax) {
using U = skstd::underlying_type_t<T>;
this->nextRange((U*)value, (U)rmin, (U)rmax);
this->nextRange((uint32_t*)value, (uint32_t)rmin, (uint32_t)rmax);
}
template <typename T>

View File

@ -234,7 +234,7 @@ static std::map<std::string, std::string> cf_api_map = {
{"api_raster_n32_canvas", "RasterN32Canvas"},
{"jpeg_encoder", "JPEGEncoder"},
{"png_encoder", "PNGEncoder"},
{"skia_pathop_fuzzer", "Pathop"},
{"skia_pathop_fuzzer", "LegacyChromiumPathop"},
{"webp_encoder", "WEBPEncoder"}
};

View File

@ -113,3 +113,90 @@ DEF_FUZZ(Pathop, fuzz) {
}
}
}
const int kLastOp = SkPathOp::kReverseDifference_SkPathOp;
void BuildPath(Fuzz* fuzz, SkPath* path) {
while (!fuzz->exhausted()) {
// Use a uint8_t to conserve bytes. This makes our "fuzzed bytes footprint"
// smaller, which leads to more efficient fuzzing.
uint8_t operation;
fuzz->next(&operation);
SkScalar a,b,c,d,e,f;
switch (operation % (SkPath::Verb::kDone_Verb + 1)) {
case SkPath::Verb::kMove_Verb:
if (fuzz->remaining() < (2*sizeof(SkScalar))) {
fuzz->deplete();
return;
}
fuzz->next(&a, &b);
path->moveTo(a, b);
break;
case SkPath::Verb::kLine_Verb:
if (fuzz->remaining() < (2*sizeof(SkScalar))) {
fuzz->deplete();
return;
}
fuzz->next(&a, &b);
path->lineTo(a, b);
break;
case SkPath::Verb::kQuad_Verb:
if (fuzz->remaining() < (4*sizeof(SkScalar))) {
fuzz->deplete();
return;
}
fuzz->next(&a, &b, &c, &d);
path->quadTo(a, b, c, d);
break;
case SkPath::Verb::kConic_Verb:
if (fuzz->remaining() < (5*sizeof(SkScalar))) {
fuzz->deplete();
return;
}
fuzz->next(&a, &b, &c, &d, &e);
path->conicTo(a, b, c, d, e);
break;
case SkPath::Verb::kCubic_Verb:
if (fuzz->remaining() < (6*sizeof(SkScalar))) {
fuzz->deplete();
return;
}
fuzz->next(&a, &b, &c, &d, &e, &f);
path->cubicTo(a, b, c, d, e, f);
break;
case SkPath::Verb::kClose_Verb:
path->close();
break;
case SkPath::Verb::kDone_Verb:
// In this case, simply exit.
return;
}
}
}
DEF_FUZZ(LegacyChromiumPathop, fuzz) {
// See https://cs.chromium.org/chromium/src/testing/libfuzzer/fuzzers/skia_pathop_fuzzer.cc
SkOpBuilder builder;
while (!fuzz->exhausted()) {
SkPath path;
uint8_t op;
fuzz->next(&op);
if (fuzz->exhausted()) {
break;
}
BuildPath(fuzz, &path);
builder.add(path, static_cast<SkPathOp>(op % (kLastOp + 1)));
}
SkPath result;
builder.resolve(&result);
}