Skip to content

Commit

Permalink
mirror echidna's shrinking
Browse files Browse the repository at this point in the history
  • Loading branch information
0xalpharush committed Dec 13, 2023
1 parent e471c52 commit 14c56bd
Showing 1 changed file with 20 additions and 36 deletions.
56 changes: 20 additions & 36 deletions fuzzing/fuzzer_worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,19 @@ func (fw *FuzzerWorker) testShrunkenCallSequence(possibleShrunkSequence calls.Ca
return validShrunkSequence, nil
}

func (fw *FuzzerWorker) shrinkParam(callSequence calls.CallSequence) {
i := fw.randomProvider.Intn(len(callSequence))
abiValuesMsgData := callSequence[i].Call.DataAbiValues
for j := 0; j < len(abiValuesMsgData.InputValues); j++ {
mutatedInput, _ := valuegeneration.MutateAbiValue(fw.sequenceGenerator.config.ValueGenerator, fw.shrinkingValueMutator, &abiValuesMsgData.Method.Inputs[j].Type, abiValuesMsgData.InputValues[j])
abiValuesMsgData.InputValues[j] = mutatedInput
}
}
func (fw *FuzzerWorker) shorten(callSequence calls.CallSequence) {
i := fw.randomProvider.Intn(len(callSequence))
callSequence = append(callSequence[:i], callSequence[i+1:]...)

Check failure on line 401 in fuzzing/fuzzer_worker.go

View workflow job for this annotation

GitHub Actions / lint

SA4006: this value of `callSequence` is never used (staticcheck)
}

// shrinkCallSequence takes a provided call sequence and attempts to shrink it by looking for redundant
// calls which can be removed, and values which can be minimized, while continuing to satisfy the provided shrink
// verifier.
Expand All @@ -398,7 +411,7 @@ func (fw *FuzzerWorker) shrinkCallSequence(callSequence calls.CallSequence, shri
optimizedSequence := callSequence

// First try to remove any calls we can. We go from start to end to avoid index shifting.
for i := 0; i < len(optimizedSequence); {
for i := 0; i < 5000; /* TODO add shrink limit config */ {
// If our fuzzer context is done, exit out immediately without results.
if utils.CheckContextDone(fw.fuzzer.ctx) {
return nil, nil
Expand All @@ -409,8 +422,13 @@ func (fw *FuzzerWorker) shrinkCallSequence(callSequence calls.CallSequence, shri
if err != nil {
return nil, err
}
possibleShrunkSequence = append(possibleShrunkSequence[:i], possibleShrunkSequence[i+1:]...)

coinToss := fw.randomProvider.Int() % 2
if coinToss == 0 {
fw.shrinkParam(possibleShrunkSequence)
} else {
fw.shorten(possibleShrunkSequence)
}
// Test the shrunken sequence.
validShrunkSequence, err := fw.testShrunkenCallSequence(possibleShrunkSequence, shrinkRequest)
if err != nil {
Expand All @@ -426,40 +444,6 @@ func (fw *FuzzerWorker) shrinkCallSequence(callSequence calls.CallSequence, shri
}
}

// Next try to shrink our values of every transaction a given number of rounds.
for i := 0; i < len(optimizedSequence); i++ {
for optimizationRound := 0; optimizationRound < 200; optimizationRound++ {
// If our fuzzer context is done, exit out immediately without results.
if utils.CheckContextDone(fw.fuzzer.ctx) {
return nil, nil
}

// Clone the optimized sequence.
possibleShrunkSequence, _ := optimizedSequence.Clone()

// Loop for each argument in the currently indexed call to mutate it.
abiValuesMsgData := possibleShrunkSequence[i].Call.DataAbiValues
for j := 0; j < len(abiValuesMsgData.InputValues); j++ {
mutatedInput, err := valuegeneration.MutateAbiValue(fw.sequenceGenerator.config.ValueGenerator, fw.shrinkingValueMutator, &abiValuesMsgData.Method.Inputs[j].Type, abiValuesMsgData.InputValues[j])
if err != nil {
return nil, fmt.Errorf("error when shrinking call sequence input argument: %v", err)
}
abiValuesMsgData.InputValues[j] = mutatedInput
}

// Test the shrunken sequence.
validShrunkSequence, err := fw.testShrunkenCallSequence(possibleShrunkSequence, shrinkRequest)
if err != nil {
return nil, err
}

// If this current sequence satisfied our conditions, set it as our optimized sequence.
if validShrunkSequence {
optimizedSequence = possibleShrunkSequence
}
}
}

// If the shrink request wanted the sequence recorded in the corpus, do so now.
if shrinkRequest.RecordResultInCorpus {
err := fw.fuzzer.corpus.AddTestResultCallSequence(optimizedSequence, fw.getNewCorpusCallSequenceWeight(), true)
Expand Down

0 comments on commit 14c56bd

Please sign in to comment.