abifuzzer.go 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  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. "fmt"
  19. "reflect"
  20. "strings"
  21. "github.com/ethereum/go-ethereum/accounts/abi"
  22. fuzz "github.com/google/gofuzz"
  23. )
  24. var (
  25. names = []string{"_name", "name", "NAME", "name_", "__", "_name_", "n"}
  26. stateMut = []string{"", "pure", "view", "payable"}
  27. stateMutabilites = []*string{&stateMut[0], &stateMut[1], &stateMut[2], &stateMut[3]}
  28. pays = []string{"", "true", "false"}
  29. payables = []*string{&pays[0], &pays[1]}
  30. vNames = []string{"a", "b", "c", "d", "e", "f", "g"}
  31. varNames = append(vNames, names...)
  32. varTypes = []string{"bool", "address", "bytes", "string",
  33. "uint8", "int8", "uint8", "int8", "uint16", "int16",
  34. "uint24", "int24", "uint32", "int32", "uint40", "int40", "uint48", "int48", "uint56", "int56",
  35. "uint64", "int64", "uint72", "int72", "uint80", "int80", "uint88", "int88", "uint96", "int96",
  36. "uint104", "int104", "uint112", "int112", "uint120", "int120", "uint128", "int128", "uint136", "int136",
  37. "uint144", "int144", "uint152", "int152", "uint160", "int160", "uint168", "int168", "uint176", "int176",
  38. "uint184", "int184", "uint192", "int192", "uint200", "int200", "uint208", "int208", "uint216", "int216",
  39. "uint224", "int224", "uint232", "int232", "uint240", "int240", "uint248", "int248", "uint256", "int256",
  40. "bytes1", "bytes2", "bytes3", "bytes4", "bytes5", "bytes6", "bytes7", "bytes8", "bytes9", "bytes10", "bytes11",
  41. "bytes12", "bytes13", "bytes14", "bytes15", "bytes16", "bytes17", "bytes18", "bytes19", "bytes20", "bytes21",
  42. "bytes22", "bytes23", "bytes24", "bytes25", "bytes26", "bytes27", "bytes28", "bytes29", "bytes30", "bytes31",
  43. "bytes32", "bytes"}
  44. )
  45. func unpackPack(abi abi.ABI, method string, input []byte) ([]interface{}, bool) {
  46. if out, err := abi.Unpack(method, input); err == nil {
  47. _, err := abi.Pack(method, out...)
  48. if err != nil {
  49. // We have some false positives as we can unpack these type successfully, but not pack them
  50. if err.Error() == "abi: cannot use []uint8 as type [0]int8 as argument" ||
  51. err.Error() == "abi: cannot use uint8 as type int8 as argument" {
  52. return out, false
  53. }
  54. panic(err)
  55. }
  56. return out, true
  57. }
  58. return nil, false
  59. }
  60. func packUnpack(abi abi.ABI, method string, input *[]interface{}) bool {
  61. if packed, err := abi.Pack(method, input); err == nil {
  62. outptr := reflect.New(reflect.TypeOf(input))
  63. err := abi.UnpackIntoInterface(outptr.Interface(), method, packed)
  64. if err != nil {
  65. panic(err)
  66. }
  67. out := outptr.Elem().Interface()
  68. if !reflect.DeepEqual(input, out) {
  69. panic(fmt.Sprintf("unpackPack is not equal, \ninput : %x\noutput: %x", input, out))
  70. }
  71. return true
  72. }
  73. return false
  74. }
  75. type args struct {
  76. name string
  77. typ string
  78. }
  79. func createABI(name string, stateMutability, payable *string, inputs []args) (abi.ABI, error) {
  80. sig := fmt.Sprintf(`[{ "type" : "function", "name" : "%v" `, name)
  81. if stateMutability != nil {
  82. sig += fmt.Sprintf(`, "stateMutability": "%v" `, *stateMutability)
  83. }
  84. if payable != nil {
  85. sig += fmt.Sprintf(`, "payable": %v `, *payable)
  86. }
  87. if len(inputs) > 0 {
  88. sig += `, "inputs" : [ {`
  89. for i, inp := range inputs {
  90. sig += fmt.Sprintf(`"name" : "%v", "type" : "%v" `, inp.name, inp.typ)
  91. if i+1 < len(inputs) {
  92. sig += ","
  93. }
  94. }
  95. sig += "} ]"
  96. sig += `, "outputs" : [ {`
  97. for i, inp := range inputs {
  98. sig += fmt.Sprintf(`"name" : "%v", "type" : "%v" `, inp.name, inp.typ)
  99. if i+1 < len(inputs) {
  100. sig += ","
  101. }
  102. }
  103. sig += "} ]"
  104. }
  105. sig += `}]`
  106. return abi.JSON(strings.NewReader(sig))
  107. }
  108. func runFuzzer(input []byte) int {
  109. good := false
  110. fuzzer := fuzz.NewFromGoFuzz(input)
  111. name := names[getUInt(fuzzer)%len(names)]
  112. stateM := stateMutabilites[getUInt(fuzzer)%len(stateMutabilites)]
  113. payable := payables[getUInt(fuzzer)%len(payables)]
  114. maxLen := 5
  115. for k := 1; k < maxLen; k++ {
  116. var arg []args
  117. for i := k; i > 0; i-- {
  118. argName := varNames[i]
  119. argTyp := varTypes[getUInt(fuzzer)%len(varTypes)]
  120. if getUInt(fuzzer)%10 == 0 {
  121. argTyp += "[]"
  122. } else if getUInt(fuzzer)%10 == 0 {
  123. arrayArgs := getUInt(fuzzer)%30 + 1
  124. argTyp += fmt.Sprintf("[%d]", arrayArgs)
  125. }
  126. arg = append(arg, args{
  127. name: argName,
  128. typ: argTyp,
  129. })
  130. }
  131. abi, err := createABI(name, stateM, payable, arg)
  132. if err != nil {
  133. continue
  134. }
  135. structs, b := unpackPack(abi, name, input)
  136. c := packUnpack(abi, name, &structs)
  137. good = good || b || c
  138. }
  139. if good {
  140. return 1
  141. }
  142. return 0
  143. }
  144. func Fuzz(input []byte) int {
  145. return runFuzzer(input)
  146. }
  147. func getUInt(fuzzer *fuzz.Fuzzer) int {
  148. var i int
  149. fuzzer.Fuzz(&i)
  150. if i < 0 {
  151. i = -i
  152. if i < 0 {
  153. return 0
  154. }
  155. }
  156. return i
  157. }