@@ -22,33 +22,31 @@ import (
2222 "strings"
2323 "testing"
2424
25- "github.com/ethereum/go-ethereum/accounts/abi"
2625 fuzz "github.com/google/gofuzz"
2726)
2827
2928// TestReplicate can be used to replicate crashers from the fuzzing tests.
3029// Just replace testString with the data in .quoted
3130func TestReplicate (t * testing.T ) {
32- testString := " \x20 \x20 \x20 \x20 \x20 \x20 \x20 \x20 \x80 \x00 \x00 \x00 \x20 \x20 \x20 \x20 \x00 "
33- data := []byte (testString )
34- fuzzAbi (data )
31+ //t.Skip("Test only useful for reproducing issues")
32+ fuzzAbi ( []byte (" \x20 \x20 \x20 \x20 \x20 \x20 \x20 \x20 \x80 \x00 \x00 \x00 \x20 \x20 \x20 \x20 \x00 " ) )
33+ // fuzzAbi([]byte("asdfasdfkadsf;lasdf;lasd;lfk") )
3534}
3635
37- func Fuzz (f * testing.F ) {
36+ // FuzzABI is the main entrypoint for fuzzing
37+ func FuzzABI (f * testing.F ) {
3838 f .Fuzz (func (t * testing.T , data []byte ) {
3939 fuzzAbi (data )
4040 })
4141}
4242
4343var (
44- names = []string {"_name" , "name" , "NAME" , "name_" , "__" , "_name_" , "n" }
45- stateMut = []string {"" , "pure" , "view" , "payable" }
46- stateMutabilites = []* string {& stateMut [0 ], & stateMut [1 ], & stateMut [2 ], & stateMut [3 ]}
47- pays = []string {"" , "true" , "false" }
48- payables = []* string {& pays [0 ], & pays [1 ]}
49- vNames = []string {"a" , "b" , "c" , "d" , "e" , "f" , "g" }
50- varNames = append (vNames , names ... )
51- varTypes = []string {"bool" , "address" , "bytes" , "string" ,
44+ names = []string {"_name" , "name" , "NAME" , "name_" , "__" , "_name_" , "n" }
45+ stateMut = []string {"pure" , "view" , "payable" }
46+ pays = []string {"true" , "false" }
47+ vNames = []string {"a" , "b" , "c" , "d" , "e" , "f" , "g" }
48+ varNames = append (vNames , names ... )
49+ varTypes = []string {"bool" , "address" , "bytes" , "string" ,
5250 "uint8" , "int8" , "uint8" , "int8" , "uint16" , "int16" ,
5351 "uint24" , "int24" , "uint32" , "int32" , "uint40" , "int40" , "uint48" , "int48" , "uint56" , "int56" ,
5452 "uint64" , "int64" , "uint72" , "int72" , "uint80" , "int80" , "uint88" , "int88" , "uint96" , "int96" ,
6260 "bytes32" , "bytes" }
6361)
6462
65- func unpackPack (abi abi. ABI , method string , input []byte ) ([]interface {}, bool ) {
63+ func unpackPack (abi ABI , method string , input []byte ) ([]interface {}, bool ) {
6664 if out , err := abi .Unpack (method , input ); err == nil {
6765 _ , err := abi .Pack (method , out ... )
6866 if err != nil {
@@ -78,7 +76,7 @@ func unpackPack(abi abi.ABI, method string, input []byte) ([]interface{}, bool)
7876 return nil , false
7977}
8078
81- func packUnpack (abi abi. ABI , method string , input * []interface {}) bool {
79+ func packUnpack (abi ABI , method string , input * []interface {}) bool {
8280 if packed , err := abi .Pack (method , input ); err == nil {
8381 outptr := reflect .New (reflect .TypeOf (input ))
8482 err := abi .UnpackIntoInterface (outptr .Interface (), method , packed )
@@ -94,12 +92,12 @@ func packUnpack(abi abi.ABI, method string, input *[]interface{}) bool {
9492 return false
9593}
9694
97- type args struct {
95+ type arg struct {
9896 name string
9997 typ string
10098}
10199
102- func createABI (name string , stateMutability , payable * string , inputs []args ) (abi. ABI , error ) {
100+ func createABI (name string , stateMutability , payable * string , inputs []arg ) (ABI , error ) {
103101 sig := fmt .Sprintf (`[{ "type" : "function", "name" : "%v" ` , name )
104102 if stateMutability != nil {
105103 sig += fmt .Sprintf (`, "stateMutability": "%v" ` , * stateMutability )
@@ -126,56 +124,55 @@ func createABI(name string, stateMutability, payable *string, inputs []args) (ab
126124 sig += "} ]"
127125 }
128126 sig += `}]`
129-
130- return abi . JSON (strings .NewReader (sig ))
127+ //fmt.Printf("sig: %s\n", sig)
128+ return JSON (strings .NewReader (sig ))
131129}
132130
133- func fuzzAbi (input []byte ) int {
134- good := false
135- fuzzer := fuzz .NewFromGoFuzz (input )
136-
137- name := names [getUInt (fuzzer )% len (names )]
138- stateM := stateMutabilites [getUInt (fuzzer )% len (stateMutabilites )]
139- payable := payables [getUInt (fuzzer )% len (payables )]
140- maxLen := 5
141- for k := 1 ; k < maxLen ; k ++ {
142- var arg []args
143- for i := k ; i > 0 ; i -- {
144- argName := varNames [i ]
145- argTyp := varTypes [getUInt (fuzzer )% len (varTypes )]
146- if getUInt (fuzzer )% 10 == 0 {
147- argTyp += "[]"
148- } else if getUInt (fuzzer )% 10 == 0 {
149- arrayArgs := getUInt (fuzzer )% 30 + 1
150- argTyp += fmt .Sprintf ("[%d]" , arrayArgs )
151- }
152- arg = append (arg , args {
153- name : argName ,
154- typ : argTyp ,
155- })
131+ func fuzzAbi (input []byte ) {
132+ var (
133+ fuzzer = fuzz .NewFromGoFuzz (input )
134+ name = oneOf (fuzzer , names )
135+ stateM = oneOfOrNil (fuzzer , stateMut )
136+ payable = oneOfOrNil (fuzzer , pays )
137+ arguments []arg
138+ )
139+ for i := 0 ; i < upTo (fuzzer , 10 ); i ++ {
140+ argName := oneOf (fuzzer , varNames )
141+ argTyp := oneOf (fuzzer , varTypes )
142+ switch upTo (fuzzer , 10 ) {
143+ case 0 : // 10% chance to make it a slice
144+ argTyp += "[]"
145+ case 1 : // 10% chance to make it an array
146+ argTyp += fmt .Sprintf ("[%d]" , 1 + upTo (fuzzer , 30 ))
147+ default :
156148 }
157- abi , err := createABI (name , stateM , payable , arg )
158- if err != nil {
159- continue
160- }
161- structs , b := unpackPack (abi , name , input )
162- c := packUnpack (abi , name , & structs )
163- good = good || b || c
149+ arguments = append (arguments , arg {name : argName , typ : argTyp })
164150 }
165- if good {
166- return 1
151+ abi , err := createABI (name , stateM , payable , arguments )
152+ if err != nil {
153+ //fmt.Printf("err: %v\n", err)
154+ panic (err )
167155 }
168- return 0
156+ structs , _ := unpackPack (abi , name , input )
157+ _ = packUnpack (abi , name , & structs )
169158}
170159
171- func getUInt (fuzzer * fuzz.Fuzzer ) int {
160+ func upTo (fuzzer * fuzz.Fuzzer , max int ) int {
172161 var i int
173162 fuzzer .Fuzz (& i )
174163 if i < 0 {
175- i = - i
176- if i < 0 {
177- return 0
178- }
164+ return (- 1 - i ) % max
165+ }
166+ return i % max
167+ }
168+
169+ func oneOf (fuzzer * fuzz.Fuzzer , options []string ) string {
170+ return options [upTo (fuzzer , len (options ))]
171+ }
172+
173+ func oneOfOrNil (fuzzer * fuzz.Fuzzer , options []string ) * string {
174+ if i := upTo (fuzzer , len (options )+ 1 ); i < len (options ) {
175+ return & options [i ]
179176 }
180- return i
177+ return nil
181178}
0 commit comments