1 /*
2 * Copyright 2022 Google, LLC
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 "include/core/SkCanvas.h"
9 #include "include/core/SkData.h"
10 #include "include/core/SkFont.h"
11 #include "include/core/SkFontMgr.h"
12 #include "include/core/SkStream.h"
13 #include "include/core/SkSurface.h"
14 #include "include/core/SkTypeface.h"
15 #include "tools/fonts/FontToolUtils.h"
16
17 #include <algorithm>
18
FuzzCOLRv1(const uint8_t * data,size_t size)19 void FuzzCOLRv1(const uint8_t* data, size_t size) {
20 // We do not want the portable fontmgr here, as it does not allow creation of fonts from bytes.
21 sk_sp<SkFontMgr> mgr = ToolUtils::TestFontMgr();
22 std::unique_ptr<SkStreamAsset> stream = SkMemoryStream::MakeDirect(data, size);
23 sk_sp<SkTypeface> typeface = mgr->makeFromStream(std::move(stream), 0);
24
25 if (!typeface) {
26 return;
27 }
28
29 auto s = SkSurfaces::Raster(SkImageInfo::MakeN32Premul(128, 128));
30 if (!s) {
31 return;
32 }
33
34 // Place at a baseline in the lower part of the canvas square, but canvas size and baseline
35 // placement are chosen arbitrarily and we just need to cover colrv1 rendering in this
36 // fuzz test.
37 SkFont colrv1Font = SkFont(typeface, 120);
38 SkCanvas* canvas = s->getCanvas();
39 SkPaint paint;
40 int numGlyphs = typeface->countGlyphs();
41
42 for (int i = 0; i < std::min(numGlyphs, 10); ++i) {
43 SkPoint origin = SkPoint::Make(10, 108);
44 SkPoint position = SkPoint::Make(0, 0);
45 SkGlyphID glyphId = i;
46 canvas->drawGlyphs(1, &glyphId, &position, origin, colrv1Font, paint);
47 }
48 }
49
50 #if defined(SK_BUILD_FOR_LIBFUZZER)
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)51 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
52 // COLRv1 corpus file sizes range from 8k for a small test glyph file to about 80k covering
53 // most of the complex Noto Emoji glyphs, compare:
54 // See https://github.com/googlefonts/color-fonts/blob/main/rebuild_fuzzer_corpus.py
55 if (size > 80 * 1024) {
56 return 0;
57 }
58 FuzzCOLRv1(data, size);
59 return 0;
60 }
61 #endif
62