xref: /aosp_15_r20/external/skia/fuzz/oss_fuzz/FuzzSkRuntimeBlender.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2023 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 "fuzz/Fuzz.h"
9 #include "fuzz/FuzzCommon.h"
10 #include "include/core/SkCanvas.h"
11 #include "include/core/SkPaint.h"
12 #include "include/core/SkShader.h"
13 #include "include/core/SkSurface.h"
14 #include "include/effects/SkRuntimeEffect.h"
15 #include "include/private/base/SkTArray.h"
16 #include "src/gpu/ganesh/GrShaderCaps.h"
17 
18 using namespace skia_private;
19 
20 /**
21  * The fuzzer treats the input bytes as an SkSL blend program. The requested number of
22  * uniforms and children are automatically synthesized to match the program's needs.
23  *
24  * We fuzz twice, with two different settings for inlining in the SkSL compiler. By default, the
25  * compiler inlines most small to medium functions. This can hide bugs related to function-calling.
26  * So we run the fuzzer once with inlining disabled, and again with it enabled.
27  * This gives us better coverage, and eases the burden on the fuzzer to inject useless noise into
28  * functions to suppress inlining.
29  */
FuzzSkRuntimeBlender_Once(const SkString & shaderText,const SkRuntimeEffect::Options & options)30 static bool FuzzSkRuntimeBlender_Once(const SkString& shaderText,
31                                       const SkRuntimeEffect::Options& options) {
32     SkRuntimeEffect::Result result = SkRuntimeEffect::MakeForBlender(shaderText, options);
33     SkRuntimeEffect* effect = result.effect.get();
34     if (!effect) {
35         return false;
36     }
37 
38     sk_sp<SkData> uniformBytes;
39     TArray<SkRuntimeEffect::ChildPtr> children;
40     FuzzCreateValidInputsForRuntimeEffect(effect, uniformBytes, children);
41 
42     sk_sp<SkBlender> blender = effect->makeBlender(uniformBytes, SkSpan(children));
43     if (!blender) {
44         return false;
45     }
46     SkPaint paint;
47     paint.setColor(SK_ColorRED);
48     paint.setBlender(std::move(blender));
49 
50     sk_sp<SkSurface> s = SkSurfaces::Raster(SkImageInfo::MakeN32Premul(4, 4));
51     if (!s) {
52         return false;
53     }
54     s->getCanvas()->drawPaint(paint);
55 
56     return true;
57 }
58 
FuzzSkRuntimeBlender(const uint8_t * data,size_t size)59 bool FuzzSkRuntimeBlender(const uint8_t *data, size_t size) {
60     // Test once with optimization disabled...
61     SkString shaderText{reinterpret_cast<const char*>(data), size};
62     SkRuntimeEffect::Options options;
63     options.forceUnoptimized = true;
64     bool result = FuzzSkRuntimeBlender_Once(shaderText, options);
65 
66     // ... and then with optimization enabled.
67     options.forceUnoptimized = false;
68     result = FuzzSkRuntimeBlender_Once(shaderText, options) || result;
69 
70     return result;
71 }
72 
73 #if defined(SK_BUILD_FOR_LIBFUZZER)
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)74 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
75     if (size > 3000) {
76         return 0;
77     }
78     FuzzSkRuntimeBlender(data, size);
79     return 0;
80 }
81 #endif
82