Browse Source

test/fuzz: add test to reproduce found fuzz errors (#6757)

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.
pull/6767/head
William Banfield 3 years ago
committed by GitHub
parent
commit
c5dc3b267f
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 54 additions and 4 deletions
  1. +33
    -0
      test/fuzz/rpc/jsonrpc/server/fuzz_test.go
  2. +19
    -4
      test/fuzz/rpc/jsonrpc/server/handler.go
  3. +1
    -0
      test/fuzz/rpc/jsonrpc/server/testdata/1184f5b8d4b6dd08709cf1513f26744167065e0d
  4. +1
    -0
      test/fuzz/rpc/jsonrpc/server/testdata/clusterfuzz-testcase-minimized-fuzz_rpc_jsonrpc_server-4738572803506176

+ 33
- 0
test/fuzz/rpc/jsonrpc/server/fuzz_test.go View File

@ -0,0 +1,33 @@
package server_test
import (
"io/ioutil"
"os"
"path/filepath"
"testing"
"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/test/fuzz/rpc/jsonrpc/server"
)
const testdataDir = "testdata"
func TestServerOnTestData(t *testing.T) {
entries, err := os.ReadDir(testdataDir)
require.NoError(t, err)
for _, e := range entries {
entry := e
t.Run(entry.Name(), func(t *testing.T) {
defer func() {
r := recover()
require.Nilf(t, r, "testdata test panic")
}()
f, err := os.Open(filepath.Join(testdataDir, entry.Name()))
require.NoError(t, err)
input, err := ioutil.ReadAll(f)
require.NoError(t, err)
server.Fuzz(input)
})
}
}

+ 19
- 4
test/fuzz/rpc/jsonrpc/server/handler.go View File

@ -1,4 +1,4 @@
package handler
package server
import (
"bytes"
@ -39,11 +39,26 @@ func Fuzz(data []byte) int {
if err := res.Body.Close(); err != nil {
panic(err)
}
if len(blob) > 0 {
recv := new(types.RPCResponse)
if err := json.Unmarshal(blob, recv); err != nil {
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
}

+ 1
- 0
test/fuzz/rpc/jsonrpc/server/testdata/1184f5b8d4b6dd08709cf1513f26744167065e0d View File

@ -0,0 +1 @@
[0]

+ 1
- 0
test/fuzz/rpc/jsonrpc/server/testdata/clusterfuzz-testcase-minimized-fuzz_rpc_jsonrpc_server-4738572803506176 View File

@ -0,0 +1 @@
[{"iD":7},{"iD":7}]

Loading…
Cancel
Save