Flutter Engine
The Flutter Engine
FuzzSkMeshSpecification.cpp
Go to the documentation of this file.
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
10
11#include "fuzz/Fuzz.h"
12
13using namespace skia_private;
14
15template <typename T>
17 T result = 0;
18 size_t bytesToCopy = std::min(sizeof(T), data.size());
19 if (bytesToCopy > 0) {
20 memcpy(&result, &data.front(), bytesToCopy);
21 data = data.subspan(bytesToCopy);
22 }
23 return result;
24}
25
26void FuzzSkMeshSpecification(const uint8_t *fuzzData, size_t fuzzSize) {
29
30 SkSpan<const uint8_t> data(fuzzData, fuzzSize);
33 size_t vertexStride;
34 SkString vs, fs;
35
36 auto fuzzByteToASCII = [&](uint8_t c, SkString* str) -> bool {
37 // Most control characters (including \0) and all high ASCII are treated as stop bytes.
38 if ((c >= 32 && c <= 127) || c == '\r' || c == '\n' || c == '\t') {
39 char ascii = c;
40 str->append(&ascii, 1);
41 return true;
42 }
43 return false;
44 };
45
46 auto fuzzByteToSkSL = [&](uint8_t c, SkString* str) -> bool {
47 // In the 0x00 - 0x80 range, treat characters as ASCII.
48 if (c < 128) {
49 return fuzzByteToASCII(c, str);
50 }
51 c -= 128;
52
53 // Dedicate a few bytes to injecting our attribute and varying names.
55 if (!attributes.empty()) {
56 str->append(attributes[c % attributes.size()].name);
57 }
58 return true;
59 }
61
63 if (!varyings.empty()) {
64 str->append(varyings[c % varyings.size()].name);
65 }
66 return true;
67 }
69
70 // Replace the remaining high-ASCII bytes with valid SkSL operators and keywords in order to
71 // improve our chances of generating a program. (We omit single-character operators since
72 // single-byte versions of those already exist in the low-ASCII space.)
73 static constexpr std::string_view kSkSLData[] = {
74 " true ",
75 " false ",
76 " if ",
77 " else ",
78 " for ",
79 " while ",
80 " do ",
81 " switch ",
82 " case ",
83 " default ",
84 " break ",
85 " continue ",
86 " discard ",
87 " return ",
88 " in ",
89 " out ",
90 " inout ",
91 " uniform ",
92 " const ",
93 " flat ",
94 " noperspective ",
95 " inline ",
96 " noinline ",
97 " $pure ",
98 " readonly ",
99 " writeonly ",
100 " buffer ",
101 " struct ",
102 " layout ",
103 " highp ",
104 " mediump ",
105 " lowp ",
106 " $es3 ",
107 " $export ",
108 " workgroup ",
109 " << ",
110 " >> ",
111 " && ",
112 " || ",
113 " ^^ ",
114 " == ",
115 " != ",
116 " <= ",
117 " >= ",
118 " += ",
119 " -= ",
120 " *= ",
121 " /= ",
122 " %= ",
123 " <<= ",
124 " >>= ",
125 " &= ",
126 " |= ",
127 " ^= ",
128 " ++ ",
129 " -- ",
130 " //",
131 " /*",
132 "*/ ",
133 " float",
134 " half",
135 " int",
136 " uint",
137 " short",
138 " ushort",
139 " bool",
140 " void",
141 " vec",
142 " ivec",
143 " bvec",
144 " mat",
145 " Attributes ",
146 " Varyings ",
147 };
148
149 c %= std::size(kSkSLData);
150 str->append(kSkSLData[c]);
151 return true;
152 };
153
154 // Pick a vertex stride; intentionally allow some bad values through.
155 vertexStride = extract<uint16_t>(data) % (SkMeshSpecification::kMaxStride + 2);
156
157 while (!data.empty()) {
158 uint8_t control = extract<uint8_t>(data) % 4;
159 // A control code with no payload can be ignored.
160 if (data.empty()) {
161 break;
162 }
163 switch (control) {
164 case 0: {
165 // Add an attribute.
166 Attribute& a = attributes.push_back();
167 a.type = (Attribute::Type)(extract<uint8_t>(data) %
169 a.offset = extract<uint16_t>(data) % (SkMeshSpecification::kMaxStride + 2);
170 while (uint8_t c = extract<char>(data)) {
171 if (!fuzzByteToASCII(c, &a.name)) {
172 break;
173 }
174 }
175 break;
176 }
177 case 1: {
178 // Add a varying.
179 Varying& v = varyings.push_back();
180 v.type = (Varying::Type)(extract<uint8_t>(data) % ((int)Varying::Type::kLast + 1));
181 while (uint8_t c = extract<char>(data)) {
182 if (!fuzzByteToASCII(c, &v.name)) {
183 break;
184 }
185 }
186 break;
187 }
188 case 2: {
189 // Convert the following data into SkSL and add it into the vertex program.
190 while (uint8_t c = extract<char>(data)) {
191 if (!fuzzByteToSkSL(c, &vs)) {
192 break;
193 }
194 }
195 break;
196 }
197 case 3: {
198 // Convert the following data into SkSL and add it into the fragment program.
199 while (uint8_t c = extract<char>(data)) {
200 if (!fuzzByteToSkSL(c, &fs)) {
201 break;
202 }
203 }
204 break;
205 }
206 }
207 }
208
209 auto result = SkMeshSpecification::Make(attributes, vertexStride, varyings, vs, fs);
210 if (result.error.isEmpty()) {
211 // TODO: synthesize a mesh with this specification and paint it.
212 printf("----\n%s\n----\n\n----\n%s\n----\n\n\n", vs.c_str(), fs.c_str());
213 }
214}
215
216#if defined(SK_BUILD_FOR_LIBFUZZER)
217extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
218 if (size > 8000) {
219 return 0;
220 }
222 return 0;
223}
224#endif
T extract(SkSpan< const uint8_t > &data)
void FuzzSkMeshSpecification(const uint8_t *fuzzData, size_t fuzzSize)
SkMeshSpecification::Attribute Attribute
Definition: SkMesh.cpp:54
SkMeshSpecification::Varying Varying
Definition: SkMesh.cpp:55
static constexpr size_t kMaxVaryings
Definition: SkMesh.h:72
static constexpr size_t kMaxAttributes
Definition: SkMesh.h:69
static constexpr size_t kMaxStride
Definition: SkMesh.h:68
static Result Make(SkSpan< const Attribute > attributes, size_t vertexStride, SkSpan< const Varying > varyings, const SkString &vs, const SkString &fs)
Definition: SkMesh.cpp:389
void append(const char text[])
Definition: SkString.h:203
const char * c_str() const
Definition: SkString.h:133
bool empty() const
Definition: SkTArray.h:199
int size() const
Definition: SkTArray.h:421
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size)
struct MyStruct a[10]
GAsyncResult * result
static float min(float r, float g, float b)
Definition: hsl.cpp:48
std::string printf(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: SkSLString.cpp:83
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
#define T
Definition: precompiler.cc:65
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63