spirv-fuzz: Fix off-by-one error in replayer (#3982)
Fixes #3981.
diff --git a/source/fuzz/replayer.cpp b/source/fuzz/replayer.cpp
index 81d36b8..5b3468e 100644
--- a/source/fuzz/replayer.cpp
+++ b/source/fuzz/replayer.cpp
@@ -100,7 +100,7 @@
if (!fresh_ids.empty()) {
first_overflow_id =
std::max(first_overflow_id,
- *std::max_element(fresh_ids.begin(), fresh_ids.end()));
+ *std::max_element(fresh_ids.begin(), fresh_ids.end()) + 1);
}
}
diff --git a/test/fuzz/replayer_test.cpp b/test/fuzz/replayer_test.cpp
index 7fa4928..151f263 100644
--- a/test/fuzz/replayer_test.cpp
+++ b/test/fuzz/replayer_test.cpp
@@ -22,6 +22,7 @@
#include "source/fuzz/transformation_add_global_variable.h"
#include "source/fuzz/transformation_add_parameter.h"
#include "source/fuzz/transformation_add_synonym.h"
+#include "source/fuzz/transformation_flatten_conditional_branch.h"
#include "source/fuzz/transformation_split_block.h"
#include "test/fuzz/fuzz_test_util.h"
@@ -406,6 +407,69 @@
MakeDataDescriptor(11, {}), MakeDataDescriptor(104, {})));
}
+TEST(ReplayerTest, ReplayWithOverflowIds) {
+ const std::string kTestShader = 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 = OpTypeInt 32 1
+ %7 = OpTypePointer Function %6
+ %50 = OpTypePointer Private %6
+ %9 = OpConstant %6 2
+ %11 = OpConstant %6 0
+ %12 = OpTypeBool
+ %17 = OpConstant %6 1
+ %4 = OpFunction %2 None %3
+ %5 = OpLabel
+ %8 = OpVariable %7 Function
+ OpStore %8 %9
+ %10 = OpLoad %6 %8
+ %13 = OpSGreaterThan %12 %10 %11
+ OpSelectionMerge %15 None
+ OpBranchConditional %13 %14 %15
+ %14 = OpLabel
+ %16 = OpLoad %6 %8
+ %18 = OpIAdd %6 %16 %17
+ OpStore %8 %18
+ OpBranch %15
+ %15 = OpLabel
+ OpReturn
+ OpFunctionEnd
+ )";
+
+ const auto env = SPV_ENV_UNIVERSAL_1_3;
+ spvtools::ValidatorOptions validator_options;
+
+ std::vector<uint32_t> binary_in;
+ SpirvTools t(env);
+ t.SetMessageConsumer(kConsoleMessageConsumer);
+ ASSERT_TRUE(t.Assemble(kTestShader, &binary_in, kFuzzAssembleOption));
+ ASSERT_TRUE(t.Validate(binary_in));
+
+ protobufs::TransformationSequence transformations;
+ *transformations.add_transformation() =
+ TransformationFlattenConditionalBranch(5, true, 0, 0, 0, {}).ToMessage();
+ *transformations.add_transformation() =
+ TransformationAddGlobalVariable(101, 50, SpvStorageClassPrivate, 11, true)
+ .ToMessage();
+
+ protobufs::FactSequence empty_facts;
+ auto replayer_result =
+ Replayer(env, kConsoleMessageConsumer, binary_in, empty_facts,
+ transformations, transformations.transformation_size(), true,
+ validator_options)
+ .Run();
+ // Replay should succeed.
+ ASSERT_EQ(Replayer::ReplayerResultStatus::kComplete, replayer_result.status);
+ // All transformations should be applied.
+ ASSERT_EQ(2, replayer_result.applied_transformations.transformation_size());
+}
+
} // namespace
} // namespace fuzz
} // namespace spvtools