diff --git a/source/fuzz/fuzzer_pass_donate_modules.cpp b/source/fuzz/fuzzer_pass_donate_modules.cpp index bb48303ef9..fc71d344c8 100644 --- a/source/fuzz/fuzzer_pass_donate_modules.cpp +++ b/source/fuzz/fuzzer_pass_donate_modules.cpp @@ -124,6 +124,7 @@ SpvStorageClass FuzzerPassDonateModules::AdaptStorageClass( case SpvStorageClassUniform: case SpvStorageClassUniformConstant: case SpvStorageClassPushConstant: + case SpvStorageClassImage: // We change these to Private return SpvStorageClassPrivate; default: @@ -721,11 +722,12 @@ bool FuzzerPassDonateModules::CanDonateInstruction( // We do not have a mapped result id for this id operand. That either // means that it is a forward reference (which is OK), that we skipped // the instruction that generated it (which is not OK), or that it is - // the id of a function that we did not donate (which is not OK). We - // check for the latter two cases. + // the id of a function or global value that we did not donate (which + // is not OK). We check for the latter two cases. if (skipped_instructions.count(*in_id) || - donor_ir_context->get_def_use_mgr()->GetDef(*in_id)->opcode() == - SpvOpFunction) { + // A function or global value does not have an associated basic + // block. + !donor_ir_context->get_instr_block(*in_id)) { result = false; return false; } diff --git a/test/fuzz/fuzzer_pass_donate_modules_test.cpp b/test/fuzz/fuzzer_pass_donate_modules_test.cpp index 432ca4f8a5..0833c1d50e 100644 --- a/test/fuzz/fuzzer_pass_donate_modules_test.cpp +++ b/test/fuzz/fuzzer_pass_donate_modules_test.cpp @@ -1058,6 +1058,85 @@ TEST(FuzzerPassDonateModulesTest, DonateCodeThatUsesImageFunctionParameter) { ASSERT_TRUE(IsValid(env, recipient_context.get())); } +TEST(FuzzerPassDonateModulesTest, DonateShaderWithImageStorageClass) { + std::string recipient_shader = R"( + OpCapability Shader + OpCapability ImageQuery + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %4 "main" + OpExecutionMode %4 OriginUpperLeft + OpSource ESSL 320 + OpSourceExtension "GL_EXT_samplerless_texture_functions" + %2 = OpTypeVoid + %3 = OpTypeFunction %2 + %4 = OpFunction %2 None %3 + %5 = OpLabel + OpReturn + OpFunctionEnd + )"; + + std::string donor_shader = R"( + OpCapability Shader + OpCapability SampledBuffer + OpCapability ImageBuffer + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %2 "MainPSPacked" + OpExecutionMode %2 OriginUpperLeft + OpDecorate %18 DescriptorSet 0 + OpDecorate %18 Binding 128 + %49 = OpTypeInt 32 0 + %50 = OpTypeFloat 32 + %58 = OpConstant %50 1 + %66 = OpConstant %49 0 + %87 = OpTypeVector %50 2 + %88 = OpConstantComposite %87 %58 %58 + %17 = OpTypeImage %49 2D 2 0 0 2 R32ui + %118 = OpTypePointer UniformConstant %17 + %123 = OpTypeVector %49 2 + %132 = OpTypeVoid + %133 = OpTypeFunction %132 + %142 = OpTypePointer Image %49 + %18 = OpVariable %118 UniformConstant + %2 = OpFunction %132 None %133 + %153 = OpLabel + %495 = OpConvertFToU %123 %88 + %501 = OpImageTexelPointer %142 %18 %495 %66 + OpReturn + OpFunctionEnd + )"; + + const auto env = SPV_ENV_UNIVERSAL_1_3; + const auto consumer = nullptr; + const auto recipient_context = + BuildModule(env, consumer, recipient_shader, kFuzzAssembleOption); + ASSERT_TRUE(IsValid(env, recipient_context.get())); + + const auto donor_context = + BuildModule(env, consumer, donor_shader, kFuzzAssembleOption); + ASSERT_TRUE(IsValid(env, donor_context.get())); + + FactManager fact_manager; + spvtools::ValidatorOptions validator_options; + TransformationContext transformation_context(&fact_manager, + validator_options); + + PseudoRandomGenerator prng(0); + FuzzerContext fuzzer_context(&prng, 100); + protobufs::TransformationSequence transformation_sequence; + + FuzzerPassDonateModules fuzzer_pass(recipient_context.get(), + &transformation_context, &fuzzer_context, + &transformation_sequence, {}); + + fuzzer_pass.DonateSingleModule(donor_context.get(), true); + + // We just check that the result is valid. Checking to what it should be + // exactly equal to would be very fragile. + ASSERT_TRUE(IsValid(env, recipient_context.get())); +} + TEST(FuzzerPassDonateModulesTest, DonateComputeShaderWithRuntimeArray) { std::string recipient_shader = R"( OpCapability Shader