• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 #include "fuzz/Fuzz.h"
9 #include "fuzz/FuzzCommon.h"
10 #include "include/core/SkPath.h"
11 #include "include/core/SkRect.h"
12 #include "include/pathops/SkPathOps.h"
13 
14 const uint8_t MAX_OPS = 20;
15 
DEF_FUZZ(Pathop,fuzz)16 DEF_FUZZ(Pathop, fuzz) {
17 
18     uint8_t choice;
19     fuzz->nextRange(&choice, 0, 4);
20     switch (choice) {
21         case 0: {
22             uint8_t ops;
23             fuzz->nextRange(&ops, 0, MAX_OPS);
24             SkOpBuilder builder;
25             for (uint8_t i = 0; i < ops && !fuzz->exhausted(); i++) {
26                 SkPath path;
27                 FuzzEvilPath(fuzz, &path, SkPath::Verb::kDone_Verb);
28                 SkPathFillType ft;
29                 fuzz->nextRange(&ft, 0, (int)SkPathFillType::kInverseEvenOdd);
30                 path.setFillType(ft);
31 
32                 SkPathOp op;
33                 fuzz->nextRange(&op, 0, SkPathOp::kReverseDifference_SkPathOp);
34                 builder.add(path, op);
35             }
36 
37             SkPath result;
38             builder.resolve(&result);
39             break;
40         }
41         case 1: {
42             SkPath path;
43             FuzzEvilPath(fuzz, &path, SkPath::Verb::kDone_Verb);
44             SkPathFillType ft;
45             fuzz->nextRange(&ft, 0, (int)SkPathFillType::kInverseEvenOdd);
46             path.setFillType(ft);
47 
48             SkPath result;
49             bool isSame;
50             fuzz->next(&isSame);
51             if (isSame) {
52                 result = path;
53             }
54             Simplify(path, &result);
55             break;
56         }
57         case 2: {
58             SkPath path;
59             FuzzEvilPath(fuzz, &path, SkPath::Verb::kDone_Verb);
60             SkPathFillType ft;
61             fuzz->nextRange(&ft, 0, SkPathFillType::kInverseEvenOdd);
62             path.setFillType(ft);
63 
64             SkPath path2;
65             FuzzEvilPath(fuzz, &path2, SkPath::Verb::kDone_Verb);
66             fuzz->nextRange(&ft, 0, SkPathFillType::kInverseEvenOdd);
67             path.setFillType(ft);
68 
69             SkPathOp op;
70             fuzz->nextRange(&op, 0, SkPathOp::kReverseDifference_SkPathOp);
71 
72             SkPath result;
73             uint8_t pickOutput;
74             fuzz->nextRange(&pickOutput, 0, 2);
75             if (pickOutput == 1) {
76                 result = path;
77             } else if (pickOutput == 2) {
78                 result = path2;
79             }
80             Op(path, path2, op, &result);
81             break;
82         }
83         case 3: {
84             SkPath path;
85             FuzzEvilPath(fuzz, &path, SkPath::Verb::kDone_Verb);
86             SkPathFillType ft;
87             fuzz->nextRange(&ft, 0, SkPathFillType::kInverseEvenOdd);
88             path.setFillType(ft);
89 
90             SkPath result;
91             bool isSame;
92             fuzz->next(&isSame);
93             if (isSame) {
94                 result = path;
95             }
96             AsWinding(path, &result);
97             break;
98         }
99         case 4: {
100             SkPath path;
101             FuzzEvilPath(fuzz, &path, SkPath::Verb::kDone_Verb);
102             SkPathFillType ft;
103             fuzz->nextRange(&ft, 0, SkPathFillType::kInverseEvenOdd);
104             path.setFillType(ft);
105 
106             SkRect result;
107             TightBounds(path, &result);
108             break;
109         }
110         default: {
111             SkASSERT(false);
112             break;
113         }
114     }
115 }
116 
117 
118 const int kLastOp = SkPathOp::kReverseDifference_SkPathOp;
119 
BuildPath(Fuzz * fuzz,SkPath * path)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.
124     uint8_t operation;
125     fuzz->next(&operation);
126     SkScalar a,b,c,d,e,f;
127 
128     switch (operation % (SkPath::Verb::kDone_Verb + 1)) {
129       case SkPath::Verb::kMove_Verb:
130         if (fuzz->remaining() < (2*sizeof(SkScalar))) {
131             fuzz->deplete();
132             return;
133         }
134         fuzz->next(&a, &b);
135         path->moveTo(a, b);
136         break;
137 
138       case SkPath::Verb::kLine_Verb:
139         if (fuzz->remaining() < (2*sizeof(SkScalar))) {
140             fuzz->deplete();
141             return;
142         }
143         fuzz->next(&a, &b);
144         path->lineTo(a, b);
145         break;
146 
147       case SkPath::Verb::kQuad_Verb:
148         if (fuzz->remaining() < (4*sizeof(SkScalar))) {
149             fuzz->deplete();
150             return;
151         }
152         fuzz->next(&a, &b, &c, &d);
153         path->quadTo(a, b, c, d);
154         break;
155 
156       case SkPath::Verb::kConic_Verb:
157         if (fuzz->remaining() < (5*sizeof(SkScalar))) {
158             fuzz->deplete();
159             return;
160         }
161         fuzz->next(&a, &b, &c, &d, &e);
162         path->conicTo(a, b, c, d, e);
163         break;
164 
165       case SkPath::Verb::kCubic_Verb:
166         if (fuzz->remaining() < (6*sizeof(SkScalar))) {
167             fuzz->deplete();
168             return;
169         }
170         fuzz->next(&a, &b, &c, &d, &e, &f);
171         path->cubicTo(a, b, c, d, e, f);
172         break;
173 
174       case SkPath::Verb::kClose_Verb:
175         path->close();
176         break;
177 
178       case SkPath::Verb::kDone_Verb:
179         // In this case, simply exit.
180         return;
181     }
182   }
183 }
184 
DEF_FUZZ(LegacyChromiumPathop,fuzz)185 DEF_FUZZ(LegacyChromiumPathop, fuzz) {
186     // See https://cs.chromium.org/chromium/src/testing/libfuzzer/fuzzers/skia_pathop_fuzzer.cc
187     SkOpBuilder builder;
188     while (!fuzz->exhausted()) {
189         SkPath path;
190         uint8_t op;
191         fuzz->next(&op);
192         if (fuzz->exhausted()) {
193             break;
194         }
195 
196         BuildPath(fuzz, &path);
197         builder.add(path, static_cast<SkPathOp>(op % (kLastOp + 1)));
198     }
199 
200     SkPath result;
201     builder.resolve(&result);
202 }
203