• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2019 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "source/fuzz/fuzzer_pass_add_useful_constructs.h"
16 #include "source/fuzz/pseudo_random_generator.h"
17 #include "source/fuzz/uniform_buffer_element_descriptor.h"
18 #include "test/fuzz/fuzz_test_util.h"
19 
20 namespace spvtools {
21 namespace fuzz {
22 namespace {
23 
AddFactHelper(FactManager * fact_manager,opt::IRContext * context,uint32_t word,const protobufs::UniformBufferElementDescriptor & descriptor)24 bool AddFactHelper(
25     FactManager* fact_manager, opt::IRContext* context, uint32_t word,
26     const protobufs::UniformBufferElementDescriptor& descriptor) {
27   protobufs::FactConstantUniform constant_uniform_fact;
28   constant_uniform_fact.add_constant_word(word);
29   *constant_uniform_fact.mutable_uniform_buffer_element_descriptor() =
30       descriptor;
31   protobufs::Fact fact;
32   *fact.mutable_constant_uniform_fact() = constant_uniform_fact;
33   return fact_manager->AddFact(fact, context);
34 }
35 
TEST(FuzzerPassAddUsefulConstructsTest,CheckBasicStuffIsAdded)36 TEST(FuzzerPassAddUsefulConstructsTest, CheckBasicStuffIsAdded) {
37   // The SPIR-V came from the following empty GLSL shader:
38   //
39   // #version 450
40   //
41   // void main()
42   // {
43   // }
44 
45   std::string shader = R"(
46                OpCapability Shader
47           %1 = OpExtInstImport "GLSL.std.450"
48                OpMemoryModel Logical GLSL450
49                OpEntryPoint Fragment %4 "main"
50                OpExecutionMode %4 OriginUpperLeft
51                OpSource GLSL 450
52                OpName %4 "main"
53           %2 = OpTypeVoid
54           %3 = OpTypeFunction %2
55           %4 = OpFunction %2 None %3
56           %5 = OpLabel
57                OpReturn
58                OpFunctionEnd
59   )";
60 
61   const auto env = SPV_ENV_UNIVERSAL_1_3;
62   const auto consumer = nullptr;
63   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
64   ASSERT_TRUE(IsValid(env, context.get()));
65 
66   FactManager fact_manager;
67   spvtools::ValidatorOptions validator_options;
68   TransformationContext transformation_context(&fact_manager,
69                                                validator_options);
70 
71   FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0).get(), 100);
72   protobufs::TransformationSequence transformation_sequence;
73 
74   FuzzerPassAddUsefulConstructs pass(context.get(), &transformation_context,
75                                      &fuzzer_context, &transformation_sequence);
76   pass.Apply();
77   ASSERT_TRUE(IsValid(env, context.get()));
78 
79   std::string after = R"(
80                OpCapability Shader
81           %1 = OpExtInstImport "GLSL.std.450"
82                OpMemoryModel Logical GLSL450
83                OpEntryPoint Fragment %4 "main"
84                OpExecutionMode %4 OriginUpperLeft
85                OpSource GLSL 450
86                OpName %4 "main"
87           %2 = OpTypeVoid
88           %3 = OpTypeFunction %2
89         %100 = OpTypeBool
90         %101 = OpTypeInt 32 1
91         %102 = OpTypeInt 32 0
92         %103 = OpTypeFloat 32
93         %104 = OpConstantTrue %100
94         %105 = OpConstantFalse %100
95         %106 = OpConstant %101 0
96         %107 = OpConstant %101 1
97         %108 = OpConstant %102 0
98         %109 = OpConstant %102 1
99         %110 = OpConstant %103 0
100         %111 = OpConstant %103 1
101           %4 = OpFunction %2 None %3
102           %5 = OpLabel
103                OpReturn
104                OpFunctionEnd
105   )";
106   ASSERT_TRUE(IsEqual(env, after, context.get()));
107 }
108 
TEST(FuzzerPassAddUsefulConstructsTest,CheckTypesIndicesAndConstantsAddedForUniformFacts)109 TEST(FuzzerPassAddUsefulConstructsTest,
110      CheckTypesIndicesAndConstantsAddedForUniformFacts) {
111   // The SPIR-V came from the following GLSL shader:
112   //
113   // #version 450
114   //
115   // struct S {
116   //   int x;
117   //   float y;
118   //   int z;
119   //   int w;
120   // };
121   //
122   // uniform buf {
123   //   S s;
124   //   uint w[10];
125   // };
126   //
127   // void main() {
128   // }
129 
130   std::string shader = R"(
131                OpCapability Shader
132           %1 = OpExtInstImport "GLSL.std.450"
133                OpMemoryModel Logical GLSL450
134                OpEntryPoint Fragment %4 "main"
135                OpExecutionMode %4 OriginUpperLeft
136                OpSource GLSL 450
137                OpName %4 "main"
138                OpName %8 "S"
139                OpMemberName %8 0 "x"
140                OpMemberName %8 1 "y"
141                OpMemberName %8 2 "z"
142                OpMemberName %8 3 "w"
143                OpName %12 "buf"
144                OpMemberName %12 0 "s"
145                OpMemberName %12 1 "w"
146                OpName %14 ""
147                OpMemberDecorate %8 0 Offset 0
148                OpMemberDecorate %8 1 Offset 4
149                OpMemberDecorate %8 2 Offset 8
150                OpMemberDecorate %8 3 Offset 12
151                OpDecorate %11 ArrayStride 16
152                OpMemberDecorate %12 0 Offset 0
153                OpMemberDecorate %12 1 Offset 16
154                OpDecorate %12 Block
155                OpDecorate %14 DescriptorSet 0
156                OpDecorate %14 Binding 0
157           %2 = OpTypeVoid
158           %3 = OpTypeFunction %2
159           %6 = OpTypeInt 32 1
160           %7 = OpTypeFloat 32
161           %8 = OpTypeStruct %6 %7 %6 %6
162           %9 = OpTypeInt 32 0
163          %10 = OpConstant %9 10
164          %11 = OpTypeArray %9 %10
165          %12 = OpTypeStruct %8 %11
166          %13 = OpTypePointer Uniform %12
167          %14 = OpVariable %13 Uniform
168           %4 = OpFunction %2 None %3
169           %5 = OpLabel
170                OpReturn
171                OpFunctionEnd
172   )";
173 
174   const auto env = SPV_ENV_UNIVERSAL_1_3;
175   const auto consumer = nullptr;
176   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
177   ASSERT_TRUE(IsValid(env, context.get()));
178 
179   FactManager fact_manager;
180   spvtools::ValidatorOptions validator_options;
181   TransformationContext transformation_context(&fact_manager,
182                                                validator_options);
183 
184   FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0).get(), 100);
185   protobufs::TransformationSequence transformation_sequence;
186 
187   // Add some uniform facts.
188 
189   // buf.s.x == 200
190   ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 200,
191                             MakeUniformBufferElementDescriptor(0, 0, {0, 0})));
192 
193   // buf.s.y == 0.5
194   const float float_value = 0.5;
195   uint32_t float_value_as_uint;
196   memcpy(&float_value_as_uint, &float_value, sizeof(float_value));
197   ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), float_value_as_uint,
198                             MakeUniformBufferElementDescriptor(0, 0, {0, 1})));
199 
200   // buf.s.z == 300
201   ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 300,
202                             MakeUniformBufferElementDescriptor(0, 0, {0, 2})));
203 
204   // buf.s.w == 400
205   ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 400,
206                             MakeUniformBufferElementDescriptor(0, 0, {0, 3})));
207 
208   // buf.w[6] = 22
209   ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 22,
210                             MakeUniformBufferElementDescriptor(0, 0, {1, 6})));
211 
212   // buf.w[8] = 23
213   ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 23,
214                             MakeUniformBufferElementDescriptor(0, 0, {1, 8})));
215 
216   // Assert some things about the module that are not true prior to adding the
217   // pass
218 
219   {
220     // No uniform int pointer
221     opt::analysis::Integer temp_type_signed_int(32, true);
222     opt::analysis::Integer* registered_type_signed_int =
223         context->get_type_mgr()
224             ->GetRegisteredType(&temp_type_signed_int)
225             ->AsInteger();
226     opt::analysis::Pointer type_pointer_uniform_signed_int(
227         registered_type_signed_int, SpvStorageClassUniform);
228     ASSERT_EQ(0,
229               context->get_type_mgr()->GetId(&type_pointer_uniform_signed_int));
230 
231     // No uniform uint pointer
232     opt::analysis::Integer temp_type_unsigned_int(32, false);
233     opt::analysis::Integer* registered_type_unsigned_int =
234         context->get_type_mgr()
235             ->GetRegisteredType(&temp_type_unsigned_int)
236             ->AsInteger();
237     opt::analysis::Pointer type_pointer_uniform_unsigned_int(
238         registered_type_unsigned_int, SpvStorageClassUniform);
239     ASSERT_EQ(
240         0, context->get_type_mgr()->GetId(&type_pointer_uniform_unsigned_int));
241 
242     // No uniform float pointer
243     opt::analysis::Float temp_type_float(32);
244     opt::analysis::Float* registered_type_float =
245         context->get_type_mgr()->GetRegisteredType(&temp_type_float)->AsFloat();
246     opt::analysis::Pointer type_pointer_uniform_float(registered_type_float,
247                                                       SpvStorageClassUniform);
248     ASSERT_EQ(0, context->get_type_mgr()->GetId(&type_pointer_uniform_float));
249 
250     // No int constants 200, 300 nor 400
251     opt::analysis::IntConstant int_constant_200(registered_type_signed_int,
252                                                 {200});
253     opt::analysis::IntConstant int_constant_300(registered_type_signed_int,
254                                                 {300});
255     opt::analysis::IntConstant int_constant_400(registered_type_signed_int,
256                                                 {400});
257     ASSERT_EQ(nullptr,
258               context->get_constant_mgr()->FindConstant(&int_constant_200));
259     ASSERT_EQ(nullptr,
260               context->get_constant_mgr()->FindConstant(&int_constant_300));
261     ASSERT_EQ(nullptr,
262               context->get_constant_mgr()->FindConstant(&int_constant_400));
263 
264     // No float constant 0.5
265     opt::analysis::FloatConstant float_constant_zero_point_five(
266         registered_type_float, {float_value_as_uint});
267     ASSERT_EQ(nullptr, context->get_constant_mgr()->FindConstant(
268                            &float_constant_zero_point_five));
269 
270     // No uint constant 22
271     opt::analysis::IntConstant uint_constant_22(registered_type_unsigned_int,
272                                                 {22});
273     ASSERT_EQ(nullptr,
274               context->get_constant_mgr()->FindConstant(&uint_constant_22));
275 
276     // No uint constant 23
277     opt::analysis::IntConstant uint_constant_23(registered_type_unsigned_int,
278                                                 {23});
279     ASSERT_EQ(nullptr,
280               context->get_constant_mgr()->FindConstant(&uint_constant_23));
281 
282     // No int constants 0, 1, 2, 3, 6, 8
283     opt::analysis::IntConstant int_constant_0(registered_type_signed_int, {0});
284     opt::analysis::IntConstant int_constant_1(registered_type_signed_int, {1});
285     opt::analysis::IntConstant int_constant_2(registered_type_signed_int, {2});
286     opt::analysis::IntConstant int_constant_3(registered_type_signed_int, {3});
287     opt::analysis::IntConstant int_constant_6(registered_type_signed_int, {6});
288     opt::analysis::IntConstant int_constant_8(registered_type_signed_int, {8});
289     ASSERT_EQ(nullptr,
290               context->get_constant_mgr()->FindConstant(&int_constant_0));
291     ASSERT_EQ(nullptr,
292               context->get_constant_mgr()->FindConstant(&int_constant_1));
293     ASSERT_EQ(nullptr,
294               context->get_constant_mgr()->FindConstant(&int_constant_2));
295     ASSERT_EQ(nullptr,
296               context->get_constant_mgr()->FindConstant(&int_constant_3));
297     ASSERT_EQ(nullptr,
298               context->get_constant_mgr()->FindConstant(&int_constant_6));
299     ASSERT_EQ(nullptr,
300               context->get_constant_mgr()->FindConstant(&int_constant_8));
301   }
302 
303   FuzzerPassAddUsefulConstructs pass(context.get(), &transformation_context,
304                                      &fuzzer_context, &transformation_sequence);
305   pass.Apply();
306   ASSERT_TRUE(IsValid(env, context.get()));
307 
308   // Now assert some things about the module that should be true following the
309   // pass.
310 
311   // We reconstruct all necessary types and constants to guard against the type
312   // and constant managers for the module having been invalidated.
313 
314   {
315     // Uniform int pointer now present
316     opt::analysis::Integer temp_type_signed_int(32, true);
317     opt::analysis::Integer* registered_type_signed_int =
318         context->get_type_mgr()
319             ->GetRegisteredType(&temp_type_signed_int)
320             ->AsInteger();
321     opt::analysis::Pointer type_pointer_uniform_signed_int(
322         registered_type_signed_int, SpvStorageClassUniform);
323     ASSERT_NE(0,
324               context->get_type_mgr()->GetId(&type_pointer_uniform_signed_int));
325 
326     // Uniform uint pointer now present
327     opt::analysis::Integer temp_type_unsigned_int(32, false);
328     opt::analysis::Integer* registered_type_unsigned_int =
329         context->get_type_mgr()
330             ->GetRegisteredType(&temp_type_unsigned_int)
331             ->AsInteger();
332     opt::analysis::Pointer type_pointer_uniform_unsigned_int(
333         registered_type_unsigned_int, SpvStorageClassUniform);
334     ASSERT_NE(
335         0, context->get_type_mgr()->GetId(&type_pointer_uniform_unsigned_int));
336 
337     // Uniform float pointer now present
338     opt::analysis::Float temp_type_float(32);
339     opt::analysis::Float* registered_type_float =
340         context->get_type_mgr()->GetRegisteredType(&temp_type_float)->AsFloat();
341     opt::analysis::Pointer type_pointer_uniform_float(registered_type_float,
342                                                       SpvStorageClassUniform);
343     ASSERT_NE(0, context->get_type_mgr()->GetId(&type_pointer_uniform_float));
344 
345     // int constants 200, 300, 400 now present
346     opt::analysis::IntConstant int_constant_200(registered_type_signed_int,
347                                                 {200});
348     opt::analysis::IntConstant int_constant_300(registered_type_signed_int,
349                                                 {300});
350     opt::analysis::IntConstant int_constant_400(registered_type_signed_int,
351                                                 {400});
352     ASSERT_NE(nullptr,
353               context->get_constant_mgr()->FindConstant(&int_constant_200));
354     ASSERT_NE(nullptr,
355               context->get_constant_mgr()->FindConstant(&int_constant_300));
356     ASSERT_NE(nullptr,
357               context->get_constant_mgr()->FindConstant(&int_constant_400));
358 
359     // float constant 0.5 now present
360     opt::analysis::FloatConstant float_constant_zero_point_five(
361         registered_type_float, {float_value_as_uint});
362     ASSERT_NE(nullptr, context->get_constant_mgr()->FindConstant(
363                            &float_constant_zero_point_five));
364 
365     // uint constant 22 now present
366     opt::analysis::IntConstant uint_constant_22(registered_type_unsigned_int,
367                                                 {22});
368     ASSERT_NE(nullptr,
369               context->get_constant_mgr()->FindConstant(&uint_constant_22));
370 
371     // uint constant 23 now present
372     opt::analysis::IntConstant uint_constant_23(registered_type_unsigned_int,
373                                                 {23});
374     ASSERT_NE(nullptr,
375               context->get_constant_mgr()->FindConstant(&uint_constant_23));
376 
377     // int constants 0, 1, 2, 3, 6, 8 now present
378     opt::analysis::IntConstant int_constant_0(registered_type_signed_int, {0});
379     opt::analysis::IntConstant int_constant_1(registered_type_signed_int, {1});
380     opt::analysis::IntConstant int_constant_2(registered_type_signed_int, {2});
381     opt::analysis::IntConstant int_constant_3(registered_type_signed_int, {3});
382     opt::analysis::IntConstant int_constant_6(registered_type_signed_int, {6});
383     opt::analysis::IntConstant int_constant_8(registered_type_signed_int, {8});
384     ASSERT_NE(nullptr,
385               context->get_constant_mgr()->FindConstant(&int_constant_0));
386     ASSERT_NE(nullptr,
387               context->get_constant_mgr()->FindConstant(&int_constant_1));
388     ASSERT_NE(nullptr,
389               context->get_constant_mgr()->FindConstant(&int_constant_2));
390     ASSERT_NE(nullptr,
391               context->get_constant_mgr()->FindConstant(&int_constant_3));
392     ASSERT_NE(nullptr,
393               context->get_constant_mgr()->FindConstant(&int_constant_6));
394     ASSERT_NE(nullptr,
395               context->get_constant_mgr()->FindConstant(&int_constant_8));
396   }
397 }
398 
399 }  // namespace
400 }  // namespace fuzz
401 }  // namespace spvtools
402