diff --git a/source/fuzz/fuzzer_pass_permute_function_variables.cpp b/source/fuzz/fuzzer_pass_permute_function_variables.cpp index af8311806..a4e19e3b1 100644 --- a/source/fuzz/fuzzer_pass_permute_function_variables.cpp +++ b/source/fuzz/fuzzer_pass_permute_function_variables.cpp @@ -31,10 +31,10 @@ FuzzerPassPermuteFunctionVariables::FuzzerPassPermuteFunctionVariables( 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 @@ void FuzzerPassPermuteFunctionVariables::Apply() { 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 @@ void FuzzerPassPermuteFunctionVariables::Apply() { } } 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 44cd5953f..aec32fe12 100644 --- a/source/fuzz/transformation_swap_function_variables.cpp +++ b/source/fuzz/transformation_swap_function_variables.cpp @@ -68,7 +68,13 @@ void TransformationSwapFunctionVariables::Apply( auto instruction2 = ir_context->get_def_use_mgr()->GetDef(message_.result_id2()); - std::swap(*instruction1, *instruction2); + std::unique_ptr temp_instruction = + MakeUnique(); + + 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 a03649683..8132aa4b0 100644 --- a/test/fuzz/transformation_swap_function_variables_test.cpp +++ b/test/fuzz/transformation_swap_function_variables_test.cpp @@ -175,6 +175,7 @@ TEST(TransformationSwapFunctionVariables, IsApplicable) { 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 @@ TEST(TransformationSwapFunctionVariables, IsApplicable) { // 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