diff --git a/fuzzing/fuzzer_worker_sequence_generator.go b/fuzzing/fuzzer_worker_sequence_generator.go index 666efb23..b54f528e 100644 --- a/fuzzing/fuzzer_worker_sequence_generator.go +++ b/fuzzing/fuzzer_worker_sequence_generator.go @@ -137,6 +137,13 @@ func NewCallSequenceGenerator(worker *FuzzerWorker, config *CallSequenceGenerato }, new(big.Int).SetUint64(config.RandomUnmodifiedCorpusTailWeight), ), + randomutils.NewWeightedRandomChoice( + CallSequenceGeneratorMutationStrategy{ + CallSequenceGeneratorFunc: callSeqGenFuncDuplicateAtRandom, + PrefetchModifyCallFunc: nil, + }, + new(big.Int).SetUint64(config.RandomUnmodifiedCorpusTailWeight), + ), randomutils.NewWeightedRandomChoice( CallSequenceGeneratorMutationStrategy{ CallSequenceGeneratorFunc: callSeqGenFuncSpliceAtRandom, @@ -380,6 +387,20 @@ func callSeqGenFuncCorpusTail(sequenceGenerator *CallSequenceGenerator, sequence return nil } +// callSeqGenFuncDuplicateAtRandom is a CallSequenceGeneratorFunc which prepares a CallSequenceGenerator to generate a sequence +// which duplicates a call sequence element at index N and inserts it at N+1 +// if random index is len(sequence)-1, it inserts the duplicated call sequence element at N-1 +func callSeqGenFuncDuplicateAtRandom(sequenceGenerator *CallSequenceGenerator, sequence calls.CallSequence) error { + randIndex := sequenceGenerator.worker.randomProvider.Intn(len(sequence)) + duplicatedElement := sequence[randIndex] + if randIndex == len(sequence)-1 { + sequence[randIndex-1] = duplicatedElement + } else { + sequence[randIndex+1] = duplicatedElement + } + return nil +} + // callSeqGenFuncSpliceAtRandom is a CallSequenceGeneratorFunc which prepares a CallSequenceGenerator to generate a // sequence which is based off of two corpus call sequence entries, from which a random length head and tail are // respectively sliced and joined together.