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