1 // Copyright (c) 2020 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_construct_composites.h"
16 
17 #include "gtest/gtest.h"
18 #include "source/fuzz/fuzzer_util.h"
19 #include "source/fuzz/pseudo_random_generator.h"
20 #include "test/fuzz/fuzz_test_util.h"
21 
22 namespace spvtools {
23 namespace fuzz {
24 namespace {
25 
TEST(FuzzerPassConstructCompositesTest,IsomorphicStructs)26 TEST(FuzzerPassConstructCompositesTest, IsomorphicStructs) {
27   // This test declares various isomorphic structs, and a struct that is made up
28   // of these isomorphic structs.  The pass to construct composites is then
29   // applied several times to check that no issues arise related to using a
30   // value of one struct type when a value of an isomorphic struct type is
31   // required.
32 
33   std::string shader = R"(
34                OpCapability Shader
35           %1 = OpExtInstImport "GLSL.std.450"
36                OpMemoryModel Logical GLSL450
37                OpEntryPoint Fragment %4 "main"
38                OpExecutionMode %4 OriginUpperLeft
39                OpSource ESSL 310
40           %2 = OpTypeVoid
41           %3 = OpTypeFunction %2
42           %6 = OpTypeFloat 32
43           %7 = OpConstant %6 0
44           %8 = OpTypeStruct %6 %6 %6
45           %9 = OpTypeStruct %6 %6 %6
46          %10 = OpTypeStruct %6 %6 %6
47          %11 = OpTypeStruct %6 %6 %6
48          %12 = OpTypeStruct %6 %6 %6
49          %13 = OpTypeStruct %8 %9 %10 %11 %12
50          %14 = OpConstantComposite %8 %7 %7 %7
51          %15 = OpConstantComposite %9 %7 %7 %7
52          %16 = OpConstantComposite %10 %7 %7 %7
53          %17 = OpConstantComposite %11 %7 %7 %7
54          %18 = OpConstantComposite %12 %7 %7 %7
55           %4 = OpFunction %2 None %3
56           %5 = OpLabel
57                OpNop
58                OpNop
59                OpNop
60                OpNop
61                OpNop
62                OpNop
63                OpNop
64                OpNop
65                OpNop
66                OpNop
67                OpNop
68                OpNop
69                OpNop
70                OpNop
71                OpNop
72                OpNop
73                OpReturn
74                OpFunctionEnd
75   )";
76 
77   const auto env = SPV_ENV_UNIVERSAL_1_3;
78   const auto consumer = nullptr;
79 
80   auto prng = MakeUnique<PseudoRandomGenerator>(0);
81 
82   for (uint32_t i = 0; i < 10; i++) {
83     const auto context =
84         BuildModule(env, consumer, shader, kFuzzAssembleOption);
85     spvtools::ValidatorOptions validator_options;
86     ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
87         context.get(), validator_options, kConsoleMessageConsumer));
88     TransformationContext transformation_context(
89         MakeUnique<FactManager>(context.get()), validator_options);
90     FuzzerContext fuzzer_context(prng.get(), 100);
91     protobufs::TransformationSequence transformation_sequence;
92 
93     FuzzerPassConstructComposites fuzzer_pass(
94         context.get(), &transformation_context, &fuzzer_context,
95         &transformation_sequence);
96 
97     fuzzer_pass.Apply();
98 
99     // We just check that the result is valid.
100     ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
101         context.get(), validator_options, kConsoleMessageConsumer));
102   }
103 }
104 
TEST(FuzzerPassConstructCompositesTest,IsomorphicArrays)105 TEST(FuzzerPassConstructCompositesTest, IsomorphicArrays) {
106   // This test declares various isomorphic arrays, and a struct that is made up
107   // of these isomorphic arrays.  The pass to construct composites is then
108   // applied several times to check that no issues arise related to using a
109   // value of one array type when a value of an isomorphic array type is
110   // required.
111 
112   std::string shader = R"(
113                OpCapability Shader
114           %1 = OpExtInstImport "GLSL.std.450"
115                OpMemoryModel Logical GLSL450
116                OpEntryPoint Fragment %4 "main"
117                OpExecutionMode %4 OriginUpperLeft
118                OpSource ESSL 310
119           %2 = OpTypeVoid
120           %3 = OpTypeFunction %2
121           %6 = OpTypeFloat 32
122          %50 = OpTypeInt 32 0
123          %51 = OpConstant %50 3
124           %7 = OpConstant %6 0
125           %8 = OpTypeArray %6 %51
126           %9 = OpTypeArray %6 %51
127          %10 = OpTypeArray %6 %51
128          %11 = OpTypeArray %6 %51
129          %12 = OpTypeArray %6 %51
130          %13 = OpTypeStruct %8 %9 %10 %11 %12
131          %14 = OpConstantComposite %8 %7 %7 %7
132          %15 = OpConstantComposite %9 %7 %7 %7
133          %16 = OpConstantComposite %10 %7 %7 %7
134          %17 = OpConstantComposite %11 %7 %7 %7
135          %18 = OpConstantComposite %12 %7 %7 %7
136           %4 = OpFunction %2 None %3
137           %5 = OpLabel
138                OpNop
139                OpNop
140                OpNop
141                OpNop
142                OpNop
143                OpNop
144                OpNop
145                OpNop
146                OpNop
147                OpNop
148                OpNop
149                OpNop
150                OpNop
151                OpNop
152                OpNop
153                OpNop
154                OpReturn
155                OpFunctionEnd
156   )";
157 
158   const auto env = SPV_ENV_UNIVERSAL_1_3;
159   const auto consumer = nullptr;
160 
161   auto prng = MakeUnique<PseudoRandomGenerator>(0);
162 
163   for (uint32_t i = 0; i < 10; i++) {
164     const auto context =
165         BuildModule(env, consumer, shader, kFuzzAssembleOption);
166     spvtools::ValidatorOptions validator_options;
167     ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
168         context.get(), validator_options, kConsoleMessageConsumer));
169     TransformationContext transformation_context(
170         MakeUnique<FactManager>(context.get()), validator_options);
171     FuzzerContext fuzzer_context(prng.get(), 100);
172     protobufs::TransformationSequence transformation_sequence;
173 
174     FuzzerPassConstructComposites fuzzer_pass(
175         context.get(), &transformation_context, &fuzzer_context,
176         &transformation_sequence);
177 
178     fuzzer_pass.Apply();
179 
180     // We just check that the result is valid.
181     ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
182         context.get(), validator_options, kConsoleMessageConsumer));
183   }
184 }
185 
186 }  // namespace
187 }  // namespace fuzz
188 }  // namespace spvtools
189