• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2020 Vasyl Teliman
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_add_copy_memory.h"
16 
17 #include "gtest/gtest.h"
18 #include "source/fuzz/fuzzer_util.h"
19 #include "source/fuzz/instruction_descriptor.h"
20 #include "test/fuzz/fuzz_test_util.h"
21 
22 namespace spvtools {
23 namespace fuzz {
24 namespace {
25 
TEST(TransformationAddCopyMemoryTest,BasicTest)26 TEST(TransformationAddCopyMemoryTest, BasicTest) {
27   std::string shader = R"(
28                OpCapability Shader
29           %1 = OpExtInstImport "GLSL.std.450"
30                OpMemoryModel Logical GLSL450
31                OpEntryPoint Fragment %4 "main"
32                OpExecutionMode %4 OriginUpperLeft
33                OpSource ESSL 310
34                OpDecorate %19 RelaxedPrecision
35                OpMemberDecorate %66 0 RelaxedPrecision
36                OpDecorate %69 RelaxedPrecision
37           %2 = OpTypeVoid
38           %3 = OpTypeFunction %2
39           %6 = OpTypeBool
40           %7 = OpTypePointer Function %6
41          %78 = OpTypePointer Private %6
42           %8 = OpTypeFunction %6 %7
43          %17 = OpTypeInt 32 1
44          %18 = OpTypePointer Function %17
45          %79 = OpTypePointer Private %17
46          %20 = OpConstant %17 0
47          %21 = OpTypeFloat 32
48          %22 = OpTypePointer Function %21
49          %80 = OpTypePointer Private %21
50          %24 = OpConstant %21 0
51          %25 = OpConstantFalse %6
52          %32 = OpConstantTrue %6
53          %33 = OpTypeVector %21 4
54          %34 = OpTypePointer Function %33
55          %81 = OpTypePointer Private %33
56          %36 = OpConstantComposite %33 %24 %24 %24 %24
57          %37 = OpTypeMatrix %33 4
58          %84 = OpConstantComposite %37 %36 %36 %36 %36
59          %38 = OpTypePointer Function %37
60          %82 = OpTypePointer Private %37
61          %44 = OpConstant %21 1
62          %66 = OpTypeStruct %17 %21 %6 %33 %37
63          %85 = OpConstantComposite %66 %20 %24 %25 %36 %84
64          %67 = OpTypePointer Function %66
65          %83 = OpTypePointer Private %66
66          %86 = OpVariable %79 Private %20
67          %87 = OpUndef %79
68          %88 = OpConstantNull %79
69           %4 = OpFunction %2 None %3
70           %5 = OpLabel
71          %19 = OpVariable %18 Function
72          %23 = OpVariable %22 Function
73          %26 = OpVariable %7 Function
74          %30 = OpVariable %7 Function
75          %35 = OpVariable %34 Function
76          %39 = OpVariable %38 Function
77          %68 = OpVariable %67 Function
78                OpStore %19 %20
79                OpStore %23 %24
80                OpStore %26 %25
81          %27 = OpFunctionCall %6 %10 %26
82                OpSelectionMerge %29 None
83                OpBranchConditional %27 %28 %31
84          %28 = OpLabel
85          %89 = OpCopyObject %18 %19
86                OpBranch %29
87          %31 = OpLabel
88                OpBranch %29
89          %76 = OpLabel
90          %77 = OpLogicalEqual %6 %25 %32
91                OpBranch %29
92          %29 = OpLabel
93          %75 = OpPhi %6 %25 %31 %32 %28 %77 %76
94                OpStore %30 %75
95          %40 = OpLoad %33 %35
96          %41 = OpLoad %33 %35
97          %42 = OpLoad %33 %35
98          %43 = OpLoad %33 %35
99          %45 = OpCompositeExtract %21 %40 0
100          %46 = OpCompositeExtract %21 %40 1
101          %47 = OpCompositeExtract %21 %40 2
102          %48 = OpCompositeExtract %21 %40 3
103          %49 = OpCompositeExtract %21 %41 0
104          %50 = OpCompositeExtract %21 %41 1
105          %51 = OpCompositeExtract %21 %41 2
106          %52 = OpCompositeExtract %21 %41 3
107          %53 = OpCompositeExtract %21 %42 0
108          %54 = OpCompositeExtract %21 %42 1
109          %55 = OpCompositeExtract %21 %42 2
110          %56 = OpCompositeExtract %21 %42 3
111          %57 = OpCompositeExtract %21 %43 0
112          %58 = OpCompositeExtract %21 %43 1
113          %59 = OpCompositeExtract %21 %43 2
114          %60 = OpCompositeExtract %21 %43 3
115          %61 = OpCompositeConstruct %33 %45 %46 %47 %48
116          %62 = OpCompositeConstruct %33 %49 %50 %51 %52
117          %63 = OpCompositeConstruct %33 %53 %54 %55 %56
118          %64 = OpCompositeConstruct %33 %57 %58 %59 %60
119          %65 = OpCompositeConstruct %37 %61 %62 %63 %64
120                OpStore %39 %65
121          %69 = OpLoad %17 %19
122          %70 = OpLoad %21 %23
123          %71 = OpLoad %6 %30
124          %72 = OpLoad %33 %35
125          %73 = OpLoad %37 %39
126          %74 = OpCompositeConstruct %66 %69 %70 %71 %72 %73
127                OpStore %68 %74
128                OpReturn
129                OpFunctionEnd
130          %10 = OpFunction %6 None %8
131           %9 = OpFunctionParameter %7
132          %11 = OpLabel
133          %12 = OpVariable %7 Function
134          %13 = OpLoad %6 %9
135                OpStore %12 %13
136          %14 = OpLoad %6 %12
137                OpReturnValue %14
138                OpFunctionEnd
139   )";
140 
141   const auto env = SPV_ENV_UNIVERSAL_1_3;
142   const auto consumer = nullptr;
143   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
144   spvtools::ValidatorOptions validator_options;
145   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
146                                                kConsoleMessageConsumer));
147   TransformationContext transformation_context(
148       MakeUnique<FactManager>(context.get()), validator_options);
149   // Target id is not fresh (59).
150   ASSERT_FALSE(TransformationAddCopyMemory(
151                    MakeInstructionDescriptor(27, SpvOpFunctionCall, 0), 59, 19,
152                    SpvStorageClassPrivate, 20)
153                    .IsApplicable(context.get(), transformation_context));
154 
155   // Instruction descriptor is invalid (id 90 is undefined).
156   ASSERT_FALSE(TransformationAddCopyMemory(
157                    MakeInstructionDescriptor(90, SpvOpVariable, 0), 90, 19,
158                    SpvStorageClassPrivate, 20)
159                    .IsApplicable(context.get(), transformation_context));
160 
161   // Cannot insert OpCopyMemory before OpPhi.
162   ASSERT_FALSE(
163       TransformationAddCopyMemory(MakeInstructionDescriptor(75, SpvOpPhi, 0),
164                                   90, 19, SpvStorageClassPrivate, 20)
165           .IsApplicable(context.get(), transformation_context));
166 
167   // Source instruction is invalid.
168   ASSERT_FALSE(TransformationAddCopyMemory(
169                    MakeInstructionDescriptor(27, SpvOpFunctionCall, 0), 90, 76,
170                    SpvStorageClassPrivate, 0)
171                    .IsApplicable(context.get(), transformation_context));
172 
173   // Source instruction's type doesn't exist.
174   ASSERT_FALSE(TransformationAddCopyMemory(
175                    MakeInstructionDescriptor(27, SpvOpFunctionCall, 0), 90, 5,
176                    SpvStorageClassPrivate, 0)
177                    .IsApplicable(context.get(), transformation_context));
178 
179   // Source instruction's type is invalid.
180   ASSERT_FALSE(
181       TransformationAddCopyMemory(MakeInstructionDescriptor(41, SpvOpLoad, 0),
182                                   90, 40, SpvStorageClassPrivate, 0)
183           .IsApplicable(context.get(), transformation_context));
184 
185   // Source instruction is OpUndef.
186   ASSERT_FALSE(
187       TransformationAddCopyMemory(MakeInstructionDescriptor(41, SpvOpLoad, 0),
188                                   90, 87, SpvStorageClassPrivate, 0)
189           .IsApplicable(context.get(), transformation_context));
190 
191   // Source instruction is OpConstantNull.
192   ASSERT_FALSE(
193       TransformationAddCopyMemory(MakeInstructionDescriptor(41, SpvOpLoad, 0),
194                                   90, 88, SpvStorageClassPrivate, 0)
195           .IsApplicable(context.get(), transformation_context));
196 
197   // Storage class is invalid.
198   ASSERT_FALSE(TransformationAddCopyMemory(
199                    MakeInstructionDescriptor(27, SpvOpFunctionCall, 0), 90, 19,
200                    SpvStorageClassWorkgroup, 20)
201                    .IsApplicable(context.get(), transformation_context));
202 
203   // Initializer is 0.
204   ASSERT_FALSE(TransformationAddCopyMemory(
205                    MakeInstructionDescriptor(27, SpvOpFunctionCall, 0), 90, 19,
206                    SpvStorageClassPrivate, 0)
207                    .IsApplicable(context.get(), transformation_context));
208 
209   // Initializer has wrong type.
210   ASSERT_FALSE(TransformationAddCopyMemory(
211                    MakeInstructionDescriptor(27, SpvOpFunctionCall, 0), 90, 19,
212                    SpvStorageClassPrivate, 25)
213                    .IsApplicable(context.get(), transformation_context));
214 
215   // Source and target instructions are in different functions.
216   ASSERT_FALSE(
217       TransformationAddCopyMemory(MakeInstructionDescriptor(13, SpvOpLoad, 0),
218                                   90, 19, SpvStorageClassPrivate, 20)
219           .IsApplicable(context.get(), transformation_context));
220 
221   // Source instruction doesn't dominate the target instruction.
222   ASSERT_FALSE(TransformationAddCopyMemory(
223                    MakeInstructionDescriptor(77, SpvOpLogicalEqual, 0), 90, 89,
224                    SpvStorageClassPrivate, 20)
225                    .IsApplicable(context.get(), transformation_context));
226 
227   // Source and target instructions are the same.
228   ASSERT_FALSE(TransformationAddCopyMemory(
229                    MakeInstructionDescriptor(19, SpvOpVariable, 0), 90, 19,
230                    SpvStorageClassPrivate, 20)
231                    .IsApplicable(context.get(), transformation_context));
232 
233   // Correct transformations.
234   uint32_t fresh_id = 90;
235   auto descriptor = MakeInstructionDescriptor(27, SpvOpFunctionCall, 0);
236   std::vector<uint32_t> source_ids = {19, 23, 26, 30, 35, 39, 68, 86};
237   std::vector<uint32_t> initializers = {20, 24, 25, 25, 36, 84, 85, 20};
238   std::vector<SpvStorageClass> storage_classes = {SpvStorageClassPrivate,
239                                                   SpvStorageClassFunction};
240   for (size_t i = 0, n = source_ids.size(); i < n; ++i) {
241     TransformationAddCopyMemory transformation(
242         descriptor, fresh_id, source_ids[i],
243         storage_classes[i % storage_classes.size()], initializers[i]);
244     ASSERT_TRUE(
245         transformation.IsApplicable(context.get(), transformation_context));
246     ApplyAndCheckFreshIds(transformation, context.get(),
247                           &transformation_context);
248     ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
249         context.get(), validator_options, kConsoleMessageConsumer));
250     ASSERT_TRUE(
251         transformation_context.GetFactManager()->PointeeValueIsIrrelevant(
252             fresh_id));
253     fresh_id++;
254   }
255 
256   std::string expected = R"(
257                OpCapability Shader
258           %1 = OpExtInstImport "GLSL.std.450"
259                OpMemoryModel Logical GLSL450
260                OpEntryPoint Fragment %4 "main"
261                OpExecutionMode %4 OriginUpperLeft
262                OpSource ESSL 310
263                OpDecorate %19 RelaxedPrecision
264                OpMemberDecorate %66 0 RelaxedPrecision
265                OpDecorate %69 RelaxedPrecision
266           %2 = OpTypeVoid
267           %3 = OpTypeFunction %2
268           %6 = OpTypeBool
269           %7 = OpTypePointer Function %6
270          %78 = OpTypePointer Private %6
271           %8 = OpTypeFunction %6 %7
272          %17 = OpTypeInt 32 1
273          %18 = OpTypePointer Function %17
274          %79 = OpTypePointer Private %17
275          %20 = OpConstant %17 0
276          %21 = OpTypeFloat 32
277          %22 = OpTypePointer Function %21
278          %80 = OpTypePointer Private %21
279          %24 = OpConstant %21 0
280          %25 = OpConstantFalse %6
281          %32 = OpConstantTrue %6
282          %33 = OpTypeVector %21 4
283          %34 = OpTypePointer Function %33
284          %81 = OpTypePointer Private %33
285          %36 = OpConstantComposite %33 %24 %24 %24 %24
286          %37 = OpTypeMatrix %33 4
287          %84 = OpConstantComposite %37 %36 %36 %36 %36
288          %38 = OpTypePointer Function %37
289          %82 = OpTypePointer Private %37
290          %44 = OpConstant %21 1
291          %66 = OpTypeStruct %17 %21 %6 %33 %37
292          %85 = OpConstantComposite %66 %20 %24 %25 %36 %84
293          %67 = OpTypePointer Function %66
294          %83 = OpTypePointer Private %66
295          %86 = OpVariable %79 Private %20
296          %87 = OpUndef %79
297          %88 = OpConstantNull %79
298          %90 = OpVariable %79 Private %20
299          %92 = OpVariable %78 Private %25
300          %94 = OpVariable %81 Private %36
301          %96 = OpVariable %83 Private %85
302           %4 = OpFunction %2 None %3
303           %5 = OpLabel
304          %97 = OpVariable %18 Function %20
305          %95 = OpVariable %38 Function %84
306          %93 = OpVariable %7 Function %25
307          %91 = OpVariable %22 Function %24
308          %19 = OpVariable %18 Function
309          %23 = OpVariable %22 Function
310          %26 = OpVariable %7 Function
311          %30 = OpVariable %7 Function
312          %35 = OpVariable %34 Function
313          %39 = OpVariable %38 Function
314          %68 = OpVariable %67 Function
315                OpStore %19 %20
316                OpStore %23 %24
317                OpStore %26 %25
318                OpCopyMemory %90 %19
319                OpCopyMemory %91 %23
320                OpCopyMemory %92 %26
321                OpCopyMemory %93 %30
322                OpCopyMemory %94 %35
323                OpCopyMemory %95 %39
324                OpCopyMemory %96 %68
325                OpCopyMemory %97 %86
326          %27 = OpFunctionCall %6 %10 %26
327                OpSelectionMerge %29 None
328                OpBranchConditional %27 %28 %31
329          %28 = OpLabel
330          %89 = OpCopyObject %18 %19
331                OpBranch %29
332          %31 = OpLabel
333                OpBranch %29
334          %76 = OpLabel
335          %77 = OpLogicalEqual %6 %25 %32
336                OpBranch %29
337          %29 = OpLabel
338          %75 = OpPhi %6 %25 %31 %32 %28 %77 %76
339                OpStore %30 %75
340          %40 = OpLoad %33 %35
341          %41 = OpLoad %33 %35
342          %42 = OpLoad %33 %35
343          %43 = OpLoad %33 %35
344          %45 = OpCompositeExtract %21 %40 0
345          %46 = OpCompositeExtract %21 %40 1
346          %47 = OpCompositeExtract %21 %40 2
347          %48 = OpCompositeExtract %21 %40 3
348          %49 = OpCompositeExtract %21 %41 0
349          %50 = OpCompositeExtract %21 %41 1
350          %51 = OpCompositeExtract %21 %41 2
351          %52 = OpCompositeExtract %21 %41 3
352          %53 = OpCompositeExtract %21 %42 0
353          %54 = OpCompositeExtract %21 %42 1
354          %55 = OpCompositeExtract %21 %42 2
355          %56 = OpCompositeExtract %21 %42 3
356          %57 = OpCompositeExtract %21 %43 0
357          %58 = OpCompositeExtract %21 %43 1
358          %59 = OpCompositeExtract %21 %43 2
359          %60 = OpCompositeExtract %21 %43 3
360          %61 = OpCompositeConstruct %33 %45 %46 %47 %48
361          %62 = OpCompositeConstruct %33 %49 %50 %51 %52
362          %63 = OpCompositeConstruct %33 %53 %54 %55 %56
363          %64 = OpCompositeConstruct %33 %57 %58 %59 %60
364          %65 = OpCompositeConstruct %37 %61 %62 %63 %64
365                OpStore %39 %65
366          %69 = OpLoad %17 %19
367          %70 = OpLoad %21 %23
368          %71 = OpLoad %6 %30
369          %72 = OpLoad %33 %35
370          %73 = OpLoad %37 %39
371          %74 = OpCompositeConstruct %66 %69 %70 %71 %72 %73
372                OpStore %68 %74
373                OpReturn
374                OpFunctionEnd
375          %10 = OpFunction %6 None %8
376           %9 = OpFunctionParameter %7
377          %11 = OpLabel
378          %12 = OpVariable %7 Function
379          %13 = OpLoad %6 %9
380                OpStore %12 %13
381          %14 = OpLoad %6 %12
382                OpReturnValue %14
383                OpFunctionEnd
384   )";
385 
386   ASSERT_TRUE(IsEqual(env, expected, context.get()));
387 }
388 
TEST(TransformationAddCopyMemoryTest,DisallowBufferBlockDecoration)389 TEST(TransformationAddCopyMemoryTest, DisallowBufferBlockDecoration) {
390   std::string shader = R"(
391                OpCapability Shader
392           %1 = OpExtInstImport "GLSL.std.450"
393                OpMemoryModel Logical GLSL450
394                OpEntryPoint GLCompute %4 "main"
395                OpExecutionMode %4 LocalSize 1 1 1
396                OpSource ESSL 320
397                OpName %4 "main"
398                OpName %7 "buf"
399                OpMemberName %7 0 "a"
400                OpMemberName %7 1 "b"
401                OpName %9 ""
402                OpMemberDecorate %7 0 Offset 0
403                OpMemberDecorate %7 1 Offset 4
404                OpDecorate %7 BufferBlock
405                OpDecorate %9 DescriptorSet 0
406                OpDecorate %9 Binding 0
407           %2 = OpTypeVoid
408           %3 = OpTypeFunction %2
409           %6 = OpTypeInt 32 1
410          %10 = OpConstant %6 42
411           %7 = OpTypeStruct %6 %6
412           %8 = OpTypePointer Uniform %7
413           %9 = OpVariable %8 Uniform
414          %50 = OpUndef %7
415           %4 = OpFunction %2 None %3
416           %5 = OpLabel
417                OpReturn
418                OpFunctionEnd
419   )";
420 
421   const auto env = SPV_ENV_UNIVERSAL_1_0;
422   const auto consumer = nullptr;
423   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
424   spvtools::ValidatorOptions validator_options;
425   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
426                                                kConsoleMessageConsumer));
427   TransformationContext transformation_context(
428       MakeUnique<FactManager>(context.get()), validator_options);
429   ASSERT_FALSE(
430       TransformationAddCopyMemory(MakeInstructionDescriptor(5, SpvOpReturn, 0),
431                                   100, 9, SpvStorageClassPrivate, 50)
432           .IsApplicable(context.get(), transformation_context));
433 }
434 
TEST(TransformationAddCopyMemoryTest,DisallowBlockDecoration)435 TEST(TransformationAddCopyMemoryTest, DisallowBlockDecoration) {
436   std::string shader = R"(
437                OpCapability Shader
438           %1 = OpExtInstImport "GLSL.std.450"
439                OpMemoryModel Logical GLSL450
440                OpEntryPoint GLCompute %4 "main" %9
441                OpExecutionMode %4 LocalSize 1 1 1
442                OpSource ESSL 320
443                OpName %4 "main"
444                OpName %7 "buf"
445                OpMemberName %7 0 "a"
446                OpMemberName %7 1 "b"
447                OpName %9 ""
448                OpMemberDecorate %7 0 Offset 0
449                OpMemberDecorate %7 1 Offset 4
450                OpDecorate %7 Block
451                OpDecorate %9 DescriptorSet 0
452                OpDecorate %9 Binding 0
453           %2 = OpTypeVoid
454           %3 = OpTypeFunction %2
455           %6 = OpTypeInt 32 1
456          %10 = OpConstant %6 42
457           %7 = OpTypeStruct %6 %6
458           %8 = OpTypePointer StorageBuffer %7
459           %9 = OpVariable %8 StorageBuffer
460          %50 = OpUndef %7
461           %4 = OpFunction %2 None %3
462           %5 = OpLabel
463                OpReturn
464                OpFunctionEnd
465   )";
466 
467   const auto env = SPV_ENV_UNIVERSAL_1_5;
468   const auto consumer = nullptr;
469   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
470   spvtools::ValidatorOptions validator_options;
471   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
472                                                kConsoleMessageConsumer));
473   TransformationContext transformation_context(
474       MakeUnique<FactManager>(context.get()), validator_options);
475   ASSERT_FALSE(
476       TransformationAddCopyMemory(MakeInstructionDescriptor(5, SpvOpReturn, 0),
477                                   100, 9, SpvStorageClassPrivate, 50)
478           .IsApplicable(context.get(), transformation_context));
479 }
480 
481 }  // namespace
482 }  // namespace fuzz
483 }  // namespace spvtools