spirv-fuzz: Support dead blocks in TransformationAddSynonym (#3832)
Fixes #3830.
diff --git a/source/fuzz/fuzzer_pass_add_synonyms.cpp b/source/fuzz/fuzzer_pass_add_synonyms.cpp
index f109174..2fa0700 100644
--- a/source/fuzz/fuzzer_pass_add_synonyms.cpp
+++ b/source/fuzz/fuzzer_pass_add_synonyms.cpp
@@ -36,6 +36,12 @@
[this](opt::Function* function, opt::BasicBlock* block,
opt::BasicBlock::iterator inst_it,
const protobufs::InstructionDescriptor& instruction_descriptor) {
+ if (GetTransformationContext()->GetFactManager()->BlockIsDead(
+ block->id())) {
+ // Don't create synonyms in dead blocks.
+ return;
+ }
+
// Skip |inst_it| if we can't insert anything above it. OpIAdd is just
// a representative of some instruction that might be produced by the
// transformation.
diff --git a/source/fuzz/fuzzer_pass_copy_objects.cpp b/source/fuzz/fuzzer_pass_copy_objects.cpp
index 4cc4044..9f7bbd6 100644
--- a/source/fuzz/fuzzer_pass_copy_objects.cpp
+++ b/source/fuzz/fuzzer_pass_copy_objects.cpp
@@ -41,6 +41,12 @@
"The opcode of the instruction we might insert before must be "
"the same as the opcode in the descriptor for the instruction");
+ if (GetTransformationContext()->GetFactManager()->BlockIsDead(
+ block->id())) {
+ // Don't create synonyms in dead blocks.
+ return;
+ }
+
// Check whether it is legitimate to insert a copy before this
// instruction.
if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpCopyObject,
diff --git a/source/fuzz/transformation_add_synonym.cpp b/source/fuzz/transformation_add_synonym.cpp
index fb657d7..bd9df13 100644
--- a/source/fuzz/transformation_add_synonym.cpp
+++ b/source/fuzz/transformation_add_synonym.cpp
@@ -68,6 +68,17 @@
return false;
}
+ const auto* insert_before_inst_block =
+ ir_context->get_instr_block(insert_before_inst);
+ assert(insert_before_inst_block &&
+ "|insert_before_inst| must be in some block");
+
+ if (transformation_context.GetFactManager()->BlockIsDead(
+ insert_before_inst_block->id())) {
+ // We don't create synonyms in dead blocks.
+ return false;
+ }
+
// Check that we can insert |message._synonymous_instruction| before
// |message_.insert_before| instruction. We use OpIAdd to represent some
// instruction that can produce a synonym.
diff --git a/test/fuzz/transformation_add_synonym_test.cpp b/test/fuzz/transformation_add_synonym_test.cpp
index aef088d..603a3db 100644
--- a/test/fuzz/transformation_add_synonym_test.cpp
+++ b/test/fuzz/transformation_add_synonym_test.cpp
@@ -1334,7 +1334,7 @@
transformation_context.GetFactManager()->PointeeValueIsIrrelevant(101));
}
-TEST(TransformationAddSynonym, DoNotCopyOpSampledImage) {
+TEST(TransformationAddSynonymTest, DoNotCopyOpSampledImage) {
// This checks that we do not try to copy the result id of an OpSampledImage
// instruction.
std::string shader = R"(
@@ -1392,7 +1392,7 @@
.IsApplicable(context.get(), transformation_context));
}
-TEST(TransformationAddSynonym, DoNotCopyVoidRunctionResult) {
+TEST(TransformationAddSynonymTest, DoNotCopyVoidRunctionResult) {
// This checks that we do not try to copy the result of a void function.
std::string shader = R"(
OpCapability Shader
@@ -1431,6 +1431,57 @@
.IsApplicable(context.get(), transformation_context));
}
+TEST(TransformationAddSynonymTest, HandlesDeadBlocks) {
+ std::string shader = R"(
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %4 "main"
+ OpExecutionMode %4 OriginUpperLeft
+ OpSource ESSL 320
+ %2 = OpTypeVoid
+ %3 = OpTypeFunction %2
+ %6 = OpTypeBool
+ %7 = OpConstantTrue %6
+ %11 = OpTypePointer Function %6
+ %4 = OpFunction %2 None %3
+ %5 = OpLabel
+ %12 = OpVariable %11 Function
+ OpSelectionMerge %10 None
+ OpBranchConditional %7 %8 %9
+ %8 = OpLabel
+ OpBranch %10
+ %9 = OpLabel
+ OpBranch %10
+ %10 = OpLabel
+ OpReturn
+ OpFunctionEnd
+ )";
+
+ const auto env = SPV_ENV_UNIVERSAL_1_3;
+ const auto consumer = nullptr;
+ const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
+
+ FactManager fact_manager(context.get());
+ spvtools::ValidatorOptions validator_options;
+ TransformationContext transformation_context(&fact_manager,
+ validator_options);
+
+ fact_manager.AddFactBlockIsDead(9);
+
+ auto insert_before = MakeInstructionDescriptor(9, SpvOpBranch, 0);
+
+ ASSERT_FALSE(TransformationAddSynonym(
+ 7, protobufs::TransformationAddSynonym::COPY_OBJECT, 100,
+ insert_before)
+ .IsApplicable(context.get(), transformation_context));
+
+ ASSERT_FALSE(TransformationAddSynonym(
+ 12, protobufs::TransformationAddSynonym::COPY_OBJECT, 100,
+ insert_before)
+ .IsApplicable(context.get(), transformation_context));
+}
+
} // namespace
} // namespace fuzz
} // namespace spvtools