Browse Source

test/fuzz: fix rpc, secret_connection and pex tests (#6190)

* test/fuzz: fix rpc, secret_connection and pex tests

- ignore empty data in rpc
- provide correct IP in pex
- spawn a goroutine for Write and do multiple Read(s)

* test/fuzz: fix init in pex test

* test/fuzz: assign NewServeMux to global var

* test/fuzz: only try to Unmarshal if blob is not empty

* run fuzz tests for PRs which modify fuzz tests themselves

* test/fuzz: move MakeSwitch into init
pull/6194/head
Anton Kaliaev 4 years ago
committed by GitHub
parent
commit
36d92cd0b6
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 65 additions and 31 deletions
  1. +4
    -0
      .github/workflows/fuzz-nightly.yml
  2. +17
    -15
      test/fuzz/p2p/pex/reactor_receive.go
  3. +32
    -10
      test/fuzz/p2p/secret_connection/read_write.go
  4. +12
    -6
      test/fuzz/rpc/jsonrpc/server/handler.go

+ 4
- 0
.github/workflows/fuzz-nightly.yml View File

@ -4,6 +4,10 @@ on:
workflow_dispatch: # allow running workflow manually workflow_dispatch: # allow running workflow manually
schedule: schedule:
- cron: '0 3 * * *' - cron: '0 3 * * *'
pull_request:
branches: [master]
paths:
- "test/fuzz/**/*.go"
jobs: jobs:
fuzz-nightly-test: fuzz-nightly-test:


+ 17
- 15
test/fuzz/p2p/pex/reactor_receive.go View File

@ -21,29 +21,31 @@ var (
func init() { func init() {
addrB := pex.NewAddrBook("./testdata/addrbook1", false) addrB := pex.NewAddrBook("./testdata/addrbook1", false)
pexR := pex.NewReactor(addrB, &pex.ReactorConfig{SeedMode: false})
if pexR == nil {
panic("NewReactor returned nil")
}
pexR = pex.NewReactor(addrB, &pex.ReactorConfig{SeedMode: false})
pexR.SetLogger(logger) pexR.SetLogger(logger)
peer := newFuzzPeer()
peer = newFuzzPeer()
pexR.AddPeer(peer) pexR.AddPeer(peer)
}
func Fuzz(data []byte) int {
if len(data) == 0 {
return -1
}
// MakeSwitch uses log.TestingLogger which can't be executed in init()
cfg := config.DefaultP2PConfig() cfg := config.DefaultP2PConfig()
cfg.PexReactor = true cfg.PexReactor = true
sw := p2p.MakeSwitch(cfg, 0, "127.0.0.1", "123.123.123", func(i int, sw *p2p.Switch) *p2p.Switch { sw := p2p.MakeSwitch(cfg, 0, "127.0.0.1", "123.123.123", func(i int, sw *p2p.Switch) *p2p.Switch {
return sw return sw
}, logger) }, logger)
pexR.SetSwitch(sw) pexR.SetSwitch(sw)
}
func Fuzz(data []byte) int {
if len(data) == 0 {
return -1
}
pexR.Receive(pex.PexChannel, peer, data) pexR.Receive(pex.PexChannel, peer, data)
if !peer.IsRunning() {
// do not increase priority for msgs which lead to peer being stopped
return 0
}
return 1 return 1
} }
@ -69,15 +71,15 @@ var defaultNodeInfo = p2p.NodeInfo{
0, 0,
), ),
NodeID: nodeID, NodeID: nodeID,
ListenAddr: "0.0.0.0:8992",
ListenAddr: "127.0.0.1:0",
Moniker: "foo1", Moniker: "foo1",
} }
func (fp *fuzzPeer) FlushStop() {} func (fp *fuzzPeer) FlushStop() {}
func (fp *fuzzPeer) ID() p2p.NodeID { return nodeID } func (fp *fuzzPeer) ID() p2p.NodeID { return nodeID }
func (fp *fuzzPeer) RemoteIP() net.IP { return net.IPv4(0, 0, 0, 0) }
func (fp *fuzzPeer) RemoteIP() net.IP { return net.IPv4(198, 163, 190, 214) }
func (fp *fuzzPeer) RemoteAddr() net.Addr { func (fp *fuzzPeer) RemoteAddr() net.Addr {
return &net.TCPAddr{IP: fp.RemoteIP(), Port: 98991, Zone: ""}
return &net.TCPAddr{IP: fp.RemoteIP(), Port: 26656, Zone: ""}
} }
func (fp *fuzzPeer) IsOutbound() bool { return false } func (fp *fuzzPeer) IsOutbound() bool { return false }
func (fp *fuzzPeer) IsPersistent() bool { return false } func (fp *fuzzPeer) IsPersistent() bool { return false }


