1 /*
2 * Copyright 2020 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 shader program. The requested number of uniforms and
22 * 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 */
FuzzSkRuntimeEffect_Once(const SkString & shaderText,const SkRuntimeEffect::Options & options)30 static bool FuzzSkRuntimeEffect_Once(const SkString& shaderText,
31 const SkRuntimeEffect::Options& options) {
32 SkRuntimeEffect::Result result = SkRuntimeEffect::MakeForShader(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<SkShader> shader = effect->makeShader(uniformBytes, SkSpan(children));
43 if (!shader) {
44 return false;
45 }
46 SkPaint paint;
47 paint.setShader(std::move(shader));
48
49 sk_sp<SkSurface> s = SkSurfaces::Raster(SkImageInfo::MakeN32Premul(4, 4));
50 if (!s) {
51 return false;
52 }
53 s->getCanvas()->drawPaint(paint);
54
55 return true;
56 }
57
FuzzSkRuntimeEffect(const uint8_t * data,size_t size)58 bool FuzzSkRuntimeEffect(const uint8_t *data, size_t size) {
59 // Test once with optimization disabled...
60 SkString shaderText{reinterpret_cast<const char*>(data), size};
61 SkRuntimeEffect::Options options;
62 options.forceUnoptimized = true;
63 bool result = FuzzSkRuntimeEffect_Once(shaderText, options);
64
65 // ... and then with optimization enabled.
66 options.forceUnoptimized = false;
67 result = FuzzSkRuntimeEffect_Once(shaderText, options) || result;
68
69 return result;
70 }
71
72 #if defined(SK_BUILD_FOR_LIBFUZZER)
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)73 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
74 if (size > 3000) {
75 return 0;
76 }
77 FuzzSkRuntimeEffect(data, size);
78 return 0;
79 }
80 #endif
81