Coverage Report

Created: 2021-08-22 09:07

/src/skia/fuzz/FuzzCommon.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2018 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
11
// We don't always want to test NaNs and infinities.
12
3.59M
static void fuzz_nice_float(Fuzz* fuzz, float* f) {
13
3.59M
    float v;
14
3.59M
    fuzz->next(&v);
15
3.59M
    constexpr float kLimit = 1.0e35f;  // FLT_MAX?
16
3.59M
    *f = (v == v && v <= kLimit && v >= -kLimit) ? v : 0.0f;
17
3.59M
}
18
19
template <typename... Args>
20
2.03M
static void fuzz_nice_float(Fuzz* fuzz, float* f, Args... rest) {
21
2.03M
    fuzz_nice_float(fuzz, f);
22
2.03M
    fuzz_nice_float(fuzz, rest...);
23
2.03M
}
FuzzCommon.cpp:void fuzz_nice_float<float*, float*, float*>(Fuzz*, float*, float*, float*, float*)
Line
Count
Source
20
201k
static void fuzz_nice_float(Fuzz* fuzz, float* f, Args... rest) {
21
201k
    fuzz_nice_float(fuzz, f);
22
201k
    fuzz_nice_float(fuzz, rest...);
23
201k
}
FuzzCommon.cpp:void fuzz_nice_float<float*>(Fuzz*, float*, float*)
Line
Count
Source
20
1.55M
static void fuzz_nice_float(Fuzz* fuzz, float* f, Args... rest) {
21
1.55M
    fuzz_nice_float(fuzz, f);
22
1.55M
    fuzz_nice_float(fuzz, rest...);
23
1.55M
}
FuzzCommon.cpp:void fuzz_nice_float<float*, float*, float*, float*>(Fuzz*, float*, float*, float*, float*, float*)
Line
Count
Source
20
48.4k
static void fuzz_nice_float(Fuzz* fuzz, float* f, Args... rest) {
21
48.4k
    fuzz_nice_float(fuzz, f);
22
48.4k
    fuzz_nice_float(fuzz, rest...);
23
48.4k
}
FuzzCommon.cpp:void fuzz_nice_float<float*, float*, float*, float*, float*>(Fuzz*, float*, float*, float*, float*, float*, float*)
Line
Count
Source
20
21.8k
static void fuzz_nice_float(Fuzz* fuzz, float* f, Args... rest) {
21
21.8k
    fuzz_nice_float(fuzz, f);
22
21.8k
    fuzz_nice_float(fuzz, rest...);
23
21.8k
}
FuzzCommon.cpp:void fuzz_nice_float<float*, float*>(Fuzz*, float*, float*, float*)
Line
Count
Source
20
207k
static void fuzz_nice_float(Fuzz* fuzz, float* f, Args... rest) {
21
207k
    fuzz_nice_float(fuzz, f);
22
207k
    fuzz_nice_float(fuzz, rest...);
23
207k
}
24
25
126k
static void fuzz_nice_rect(Fuzz* fuzz, SkRect* r) {
26
126k
    fuzz_nice_float(fuzz, &r->fLeft, &r->fTop, &r->fRight, &r->fBottom);
27
126k
    r->sort();
28
126k
}
29
30
// allows some float values for path points
31
207k
void FuzzNicePath(Fuzz* fuzz, SkPath* path, int maxOps) {
32
207k
    if (maxOps <= 0 || fuzz->exhausted() || path->countPoints() > 100000) {
33
5.51k
        return;
34
5.51k
    }
35
202k
    uint8_t fillType;
36
202k
    fuzz->nextRange(&fillType, 0, (uint8_t)SkPathFillType::kInverseEvenOdd);
37
202k
    path->setFillType((SkPathFillType)fillType);
38
202k
    uint8_t numOps;
39
202k
    fuzz->nextRange(&numOps, 0, maxOps);
40
3.09M
    for (uint8_t i = 0; i < numOps; ++i) {
41
        // When we start adding the path to itself, the fuzzer can make an
42
        // exponentially long path, which causes timeouts.
43
2.89M
        if (path->countPoints() > 100000) {
44
1.99k
            return;
45
1.99k
        }
46
        // How many items in the switch statement below.
47
2.89M
        constexpr uint8_t PATH_OPERATIONS = 32;
48
2.89M
        uint8_t op;
49
2.89M
        fuzz->nextRange(&op, 0, PATH_OPERATIONS);
50
2.89M
        bool test;
51
2.89M
        SkPath p;
52
2.89M
        SkMatrix m;
53
2.89M
        SkRRect rr;
54
2.89M
        SkRect r;
55
2.89M
        SkPathDirection dir;
56
2.89M
        unsigned int ui;
57
2.89M
        SkScalar a, b, c, d, e, f;
58
2.89M
        switch (op) {
59
1.20M
            case 0:
60
1.20M
                fuzz_nice_float(fuzz, &a, &b);
61
1.20M
                path->moveTo(a, b);
62
1.20M
                break;
63
29.4k
            case 1:
64
29.4k
                fuzz_nice_float(fuzz, &a, &b);
65
29.4k
                path->rMoveTo(a, b);
66
29.4k
                break;
67
15.3k
            case 2:
68
15.3k
                fuzz_nice_float(fuzz, &a, &b);
69
15.3k
                path->lineTo(a, b);
70
15.3k
                break;
71
13.8k
            case 3:
72
13.8k
                fuzz_nice_float(fuzz, &a, &b);
73
13.8k
                path->rLineTo(a, b);
74
13.8k
                break;
75
6.32k
            case 4:
76
6.32k
                fuzz_nice_float(fuzz, &a, &b, &c, &d);
77
6.32k
                path->quadTo(a, b, c, d);
78
6.32k
                break;
79
19.7k
            case 5:
80
19.7k
                fuzz_nice_float(fuzz, &a, &b, &c, &d);
81
19.7k
                path->rQuadTo(a, b, c, d);
82
19.7k
                break;
83
8.22k
            case 6:
84
8.22k
                fuzz_nice_float(fuzz, &a, &b, &c, &d, &e);
85
8.22k
                path->conicTo(a, b, c, d, e);
86
8.22k
                break;
87
8.72k
            case 7:
88
8.72k
                fuzz_nice_float(fuzz, &a, &b, &c, &d, &e);
89
8.72k
                path->rConicTo(a, b, c, d, e);
90
8.72k
                break;
91
17.2k
            case 8:
92
17.2k
                fuzz_nice_float(fuzz, &a, &b, &c, &d, &e, &f);
93
17.2k
                path->cubicTo(a, b, c, d, e, f);
94
17.2k
                break;
95
4.64k
            case 9:
96
4.64k
                fuzz_nice_float(fuzz, &a, &b, &c, &d, &e, &f);
97
4.64k
                path->rCubicTo(a, b, c, d, e, f);
98
4.64k
                break;
99
9.64k
            case 10:
100
9.64k
                fuzz_nice_float(fuzz, &a, &b, &c, &d, &e);
101
9.64k
                path->arcTo(a, b, c, d, e);
102
9.64k
                break;
103
23.0k
            case 11:
104
23.0k
                fuzz_nice_float(fuzz, &a, &b);
105
23.0k
                fuzz_nice_rect(fuzz, &r);
106
23.0k
                fuzz->next(&test);
107
23.0k
                path->arcTo(r, a, b, test);
108
23.0k
                break;
109
19.4k
            case 12:
110
19.4k
                path->close();
111
19.4k
                break;
112
6.26k
            case 13:
113
6.26k
                fuzz_nice_rect(fuzz, &r);
114
6.26k
                fuzz->nextRange(&ui, 0, 1);
115
6.26k
                dir = static_cast<SkPathDirection>(ui);
116
6.26k
                path->addRect(r, dir);
117
6.26k
                break;
118
2.43k
            case 14:
119
2.43k
                fuzz->nextRange(&ui, 0, 1);
120
2.43k
                dir = static_cast<SkPathDirection>(ui);
121
2.43k
                fuzz_nice_rect(fuzz, &r);
122
2.43k
                fuzz->next(&ui);
123
2.43k
                path->addRect(r, dir, ui);
124
2.43k
                break;
125
8.54k
            case 15:
126
8.54k
                fuzz->nextRange(&ui, 0, 1);
127
8.54k
                dir = static_cast<SkPathDirection>(ui);
128
8.54k
                fuzz_nice_rect(fuzz, &r);
129
8.54k
                path->addOval(r, dir);
130
8.54k
                break;
131
13.2k
            case 16:
132
13.2k
                fuzz->nextRange(&ui, 0, 1);
133
13.2k
                dir = static_cast<SkPathDirection>(ui);
134
13.2k
                fuzz_nice_rect(fuzz, &r);
135
13.2k
                fuzz->next(&ui);
136
13.2k
                path->addOval(r, dir, ui);
137
13.2k
                break;
138
6.68k
            case 17:
139
6.68k
                fuzz->nextRange(&ui, 0, 1);
140
6.68k
                dir = static_cast<SkPathDirection>(ui);
141
6.68k
                fuzz_nice_float(fuzz, &a, &b, &c);
142
6.68k
                path->addCircle(a, b, c, dir);
143
6.68k
                break;
144
8.48k
            case 18:
145
8.48k
                fuzz_nice_rect(fuzz, &r);
146
8.48k
                fuzz_nice_float(fuzz, &a, &b);
147
8.48k
                path->addArc(r, a, b);
148
8.48k
                break;
149
16.1k
            case 19:
150
16.1k
                fuzz_nice_float(fuzz, &a, &b);
151
16.1k
                fuzz_nice_rect(fuzz, &r);
152
16.1k
                fuzz->nextRange(&ui, 0, 1);
153
16.1k
                dir = static_cast<SkPathDirection>(ui);
154
16.1k
                path->addRoundRect(r, a, b, dir);
155
16.1k
                break;
156
5.21k
            case 20:
157
5.21k
                FuzzNiceRRect(fuzz, &rr);
158
5.21k
                fuzz->nextRange(&ui, 0, 1);
159
5.21k
                dir = static_cast<SkPathDirection>(ui);
160
5.21k
                path->addRRect(rr, dir);
161
5.21k
                break;
162
15.4k
            case 21:
163
15.4k
                fuzz->nextRange(&ui, 0, 1);
164
15.4k
                dir = static_cast<SkPathDirection>(ui);
165
15.4k
                FuzzNiceRRect(fuzz, &rr);
166
15.4k
                path->addRRect(rr, dir, ui);
167
15.4k
                break;
168
7.13k
            case 22: {
169
7.13k
                fuzz->nextRange(&ui, 0, 1);
170
7.13k
                SkPath::AddPathMode mode = static_cast<SkPath::AddPathMode>(ui);
171
7.13k
                FuzzNiceMatrix(fuzz, &m);
172
7.13k
                FuzzNicePath(fuzz, &p, maxOps-1);
173
7.13k
                path->addPath(p, m, mode);
174
7.13k
                break;
175
0
            }
176
8.46k
            case 23: {
177
8.46k
                fuzz->nextRange(&ui, 0, 1);
178
8.46k
                SkPath::AddPathMode mode = static_cast<SkPath::AddPathMode>(ui);
179
8.46k
                FuzzNiceMatrix(fuzz, &m);
180
8.46k
                path->addPath(*path, m, mode);
181
8.46k
                break;
182
0
            }
183
85.1k
            case 24:
184
85.1k
                FuzzNicePath(fuzz, &p, maxOps-1);
185
85.1k
                path->reverseAddPath(p);
186
85.1k
                break;
187
22.3k
            case 25:
188
22.3k
                path->addPath(*path);
189
22.3k
                break;
190
29.4k
            case 26:
191
29.4k
                path->reverseAddPath(*path);
192
29.4k
                break;
193
9.73k
            case 27:
194
9.73k
                fuzz_nice_float(fuzz, &a, &b);
195
9.73k
                path->offset(a, b, path);
196
9.73k
                break;
197
21.3k
            case 28:
198
21.3k
                FuzzNicePath(fuzz, &p, maxOps-1);
199
21.3k
                fuzz_nice_float(fuzz, &a, &b);
200
21.3k
                p.offset(a, b, path);
201
21.3k
                break;
202
9.51k
            case 29:
203
9.51k
                FuzzNiceMatrix(fuzz, &m);
204
9.51k
                path->transform(m, path);
205
9.51k
                break;
206
29.8k
            case 30:
207
29.8k
                FuzzNicePath(fuzz, &p, maxOps-1);
208
29.8k
                FuzzNiceMatrix(fuzz, &m);
209
29.8k
                p.transform(m, path);
210
29.8k
                break;
211
4.39k
            case 31:
212
4.39k
                fuzz_nice_float(fuzz, &a, &b);
213
4.39k
                path->setLastPt(a, b);
214
4.39k
                break;
215
216
1.19M
            default:
217
1.19M
                SkASSERT(false);
218
1.19M
                break;
219
2.89M
        }
220
2.89M
        SkASSERTF(       path->isValid(),        "path->isValid() failed at op %d, case %d", i, op);
221
2.89M
    }
222
202k
}
223
224
// allows all float values for path points
225
27.7k
void FuzzEvilPath(Fuzz* fuzz, SkPath* path, int last_verb) {
226
373k
  while (!fuzz->exhausted()) {
227
    // Use a uint8_t to conserve bytes.  This makes our "fuzzed bytes footprint"
228
    // smaller, which leads to more efficient fuzzing.
229
360k
    uint8_t operation;
230
360k
    fuzz->next(&operation);
231
360k
    SkScalar a,b,c,d,e,f;
232
233
360k
    switch (operation % (last_verb + 1)) {
234
26.1k
      case SkPath::Verb::kMove_Verb:
235
26.1k
        fuzz->next(&a, &b);
236
26.1k
        path->moveTo(a, b);
237
26.1k
        break;
238
239
72.8k
      case SkPath::Verb::kLine_Verb:
240
72.8k
        fuzz->next(&a, &b);
241
72.8k
        path->lineTo(a, b);
242
72.8k
        break;
243
244
33.3k
      case SkPath::Verb::kQuad_Verb:
245
33.3k
        fuzz->next(&a, &b, &c, &d);
246
33.3k
        path->quadTo(a, b, c, d);
247
33.3k
        break;
248
249
28.9k
      case SkPath::Verb::kConic_Verb:
250
28.9k
        fuzz->next(&a, &b, &c, &d, &e);
251
28.9k
        path->conicTo(a, b, c, d, e);
252
28.9k
        break;
253
254
19.7k
      case SkPath::Verb::kCubic_Verb:
255
19.7k
        fuzz->next(&a, &b, &c, &d, &e, &f);
256
19.7k
        path->cubicTo(a, b, c, d, e, f);
257
19.7k
        break;
258
259
164k
      case SkPath::Verb::kClose_Verb:
260
164k
        path->close();
261
164k
        break;
262
263
14.8k
      case SkPath::Verb::kDone_Verb:
264
        // In this case, simply exit.
265
14.8k
        return;
266
360k
    }
267
360k
  }
268
27.7k
}
269
270
48.2k
void FuzzNiceRRect(Fuzz* fuzz, SkRRect* rr) {
271
48.2k
    SkRect r;
272
48.2k
    fuzz_nice_rect(fuzz, &r);
273
274
48.2k
    SkVector radii[4];
275
193k
    for (SkVector& vec : radii) {
276
193k
        fuzz->nextRange(&vec.fX, 0.0f, 1.0f);
277
193k
        vec.fX *= 0.5f * r.width();
278
193k
        fuzz->nextRange(&vec.fY, 0.0f, 1.0f);
279
193k
        vec.fY *= 0.5f * r.height();
280
193k
    }
281
48.2k
    rr->setRectRadii(r, radii);
282
48.2k
    SkASSERT(rr->isValid());
283
48.2k
}
284
285
127k
void FuzzNiceMatrix(Fuzz* fuzz, SkMatrix* m) {
286
127k
    constexpr int kArrayLength = 9;
287
127k
    SkScalar buffer[kArrayLength];
288
127k
    int matrixType;
289
127k
    fuzz->nextRange(&matrixType, 0, 4);
290
127k
    switch (matrixType) {
291
57.4k
        case 0:  // identity
292
57.4k
            *m = SkMatrix::I();
293
57.4k
            return;
294
1.30k
        case 1:  // translate
295
1.30k
            fuzz->nextRange(&buffer[0], -4000.0f, 4000.0f);
296
1.30k
            fuzz->nextRange(&buffer[1], -4000.0f, 4000.0f);
297
1.30k
            *m = SkMatrix::Translate(buffer[0], buffer[1]);
298
1.30k
            return;
299
2.83k
        case 2:  // translate + scale
300
2.83k
            fuzz->nextRange(&buffer[0], -400.0f, 400.0f);
301
2.83k
            fuzz->nextRange(&buffer[1], -400.0f, 400.0f);
302
2.83k
            fuzz->nextRange(&buffer[2], -4000.0f, 4000.0f);
303
2.83k
            fuzz->nextRange(&buffer[3], -4000.0f, 4000.0f);
304
2.83k
            *m = SkMatrix::Scale(buffer[0], buffer[1]);
305
2.83k
            m->postTranslate(buffer[2], buffer[3]);
306
2.83k
            return;
307
1.23k
        case 3:  // affine
308
1.23k
            fuzz->nextN(buffer, 6);
309
1.23k
            m->setAffine(buffer);
310
1.23k
            return;
311
64.8k
        case 4:  // perspective
312
64.8k
            fuzz->nextN(buffer, kArrayLength);
313
64.8k
            m->set9(buffer);
314
64.8k
            return;
315
0
        default:
316
0
            SkASSERT(false);
317
0
            return;
318
127k
    }
319
127k
}
320
321
50.1k
void FuzzNiceRegion(Fuzz* fuzz, SkRegion* region, int maxN) {
322
50.1k
    uint8_t N;
323
50.1k
    fuzz->nextRange(&N, 0, maxN);
324
199k
    for (uint8_t i = 0; i < N; ++i) {
325
155k
        SkIRect r;
326
155k
        SkRegion::Op op;
327
        // Avoid the sentinel value used by Region.
328
155k
        fuzz->nextRange(&r.fLeft,   -2147483646, 2147483646);
329
155k
        fuzz->nextRange(&r.fTop,    -2147483646, 2147483646);
330
155k
        fuzz->nextRange(&r.fRight,  -2147483646, 2147483646);
331
155k
        fuzz->nextRange(&r.fBottom, -2147483646, 2147483646);
332
155k
        r.sort();
333
155k
        fuzz->nextEnum(&op, SkRegion::kLastOp);
334
155k
        if (!region->op(r, op)) {
335
6.14k
            return;
336
6.14k
        }
337
155k
    }
338
50.1k
}