2 * Copyright 2016 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
9 #include "fuzz/FuzzCommon.h"
10 #include "include/core/SkPath.h"
11 #include "include/core/SkRect.h"
12 #include "include/pathops/SkPathOps.h"
14 const uint8_t MAX_OPS = 20;
16 DEF_FUZZ(Pathop, fuzz) {
19 fuzz->nextRange(&choice, 0, 4);
23 fuzz->nextRange(&ops, 0, MAX_OPS);
25 for (uint8_t i = 0; i < ops && !fuzz->exhausted(); i++) {
27 FuzzEvilPath(fuzz, &path, SkPath::Verb::kDone_Verb);
29 fuzz->nextRange(&ft, 0, (int)SkPathFillType::kInverseEvenOdd);
33 fuzz->nextRange(&op, 0, SkPathOp::kReverseDifference_SkPathOp);
34 builder.add(path, op);
38 builder.resolve(&result);
43 FuzzEvilPath(fuzz, &path, SkPath::Verb::kDone_Verb);
45 fuzz->nextRange(&ft, 0, (int)SkPathFillType::kInverseEvenOdd);
54 Simplify(path, &result);
59 FuzzEvilPath(fuzz, &path, SkPath::Verb::kDone_Verb);
61 fuzz->nextRange(&ft, 0, SkPathFillType::kInverseEvenOdd);
65 FuzzEvilPath(fuzz, &path2, SkPath::Verb::kDone_Verb);
66 fuzz->nextRange(&ft, 0, SkPathFillType::kInverseEvenOdd);
70 fuzz->nextRange(&op, 0, SkPathOp::kReverseDifference_SkPathOp);
74 fuzz->nextRange(&pickOutput, 0, 2);
75 if (pickOutput == 1) {
77 } else if (pickOutput == 2) {
80 Op(path, path2, op, &result);
85 FuzzEvilPath(fuzz, &path, SkPath::Verb::kDone_Verb);
87 fuzz->nextRange(&ft, 0, SkPathFillType::kInverseEvenOdd);
96 AsWinding(path, &result);
101 FuzzEvilPath(fuzz, &path, SkPath::Verb::kDone_Verb);
103 fuzz->nextRange(&ft, 0, SkPathFillType::kInverseEvenOdd);
104 path.setFillType(ft);
107 TightBounds(path, &result);
118 const int kLastOp = SkPathOp::kReverseDifference_SkPathOp;
120 void BuildPath(Fuzz* fuzz, SkPath* path) {
121 while (!fuzz->exhausted()) {
122 // Use a uint8_t to conserve bytes. This makes our "fuzzed bytes footprint"
123 // smaller, which leads to more efficient fuzzing.
125 fuzz->next(&operation);
126 SkScalar a,b,c,d,e,f;
128 switch (operation % (SkPath::Verb::kDone_Verb + 1)) {
129 case SkPath::Verb::kMove_Verb:
130 if (fuzz->remaining() < (2*sizeof(SkScalar))) {
138 case SkPath::Verb::kLine_Verb:
139 if (fuzz->remaining() < (2*sizeof(SkScalar))) {
147 case SkPath::Verb::kQuad_Verb:
148 if (fuzz->remaining() < (4*sizeof(SkScalar))) {
152 fuzz->next(&a, &b, &c, &d);
153 path->quadTo(a, b, c, d);
156 case SkPath::Verb::kConic_Verb:
157 if (fuzz->remaining() < (5*sizeof(SkScalar))) {
161 fuzz->next(&a, &b, &c, &d, &e);
162 path->conicTo(a, b, c, d, e);
165 case SkPath::Verb::kCubic_Verb:
166 if (fuzz->remaining() < (6*sizeof(SkScalar))) {
170 fuzz->next(&a, &b, &c, &d, &e, &f);
171 path->cubicTo(a, b, c, d, e, f);
174 case SkPath::Verb::kClose_Verb:
178 case SkPath::Verb::kDone_Verb:
179 // In this case, simply exit.
185 DEF_FUZZ(LegacyChromiumPathop, fuzz) {
186 // See https://cs.chromium.org/chromium/src/testing/libfuzzer/fuzzers/skia_pathop_fuzzer.cc
188 while (!fuzz->exhausted()) {
192 if (fuzz->exhausted()) {
196 BuildPath(fuzz, &path);
197 builder.add(path, static_cast<SkPathOp>(op % (kLastOp + 1)));
201 builder.resolve(&result);