spirv-fuzz: Enhancing permute function variables and its testing (#4295)
Fixes the way instruction swapping is implemented.
Fixes #4257.
Fixes #4259.
diff --git a/source/fuzz/fuzzer_pass_permute_function_variables.cpp b/source/fuzz/fuzzer_pass_permute_function_variables.cpp
index af83118..a4e19e3 100644
--- a/source/fuzz/fuzzer_pass_permute_function_variables.cpp
+++ b/source/fuzz/fuzzer_pass_permute_function_variables.cpp
@@ -31,10 +31,10 @@
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations)
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
- transformations) {} // Here we call parent constructor
+ transformations) {} // Here we call parent constructor.
void FuzzerPassPermuteFunctionVariables::Apply() {
- // Permuting OpVariable instructions in each function
+ // Permuting OpVariable instructions in each function.
for (auto& function : *GetIRContext()->module()) {
if (!GetFuzzerContext()->ChoosePercentage(
GetFuzzerContext()->GetChanceOfPermutingFunctionVariables())) {
@@ -49,7 +49,9 @@
variables.push_back(&instruction);
}
}
-
+ if (variables.size() <= 1) {
+ continue;
+ }
do {
uint32_t instruction_1_index = GetFuzzerContext()->RandomIndex(variables);
uint32_t instruction_2_index = GetFuzzerContext()->RandomIndex(variables);
@@ -61,8 +63,9 @@
}
} while (GetFuzzerContext()->ChoosePercentage(
- GetFuzzerContext()
- ->GetChanceOfSwappingAnotherPairOfFunctionVariables()));
+ GetFuzzerContext()
+ ->GetChanceOfSwappingAnotherPairOfFunctionVariables()) &&
+ variables.size() > 2);
}
}
diff --git a/source/fuzz/transformation_swap_function_variables.cpp b/source/fuzz/transformation_swap_function_variables.cpp
index 44cd595..aec32fe 100644
--- a/source/fuzz/transformation_swap_function_variables.cpp
+++ b/source/fuzz/transformation_swap_function_variables.cpp
@@ -68,7 +68,13 @@
auto instruction2 =
ir_context->get_def_use_mgr()->GetDef(message_.result_id2());
- std::swap(*instruction1, *instruction2);
+ std::unique_ptr<opt::Instruction> temp_instruction =
+ MakeUnique<opt::Instruction>();
+
+ temp_instruction->InsertBefore(instruction1);
+ instruction1->InsertAfter(instruction2);
+ instruction2->InsertAfter(temp_instruction.get());
+ temp_instruction->RemoveFromList();
}
protobufs::Transformation TransformationSwapFunctionVariables::ToMessage()
diff --git a/test/fuzz/transformation_swap_function_variables_test.cpp b/test/fuzz/transformation_swap_function_variables_test.cpp
index a036496..8132aa4 100644
--- a/test/fuzz/transformation_swap_function_variables_test.cpp
+++ b/test/fuzz/transformation_swap_function_variables_test.cpp
@@ -175,6 +175,7 @@
const auto env = SPV_ENV_UNIVERSAL_1_5;
const auto consumer = nullptr;
+ // Get Unique pointer of IRContext.
const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
spvtools::ValidatorOptions validator_options;
@@ -185,24 +186,40 @@
// Successful transformations
{
+ auto first_instruction = context->get_def_use_mgr()->GetDef(24);
+ auto second_instruction = context->get_def_use_mgr()->GetDef(28);
// Swap two OpVariable instructions in the same function.
TransformationSwapFunctionVariables transformation(24, 28);
+
ASSERT_TRUE(
transformation.IsApplicable(context.get(), transformation_context));
+
ApplyAndCheckFreshIds(transformation, context.get(),
&transformation_context);
+
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
context.get(), validator_options, kConsoleMessageConsumer));
+
+ ASSERT_EQ(first_instruction, context->get_def_use_mgr()->GetDef(24));
+ ASSERT_EQ(second_instruction, context->get_def_use_mgr()->GetDef(28));
}
{
+ auto first_instruction = context->get_def_use_mgr()->GetDef(38);
+ auto second_instruction = context->get_def_use_mgr()->GetDef(40);
// Swap two OpVariable instructions in the same function.
TransformationSwapFunctionVariables transformation(38, 40);
+
ASSERT_TRUE(
transformation.IsApplicable(context.get(), transformation_context));
+
ApplyAndCheckFreshIds(transformation, context.get(),
&transformation_context);
+
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
context.get(), validator_options, kConsoleMessageConsumer));
+
+ ASSERT_EQ(first_instruction, context->get_def_use_mgr()->GetDef(38));
+ ASSERT_EQ(second_instruction, context->get_def_use_mgr()->GetDef(40));
}
std::string after_transformation = R"(
OpCapability Shader