• 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/transformation_store.h"
16 #include "source/fuzz/instruction_descriptor.h"
17 #include "test/fuzz/fuzz_test_util.h"
18 
19 namespace spvtools {
20 namespace fuzz {
21 namespace {
22 
TEST(TransformationStoreTest,BasicTest)23 TEST(TransformationStoreTest, BasicTest) {
24   std::string shader = R"(
25                OpCapability Shader
26           %1 = OpExtInstImport "GLSL.std.450"
27                OpMemoryModel Logical GLSL450
28                OpEntryPoint Fragment %4 "main" %92 %52 %53
29                OpExecutionMode %4 OriginUpperLeft
30                OpSource ESSL 310
31                OpDecorate %92 BuiltIn FragCoord
32           %2 = OpTypeVoid
33           %3 = OpTypeFunction %2
34           %6 = OpTypeInt 32 1
35           %7 = OpTypeFloat 32
36           %8 = OpTypeStruct %6 %7
37           %9 = OpTypePointer Function %8
38          %10 = OpTypeFunction %6 %9
39          %14 = OpConstant %6 0
40          %15 = OpTypePointer Function %6
41          %51 = OpTypePointer Private %6
42          %21 = OpConstant %6 2
43          %23 = OpConstant %6 1
44          %24 = OpConstant %7 1
45          %25 = OpTypePointer Function %7
46          %50 = OpTypePointer Private %7
47          %34 = OpTypeBool
48          %35 = OpConstantFalse %34
49          %60 = OpConstantNull %50
50          %61 = OpUndef %51
51          %52 = OpVariable %50 Private
52          %53 = OpVariable %51 Private
53          %80 = OpConstantComposite %8 %21 %24
54          %90 = OpTypeVector %7 4
55          %91 = OpTypePointer Input %90
56          %92 = OpVariable %91 Input
57          %93 = OpConstantComposite %90 %24 %24 %24 %24
58           %4 = OpFunction %2 None %3
59           %5 = OpLabel
60          %20 = OpVariable %9 Function
61          %27 = OpVariable %9 Function ; irrelevant
62          %22 = OpAccessChain %15 %20 %14
63          %44 = OpCopyObject %9 %20
64          %26 = OpAccessChain %25 %20 %23
65          %29 = OpFunctionCall %6 %12 %27
66          %30 = OpAccessChain %15 %20 %14
67          %45 = OpCopyObject %15 %30
68          %81 = OpCopyObject %9 %27 ; irrelevant
69          %33 = OpAccessChain %15 %20 %14
70                OpSelectionMerge %37 None
71                OpBranchConditional %35 %36 %37
72          %36 = OpLabel
73          %38 = OpAccessChain %15 %20 %14
74          %40 = OpAccessChain %15 %20 %14
75          %43 = OpAccessChain %15 %20 %14
76          %82 = OpCopyObject %9 %27 ; irrelevant
77                OpBranch %37
78          %37 = OpLabel
79                OpReturn
80                OpFunctionEnd
81          %12 = OpFunction %6 None %10
82          %11 = OpFunctionParameter %9 ; irrelevant
83          %13 = OpLabel
84          %46 = OpCopyObject %9 %11 ; irrelevant
85          %16 = OpAccessChain %15 %11 %14 ; irrelevant
86          %95 = OpCopyObject %8 %80
87                OpReturnValue %21
88                OpFunctionEnd
89   )";
90 
91   const auto env = SPV_ENV_UNIVERSAL_1_4;
92   const auto consumer = nullptr;
93   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
94   ASSERT_TRUE(IsValid(env, context.get()));
95 
96   FactManager fact_manager;
97   spvtools::ValidatorOptions validator_options;
98   TransformationContext transformation_context(&fact_manager,
99                                                validator_options);
100 
101   transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
102       27);
103   transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
104       11);
105   transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
106       46);
107   transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
108       16);
109   transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
110       52);
111   transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
112       81);
113   transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
114       82);
115 
116   transformation_context.GetFactManager()->AddFactBlockIsDead(36);
117 
118   // Variables with pointee types:
119   //  52 - ptr_to(7)
120   //  53 - ptr_to(6)
121   //  20 - ptr_to(8)
122   //  27 - ptr_to(8) - irrelevant
123   //  92 - ptr_to(90) - read only
124 
125   // Access chains with pointee type:
126   //  22 - ptr_to(6)
127   //  26 - ptr_to(6)
128   //  30 - ptr_to(6)
129   //  33 - ptr_to(6)
130   //  38 - ptr_to(6)
131   //  40 - ptr_to(6)
132   //  43 - ptr_to(6)
133   //  16 - ptr_to(6) - irrelevant
134 
135   // Copied object with pointee type:
136   //  44 - ptr_to(8)
137   //  45 - ptr_to(6)
138   //  46 - ptr_to(8) - irrelevant
139   //  81 - ptr_to(8) - irrelevant
140   //  82 - ptr_to(8) - irrelevant
141 
142   // Function parameters with pointee type:
143   //  11 - ptr_to(8) - irrelevant
144 
145   // Pointers that cannot be used:
146   //  60 - null
147   //  61 - undefined
148 
149   // Bad: attempt to store to 11 from outside its function
150   ASSERT_FALSE(TransformationStore(
151                    11, 80, MakeInstructionDescriptor(38, SpvOpAccessChain, 0))
152                    .IsApplicable(context.get(), transformation_context));
153 
154   // Bad: pointer is not available
155   ASSERT_FALSE(TransformationStore(
156                    81, 80, MakeInstructionDescriptor(45, SpvOpCopyObject, 0))
157                    .IsApplicable(context.get(), transformation_context));
158 
159   // Bad: attempt to insert before OpVariable
160   ASSERT_FALSE(TransformationStore(
161                    52, 24, MakeInstructionDescriptor(27, SpvOpVariable, 0))
162                    .IsApplicable(context.get(), transformation_context));
163 
164   // Bad: pointer id does not exist
165   ASSERT_FALSE(TransformationStore(
166                    1000, 24, MakeInstructionDescriptor(38, SpvOpAccessChain, 0))
167                    .IsApplicable(context.get(), transformation_context));
168 
169   // Bad: pointer id exists but does not have a type
170   ASSERT_FALSE(TransformationStore(
171                    5, 24, MakeInstructionDescriptor(38, SpvOpAccessChain, 0))
172                    .IsApplicable(context.get(), transformation_context));
173 
174   // Bad: pointer id exists and has a type, but is not a pointer
175   ASSERT_FALSE(TransformationStore(
176                    24, 24, MakeInstructionDescriptor(38, SpvOpAccessChain, 0))
177                    .IsApplicable(context.get(), transformation_context));
178 
179   // Bad: attempt to store to a null pointer
180   ASSERT_FALSE(TransformationStore(
181                    60, 24, MakeInstructionDescriptor(38, SpvOpAccessChain, 0))
182                    .IsApplicable(context.get(), transformation_context));
183 
184   // Bad: attempt to store to an undefined pointer
185   ASSERT_FALSE(TransformationStore(
186                    61, 21, MakeInstructionDescriptor(38, SpvOpAccessChain, 0))
187                    .IsApplicable(context.get(), transformation_context));
188 
189   // Bad: %82 is not available at the program point
190   ASSERT_FALSE(
191       TransformationStore(82, 80, MakeInstructionDescriptor(37, SpvOpReturn, 0))
192           .IsApplicable(context.get(), transformation_context));
193 
194   // Bad: value id does not exist
195   ASSERT_FALSE(TransformationStore(
196                    27, 1000, MakeInstructionDescriptor(38, SpvOpAccessChain, 0))
197                    .IsApplicable(context.get(), transformation_context));
198 
199   // Bad: value id exists but does not have a type
200   ASSERT_FALSE(TransformationStore(
201                    27, 15, MakeInstructionDescriptor(38, SpvOpAccessChain, 0))
202                    .IsApplicable(context.get(), transformation_context));
203 
204   // Bad: value id exists but has the wrong type
205   ASSERT_FALSE(TransformationStore(
206                    27, 14, MakeInstructionDescriptor(38, SpvOpAccessChain, 0))
207                    .IsApplicable(context.get(), transformation_context));
208 
209   // Bad: attempt to store to read-only variable
210   ASSERT_FALSE(TransformationStore(
211                    92, 93, MakeInstructionDescriptor(40, SpvOpAccessChain, 0))
212                    .IsApplicable(context.get(), transformation_context));
213 
214   // Bad: value is not available
215   ASSERT_FALSE(TransformationStore(
216                    27, 95, MakeInstructionDescriptor(40, SpvOpAccessChain, 0))
217                    .IsApplicable(context.get(), transformation_context));
218 
219   // Bad: variable being stored to does not have an irrelevant pointee value,
220   // and the store is not in a dead block.
221   ASSERT_FALSE(TransformationStore(
222                    20, 95, MakeInstructionDescriptor(45, SpvOpCopyObject, 0))
223                    .IsApplicable(context.get(), transformation_context));
224 
225   // The described instruction does not exist.
226   ASSERT_FALSE(TransformationStore(
227                    27, 80, MakeInstructionDescriptor(1000, SpvOpAccessChain, 0))
228                    .IsApplicable(context.get(), transformation_context));
229 
230   {
231     // Store to irrelevant variable from dead block.
232     TransformationStore transformation(
233         27, 80, MakeInstructionDescriptor(38, SpvOpAccessChain, 0));
234     ASSERT_TRUE(
235         transformation.IsApplicable(context.get(), transformation_context));
236     transformation.Apply(context.get(), &transformation_context);
237     ASSERT_TRUE(IsValid(env, context.get()));
238   }
239 
240   {
241     // Store to irrelevant variable from live block.
242     TransformationStore transformation(
243         11, 95, MakeInstructionDescriptor(95, SpvOpReturnValue, 0));
244     ASSERT_TRUE(
245         transformation.IsApplicable(context.get(), transformation_context));
246     transformation.Apply(context.get(), &transformation_context);
247     ASSERT_TRUE(IsValid(env, context.get()));
248   }
249 
250   {
251     // Store to irrelevant variable from live block.
252     TransformationStore transformation(
253         46, 80, MakeInstructionDescriptor(95, SpvOpReturnValue, 0));
254     ASSERT_TRUE(
255         transformation.IsApplicable(context.get(), transformation_context));
256     transformation.Apply(context.get(), &transformation_context);
257     ASSERT_TRUE(IsValid(env, context.get()));
258   }
259 
260   {
261     // Store to irrelevant variable from live block.
262     TransformationStore transformation(
263         16, 21, MakeInstructionDescriptor(95, SpvOpReturnValue, 0));
264     ASSERT_TRUE(
265         transformation.IsApplicable(context.get(), transformation_context));
266     transformation.Apply(context.get(), &transformation_context);
267     ASSERT_TRUE(IsValid(env, context.get()));
268   }
269 
270   {
271     // Store to non-irrelevant variable from dead block.
272     TransformationStore transformation(
273         53, 21, MakeInstructionDescriptor(38, SpvOpAccessChain, 0));
274     ASSERT_TRUE(
275         transformation.IsApplicable(context.get(), transformation_context));
276     transformation.Apply(context.get(), &transformation_context);
277     ASSERT_TRUE(IsValid(env, context.get()));
278   }
279 
280   std::string after_transformation = R"(
281                OpCapability Shader
282           %1 = OpExtInstImport "GLSL.std.450"
283                OpMemoryModel Logical GLSL450
284                OpEntryPoint Fragment %4 "main" %92 %52 %53
285                OpExecutionMode %4 OriginUpperLeft
286                OpSource ESSL 310
287                OpDecorate %92 BuiltIn FragCoord
288           %2 = OpTypeVoid
289           %3 = OpTypeFunction %2
290           %6 = OpTypeInt 32 1
291           %7 = OpTypeFloat 32
292           %8 = OpTypeStruct %6 %7
293           %9 = OpTypePointer Function %8
294          %10 = OpTypeFunction %6 %9
295          %14 = OpConstant %6 0
296          %15 = OpTypePointer Function %6
297          %51 = OpTypePointer Private %6
298          %21 = OpConstant %6 2
299          %23 = OpConstant %6 1
300          %24 = OpConstant %7 1
301          %25 = OpTypePointer Function %7
302          %50 = OpTypePointer Private %7
303          %34 = OpTypeBool
304          %35 = OpConstantFalse %34
305          %60 = OpConstantNull %50
306          %61 = OpUndef %51
307          %52 = OpVariable %50 Private
308          %53 = OpVariable %51 Private
309          %80 = OpConstantComposite %8 %21 %24
310          %90 = OpTypeVector %7 4
311          %91 = OpTypePointer Input %90
312          %92 = OpVariable %91 Input
313          %93 = OpConstantComposite %90 %24 %24 %24 %24
314           %4 = OpFunction %2 None %3
315           %5 = OpLabel
316          %20 = OpVariable %9 Function
317          %27 = OpVariable %9 Function ; irrelevant
318          %22 = OpAccessChain %15 %20 %14
319          %44 = OpCopyObject %9 %20
320          %26 = OpAccessChain %25 %20 %23
321          %29 = OpFunctionCall %6 %12 %27
322          %30 = OpAccessChain %15 %20 %14
323          %45 = OpCopyObject %15 %30
324          %81 = OpCopyObject %9 %27 ; irrelevant
325          %33 = OpAccessChain %15 %20 %14
326                OpSelectionMerge %37 None
327                OpBranchConditional %35 %36 %37
328          %36 = OpLabel
329                OpStore %27 %80
330                OpStore %53 %21
331          %38 = OpAccessChain %15 %20 %14
332          %40 = OpAccessChain %15 %20 %14
333          %43 = OpAccessChain %15 %20 %14
334          %82 = OpCopyObject %9 %27 ; irrelevant
335                OpBranch %37
336          %37 = OpLabel
337                OpReturn
338                OpFunctionEnd
339          %12 = OpFunction %6 None %10
340          %11 = OpFunctionParameter %9 ; irrelevant
341          %13 = OpLabel
342          %46 = OpCopyObject %9 %11 ; irrelevant
343          %16 = OpAccessChain %15 %11 %14 ; irrelevant
344          %95 = OpCopyObject %8 %80
345                OpStore %11 %95
346                OpStore %46 %80
347                OpStore %16 %21
348                OpReturnValue %21
349                OpFunctionEnd
350   )";
351   ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
352 }
353 
354 }  // namespace
355 }  // namespace fuzz
356 }  // namespace spvtools
357