Coverage Report

Created: 2024-05-20 07:14

/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.7k
DEF_FUZZ(Pathop, fuzz) {
17
18
10.7k
    uint8_t choice;
19
10.7k
    fuzz->nextRange(&choice, 0, 4);
20
10.7k
    switch (choice) {
21
2.63k
        case 0: {
22
2.63k
            uint8_t ops;
23
2.63k
            fuzz->nextRange(&ops, 0, MAX_OPS);
24
2.63k
            SkOpBuilder builder;
25
19.7k
            for (uint8_t i = 0; i < ops && !fuzz->exhausted(); i++) {
26
17.1k
                SkPath path;
27
17.1k
                FuzzEvilPath(fuzz, &path, SkPath::Verb::kDone_Verb);
28
17.1k
                SkPathFillType ft;
29
17.1k
                fuzz->nextRange(&ft, 0, (int)SkPathFillType::kInverseEvenOdd);
30
17.1k
                path.setFillType(ft);
31
32
17.1k
                SkPathOp op;
33
17.1k
                fuzz->nextRange(&op, 0, SkPathOp::kReverseDifference_SkPathOp);
34
17.1k
                builder.add(path, op);
35
17.1k
            }
36
37
2.63k
            SkPath result;
38
2.63k
            builder.resolve(&result);
39
2.63k
            break;
40
0
        }
41
2.30k
        case 1: {
42
2.30k
            SkPath path;
43
2.30k
            FuzzEvilPath(fuzz, &path, SkPath::Verb::kDone_Verb);
44
2.30k
            SkPathFillType ft;
45
2.30k
            fuzz->nextRange(&ft, 0, (int)SkPathFillType::kInverseEvenOdd);
46
2.30k
            path.setFillType(ft);
47
48
2.30k
            SkPath result;
49
2.30k
            bool isSame;
50
2.30k
            fuzz->next(&isSame);
51
2.30k
            if (isSame) {
52
50
                result = path;
53
50
            }
54
2.30k
            Simplify(path, &result);
55
2.30k
            break;
56
0
        }
57
4.63k
        case 2: {
58
4.63k
            SkPath path;
59
4.63k
            FuzzEvilPath(fuzz, &path, SkPath::Verb::kDone_Verb);
60
4.63k
            SkPathFillType ft;
61
4.63k
            fuzz->nextRange(&ft, 0, SkPathFillType::kInverseEvenOdd);
62
4.63k
            path.setFillType(ft);
63
64
4.63k
            SkPath path2;
65
4.63k
            FuzzEvilPath(fuzz, &path2, SkPath::Verb::kDone_Verb);
66
4.63k
            fuzz->nextRange(&ft, 0, SkPathFillType::kInverseEvenOdd);
67
4.63k
            path.setFillType(ft);
68
69
4.63k
            SkPathOp op;
70
4.63k
            fuzz->nextRange(&op, 0, SkPathOp::kReverseDifference_SkPathOp);
71
72
4.63k
            SkPath result;
73
4.63k
            uint8_t pickOutput;
74
4.63k
            fuzz->nextRange(&pickOutput, 0, 2);
75
4.63k
            if (pickOutput == 1) {
76
1
                result = path;
77
4.63k
            } else if (pickOutput == 2) {
78
199
                result = path2;
79
199
            }
80
4.63k
            Op(path, path2, op, &result);
81
4.63k
            break;
82
0
        }
83
726
        case 3: {
84
726
            SkPath path;
85
726
            FuzzEvilPath(fuzz, &path, SkPath::Verb::kDone_Verb);
86
726
            SkPathFillType ft;
87
726
            fuzz->nextRange(&ft, 0, SkPathFillType::kInverseEvenOdd);
88
726
            path.setFillType(ft);
89
90
726
            SkPath result;
91
726
            bool isSame;
92
726
            fuzz->next(&isSame);
93
726
            if (isSame) {
94
159
                result = path;
95
159
            }
96
726
            AsWinding(path, &result);
97
726
            break;
98
0
        }
99
478
        case 4: {
100
478
            SkPath path;
101
478
            FuzzEvilPath(fuzz, &path, SkPath::Verb::kDone_Verb);
102
478
            SkPathFillType ft;
103
478
            fuzz->nextRange(&ft, 0, SkPathFillType::kInverseEvenOdd);
104
478
            path.setFillType(ft);
105
106
478
            SkRect result;
107
478
            TightBounds(path, &result);
108
478
            break;
109
0
        }
110
0
        default: {
111
0
            SkASSERT(false);
112
0
            break;
113
0
        }
114
10.7k
    }
115
10.7k
}
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
}