Coverage Report

Created: 2021-08-22 09:07

/src/skia/fuzz/FuzzDrawFunctions.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2016 Mozilla Foundation
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 "include/core/SkBitmap.h"
10
#include "include/core/SkCanvas.h"
11
#include "include/core/SkFont.h"
12
#include "include/core/SkImage.h"
13
#include "include/core/SkPath.h"
14
#include "include/core/SkSurface.h"
15
#include "include/core/SkTextBlob.h"
16
#include "include/core/SkTypeface.h"
17
#include "src/core/SkPaintPriv.h"
18
19
static const int kBmpSize = 24;
20
static const int kMaxX = 250;
21
static const int kMaxY = 250;
22
static const int kPtsLen = 10;
23
static const int kTxtLen = 5;
24
25
182
static void init_string(Fuzz* fuzz, char* str, size_t bufSize) {
26
910
    for (size_t i = 0; i < bufSize-1; ++i) {
27
728
        fuzz->nextRange(&str[i], 0x20, 0x7E); // printable ASCII
28
728
    }
29
182
    str[bufSize-1] = '\0';
30
182
}
31
32
// make_paint mostly borrowed from FilterFuzz.cpp
33
8.26k
static void init_paint(Fuzz* fuzz, SkPaint* p) {
34
8.26k
    bool b;
35
8.26k
    fuzz->next(&b);
36
8.26k
    p->setAntiAlias(b);
37
38
8.26k
    uint8_t tmp_u8;
39
8.26k
    fuzz->nextRange(&tmp_u8, 0, (int)SkBlendMode::kLastMode);
40
8.26k
    p->setBlendMode(static_cast<SkBlendMode>(tmp_u8));
41
42
8.26k
    SkColor co;
43
8.26k
    fuzz->next(&co);
44
8.26k
    p->setColor(co);
45
46
8.26k
    fuzz->next(&b);
47
8.26k
    p->setDither(b);
48
49
8.26k
    fuzz->nextRange(&tmp_u8, 0, (int)SkPaint::kLast_Cap);
50
8.26k
    p->setStrokeCap(static_cast<SkPaint::Cap>(tmp_u8));
51
52
8.26k
    fuzz->nextRange(&tmp_u8, 0, (int)SkPaint::kLast_Join);
53
8.26k
    p->setStrokeJoin(static_cast<SkPaint::Join>(tmp_u8));
54
55
8.26k
    SkScalar sc;
56
8.26k
    fuzz->next(&sc);
57
8.26k
    p->setStrokeMiter(sc);
58
59
8.26k
    fuzz->next(&sc);
60
8.26k
    p->setStrokeWidth(sc);
61
62
8.26k
    fuzz->nextRange(&tmp_u8, 0, (int)SkPaint::kStrokeAndFill_Style);
63
8.26k
    p->setStyle(static_cast<SkPaint::Style>(tmp_u8));
64
8.26k
}
65
66
1.78k
static void init_bitmap(Fuzz* fuzz, SkBitmap* bmp) {
67
1.78k
    uint8_t colorType;
68
1.78k
    fuzz->nextRange(&colorType, 0, (int)kLastEnum_SkColorType);
69
    // ColorType needs to match what the system configuration is.
70
1.78k
    if (colorType == kRGBA_8888_SkColorType || colorType == kBGRA_8888_SkColorType) {
71
846
        colorType = kN32_SkColorType;
72
846
    }
73
1.78k
    bool b;
74
1.78k
    fuzz->next(&b);
75
1.78k
    SkImageInfo info = SkImageInfo::Make(kBmpSize,
76
1.78k
                                         kBmpSize,
77
1.78k
                                         (SkColorType)colorType,
78
1.00k
                                         b ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
79
1.78k
    if (!bmp->tryAllocPixels(info)) {
80
0
        SkDEBUGF("Bitmap not allocated\n");
81
0
    }
82
1.78k
    SkColor c;
83
1.78k
    fuzz->next(&c);
84
1.78k
    bmp->eraseColor(c);
85
86
1.78k
    fuzz->next(&b);
87
1.78k
    SkPaint p;
88
1.78k
    if (b) {
89
64
        init_paint(fuzz, &p);
90
64
    }
91
1.72k
    else {
92
1.72k
        fuzz->next(&c);
93
1.72k
        p.setColor(c);
94
1.72k
    }
95
1.78k
}
96
97
8.20k
static void init_surface(Fuzz* fuzz, sk_sp<SkSurface>* s) {
98
8.20k
    uint8_t x, y;
99
8.20k
    fuzz->nextRange(&x, 1, kMaxX);
100
8.20k
    fuzz->nextRange(&y, 1, kMaxY);
101
8.20k
    *s = SkSurface::MakeRasterN32Premul(x, y);
102
103
8.20k
    if (!*s) {
104
        // Was possibly too big for the memory constrained fuzzing environments
105
0
        *s = SkSurface::MakeNull(x, y);
106
0
    }
107
8.20k
}
108
109
110
182
static void fuzz_drawText(Fuzz* fuzz, sk_sp<SkTypeface> typeface) {
111
182
    SkFont font(typeface);
112
182
    SkPaint p;
113
182
    init_paint(fuzz, &p);
114
182
    sk_sp<SkSurface> surface;
115
182
    init_surface(fuzz, &surface);
116
117
182
    char text[kTxtLen];
118
182
    init_string(fuzz, text, kTxtLen);
119
120
182
    SkScalar x, y;
121
182
    fuzz->next(&x, &y);
122
    // populate pts array
123
182
    SkPoint pts[kPtsLen];
124
2.00k
    for (uint8_t i = 0; i < kPtsLen; ++i) {
125
1.82k
        pts[i].set(x, y);
126
1.82k
        x += font.getSize();
127
1.82k
    }
128
129
182
    bool b;
130
182
    fuzz->next(&b);
131
182
    font.setForceAutoHinting(b);
132
182
    fuzz->next(&b);
133
182
    font.setEmbeddedBitmaps(b);
134
182
    fuzz->next(&b);
135
182
    font.setEmbolden(b);
136
182
    fuzz->next(&b);
137
148
    font.setEdging(b ? SkFont::Edging::kAntiAlias : SkFont::Edging::kSubpixelAntiAlias);
138
182
    fuzz->next(&b);
139
182
    font.setLinearMetrics(b);
140
182
    fuzz->next(&b);
141
182
    font.setSubpixel(b);
142
182
    fuzz->next(&x);
143
182
    font.setScaleX(x);
144
182
    fuzz->next(&x);
145
182
    font.setSkewX(x);
146
182
    fuzz->next(&x);
147
182
    font.setSize(x);
148
149
182
    SkCanvas* cnv = surface->getCanvas();
150
182
    fuzz->next(&x);
151
182
    fuzz->next(&y);
152
182
    cnv->drawTextBlob(SkTextBlob::MakeFromPosText(text, kTxtLen-1, pts, font), x, y, p);
153
182
}
154
155
772
static void fuzz_drawCircle(Fuzz* fuzz) {
156
772
    SkPaint p;
157
772
    init_paint(fuzz, &p);
158
772
    sk_sp<SkSurface> surface;
159
772
    init_surface(fuzz, &surface);
160
161
772
    SkScalar a, b, c;
162
772
    fuzz->next(&a, &b, &c);
163
772
    surface->getCanvas()->drawCircle(a, b, c, p);
164
772
}
165
166
1.02k
static void fuzz_drawLine(Fuzz* fuzz) {
167
1.02k
    SkPaint p;
168
1.02k
    init_paint(fuzz, &p);
169
1.02k
    sk_sp<SkSurface> surface;
170
1.02k
    init_surface(fuzz, &surface);
171
172
1.02k
    SkScalar a, b, c, d;
173
1.02k
    fuzz->next(&a, &b, &c, &d);
174
1.02k
    surface->getCanvas()->drawLine(a, b, c, d, p);
175
1.02k
}
176
177
687
static void fuzz_drawRect(Fuzz* fuzz) {
178
687
    SkPaint p;
179
687
    init_paint(fuzz, &p);
180
687
    sk_sp<SkSurface> surface;
181
687
    init_surface(fuzz, &surface);
182
183
687
    SkScalar a, b, c, d;
184
687
    fuzz->next(&a, &b, &c, &d);
185
687
    SkRect r;
186
687
    r = SkRect::MakeXYWH(a, b, c, d);
187
188
687
    SkCanvas* cnv = surface->getCanvas();
189
687
    cnv->drawRect(r, p);
190
191
687
    bool bl;
192
687
    fuzz->next(&bl);
193
687
    fuzz->next(&a, &b, &c, &d);
194
687
    r = SkRect::MakeXYWH(a, b, c, d);
195
687
    cnv->clipRect(r, SkClipOp::kIntersect, bl);
196
687
}
197
198
3.64k
static void fuzz_drawPath(Fuzz* fuzz) {
199
3.64k
    SkPaint p;
200
3.64k
    init_paint(fuzz, &p);
201
3.64k
    sk_sp<SkSurface> surface;
202
3.64k
    init_surface(fuzz, &surface);
203
204
    // TODO(kjlubick): put the ability to fuzz a path in shared file, with
205
    // other common things (e.g. rects, lines)
206
3.64k
    uint8_t i, j;
207
3.64k
    fuzz->nextRange(&i, 0, 10); // set i to number of operations to perform
208
3.64k
    SkPath path;
209
3.64k
    SkScalar a, b, c, d, e, f;
210
28.9k
    for (int k = 0; k < i; ++k) {
211
25.3k
        fuzz->nextRange(&j, 0, 5); // set j to choose operation to perform
212
25.3k
        switch (j) {
213
17.6k
            case 0:
214
17.6k
                fuzz->next(&a, &b);
215
17.6k
                path.moveTo(a, b);
216
17.6k
                break;
217
710
            case 1:
218
710
                fuzz->next(&a, &b);
219
710
                path.lineTo(a, b);
220
710
                break;
221
614
            case 2:
222
614
                fuzz->next(&a, &b, &c, &d);
223
614
                path.quadTo(a, b, c, d);
224
614
                break;
225
451
            case 3:
226
451
                fuzz->next(&a, &b, &c, &d, &e);
227
451
                path.conicTo(a, b, c, d, e);
228
451
                break;
229
3.46k
            case 4:
230
3.46k
                fuzz->next(&a, &b, &c, &d, &e, &f);
231
3.46k
                path.cubicTo(a, b, c, d, e, f);
232
3.46k
                break;
233
2.40k
            case 5:
234
2.40k
                fuzz->next(&a, &b, &c, &d, &e);
235
2.40k
                path.arcTo(a, b, c, d, e);
236
2.40k
                break;
237
25.3k
        }
238
25.3k
    }
239
3.64k
    path.close();
240
241
3.64k
    SkCanvas* cnv = surface->getCanvas();
242
3.64k
    cnv->drawPath(path, p);
243
244
3.64k
    bool bl;
245
3.64k
    fuzz->next(&bl);
246
3.64k
    cnv->clipPath(path, SkClipOp::kIntersect, bl);
247
3.64k
}
248
249
1.78k
static void fuzz_drawImage(Fuzz* fuzz) {
250
1.78k
    SkPaint p;
251
1.78k
    init_paint(fuzz, &p);
252
1.78k
    sk_sp<SkSurface> surface;
253
1.78k
    init_surface(fuzz, &surface);
254
1.78k
    SkBitmap bmp;
255
1.78k
    init_bitmap(fuzz, &bmp);
256
257
1.78k
    sk_sp<SkImage> image(bmp.asImage());
258
259
1.78k
    bool bl;
260
1.78k
    fuzz->next(&bl);
261
1.78k
    SkScalar a, b;
262
1.78k
    fuzz->next(&a, &b);
263
1.78k
    if (bl) {
264
1.31k
        surface->getCanvas()->drawImage(image, a, b, SkSamplingOptions(), &p);
265
1.31k
    }
266
467
    else {
267
467
        SkRect dst = SkRect::MakeWH(a, b);
268
467
        fuzz->next(&a, &b);
269
467
        SkRect src = SkRect::MakeWH(a, b);
270
467
        uint8_t x;
271
467
        fuzz->nextRange(&x, 0, 1);
272
467
        SkCanvas::SrcRectConstraint cst = (SkCanvas::SrcRectConstraint)x;
273
467
        surface->getCanvas()->drawImageRect(image.get(), src, dst, SkSamplingOptions(), &p, cst);
274
467
    }
275
1.78k
}
276
277
102
static void fuzz_drawPaint(Fuzz* fuzz) {
278
102
    SkPaint l, p;
279
102
    init_paint(fuzz, &p);
280
102
    sk_sp<SkSurface> surface;
281
102
    init_surface(fuzz, &surface);
282
283
102
    surface->getCanvas()->drawPaint(p);
284
102
}
285
286
8.20k
DEF_FUZZ(DrawFunctions, fuzz) {
287
8.20k
    uint8_t i;
288
8.20k
    fuzz->next(&i);
289
290
8.20k
    switch(i) {
291
182
        case 0: {
292
182
            sk_sp<SkTypeface> f = SkTypeface::MakeDefault();
293
182
            if (f == nullptr) {
294
0
              SkDebugf("Could not initialize font.\n");
295
0
              fuzz->signalBug();
296
0
            }
297
182
            SkDEBUGF("Fuzz DrawText\n");
298
182
            fuzz_drawText(fuzz, f);
299
182
            return;
300
0
        }
301
687
        case 1:
302
687
            SkDEBUGF("Fuzz DrawRect\n");
303
687
            fuzz_drawRect(fuzz);
304
687
            return;
305
772
        case 2:
306
772
            SkDEBUGF("Fuzz DrawCircle\n");
307
772
            fuzz_drawCircle(fuzz);
308
772
            return;
309
1.02k
        case 3:
310
1.02k
            SkDEBUGF("Fuzz DrawLine\n");
311
1.02k
            fuzz_drawLine(fuzz);
312
1.02k
            return;
313
3.64k
        case 4:
314
3.64k
            SkDEBUGF("Fuzz DrawPath\n");
315
3.64k
            fuzz_drawPath(fuzz);
316
3.64k
            return;
317
1.78k
        case 5:
318
1.78k
            SkDEBUGF("Fuzz DrawImage/DrawImageRect\n");
319
1.78k
            fuzz_drawImage(fuzz);
320
1.78k
            return;
321
102
        case 6:
322
102
            SkDEBUGF("Fuzz DrawPaint\n");
323
102
            fuzz_drawPaint(fuzz);
324
102
            return;
325
8.20k
    }
326
8.20k
}