Coverage Report

Created: 2024-09-14 07:19

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