transformation_mutate_pointer_test.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  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. #include "source/fuzz/transformation_mutate_pointer.h"
  15. #include "gtest/gtest.h"
  16. #include "source/fuzz/fuzzer_util.h"
  17. #include "source/fuzz/instruction_descriptor.h"
  18. #include "test/fuzz/fuzz_test_util.h"
  19. namespace spvtools {
  20. namespace fuzz {
  21. namespace {
  22. TEST(TransformationMutatePointerTest, BasicTest) {
  23. std::string shader = R"(
  24. OpCapability Shader
  25. OpCapability VariablePointers
  26. %1 = OpExtInstImport "GLSL.std.450"
  27. OpMemoryModel Logical GLSL450
  28. OpEntryPoint Fragment %4 "main"
  29. OpExecutionMode %4 OriginUpperLeft
  30. OpSource ESSL 310
  31. %2 = OpTypeVoid
  32. %3 = OpTypeFunction %2
  33. %6 = OpTypeInt 32 1
  34. %7 = OpTypeFloat 32
  35. %34 = OpConstant %7 0
  36. %36 = OpConstant %6 0
  37. %14 = OpTypeVector %7 3
  38. %35 = OpConstantComposite %14 %34 %34 %34
  39. %15 = OpTypeMatrix %14 2
  40. %8 = OpConstant %6 5
  41. %9 = OpTypeArray %7 %8
  42. %37 = OpConstantComposite %9 %34 %34 %34 %34 %34
  43. %11 = OpTypeStruct
  44. %38 = OpConstantComposite %11
  45. %39 = OpConstantComposite %15 %35 %35
  46. %31 = OpTypePointer Function %14
  47. %10 = OpTypeStruct %7 %6 %9 %11 %15 %14
  48. %40 = OpConstantComposite %10 %34 %36 %37 %38 %39 %35
  49. %13 = OpTypePointer Function %10
  50. %16 = OpTypePointer Private %10
  51. %17 = OpTypePointer Workgroup %10
  52. %18 = OpTypeStruct %16
  53. %19 = OpTypePointer Private %18
  54. %20 = OpVariable %16 Private
  55. %21 = OpVariable %17 Workgroup
  56. %22 = OpVariable %19 Private
  57. %23 = OpTypePointer Output %6
  58. %24 = OpVariable %23 Output
  59. %27 = OpTypeFunction %2 %13
  60. %33 = OpConstantNull %16
  61. %4 = OpFunction %2 None %3
  62. %5 = OpLabel
  63. OpReturn
  64. OpFunctionEnd
  65. %28 = OpFunction %2 None %27
  66. %29 = OpFunctionParameter %13
  67. %30 = OpLabel
  68. %25 = OpVariable %13 Function
  69. %26 = OpAccessChain %31 %25 %8
  70. OpReturn
  71. OpFunctionEnd
  72. )";
  73. const auto env = SPV_ENV_UNIVERSAL_1_3;
  74. const auto consumer = nullptr;
  75. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  76. spvtools::ValidatorOptions validator_options;
  77. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  78. kConsoleMessageConsumer));
  79. TransformationContext transformation_context(
  80. MakeUnique<FactManager>(context.get()), validator_options);
  81. transformation_context.GetFactManager()->AddFactIdIsIrrelevant(35);
  82. transformation_context.GetFactManager()->AddFactIdIsIrrelevant(39);
  83. const auto insert_before =
  84. MakeInstructionDescriptor(26, spv::Op::OpReturn, 0);
  85. // 20 is not a fresh id.
  86. ASSERT_FALSE(TransformationMutatePointer(20, 20, insert_before)
  87. .IsApplicable(context.get(), transformation_context));
  88. // |insert_before| instruction descriptor is invalid.
  89. ASSERT_FALSE(TransformationMutatePointer(
  90. 20, 70, MakeInstructionDescriptor(26, spv::Op::OpStore, 0))
  91. .IsApplicable(context.get(), transformation_context));
  92. // Can't insert OpLoad before OpVariable.
  93. ASSERT_FALSE(
  94. TransformationMutatePointer(
  95. 20, 70, MakeInstructionDescriptor(26, spv::Op::OpVariable, 0))
  96. .IsApplicable(context.get(), transformation_context));
  97. // |pointer_id| doesn't exist in the module.
  98. ASSERT_FALSE(TransformationMutatePointer(70, 70, insert_before)
  99. .IsApplicable(context.get(), transformation_context));
  100. // |pointer_id| doesn't have a type id.
  101. ASSERT_FALSE(TransformationMutatePointer(11, 70, insert_before)
  102. .IsApplicable(context.get(), transformation_context));
  103. // |pointer_id| is a result id of OpConstantNull.
  104. ASSERT_FALSE(TransformationMutatePointer(33, 70, insert_before)
  105. .IsApplicable(context.get(), transformation_context));
  106. // |pointer_id| is not a pointer instruction.
  107. ASSERT_FALSE(TransformationMutatePointer(8, 70, insert_before)
  108. .IsApplicable(context.get(), transformation_context));
  109. // |pointer_id| has invalid storage class
  110. ASSERT_FALSE(TransformationMutatePointer(24, 70, insert_before)
  111. .IsApplicable(context.get(), transformation_context));
  112. // |pointer_id|'s pointee contains non-scalar and non-composite constituents.
  113. ASSERT_FALSE(TransformationMutatePointer(22, 70, insert_before)
  114. .IsApplicable(context.get(), transformation_context));
  115. // There is no irrelevant zero constant to insert into the |pointer_id|.
  116. ASSERT_FALSE(TransformationMutatePointer(20, 70, insert_before)
  117. .IsApplicable(context.get(), transformation_context));
  118. // |pointer_id| is not available before |insert_before|.
  119. ASSERT_FALSE(
  120. TransformationMutatePointer(
  121. 26, 70, MakeInstructionDescriptor(26, spv::Op::OpAccessChain, 0))
  122. .IsApplicable(context.get(), transformation_context));
  123. transformation_context.GetFactManager()->AddFactIdIsIrrelevant(40);
  124. uint32_t fresh_id = 70;
  125. uint32_t pointer_ids[] = {
  126. 20, // Mutate Private variable.
  127. 21, // Mutate Workgroup variable.
  128. 25, // Mutate Function variable.
  129. 29, // Mutate function parameter.
  130. 26, // Mutate OpAccessChain.
  131. };
  132. for (auto pointer_id : pointer_ids) {
  133. TransformationMutatePointer transformation(pointer_id, fresh_id++,
  134. insert_before);
  135. ASSERT_TRUE(
  136. transformation.IsApplicable(context.get(), transformation_context));
  137. ApplyAndCheckFreshIds(transformation, context.get(),
  138. &transformation_context);
  139. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
  140. context.get(), validator_options, kConsoleMessageConsumer));
  141. }
  142. std::string after_transformation = R"(
  143. OpCapability Shader
  144. OpCapability VariablePointers
  145. %1 = OpExtInstImport "GLSL.std.450"
  146. OpMemoryModel Logical GLSL450
  147. OpEntryPoint Fragment %4 "main"
  148. OpExecutionMode %4 OriginUpperLeft
  149. OpSource ESSL 310
  150. %2 = OpTypeVoid
  151. %3 = OpTypeFunction %2
  152. %6 = OpTypeInt 32 1
  153. %7 = OpTypeFloat 32
  154. %34 = OpConstant %7 0
  155. %36 = OpConstant %6 0
  156. %14 = OpTypeVector %7 3
  157. %35 = OpConstantComposite %14 %34 %34 %34
  158. %15 = OpTypeMatrix %14 2
  159. %8 = OpConstant %6 5
  160. %9 = OpTypeArray %7 %8
  161. %37 = OpConstantComposite %9 %34 %34 %34 %34 %34
  162. %11 = OpTypeStruct
  163. %38 = OpConstantComposite %11
  164. %39 = OpConstantComposite %15 %35 %35
  165. %31 = OpTypePointer Function %14
  166. %10 = OpTypeStruct %7 %6 %9 %11 %15 %14
  167. %40 = OpConstantComposite %10 %34 %36 %37 %38 %39 %35
  168. %13 = OpTypePointer Function %10
  169. %16 = OpTypePointer Private %10
  170. %17 = OpTypePointer Workgroup %10
  171. %18 = OpTypeStruct %16
  172. %19 = OpTypePointer Private %18
  173. %20 = OpVariable %16 Private
  174. %21 = OpVariable %17 Workgroup
  175. %22 = OpVariable %19 Private
  176. %23 = OpTypePointer Output %6
  177. %24 = OpVariable %23 Output
  178. %27 = OpTypeFunction %2 %13
  179. %33 = OpConstantNull %16
  180. %4 = OpFunction %2 None %3
  181. %5 = OpLabel
  182. OpReturn
  183. OpFunctionEnd
  184. %28 = OpFunction %2 None %27
  185. %29 = OpFunctionParameter %13
  186. %30 = OpLabel
  187. %25 = OpVariable %13 Function
  188. %26 = OpAccessChain %31 %25 %8
  189. ; modified Private variable
  190. %70 = OpLoad %10 %20
  191. OpStore %20 %40
  192. OpStore %20 %70
  193. ; modified Workgroup variable
  194. %71 = OpLoad %10 %21
  195. OpStore %21 %40
  196. OpStore %21 %71
  197. ; modified Function variable
  198. %72 = OpLoad %10 %25
  199. OpStore %25 %40
  200. OpStore %25 %72
  201. ; modified function parameter
  202. %73 = OpLoad %10 %29
  203. OpStore %29 %40
  204. OpStore %29 %73
  205. ; modified OpAccessChain
  206. %74 = OpLoad %14 %26
  207. OpStore %26 %35
  208. OpStore %26 %74
  209. OpReturn
  210. OpFunctionEnd
  211. )";
  212. ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
  213. }
  214. TEST(TransformationMutatePointerTest, HandlesUnreachableBlocks) {
  215. std::string shader = R"(
  216. OpCapability Shader
  217. %1 = OpExtInstImport "GLSL.std.450"
  218. OpMemoryModel Logical GLSL450
  219. OpEntryPoint Fragment %4 "main"
  220. OpExecutionMode %4 OriginUpperLeft
  221. OpSource ESSL 310
  222. %2 = OpTypeVoid
  223. %3 = OpTypeFunction %2
  224. %6 = OpTypeInt 32 1
  225. %7 = OpConstant %6 0
  226. %8 = OpTypePointer Function %6
  227. %11 = OpTypePointer Private %6
  228. %12 = OpVariable %11 Private
  229. %4 = OpFunction %2 None %3
  230. %5 = OpLabel
  231. %9 = OpVariable %8 Function
  232. OpReturn
  233. %10 = OpLabel
  234. OpReturn
  235. OpFunctionEnd
  236. )";
  237. const auto env = SPV_ENV_UNIVERSAL_1_3;
  238. const auto consumer = nullptr;
  239. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  240. spvtools::ValidatorOptions validator_options;
  241. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  242. kConsoleMessageConsumer));
  243. TransformationContext transformation_context(
  244. MakeUnique<FactManager>(context.get()), validator_options);
  245. transformation_context.GetFactManager()->AddFactIdIsIrrelevant(7);
  246. ASSERT_FALSE(
  247. context->GetDominatorAnalysis(context->GetFunction(4))->IsReachable(10));
  248. const auto insert_before =
  249. MakeInstructionDescriptor(10, spv::Op::OpReturn, 0);
  250. // Can mutate a global variable in an unreachable block.
  251. TransformationMutatePointer transformation(12, 50, insert_before);
  252. ASSERT_TRUE(
  253. transformation.IsApplicable(context.get(), transformation_context));
  254. ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
  255. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  256. kConsoleMessageConsumer));
  257. std::string after_transformation = R"(
  258. OpCapability Shader
  259. %1 = OpExtInstImport "GLSL.std.450"
  260. OpMemoryModel Logical GLSL450
  261. OpEntryPoint Fragment %4 "main"
  262. OpExecutionMode %4 OriginUpperLeft
  263. OpSource ESSL 310
  264. %2 = OpTypeVoid
  265. %3 = OpTypeFunction %2
  266. %6 = OpTypeInt 32 1
  267. %7 = OpConstant %6 0
  268. %8 = OpTypePointer Function %6
  269. %11 = OpTypePointer Private %6
  270. %12 = OpVariable %11 Private
  271. %4 = OpFunction %2 None %3
  272. %5 = OpLabel
  273. %9 = OpVariable %8 Function
  274. OpReturn
  275. %10 = OpLabel
  276. %50 = OpLoad %6 %12
  277. OpStore %12 %7
  278. OpStore %12 %50
  279. OpReturn
  280. OpFunctionEnd
  281. )";
  282. ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
  283. }
  284. } // namespace
  285. } // namespace fuzz
  286. } // namespace spvtools