+ 32
- 10
test/fuzz/p2p/secret_connection/read_write.go View File

@ -17,18 +17,40 @@ func Fuzz(data []byte) int {
} }
fooConn, barConn := makeSecretConnPair() fooConn, barConn := makeSecretConnPair()
n, err := fooConn.Write(data)
if err != nil {
panic(err)
}
dataRead := make([]byte, n)
m, err := barConn.Read(dataRead)
if err != nil {
panic(err)
// Run Write in a separate goroutine because if data is greater than 1024
// bytes, each Write must be followed by Read (see io.Pipe documentation).
go func() {
// Copy data because Write modifies the slice.
dataToWrite := make([]byte, len(data))
copy(dataToWrite, data)
n, err := fooConn.Write(dataToWrite)
if err != nil {
panic(err)
}
if n < len(data) {
panic(fmt.Sprintf("wanted to write %d bytes, but %d was written", len(data), n))
}
}()
dataRead := make([]byte, len(data))
totalRead := 0
for totalRead < len(data) {
buf := make([]byte, len(data)-totalRead)
m, err := barConn.Read(buf)
if err != nil {
panic(err)
}
copy(dataRead[totalRead:], buf[:m])
totalRead += m
log.Printf("total read: %d", totalRead)
} }
if !bytes.Equal(data[:n], dataRead[:m]) {
panic(fmt.Sprintf("bytes written %X != read %X", data[:n], dataRead[:m]))
if !bytes.Equal(data, dataRead) {
panic("bytes written != read")
} }
return 1 return 1
} }


+ 12
- 6
test/fuzz/rpc/jsonrpc/server/handler.go View File

@ -6,6 +6,7 @@ import (
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"os"
"github.com/tendermint/tendermint/libs/log" "github.com/tendermint/tendermint/libs/log"
rs "github.com/tendermint/tendermint/rpc/jsonrpc/server" rs "github.com/tendermint/tendermint/rpc/jsonrpc/server"
@ -18,13 +19,16 @@ var rpcFuncMap = map[string]*rs.RPCFunc{
var mux *http.ServeMux var mux *http.ServeMux
func init() { func init() {
mux := http.NewServeMux()
buf := new(bytes.Buffer)
lgr := log.NewTMLogger(buf)
mux = http.NewServeMux()
lgr := log.NewTMLogger(log.NewSyncWriter(os.Stdout))
rs.RegisterRPCFuncs(mux, rpcFuncMap, lgr) rs.RegisterRPCFuncs(mux, rpcFuncMap, lgr)
} }
func Fuzz(data []byte) int { func Fuzz(data []byte) int {
if len(data) == 0 {
return -1
}
req, _ := http.NewRequest("POST", "http://localhost/", bytes.NewReader(data)) req, _ := http.NewRequest("POST", "http://localhost/", bytes.NewReader(data))
rec := httptest.NewRecorder() rec := httptest.NewRecorder()
mux.ServeHTTP(rec, req) mux.ServeHTTP(rec, req)
@ -36,9 +40,11 @@ func Fuzz(data []byte) int {
if err := res.Body.Close(); err != nil { if err := res.Body.Close(); err != nil {
panic(err) panic(err)
} }
recv := new(types.RPCResponse)
if err := json.Unmarshal(blob, recv); err != nil {
panic(err)
if len(blob) > 0 {
recv := new(types.RPCResponse)
if err := json.Unmarshal(blob, recv); err != nil {
panic(err)
}
} }
return 1 return 1
} }

Loading…
Cancel
Save