88 "github.com/crytic/medusa/fuzzing/calls"
99 "github.com/crytic/medusa/fuzzing/contracts"
1010 "github.com/crytic/medusa/fuzzing/valuegeneration"
11+ "github.com/crytic/medusa/utils"
1112 "github.com/crytic/medusa/utils/randomutils"
1213)
1314
@@ -98,7 +99,7 @@ type CallSequenceGeneratorConfig struct {
9899// CallSequenceGeneratorFunc defines a method used to populate a provided call sequence with generated calls.
99100// Returns an optional PrefetchModifyCallFunc to be executed prior to the fetching of each element, or an error if
100101// one occurs.
101- type CallSequenceGeneratorFunc func (sequenceGenerator * CallSequenceGenerator , sequence calls.CallSequence ) error
102+ type CallSequenceGeneratorFunc func (provider * rand. Rand , sequenceGenerator func () (calls. CallSequence , error ) , sequence calls.CallSequence ) error
102103
103104// PrefetchModifyCallFunc defines a method used to modify a call sequence element before being fetched from this
104105// provider for use.
@@ -241,7 +242,7 @@ func (g *CallSequenceGenerator) InitializeNextSequence() (bool, error) {
241242 // If we have a corpus mutation method, call it to generate our base sequence, then set the pre-fetch modify
242243 // call function.
243244 if corpusMutationFunc != nil && corpusMutationFunc .CallSequenceGeneratorFunc != nil {
244- err = corpusMutationFunc .CallSequenceGeneratorFunc (g , g .baseSequence )
245+ err = corpusMutationFunc .CallSequenceGeneratorFunc (g . worker . randomProvider , g . worker . fuzzer . corpus . RandomMutationTargetSequence , g .baseSequence )
245246 if err != nil {
246247 return true , fmt .Errorf ("could not generate a corpus mutation derived call sequence due to an error executing a mutation method: %v" , err )
247248 }
@@ -364,18 +365,42 @@ func (g *CallSequenceGenerator) generateNewElement() (*calls.CallSequenceElement
364365 return calls .NewCallSequenceElement (selectedMethod .Contract , msg , blockNumberDelay , blockTimestampDelay ), nil
365366}
366367
367- func callSeqSwapRandomElement (sequenceGenerator * CallSequenceGenerator , sequence calls.CallSequence ) error {
368+ // prefetchModifyCallFuncMutate is a PrefetchModifyCallFunc, called by a CallSequenceGenerator to apply mutations
369+ // to a call sequence element, prior to it being fetched.
370+ // Returns an error if one occurs.
371+ func prefetchModifyCallFuncMutate (sequenceGenerator * CallSequenceGenerator , element * calls.CallSequenceElement ) error {
372+ // If this element has no ABI value based call data, exit early.
373+ if element .Call == nil || element .Call .DataAbiValues == nil {
374+ return nil
375+ }
376+
377+ // Loop for each input value and mutate it
378+ abiValuesMsgData := element .Call .DataAbiValues
379+ for i := 0 ; i < len (abiValuesMsgData .InputValues ); i ++ {
380+ mutatedInput , err := valuegeneration .MutateAbiValue (sequenceGenerator .config .ValueGenerator , sequenceGenerator .config .ValueMutator , & abiValuesMsgData .Method .Inputs [i ].Type , abiValuesMsgData .InputValues [i ])
381+ if err != nil {
382+ return fmt .Errorf ("error when mutating call sequence input argument: %v" , err )
383+ }
384+ abiValuesMsgData .InputValues [i ] = mutatedInput
385+ }
386+ // Re-encode the message's calldata
387+ element .Call .WithDataAbiValues (abiValuesMsgData )
388+
389+ return nil
390+ }
391+
392+ func callSeqSwapRandomElement (provider * rand.Rand , sequenceGenerator func () (calls.CallSequence , error ), sequence calls.CallSequence ) error {
368393 // Swap the element
369- swappedSequence := swapRandList (sequence )
394+ swappedSequence := swapRandList (provider , sequence )
370395
371396 copy (sequence , swappedSequence )
372397
373398 return nil
374399}
375400
376- func callSeqDeleteRandomElement (sequenceGenerator * CallSequenceGenerator , sequence calls.CallSequence ) error {
401+ func callSeqDeleteRandomElement (provider * rand. Rand , sequenceGenerator func () (calls. CallSequence , error ) , sequence calls.CallSequence ) error {
377402 // Delete the element
378- deletedSequence := deleteRandList (sequence )
403+ deletedSequence := deleteRandList (provider , sequence )
379404
380405 copy (sequence , deletedSequence )
381406
@@ -385,15 +410,16 @@ func callSeqDeleteRandomElement(sequenceGenerator *CallSequenceGenerator, sequen
385410// callSeqGenFuncCorpusHead is a CallSequenceGeneratorFunc which prepares a CallSequenceGenerator to generate a sequence
386411// whose head is based off of an existing corpus call sequence.
387412// Returns an error if one occurs.
388- func callSeqGenFuncCorpusHead (sequenceGenerator * CallSequenceGenerator , sequence calls.CallSequence ) error {
413+ func callSeqGenFuncCorpusHead (provider * rand. Rand , sequenceGenerator func () (calls. CallSequence , error ) , sequence calls.CallSequence ) error {
389414 // Obtain a call sequence from the corpus
390- corpusSequence , err := sequenceGenerator . worker . fuzzer . corpus . RandomMutationTargetSequence ()
415+ corpusSequence , err := sequenceGenerator ()
391416 if err != nil {
392417 return fmt .Errorf ("could not obtain corpus call sequence for head mutation: %v" , err )
393418 }
394419
395- // Append the new calls to the end of the corpus sequence
396- spliced := append (corpusSequence , sequence ... )
420+ // Prepend the new calls to the end of the corpus sequence
421+ i := provider .Intn (len (corpusSequence )) + 1
422+ spliced := append (corpusSequence [:i ], sequence ... )
397423
398424 copy (sequence , spliced )
399425
@@ -403,15 +429,18 @@ func callSeqGenFuncCorpusHead(sequenceGenerator *CallSequenceGenerator, sequence
403429// callSeqGenFuncCorpusTail is a CallSequenceGeneratorFunc which prepares a CallSequenceGenerator to generate a sequence
404430// whose tail is based off of an existing corpus call sequence.
405431// Returns an error if one occurs.
406- func callSeqGenFuncCorpusTail (sequenceGenerator * CallSequenceGenerator , sequence calls.CallSequence ) error {
432+ func callSeqGenFuncCorpusTail (provider * rand. Rand , sequenceGenerator func () (calls. CallSequence , error ) , sequence calls.CallSequence ) error {
407433 // Obtain a call sequence from the corpus
408- corpusSequence , err := sequenceGenerator . worker . fuzzer . corpus . RandomMutationTargetSequence ()
434+ corpusSequence , err := sequenceGenerator ()
409435 if err != nil {
410436 return fmt .Errorf ("could not obtain corpus call sequence for tail mutation: %v" , err )
411437 }
412438
413- // Prepend the new calls to the start of the corpus sequence
414- spliced := append (sequence , corpusSequence ... )
439+ maxLength := utils .Min (len (sequence ), len (corpusSequence ))
440+ i := provider .Intn (maxLength ) + 1
441+ fmt .Println ("i: " , i )
442+ // Append the new calls to the end of the corpus sequence
443+ spliced := append (sequence [i :], corpusSequence ... )
415444
416445 copy (sequence , spliced )
417446
@@ -420,10 +449,10 @@ func callSeqGenFuncCorpusTail(sequenceGenerator *CallSequenceGenerator, sequence
420449
421450// callSeqGenFuncExpansion is a CallSequenceGeneratorFunc which prepares a CallSequenceGenerator to generate a
422451// sequence which is expanded up to 30 times by replicating an existing call sequence element at a random position.
423- func callSeqGenFuncExpansion (sequenceGenerator * CallSequenceGenerator , sequence calls.CallSequence ) error {
452+ func callSeqGenFuncExpansion (provider * rand. Rand , sequenceGenerator func () (calls. CallSequence , error ) , sequence calls.CallSequence ) error {
424453
425454 // Expand the sequence
426- expandedSequence := expandRandList (sequence )
455+ expandedSequence := expandRandList (provider , sequence )
427456
428457 copy (sequence , expandedSequence )
429458
@@ -434,19 +463,18 @@ func callSeqGenFuncExpansion(sequenceGenerator *CallSequenceGenerator, sequence
434463// sequence which is based off of two corpus call sequence entries, from which a random length head and tail are
435464// respectively sliced and joined together.
436465// Returns an error if one occurs.
437- func callSeqGenFuncSpliceAtRandom (sequenceGenerator * CallSequenceGenerator , sequence calls.CallSequence ) error {
466+ func callSeqGenFuncSpliceAtRandom (provider * rand. Rand , sequenceGenerator func () (calls. CallSequence , error ) , sequence calls.CallSequence ) error {
438467 // Obtain two corpus call sequence entries
439- headSequence , err := sequenceGenerator . worker . fuzzer . corpus . RandomMutationTargetSequence ()
468+ headSequence , err := sequenceGenerator ()
440469 if err != nil {
441- return fmt .Errorf ("could not obtain head corpus call sequence for splice-at-random corpus mutation: %v" , err )
442470 }
443- tailSequence , err := sequenceGenerator . worker . fuzzer . corpus . RandomMutationTargetSequence ()
471+ tailSequence , err := sequenceGenerator ()
444472 if err != nil {
445473 return fmt .Errorf ("could not obtain tail corpus call sequence for splice-at-random corpus mutation: %v" , err )
446474 }
447475
448476 // Splice the two sequences
449- splicedSequence := spliceAtRandom (headSequence , tailSequence )
477+ splicedSequence := spliceAtRandom (provider , headSequence , tailSequence )
450478
451479 copy (sequence , splicedSequence )
452480
@@ -457,99 +485,76 @@ func callSeqGenFuncSpliceAtRandom(sequenceGenerator *CallSequenceGenerator, sequ
457485// sequence which is based off of two corpus call sequence entries, from which a random number of transactions are
458486// taken and interleaved (each element of one sequence will be followed by an element of the other).
459487// Returns an error if one occurs.
460- func callSeqGenFuncInterleaveAtRandom (sequenceGenerator * CallSequenceGenerator , sequence calls.CallSequence ) error {
488+ func callSeqGenFuncInterleaveAtRandom (provider * rand. Rand , sequenceGenerator func () (calls. CallSequence , error ) , sequence calls.CallSequence ) error {
461489 // Obtain two corpus call sequence entries
462- firstSequence , err := sequenceGenerator . worker . fuzzer . corpus . RandomMutationTargetSequence ()
490+ firstSequence , err := sequenceGenerator ()
463491 if err != nil {
464492 return fmt .Errorf ("could not obtain first corpus call sequence for interleave-at-random corpus mutation: %v" , err )
465493 }
466- secondSequence , err := sequenceGenerator . worker . fuzzer . corpus . RandomMutationTargetSequence ()
494+ secondSequence , err := sequenceGenerator ()
467495 if err != nil {
468496 return fmt .Errorf ("could not obtain second corpus call sequence for interleave-at-random corpus mutation: %v" , err )
469497 }
470498
471499 // Interleave the two sequences
472- interleavedSequence := interleaveAtRandom (firstSequence , secondSequence )
500+ interleavedSequence := interleaveAtRandom (provider , firstSequence , secondSequence )
473501
474502 copy (sequence , interleavedSequence )
475503
476504 return nil
477505}
478506
479- // prefetchModifyCallFuncMutate is a PrefetchModifyCallFunc, called by a CallSequenceGenerator to apply mutations
480- // to a call sequence element, prior to it being fetched.
481- // Returns an error if one occurs.
482- func prefetchModifyCallFuncMutate (sequenceGenerator * CallSequenceGenerator , element * calls.CallSequenceElement ) error {
483- // If this element has no ABI value based call data, exit early.
484- if element .Call == nil || element .Call .DataAbiValues == nil {
485- return nil
486- }
487-
488- // Loop for each input value and mutate it
489- abiValuesMsgData := element .Call .DataAbiValues
490- for i := 0 ; i < len (abiValuesMsgData .InputValues ); i ++ {
491- mutatedInput , err := valuegeneration .MutateAbiValue (sequenceGenerator .config .ValueGenerator , sequenceGenerator .config .ValueMutator , & abiValuesMsgData .Method .Inputs [i ].Type , abiValuesMsgData .InputValues [i ])
492- if err != nil {
493- return fmt .Errorf ("error when mutating call sequence input argument: %v" , err )
494- }
495- abiValuesMsgData .InputValues [i ] = mutatedInput
496- }
497- // Re-encode the message's calldata
498- element .Call .WithDataAbiValues (abiValuesMsgData )
499-
500- return nil
501- }
502-
503507// expandAt expands the element at index k by t times.
504- func expandAt [T any ](xs []T , k int , t int ) []T {
508+ func expandAt [T any ](xs []* T , k int , t int ) []* T {
505509 if len (xs ) == 0 {
506510 return xs
507511 }
508512 return append (append (xs [:k ], repeat (xs [k ], t )... ), xs [k + 1 :]... )
509513}
510514
511515// repeat replicates an element t times.
512- func repeat [T any ](v T , t int ) []T {
513- res := make ([]T , t )
516+ func repeat [T any ](v * T , t int ) []* T {
517+ res := make ([]* T , t )
514518 for i := range res {
515519 res [i ] = v
516520 }
517521 return res
518522}
519523
520524// expandRandList expands a random element of the list by 1 to 32 times.
521- func expandRandList [T any ](xs []T ) []T {
525+ func expandRandList [T any ](provider * rand. Rand , xs []* T ) []* T {
522526 l := len (xs )
523527 if l == 0 || l >= 32 {
524528 return xs
525529 }
526- k := rand .Intn (l )
527- t := rand .Intn (min (32 , l )) + 1
530+ k := provider .Intn (l )
531+ t := provider .Intn (min (32 , l )) + 1
528532 return expandAt (xs , k , t )
529533}
530534
531535// deleteAt deletes the element at the given index.
532- func deleteAt [T any ](xs []T , n int ) []T {
533- return append (xs [:n ], xs [n + 1 :]... )
536+ func deleteAt [T any ](xs []* T , n int ) []* T {
537+ xs [n ] = nil
538+ return xs
534539}
535540
536541// deleteRandList deletes a random element from the list.
537- func deleteRandList [T any ](xs []T ) []T {
542+ func deleteRandList [T any ](provider * rand. Rand , xs []* T ) []* T {
538543 if len (xs ) == 0 {
539544 return xs
540545 }
541- k := rand .Intn (len (xs ))
546+ k := provider .Intn (len (xs ))
542547 return deleteAt (xs , k )
543548}
544549
545550// swapAt swaps two elements in the list.
546- func swapAt [T any ](xs []T , i , j int ) []T {
551+ func swapAt [T any ](xs []* T , i , j int ) []* T {
547552 xs [i ], xs [j ] = xs [j ], xs [i ]
548553 return xs
549554}
550555
551556// swapRandList swaps two random elements in the list.
552- func swapRandList [T any ](xs []T ) []T {
557+ func swapRandList [T any ](provider * rand. Rand , xs []* T ) []* T {
553558 if len (xs ) == 0 {
554559 return xs
555560 }
@@ -558,26 +563,26 @@ func swapRandList[T any](xs []T) []T {
558563}
559564
560565// spliceAtRandom splices two lists at random positions.
561- func spliceAtRandom [T any ](xs1 , xs2 []T ) []T {
566+ func spliceAtRandom [T any ](provider * rand. Rand , xs1 , xs2 []* T ) []* T {
562567 idx1 , idx2 := rand .Intn (len (xs1 )), rand .Intn (len (xs2 ))
563568 return append (xs1 [:idx1 ], xs2 [idx2 :]... )
564569}
565570
566571// interleaveAtRandom interleaves two lists at random positions.
567- func interleaveAtRandom [T any ](xs1 , xs2 []T ) []T {
572+ func interleaveAtRandom [T any ](provider * rand. Rand , xs1 , xs2 []* T ) []* T {
568573 idx1 , idx2 := rand .Intn (len (xs1 )), rand .Intn (len (xs2 ))
569574 return interleaveLL (xs1 [:idx1 ], xs2 [:idx2 ])
570575}
571576
572577// interleaveLL interleaves two lists.
573- func interleaveLL [T any ](a , b []T ) []T {
578+ func interleaveLL [T any ](a , b []* T ) []* T {
574579 if len (a ) == 0 {
575580 return b
576581 }
577582 if len (b ) == 0 {
578583 return a
579584 }
580- return append ([]T {a [0 ], b [0 ]}, interleaveLL (a [1 :], b [1 :])... )
585+ return append ([]* T {a [0 ], b [0 ]}, interleaveLL (a [1 :], b [1 :])... )
581586}
582587
583588// min returns the smaller of two integers.
0 commit comments