Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

shrinking experiment #268

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion fuzzing/fuzzer.go
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,7 @@ func defaultCallSequenceGeneratorConfigFunc(fuzzer *Fuzzer, valueSet *valuegener
func defaultShrinkingValueMutatorFunc(fuzzer *Fuzzer, valueSet *valuegeneration.ValueSet, randomProvider *rand.Rand) (valuegeneration.ValueMutator, error) {
// Create the shrinking value mutator for the worker.
shrinkingValueMutatorConfig := &valuegeneration.ShrinkingValueMutatorConfig{
ShrinkValueProbability: 0.1,
ShrinkValueProbability: 1,
}
shrinkingValueMutator := valuegeneration.NewShrinkingValueMutator(shrinkingValueMutatorConfig, valueSet, randomProvider)
return shrinkingValueMutator, nil
Expand Down
60 changes: 21 additions & 39 deletions fuzzing/fuzzer_worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,20 @@ 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:]...)
}

// 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 +412,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; i++ /* 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,55 +423,23 @@ 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 || len(possibleShrunkSequence) == 1 {
fw.shrinkParam(&possibleShrunkSequence)
} else {
fw.shorten(&possibleShrunkSequence)
}
// 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
} else {
// We didn't remove an item at this index, so we'll iterate to the next one.
i++
}
}

// 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.
Expand Down
11 changes: 9 additions & 2 deletions fuzzing/valuegeneration/mutator_shrinking.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package valuegeneration

import (
"github.com/crytic/medusa/utils"
"github.com/ethereum/go-ethereum/common"
"math/big"
"math/rand"

"github.com/crytic/medusa/utils"
"github.com/ethereum/go-ethereum/common"
)

// ShrinkingValueMutator represents a ValueMutator used to shrink function inputs and call arguments.
Expand Down Expand Up @@ -96,7 +97,9 @@ func (g *ShrinkingValueMutator) MutateBytes(b []byte) []byte {
randomGeneratorDecision := g.randomProvider.Float32()
if randomGeneratorDecision < g.config.ShrinkValueProbability {
// Mutate the data for our desired number of rounds

input := bytesShrinkingMethods[g.randomProvider.Intn(len(bytesShrinkingMethods))](g, b)

return input
}
return b
Expand Down Expand Up @@ -182,6 +185,10 @@ var stringShrinkingMethods = []func(*ShrinkingValueMutator, string) string{
i := g.randomProvider.Intn(len(s))
return s[:i] + s[i+1:]
},
// ???
func(g *ShrinkingValueMutator, s string) string {
return ""
},
}

// MutateString takes a string input and returns a mutated value based off the input.
Expand Down
Loading