abifuzzer.go 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. // Copyright 2020 The go-ethereum Authors
  2. // This file is part of the go-ethereum library.
  3. //
  4. // The go-ethereum library is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU Lesser General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // The go-ethereum library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU Lesser General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Lesser General Public License
  15. // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
  16. package abi
  17. import (
  18. "bytes"
  19. "fmt"
  20. "math/rand"
  21. "reflect"
  22. "strings"
  23. "github.com/ethereum/go-ethereum/accounts/abi"
  24. "github.com/ethereum/go-ethereum/crypto"
  25. fuzz "github.com/google/gofuzz"
  26. )
  27. func unpackPack(abi abi.ABI, method string, inputType []interface{}, input []byte) bool {
  28. outptr := reflect.New(reflect.TypeOf(inputType))
  29. if err := abi.UnpackIntoInterface(outptr.Interface(), method, input); err == nil {
  30. output, err := abi.Pack(method, input)
  31. if err != nil {
  32. // We have some false positives as we can unpack these type successfully, but not pack them
  33. if err.Error() == "abi: cannot use []uint8 as type [0]int8 as argument" ||
  34. err.Error() == "abi: cannot use uint8 as type int8 as argument" {
  35. return false
  36. }
  37. panic(err)
  38. }
  39. if !bytes.Equal(input, output[4:]) {
  40. panic(fmt.Sprintf("unpackPack is not equal, \ninput : %x\noutput: %x", input, output[4:]))
  41. }
  42. return true
  43. }
  44. return false
  45. }
  46. func packUnpack(abi abi.ABI, method string, input []interface{}) bool {
  47. if packed, err := abi.Pack(method, input); err == nil {
  48. outptr := reflect.New(reflect.TypeOf(input))
  49. err := abi.UnpackIntoInterface(outptr.Interface(), method, packed)
  50. if err != nil {
  51. panic(err)
  52. }
  53. out := outptr.Elem().Interface()
  54. if !reflect.DeepEqual(input, out) {
  55. panic(fmt.Sprintf("unpackPack is not equal, \ninput : %x\noutput: %x", input, out))
  56. }
  57. return true
  58. }
  59. return false
  60. }
  61. type args struct {
  62. name string
  63. typ string
  64. }
  65. func createABI(name string, stateMutability, payable *string, inputs []args) (abi.ABI, error) {
  66. sig := fmt.Sprintf(`[{ "type" : "function", "name" : "%v" `, name)
  67. if stateMutability != nil {
  68. sig += fmt.Sprintf(`, "stateMutability": "%v" `, *stateMutability)
  69. }
  70. if payable != nil {
  71. sig += fmt.Sprintf(`, "payable": %v `, *payable)
  72. }
  73. if len(inputs) > 0 {
  74. sig += `, "inputs" : [ {`
  75. for i, inp := range inputs {
  76. sig += fmt.Sprintf(`"name" : "%v", "type" : "%v" `, inp.name, inp.typ)
  77. if i+1 < len(inputs) {
  78. sig += ","
  79. }
  80. }
  81. sig += "} ]"
  82. sig += `, "outputs" : [ {`
  83. for i, inp := range inputs {
  84. sig += fmt.Sprintf(`"name" : "%v", "type" : "%v" `, inp.name, inp.typ)
  85. if i+1 < len(inputs) {
  86. sig += ","
  87. }
  88. }
  89. sig += "} ]"
  90. }
  91. sig += `}]`
  92. return abi.JSON(strings.NewReader(sig))
  93. }
  94. func fillStruct(structs []interface{}, data []byte) {
  95. if structs != nil && len(data) != 0 {
  96. fuzz.NewFromGoFuzz(data).Fuzz(&structs)
  97. }
  98. }
  99. func createStructs(args []args) []interface{} {
  100. structs := make([]interface{}, len(args))
  101. for i, arg := range args {
  102. t, err := abi.NewType(arg.typ, "", nil)
  103. if err != nil {
  104. panic(err)
  105. }
  106. structs[i] = reflect.New(t.GetType()).Elem()
  107. }
  108. return structs
  109. }
  110. func runFuzzer(input []byte) int {
  111. good := false
  112. names := []string{"_name", "name", "NAME", "name_", "__", "_name_", "n"}
  113. stateMut := []string{"", "pure", "view", "payable"}
  114. stateMutabilites := []*string{nil, &stateMut[0], &stateMut[1], &stateMut[2], &stateMut[3]}
  115. pays := []string{"true", "false"}
  116. payables := []*string{nil, &pays[0], &pays[1]}
  117. varNames := []string{"a", "b", "c", "d", "e", "f", "g"}
  118. varNames = append(varNames, names...)
  119. varTypes := []string{"bool", "address", "bytes", "string",
  120. "uint8", "int8", "uint8", "int8", "uint16", "int16",
  121. "uint24", "int24", "uint32", "int32", "uint40", "int40", "uint48", "int48", "uint56", "int56",
  122. "uint64", "int64", "uint72", "int72", "uint80", "int80", "uint88", "int88", "uint96", "int96",
  123. "uint104", "int104", "uint112", "int112", "uint120", "int120", "uint128", "int128", "uint136", "int136",
  124. "uint144", "int144", "uint152", "int152", "uint160", "int160", "uint168", "int168", "uint176", "int176",
  125. "uint184", "int184", "uint192", "int192", "uint200", "int200", "uint208", "int208", "uint216", "int216",
  126. "uint224", "int224", "uint232", "int232", "uint240", "int240", "uint248", "int248", "uint256", "int256",
  127. "bytes1", "bytes2", "bytes3", "bytes4", "bytes5", "bytes6", "bytes7", "bytes8", "bytes9", "bytes10", "bytes11",
  128. "bytes12", "bytes13", "bytes14", "bytes15", "bytes16", "bytes17", "bytes18", "bytes19", "bytes20", "bytes21",
  129. "bytes22", "bytes23", "bytes24", "bytes25", "bytes26", "bytes27", "bytes28", "bytes29", "bytes30", "bytes31",
  130. "bytes32", "bytes"}
  131. rnd := rand.New(rand.NewSource(123456))
  132. if len(input) > 0 {
  133. kec := crypto.Keccak256(input)
  134. rnd = rand.New(rand.NewSource(int64(kec[0])))
  135. }
  136. name := names[rnd.Intn(len(names))]
  137. stateM := stateMutabilites[rnd.Intn(len(stateMutabilites))]
  138. payable := payables[rnd.Intn(len(payables))]
  139. maxLen := 5
  140. for k := 1; k < maxLen; k++ {
  141. var arg []args
  142. for i := k; i > 0; i-- {
  143. argName := varNames[i]
  144. argTyp := varTypes[rnd.Int31n(int32(len(varTypes)))]
  145. if rnd.Int31n(10) == 0 {
  146. argTyp += "[]"
  147. } else if rnd.Int31n(10) == 0 {
  148. arrayArgs := rnd.Int31n(30) + 1
  149. argTyp += fmt.Sprintf("[%d]", arrayArgs)
  150. }
  151. arg = append(arg, args{
  152. name: argName,
  153. typ: argTyp,
  154. })
  155. }
  156. abi, err := createABI(name, stateM, payable, arg)
  157. if err != nil {
  158. continue
  159. }
  160. structs := createStructs(arg)
  161. b := unpackPack(abi, name, structs, input)
  162. fillStruct(structs, input)
  163. c := packUnpack(abi, name, structs)
  164. good = good || b || c
  165. }
  166. if good {
  167. return 1
  168. }
  169. return 0
  170. }
  171. func Fuzz(input []byte) int {
  172. return runFuzzer(input)
  173. }