mirror of
https://github.com/tendermint/tendermint.git
synced 2026-02-09 13:30:11 +00:00
This change does two things: 1. It fixes the json fuzzer to account for receiving array results. Arrays are returned by the rpc server when the input data is an array. 2. Adds a `fuzz_test.go` file and corresponding `testdata` directory containing the failing test case. This seems like a reasonable way to add and track previous crash issues in our fuzz test cases. The upcoming stdlib go fuzz tool does effectively this automatically.
65 lines
1.4 KiB
Go
65 lines
1.4 KiB
Go
package server
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"io/ioutil"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
|
|
"github.com/tendermint/tendermint/libs/log"
|
|
rs "github.com/tendermint/tendermint/rpc/jsonrpc/server"
|
|
types "github.com/tendermint/tendermint/rpc/jsonrpc/types"
|
|
)
|
|
|
|
var rpcFuncMap = map[string]*rs.RPCFunc{
|
|
"c": rs.NewRPCFunc(func(s string, i int) (string, int) { return "foo", 200 }, "s,i", false),
|
|
}
|
|
var mux *http.ServeMux
|
|
|
|
func init() {
|
|
mux = http.NewServeMux()
|
|
lgr := log.MustNewDefaultLogger(log.LogFormatPlain, log.LogLevelInfo, false)
|
|
rs.RegisterRPCFuncs(mux, rpcFuncMap, lgr)
|
|
}
|
|
|
|
func Fuzz(data []byte) int {
|
|
if len(data) == 0 {
|
|
return -1
|
|
}
|
|
|
|
req, _ := http.NewRequest("POST", "http://localhost/", bytes.NewReader(data))
|
|
rec := httptest.NewRecorder()
|
|
mux.ServeHTTP(rec, req)
|
|
res := rec.Result()
|
|
blob, err := ioutil.ReadAll(res.Body)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
if err := res.Body.Close(); err != nil {
|
|
panic(err)
|
|
}
|
|
if len(blob) == 0 {
|
|
return 1
|
|
}
|
|
|
|
if inputJSONIsMultiElementSlice(data) {
|
|
recv := []types.RPCResponse{}
|
|
if err := json.Unmarshal(blob, &recv); err != nil {
|
|
panic(err)
|
|
}
|
|
return 1
|
|
}
|
|
recv := &types.RPCResponse{}
|
|
if err := json.Unmarshal(blob, recv); err != nil {
|
|
panic(err)
|
|
}
|
|
return 1
|
|
}
|
|
|
|
func inputJSONIsMultiElementSlice(input []byte) bool {
|
|
slice := []interface{}{}
|
|
err := json.Unmarshal(input, &slice)
|
|
return err == nil && len(slice) > 1
|
|
}
|