Coverage Report

Created: 2024-05-20 07:14

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