Coverage Report

Created: 2024-09-14 07:19

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