From df22e7354cda539b855fe1c3148f1e7af33d2bf3 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Mon, 25 Jan 2021 11:41:59 +0400 Subject: [PATCH] test/fuzz: move fuzz tests into this repo (#5918) Co-authored-by: Emmanuel T Odeke Closes #5907 - add init-corpus to blockchain reactor - remove validator-set FromBytes test now that we have proto, we don't need to test it! bye amino - simplify mempool test do we want to test remote ABCI app? - do not recreate mux on every crash in jsonrpc test - update p2p pex reactor test - remove p2p/listener test the API has changed + I did not understand what it's tested anyway - update secretconnection test - add readme and makefile - list inputs in readme - add nightly workflow - remove blockchain fuzz test EncodeMsg / DecodeMsg no longer exist --- .github/workflows/fuzz-nightly.yml | 63 + .gitignore | 6 +- go.mod | 1 + go.sum | 4 + test/README.md | 6 + test/fuzz/Makefile | 39 + test/fuzz/README.md | 72 + test/fuzz/mempool/checktx.go | 34 + test/fuzz/p2p/addrbook/fuzz.go | 35 + test/fuzz/p2p/addrbook/init-corpus/main.go | 58 + test/fuzz/p2p/pex/init-corpus/main.go | 82 + test/fuzz/p2p/pex/reactor_receive.go | 86 + test/fuzz/p2p/pex/testdata/addrbook1 | 1705 +++++++++++++++++ .../p2p/secret_connection/init-corpus/main.go | 48 + test/fuzz/p2p/secret_connection/read_write.go | 107 ++ test/fuzz/rpc/jsonrpc/server/handler.go | 44 + 16 files changed, 2389 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/fuzz-nightly.yml create mode 100644 test/fuzz/Makefile create mode 100644 test/fuzz/README.md create mode 100644 test/fuzz/mempool/checktx.go create mode 100644 test/fuzz/p2p/addrbook/fuzz.go create mode 100644 test/fuzz/p2p/addrbook/init-corpus/main.go create mode 100644 test/fuzz/p2p/pex/init-corpus/main.go create mode 100644 test/fuzz/p2p/pex/reactor_receive.go create mode 100644 test/fuzz/p2p/pex/testdata/addrbook1 create mode 100644 test/fuzz/p2p/secret_connection/init-corpus/main.go create mode 100644 test/fuzz/p2p/secret_connection/read_write.go create mode 100644 test/fuzz/rpc/jsonrpc/server/handler.go diff --git a/.github/workflows/fuzz-nightly.yml b/.github/workflows/fuzz-nightly.yml new file mode 100644 index 000000000..6df36db06 --- /dev/null +++ b/.github/workflows/fuzz-nightly.yml @@ -0,0 +1,63 @@ +# Runs fuzzing nightly. +name: fuzz-nightly +on: + workflow_dispatch: # allow running workflow manually + schedule: + - cron: '0 3 * * *' + +jobs: + fuzz-nightly-test: + runs-on: ubuntu-latest + steps: + - uses: actions/setup-go@v2 + with: + go-version: '1.15' + + - uses: actions/checkout@v2 + + - name: Install go-fuzz + working-directory: test/fuzz + run: go get -u github.com/dvyukov/go-fuzz/go-fuzz github.com/dvyukov/go-fuzz/go-fuzz-build + + - name: Fuzz mempool + working-directory: test/fuzz + run: timeout 10m make fuzz-mempool + + - name: Fuzz p2p-addrbook + working-directory: test/fuzz + run: timeout 10m make fuzz-p2p-addrbook + + - name: Fuzz p2p-pex + working-directory: test/fuzz + run: timeout 10m make fuzz-p2p-pex + + - name: Fuzz p2p-sc + working-directory: test/fuzz + run: timeout 10m make fuzz-p2p-sc + + - name: Fuzz p2p-rpc-server + working-directory: test/fuzz + run: timeout 10m make fuzz-rpc-server + + - name: Set crashers count + working-directory: test/fuzz + run: echo "::set-output name=crashers-count::$(find . -type d -name "crashers" | xargs -I % sh -c 'ls % | wc -l' | awk '{total += $1} END {print total}')" + id: set-crashers-count + outputs: + crashers_count: ${{ steps.set-crashers-count.outputs.crashers-count }} + + fuzz-nightly-fail: + needs: fuzz-nightly-test + if: ${{ needs.set-crashers-count.outputs.crashers-count != 0 }} + runs-on: ubuntu-latest + steps: + - name: Notify Slack if any crashers + uses: rtCamp/action-slack-notify@ae4223259071871559b6e9d08b24a63d71b3f0c0 + env: + SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} + SLACK_CHANNEL: tendermint-internal + SLACK_USERNAME: Nightly Fuzz Tests + SLACK_ICON_EMOJI: ':skull:' + SLACK_COLOR: danger + SLACK_MESSAGE: Crashers found in Nightly Fuzz tests + SLACK_FOOTER: '' diff --git a/.gitignore b/.gitignore index d5442f35d..40bfa28d8 100644 --- a/.gitignore +++ b/.gitignore @@ -40,4 +40,8 @@ test/e2e/networks/*/ test/logs test/maverick/maverick test/p2p/data/ -vendor \ No newline at end of file +vendor +test/fuzz/**/corpus +test/fuzz/**/crashers +test/fuzz/**/suppressions +test/fuzz/**/*.zip diff --git a/go.mod b/go.mod index 8f2176b22..042c094a1 100644 --- a/go.mod +++ b/go.mod @@ -10,6 +10,7 @@ require ( github.com/btcsuite/btcutil v1.0.2 github.com/confio/ics23/go v0.6.3 github.com/cosmos/iavl v0.15.3 + github.com/dvyukov/go-fuzz v0.0.0-20210103155950-6a8e9d1f2415 // indirect github.com/fortytw2/leaktest v1.3.0 github.com/go-kit/kit v0.10.0 github.com/go-logfmt/logfmt v0.5.0 diff --git a/go.sum b/go.sum index 555ee31c9..b580449b2 100644 --- a/go.sum +++ b/go.sum @@ -130,6 +130,8 @@ github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8 github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dvyukov/go-fuzz v0.0.0-20210103155950-6a8e9d1f2415 h1:q1oJaUPdmpDm/VyXosjgPgr6wS7c5iV2p0PwJD73bUI= +github.com/dvyukov/go-fuzz v0.0.0-20210103155950-6a8e9d1f2415/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw= github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= @@ -627,6 +629,7 @@ golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -756,6 +759,7 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a h1:CB3a9Nez8M13wwlr/E2YtwoU+qYHKfC+JrDa45RXXoQ= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/test/README.md b/test/README.md index 0e0d666e5..230b7339c 100644 --- a/test/README.md +++ b/test/README.md @@ -14,3 +14,9 @@ and run the following tests in docker containers: - counter app over grpc - persistence tests - crash tendermint at each of many predefined points, restart, and ensure it syncs properly with the app + +## Fuzzing + +[Fuzzing](https://en.wikipedia.org/wiki/Fuzzing) of various system inputs. + +See `./fuzz/README.md` for more details. diff --git a/test/fuzz/Makefile b/test/fuzz/Makefile new file mode 100644 index 000000000..96b332dcf --- /dev/null +++ b/test/fuzz/Makefile @@ -0,0 +1,39 @@ +#!/usr/bin/make -f + +.PHONY: fuzz-mempool +fuzz-mempool: + cd mempool && \ + rm -f *-fuzz.zip && \ + go-fuzz-build && \ + go-fuzz + +.PHONY: fuzz-p2p-addrbook +fuzz-p2p-addrbook: + cd p2p/addrbook && \ + rm -f *-fuzz.zip && \ + go run ./init-corpus/main.go && \ + go-fuzz-build && \ + go-fuzz + +.PHONY: fuzz-p2p-pex +fuzz-p2p-pex: + cd p2p/pex && \ + rm -f *-fuzz.zip && \ + go run ./init-corpus/main.go && \ + go-fuzz-build && \ + go-fuzz + +.PHONY: fuzz-p2p-sc +fuzz-p2p-sc: + cd p2p/secret_connection && \ + rm -f *-fuzz.zip && \ + go run ./init-corpus/main.go && \ + go-fuzz-build && \ + go-fuzz + +.PHONY: fuzz-rpc-server +fuzz-rpc-server: + cd rpc/jsonrpc/server && \ + rm -f *-fuzz.zip && \ + go-fuzz-build && \ + go-fuzz diff --git a/test/fuzz/README.md b/test/fuzz/README.md new file mode 100644 index 000000000..707217afd --- /dev/null +++ b/test/fuzz/README.md @@ -0,0 +1,72 @@ +# fuzz + +Fuzzing for various packages in Tendermint using [go-fuzz](https://github.com/dvyukov/go-fuzz) library. + +Inputs: + +- mempool `CheckTx` (using kvstore in-process ABCI app) +- p2p `Addrbook#AddAddress` +- p2p `pex.Reactor#Receive` +- p2p `SecretConnection#Read` and `SecretConnection#Write` +- rpc jsonrpc server + +## Directory structure + +``` +| test +| |- corpus/ +| |- crashers/ +| |- init-corpus/ +| |- suppressions/ +| |- testdata/ +| |- .go +``` + +`/corpus` directory contains corpus data. The idea is to help the fuzzier to +understand what bytes sequences are semantically valid (e.g. if we're testing +PNG decoder, then we would put black-white PNG into corpus directory; with +blockchain reactor - we would put blockchain messages into corpus). + +`/init-corpus` (if present) contains a script for generating corpus data. + +`/testdata` directory may contain an additional data (like `addrbook.json`). + +Upon running the fuzzier, `/crashers` and `/suppressions` dirs will be created, +along with .zip archive. `/crashers` will show any inputs, which have +lead to panics (plus a trace). `/suppressions` will show any suppressed inputs. + +## Running + +```sh +make fuzz-mempool +make fuzz-p2p-addrbook +make fuzz-p2p-pex +make fuzz-p2p-sc +make fuzz-rpc-server +``` + +Each command will create corpus data (if needed), generate a fuzz archive and +call `go-fuzz` executable. + +Then watch out for the respective outputs in the fuzzer output to announce new +crashers which can be found in the directory `crashers`. + +For example if we find + +```sh +ls crashers/ +61bde465f47c93254d64d643c3b2480e0a54666e +61bde465f47c93254d64d643c3b2480e0a54666e.output +61bde465f47c93254d64d643c3b2480e0a54666e.quoted +da39a3ee5e6b4b0d3255bfef95601890afd80709 +da39a3ee5e6b4b0d3255bfef95601890afd80709.output +da39a3ee5e6b4b0d3255bfef95601890afd80709.quoted +``` + +the crashing bytes generated by the fuzzer will be in +`61bde465f47c93254d64d643c3b2480e0a54666e` the respective crash report in +`61bde465f47c93254d64d643c3b2480e0a54666e.output` + +and the bug report can be created by retrieving the bytes in +`61bde465f47c93254d64d643c3b2480e0a54666e` and feeding those back into the +`Fuzz` function. diff --git a/test/fuzz/mempool/checktx.go b/test/fuzz/mempool/checktx.go new file mode 100644 index 000000000..3193b169d --- /dev/null +++ b/test/fuzz/mempool/checktx.go @@ -0,0 +1,34 @@ +package checktx + +import ( + "github.com/tendermint/tendermint/abci/example/kvstore" + "github.com/tendermint/tendermint/config" + mempl "github.com/tendermint/tendermint/mempool" + "github.com/tendermint/tendermint/proxy" +) + +var mempool mempl.Mempool + +func init() { + app := kvstore.NewApplication() + cc := proxy.NewLocalClientCreator(app) + appConnMem, _ := cc.NewABCIClient() + err := appConnMem.Start() + if err != nil { + panic(err) + } + + cfg := config.DefaultMempoolConfig() + cfg.Broadcast = false + + mempool = mempl.NewCListMempool(cfg, appConnMem, 0) +} + +func Fuzz(data []byte) int { + err := mempool.CheckTx(data, nil, mempl.TxInfo{}) + if err != nil { + return 0 + } + + return 1 +} diff --git a/test/fuzz/p2p/addrbook/fuzz.go b/test/fuzz/p2p/addrbook/fuzz.go new file mode 100644 index 000000000..f2799ef04 --- /dev/null +++ b/test/fuzz/p2p/addrbook/fuzz.go @@ -0,0 +1,35 @@ +// nolint: gosec +package addr + +import ( + "encoding/json" + "fmt" + "math/rand" + + "github.com/tendermint/tendermint/p2p" + "github.com/tendermint/tendermint/p2p/pex" +) + +var addrBook = pex.NewAddrBook("./testdata/addrbook.json", true) + +func Fuzz(data []byte) int { + addr := new(p2p.NetAddress) + if err := json.Unmarshal(data, addr); err != nil { + return -1 + } + + // Fuzz AddAddress. + err := addrBook.AddAddress(addr, addr) + if err != nil { + return 0 + } + + // Also, make sure PickAddress always returns a non-nil address. + bias := rand.Intn(100) + if p := addrBook.PickAddress(bias); p == nil { + panic(fmt.Sprintf("picked a nil address (bias: %d, addrBook size: %v)", + bias, addrBook.Size())) + } + + return 1 +} diff --git a/test/fuzz/p2p/addrbook/init-corpus/main.go b/test/fuzz/p2p/addrbook/init-corpus/main.go new file mode 100644 index 000000000..ff9dd9107 --- /dev/null +++ b/test/fuzz/p2p/addrbook/init-corpus/main.go @@ -0,0 +1,58 @@ +// nolint: gosec +package main + +import ( + "encoding/json" + "flag" + "fmt" + "io/ioutil" + "log" + "net" + "os" + "path/filepath" + + "github.com/tendermint/tendermint/crypto/ed25519" + "github.com/tendermint/tendermint/p2p" +) + +func main() { + baseDir := flag.String("base", ".", `where the "corpus" directory will live`) + flag.Parse() + + initCorpus(*baseDir) +} + +func initCorpus(baseDir string) { + log.SetFlags(0) + + // create "corpus" directory + corpusDir := filepath.Join(baseDir, "corpus") + if err := os.MkdirAll(corpusDir, 0755); err != nil { + log.Fatalf("Creating %q err: %v", corpusDir, err) + } + + // create corpus + privKey := ed25519.GenPrivKey() + addrs := []*p2p.NetAddress{ + {ID: p2p.NodeIDFromPubKey(privKey.PubKey()), IP: net.IPv4(0, 0, 0, 0), Port: 0}, + {ID: p2p.NodeIDFromPubKey(privKey.PubKey()), IP: net.IPv4(127, 0, 0, 0), Port: 80}, + {ID: p2p.NodeIDFromPubKey(privKey.PubKey()), IP: net.IPv4(213, 87, 10, 200), Port: 8808}, + {ID: p2p.NodeIDFromPubKey(privKey.PubKey()), IP: net.IPv4(111, 111, 111, 111), Port: 26656}, + {ID: p2p.NodeIDFromPubKey(privKey.PubKey()), IP: net.ParseIP("2001:db8::68"), Port: 26656}, + } + + for i, addr := range addrs { + filename := filepath.Join(corpusDir, fmt.Sprintf("%d.json", i)) + + bz, err := json.Marshal(addr) + if err != nil { + log.Fatalf("can't marshal %v: %v", addr, err) + } + + if err := ioutil.WriteFile(filename, bz, 0644); err != nil { + log.Fatalf("can't write %v to %q: %v", addr, filename, err) + } + + log.Printf("wrote %q", filename) + } +} diff --git a/test/fuzz/p2p/pex/init-corpus/main.go b/test/fuzz/p2p/pex/init-corpus/main.go new file mode 100644 index 000000000..55ee0d8f3 --- /dev/null +++ b/test/fuzz/p2p/pex/init-corpus/main.go @@ -0,0 +1,82 @@ +// nolint: gosec +package main + +import ( + "flag" + "fmt" + "io/ioutil" + "log" + "math/rand" + "os" + "path/filepath" + + "github.com/tendermint/tendermint/crypto/ed25519" + "github.com/tendermint/tendermint/p2p" + tmp2p "github.com/tendermint/tendermint/proto/tendermint/p2p" +) + +func main() { + baseDir := flag.String("base", ".", `where the "corpus" directory will live`) + flag.Parse() + + initCorpus(*baseDir) +} + +func initCorpus(rootDir string) { + log.SetFlags(0) + + corpusDir := filepath.Join(rootDir, "corpus") + if err := os.MkdirAll(corpusDir, 0755); err != nil { + log.Fatalf("Creating %q err: %v", corpusDir, err) + } + sizes := []int{0, 1, 2, 17, 5, 31} + + // Make the PRNG predictable + rand.Seed(10) + + for _, n := range sizes { + var addrs []*p2p.NetAddress + + // IPv4 addresses + for i := 0; i < n; i++ { + privKey := ed25519.GenPrivKey() + addr := fmt.Sprintf( + "%s@%v.%v.%v.%v:26656", + p2p.NodeIDFromPubKey(privKey.PubKey()), + rand.Int()%256, + rand.Int()%256, + rand.Int()%256, + rand.Int()%256, + ) + netAddr, _ := p2p.NewNetAddressString(addr) + addrs = append(addrs, netAddr) + } + + // IPv6 addresses + privKey := ed25519.GenPrivKey() + ipv6a, err := p2p.NewNetAddressString( + fmt.Sprintf("%s@[ff02::1:114]:26656", p2p.NodeIDFromPubKey(privKey.PubKey()))) + if err != nil { + log.Fatalf("can't create a new netaddress: %v", err) + } + addrs = append(addrs, ipv6a) + + msg := tmp2p.Message{ + Sum: &tmp2p.Message_PexAddrs{ + PexAddrs: &tmp2p.PexAddrs{Addrs: p2p.NetAddressesToProto(addrs)}, + }, + } + bz, err := msg.Marshal() + if err != nil { + log.Fatalf("unable to marshal: %v", err) + } + + filename := filepath.Join(rootDir, "corpus", fmt.Sprintf("%d", n)) + + if err := ioutil.WriteFile(filename, bz, 0644); err != nil { + log.Fatalf("can't write %X to %q: %v", bz, filename, err) + } + + log.Printf("wrote %q", filename) + } +} diff --git a/test/fuzz/p2p/pex/reactor_receive.go b/test/fuzz/p2p/pex/reactor_receive.go new file mode 100644 index 000000000..37853810f --- /dev/null +++ b/test/fuzz/p2p/pex/reactor_receive.go @@ -0,0 +1,86 @@ +package pex + +import ( + "net" + + "github.com/tendermint/tendermint/config" + "github.com/tendermint/tendermint/crypto/ed25519" + "github.com/tendermint/tendermint/libs/log" + "github.com/tendermint/tendermint/libs/service" + "github.com/tendermint/tendermint/p2p" + "github.com/tendermint/tendermint/p2p/pex" + "github.com/tendermint/tendermint/version" +) + +var ( + pexR *pex.Reactor + peer p2p.Peer +) + +func init() { + addrB := pex.NewAddrBook("./testdata/addrbook1", false) + pexR := pex.NewReactor(addrB, &pex.ReactorConfig{SeedMode: false}) + if pexR == nil { + panic("NewReactor returned nil") + } + pexR.SetLogger(log.NewNopLogger()) + peer := newFuzzPeer() + pexR.AddPeer(peer) + +} + +func Fuzz(data []byte) int { + // MakeSwitch uses log.TestingLogger which can't be executed in init() + cfg := config.DefaultP2PConfig() + cfg.PexReactor = true + sw := p2p.MakeSwitch(cfg, 0, "127.0.0.1", "123.123.123", func(i int, sw *p2p.Switch) *p2p.Switch { + return sw + }) + pexR.SetSwitch(sw) + + pexR.Receive(pex.PexChannel, peer, data) + return 1 +} + +type fuzzPeer struct { + *service.BaseService + m map[string]interface{} +} + +var _ p2p.Peer = (*fuzzPeer)(nil) + +func newFuzzPeer() *fuzzPeer { + fp := &fuzzPeer{m: make(map[string]interface{})} + fp.BaseService = service.NewBaseService(nil, "fuzzPeer", fp) + return fp +} + +var privKey = ed25519.GenPrivKey() +var nodeID = p2p.NodeIDFromPubKey(privKey.PubKey()) +var defaultNodeInfo = p2p.NodeInfo{ + ProtocolVersion: p2p.NewProtocolVersion( + version.P2PProtocol, + version.BlockProtocol, + 0, + ), + NodeID: nodeID, + ListenAddr: "0.0.0.0:98992", + Moniker: "foo1", +} + +func (fp *fuzzPeer) FlushStop() {} +func (fp *fuzzPeer) ID() p2p.NodeID { return nodeID } +func (fp *fuzzPeer) RemoteIP() net.IP { return net.IPv4(0, 0, 0, 0) } +func (fp *fuzzPeer) RemoteAddr() net.Addr { + return &net.TCPAddr{IP: fp.RemoteIP(), Port: 98991, Zone: ""} +} +func (fp *fuzzPeer) IsOutbound() bool { return false } +func (fp *fuzzPeer) IsPersistent() bool { return false } +func (fp *fuzzPeer) CloseConn() error { return nil } +func (fp *fuzzPeer) NodeInfo() p2p.NodeInfo { return defaultNodeInfo } +func (fp *fuzzPeer) Status() p2p.ConnectionStatus { var cs p2p.ConnectionStatus; return cs } +func (fp *fuzzPeer) SocketAddr() *p2p.NetAddress { return p2p.NewNetAddress(fp.ID(), fp.RemoteAddr()) } +func (fp *fuzzPeer) Send(byte, []byte) bool { return true } +func (fp *fuzzPeer) TrySend(byte, []byte) bool { return true } +func (fp *fuzzPeer) Set(key string, value interface{}) { fp.m[key] = value } +func (fp *fuzzPeer) Get(key string) interface{} { return fp.m[key] } diff --git a/test/fuzz/p2p/pex/testdata/addrbook1 b/test/fuzz/p2p/pex/testdata/addrbook1 new file mode 100644 index 000000000..acf3e721d --- /dev/null +++ b/test/fuzz/p2p/pex/testdata/addrbook1 @@ -0,0 +1,1705 @@ +{ + "Key": "badd73ebd4eeafbaefc01e0c", + "Addrs": [ + { + "Addr": { + "IP": "233.174.138.192", + "Port": 48186 + }, + "Src": { + "IP": "198.37.90.115", + "Port": 29492 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692278-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 55 + ] + }, + { + "Addr": { + "IP": "181.28.96.104", + "Port": 26776 + }, + "Src": { + "IP": "183.12.35.241", + "Port": 26794 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692289-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 18 + ] + }, + { + "Addr": { + "IP": "141.85.194.118", + "Port": 39768 + }, + "Src": { + "IP": "120.130.90.63", + "Port": 61750 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692383-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 185 + ] + }, + { + "Addr": { + "IP": "167.72.9.155", + "Port": 9542 + }, + "Src": { + "IP": "95.158.40.108", + "Port": 14929 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692604-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 250 + ] + }, + { + "Addr": { + "IP": "124.118.94.27", + "Port": 50333 + }, + "Src": { + "IP": "208.169.57.96", + "Port": 19754 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692046-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 0 + ] + }, + { + "Addr": { + "IP": "158.197.4.226", + "Port": 25979 + }, + "Src": { + "IP": "3.129.219.107", + "Port": 50374 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692211-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 174 + ] + }, + { + "Addr": { + "IP": "170.42.135.37", + "Port": 34524 + }, + "Src": { + "IP": "73.125.53.212", + "Port": 49691 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692241-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 14 + ] + }, + { + "Addr": { + "IP": "234.69.254.147", + "Port": 31885 + }, + "Src": { + "IP": "167.106.61.34", + "Port": 22187 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692609-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 213 + ] + }, + { + "Addr": { + "IP": "32.176.173.90", + "Port": 17250 + }, + "Src": { + "IP": "118.91.243.12", + "Port": 26781 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692273-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 35 + ] + }, + { + "Addr": { + "IP": "162.154.114.145", + "Port": 13875 + }, + "Src": { + "IP": "198.178.108.166", + "Port": 59623 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692373-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 216 + ] + }, + { + "Addr": { + "IP": "67.128.167.93", + "Port": 50513 + }, + "Src": { + "IP": "104.93.115.28", + "Port": 48298 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692399-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 18 + ] + }, + { + "Addr": { + "IP": "132.175.221.206", + "Port": 61037 + }, + "Src": { + "IP": "112.49.189.65", + "Port": 56186 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692422-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 31 + ] + }, + { + "Addr": { + "IP": "155.49.24.238", + "Port": 26261 + }, + "Src": { + "IP": "97.10.121.246", + "Port": 8694 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692473-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 23 + ] + }, + { + "Addr": { + "IP": "22.215.7.233", + "Port": 32487 + }, + "Src": { + "IP": "214.236.105.23", + "Port": 26870 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692572-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 255 + ] + }, + { + "Addr": { + "IP": "253.170.228.231", + "Port": 5002 + }, + "Src": { + "IP": "225.49.137.209", + "Port": 16908 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692619-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 161 + ] + }, + { + "Addr": { + "IP": "162.126.204.39", + "Port": 62618 + }, + "Src": { + "IP": "250.214.168.131", + "Port": 3237 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.69203-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 7 + ] + }, + { + "Addr": { + "IP": "83.154.228.215", + "Port": 23508 + }, + "Src": { + "IP": "66.33.77.170", + "Port": 52207 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692153-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 8 + ] + }, + { + "Addr": { + "IP": "132.49.63.65", + "Port": 53651 + }, + "Src": { + "IP": "250.164.163.212", + "Port": 8612 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692253-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 98 + ] + }, + { + "Addr": { + "IP": "200.168.34.12", + "Port": 61901 + }, + "Src": { + "IP": "133.185.186.115", + "Port": 14186 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692488-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 214 + ] + }, + { + "Addr": { + "IP": "31.93.45.219", + "Port": 61036 + }, + "Src": { + "IP": "176.191.214.170", + "Port": 33402 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692024-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 68 + ] + }, + { + "Addr": { + "IP": "250.189.27.93", + "Port": 51665 + }, + "Src": { + "IP": "93.161.116.107", + "Port": 53482 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692196-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 42 + ] + }, + { + "Addr": { + "IP": "50.7.17.126", + "Port": 64300 + }, + "Src": { + "IP": "233.234.64.214", + "Port": 61061 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692444-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 13 + ] + }, + { + "Addr": { + "IP": "88.85.81.64", + "Port": 34834 + }, + "Src": { + "IP": "4.240.150.250", + "Port": 63064 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692248-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 195 + ] + }, + { + "Addr": { + "IP": "242.117.244.198", + "Port": 4363 + }, + "Src": { + "IP": "149.29.34.42", + "Port": 62567 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692263-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 174 + ] + }, + { + "Addr": { + "IP": "245.155.175.114", + "Port": 37262 + }, + "Src": { + "IP": "75.85.36.49", + "Port": 7101 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692313-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 135 + ] + }, + { + "Addr": { + "IP": "224.184.241.26", + "Port": 55870 + }, + "Src": { + "IP": "52.15.194.216", + "Port": 4733 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692327-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 74 + ] + }, + { + "Addr": { + "IP": "43.178.26.188", + "Port": 55914 + }, + "Src": { + "IP": "103.250.250.35", + "Port": 1566 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692577-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 65 + ] + }, + { + "Addr": { + "IP": "102.117.172.117", + "Port": 35855 + }, + "Src": { + "IP": "114.152.204.187", + "Port": 21156 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692158-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 80 + ] + }, + { + "Addr": { + "IP": "39.33.41.199", + "Port": 51600 + }, + "Src": { + "IP": "119.65.88.38", + "Port": 41239 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692188-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 24 + ] + }, + { + "Addr": { + "IP": "63.164.56.227", + "Port": 1660 + }, + "Src": { + "IP": "169.54.47.92", + "Port": 2818 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692227-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 10 + ] + }, + { + "Addr": { + "IP": "50.183.223.115", + "Port": 26910 + }, + "Src": { + "IP": "115.98.199.4", + "Port": 8767 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692201-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 65 + ] + }, + { + "Addr": { + "IP": "132.94.203.167", + "Port": 53156 + }, + "Src": { + "IP": "17.195.234.168", + "Port": 29405 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692294-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 240 + ] + }, + { + "Addr": { + "IP": "135.194.230.212", + "Port": 14340 + }, + "Src": { + "IP": "160.2.241.10", + "Port": 36553 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692363-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 63 + ] + }, + { + "Addr": { + "IP": "116.53.200.25", + "Port": 27092 + }, + "Src": { + "IP": "219.104.163.247", + "Port": 50476 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692543-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 201 + ] + }, + { + "Addr": { + "IP": "125.77.44.185", + "Port": 55291 + }, + "Src": { + "IP": "77.15.232.117", + "Port": 6934 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692589-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 8 + ] + }, + { + "Addr": { + "IP": "27.221.35.172", + "Port": 26418 + }, + "Src": { + "IP": "252.18.49.70", + "Port": 9835 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692068-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 80 + ] + }, + { + "Addr": { + "IP": "133.225.167.135", + "Port": 59468 + }, + "Src": { + "IP": "110.223.163.74", + "Port": 22576 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.69213-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 164 + ] + }, + { + "Addr": { + "IP": "155.131.178.240", + "Port": 60476 + }, + "Src": { + "IP": "143.82.157.1", + "Port": 43821 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692173-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 34 + ] + }, + { + "Addr": { + "IP": "207.13.48.52", + "Port": 28549 + }, + "Src": { + "IP": "238.224.177.29", + "Port": 44100 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692594-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 113 + ] + }, + { + "Addr": { + "IP": "91.137.2.184", + "Port": 44887 + }, + "Src": { + "IP": "72.131.70.84", + "Port": 29960 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692627-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 199 + ] + }, + { + "Addr": { + "IP": "169.59.252.76", + "Port": 57711 + }, + "Src": { + "IP": "194.132.91.119", + "Port": 18037 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692478-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 124 + ] + }, + { + "Addr": { + "IP": "25.174.143.229", + "Port": 41540 + }, + "Src": { + "IP": "58.215.132.148", + "Port": 64950 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692534-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 88 + ] + }, + { + "Addr": { + "IP": "71.239.78.239", + "Port": 46938 + }, + "Src": { + "IP": "156.98.186.169", + "Port": 32046 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692116-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 154 + ] + }, + { + "Addr": { + "IP": "94.137.107.61", + "Port": 20756 + }, + "Src": { + "IP": "101.201.138.179", + "Port": 22877 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692414-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 233 + ] + }, + { + "Addr": { + "IP": "216.62.174.112", + "Port": 60162 + }, + "Src": { + "IP": "225.114.119.144", + "Port": 1575 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692464-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 132 + ] + }, + { + "Addr": { + "IP": "65.183.81.125", + "Port": 17511 + }, + "Src": { + "IP": "12.96.14.61", + "Port": 42308 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692308-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 153 + ] + }, + { + "Addr": { + "IP": "142.26.87.52", + "Port": 41967 + }, + "Src": { + "IP": "60.124.157.139", + "Port": 20727 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692321-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 29 + ] + }, + { + "Addr": { + "IP": "13.77.198.44", + "Port": 54508 + }, + "Src": { + "IP": "142.73.70.174", + "Port": 19525 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692553-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 170 + ] + }, + { + "Addr": { + "IP": "63.192.219.12", + "Port": 46603 + }, + "Src": { + "IP": "26.136.66.29", + "Port": 38924 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692558-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 203 + ] + }, + { + "Addr": { + "IP": "120.82.251.151", + "Port": 43723 + }, + "Src": { + "IP": "136.104.122.219", + "Port": 47452 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692599-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 103 + ] + }, + { + "Addr": { + "IP": "74.79.96.159", + "Port": 46646 + }, + "Src": { + "IP": "218.60.242.116", + "Port": 5361 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692145-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 121 + ] + }, + { + "Addr": { + "IP": "194.65.211.174", + "Port": 43464 + }, + "Src": { + "IP": "87.5.112.153", + "Port": 56348 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692163-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 96 + ] + }, + { + "Addr": { + "IP": "237.158.179.80", + "Port": 32231 + }, + "Src": { + "IP": "210.240.52.244", + "Port": 29142 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692183-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 27 + ] + }, + { + "Addr": { + "IP": "81.157.122.4", + "Port": 9917 + }, + "Src": { + "IP": "213.226.144.152", + "Port": 29950 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692614-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 33 + ] + }, + { + "Addr": { + "IP": "180.147.73.220", + "Port": 367 + }, + "Src": { + "IP": "32.229.253.215", + "Port": 62165 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692529-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 240 + ] + }, + { + "Addr": { + "IP": "83.110.235.17", + "Port": 33231 + }, + "Src": { + "IP": "230.54.162.85", + "Port": 51569 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692563-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 234 + ] + }, + { + "Addr": { + "IP": "100.252.20.2", + "Port": 1633 + }, + "Src": { + "IP": "52.136.47.198", + "Port": 31916 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692644-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 254 + ] + }, + { + "Addr": { + "IP": "74.5.247.79", + "Port": 18703 + }, + "Src": { + "IP": "200.247.68.128", + "Port": 55844 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692378-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 160 + ] + }, + { + "Addr": { + "IP": "17.220.231.87", + "Port": 59015 + }, + "Src": { + "IP": "54.207.49.4", + "Port": 17877 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692404-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 21 + ] + }, + { + "Addr": { + "IP": "156.194.57.127", + "Port": 18944 + }, + "Src": { + "IP": "154.94.235.84", + "Port": 61610 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692439-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 32 + ] + }, + { + "Addr": { + "IP": "137.57.172.158", + "Port": 32031 + }, + "Src": { + "IP": "144.160.225.126", + "Port": 43225 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692568-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 4 + ] + }, + { + "Addr": { + "IP": "101.220.101.200", + "Port": 26480 + }, + "Src": { + "IP": "130.225.42.1", + "Port": 2522 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692637-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 173 + ] + }, + { + "Addr": { + "IP": "136.233.185.164", + "Port": 34011 + }, + "Src": { + "IP": "112.127.216.43", + "Port": 55317 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692649-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 106 + ] + }, + { + "Addr": { + "IP": "101.189.107.148", + "Port": 28671 + }, + "Src": { + "IP": "213.55.140.235", + "Port": 2547 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692178-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 72 + ] + }, + { + "Addr": { + "IP": "61.190.60.64", + "Port": 58467 + }, + "Src": { + "IP": "206.86.120.31", + "Port": 54422 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692358-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 191 + ] + }, + { + "Addr": { + "IP": "227.51.127.223", + "Port": 52754 + }, + "Src": { + "IP": "124.24.12.47", + "Port": 59878 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692393-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 122 + ] + }, + { + "Addr": { + "IP": "101.19.152.238", + "Port": 47491 + }, + "Src": { + "IP": "211.30.216.184", + "Port": 17610 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692135-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 251 + ] + }, + { + "Addr": { + "IP": "182.198.35.238", + "Port": 15065 + }, + "Src": { + "IP": "239.67.104.149", + "Port": 43039 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692268-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 179 + ] + }, + { + "Addr": { + "IP": "233.12.68.51", + "Port": 47544 + }, + "Src": { + "IP": "203.224.119.48", + "Port": 23337 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692454-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 51 + ] + }, + { + "Addr": { + "IP": "181.30.35.80", + "Port": 500 + }, + "Src": { + "IP": "174.200.32.161", + "Port": 10174 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692503-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 69 + ] + }, + { + "Addr": { + "IP": "49.104.89.21", + "Port": 54774 + }, + "Src": { + "IP": "245.95.238.161", + "Port": 14339 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692654-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 120 + ] + }, + { + "Addr": { + "IP": "65.150.169.199", + "Port": 11589 + }, + "Src": { + "IP": "150.110.183.207", + "Port": 17694 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692041-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 182 + ] + }, + { + "Addr": { + "IP": "84.203.198.48", + "Port": 47122 + }, + "Src": { + "IP": "141.209.147.221", + "Port": 26085 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692056-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 74 + ] + }, + { + "Addr": { + "IP": "220.10.106.180", + "Port": 27439 + }, + "Src": { + "IP": "124.170.244.46", + "Port": 5249 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692125-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 166 + ] + }, + { + "Addr": { + "IP": "120.208.32.34", + "Port": 27224 + }, + "Src": { + "IP": "64.194.118.103", + "Port": 24388 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.69251-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 149 + ] + }, + { + "Addr": { + "IP": "245.182.67.231", + "Port": 58067 + }, + "Src": { + "IP": "62.108.238.220", + "Port": 41851 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692522-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 201 + ] + }, + { + "Addr": { + "IP": "50.81.160.105", + "Port": 8113 + }, + "Src": { + "IP": "129.187.68.121", + "Port": 58612 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692284-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 94 + ] + }, + { + "Addr": { + "IP": "101.116.47.155", + "Port": 20287 + }, + "Src": { + "IP": "94.34.167.170", + "Port": 41821 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692299-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 134 + ] + }, + { + "Addr": { + "IP": "159.253.213.86", + "Port": 5222 + }, + "Src": { + "IP": "124.47.162.125", + "Port": 45742 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692429-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 25 + ] + }, + { + "Addr": { + "IP": "124.72.81.213", + "Port": 35723 + }, + "Src": { + "IP": "201.65.186.55", + "Port": 26602 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692493-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 199 + ] + }, + { + "Addr": { + "IP": "77.216.197.130", + "Port": 49129 + }, + "Src": { + "IP": "245.160.14.27", + "Port": 38908 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692517-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 58 + ] + }, + { + "Addr": { + "IP": "175.46.154.0", + "Port": 15297 + }, + "Src": { + "IP": "6.10.7.13", + "Port": 9657 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692583-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 89 + ] + }, + { + "Addr": { + "IP": "176.71.131.235", + "Port": 14342 + }, + "Src": { + "IP": "1.36.215.198", + "Port": 21709 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692206-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 135 + ] + }, + { + "Addr": { + "IP": "34.211.134.186", + "Port": 31608 + }, + "Src": { + "IP": "187.87.12.183", + "Port": 32977 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692221-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 71 + ] + }, + { + "Addr": { + "IP": "238.63.227.107", + "Port": 49502 + }, + "Src": { + "IP": "185.51.127.143", + "Port": 22728 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692483-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 61 + ] + }, + { + "Addr": { + "IP": "160.65.76.45", + "Port": 27307 + }, + "Src": { + "IP": "170.175.198.16", + "Port": 44759 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692051-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 36 + ] + }, + { + "Addr": { + "IP": "152.22.79.90", + "Port": 25861 + }, + "Src": { + "IP": "216.183.31.190", + "Port": 9185 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692409-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 163 + ] + }, + { + "Addr": { + "IP": "200.2.175.37", + "Port": 57270 + }, + "Src": { + "IP": "108.20.254.94", + "Port": 32812 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692434-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 96 + ] + }, + { + "Addr": { + "IP": "111.16.237.10", + "Port": 45200 + }, + "Src": { + "IP": "215.82.246.115", + "Port": 42333 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692469-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 21 + ] + }, + { + "Addr": { + "IP": "166.217.195.221", + "Port": 4579 + }, + "Src": { + "IP": "148.153.131.183", + "Port": 13848 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692498-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 78 + ] + }, + { + "Addr": { + "IP": "1.226.156.147", + "Port": 61660 + }, + "Src": { + "IP": "169.138.16.69", + "Port": 23455 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692548-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 121 + ] + }, + { + "Addr": { + "IP": "108.209.27.58", + "Port": 59102 + }, + "Src": { + "IP": "140.27.139.90", + "Port": 52154 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692014-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 53 + ] + }, + { + "Addr": { + "IP": "221.244.202.95", + "Port": 5032 + }, + "Src": { + "IP": "230.152.141.80", + "Port": 19457 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692168-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 106 + ] + }, + { + "Addr": { + "IP": "55.87.1.138", + "Port": 39686 + }, + "Src": { + "IP": "55.22.167.132", + "Port": 35663 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692258-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 174 + ] + }, + { + "Addr": { + "IP": "209.53.148.74", + "Port": 18502 + }, + "Src": { + "IP": "195.108.121.25", + "Port": 16730 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692304-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 180 + ] + }, + { + "Addr": { + "IP": "21.66.206.236", + "Port": 10771 + }, + "Src": { + "IP": "236.195.50.16", + "Port": 30697 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692368-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 22 + ] + }, + { + "Addr": { + "IP": "190.87.236.91", + "Port": 58378 + }, + "Src": { + "IP": "72.224.218.34", + "Port": 44817 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692459-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 127 + ] + }, + { + "Addr": { + "IP": "197.172.79.170", + "Port": 24958 + }, + "Src": { + "IP": "71.22.4.12", + "Port": 28558 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692036-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 251 + ] + }, + { + "Addr": { + "IP": "160.176.234.94", + "Port": 47013 + }, + "Src": { + "IP": "212.172.24.59", + "Port": 29594 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692062-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 99 + ] + }, + { + "Addr": { + "IP": "170.206.180.18", + "Port": 26212 + }, + "Src": { + "IP": "228.135.62.18", + "Port": 26164 + }, + "Attempts": 0, + "LastAttempt": "2017-11-07T01:11:34.692234-07:00", + "LastSuccess": "0001-01-01T00:00:00Z", + "BucketType": 1, + "Buckets": [ + 34 + ] + } + ] +} diff --git a/test/fuzz/p2p/secret_connection/init-corpus/main.go b/test/fuzz/p2p/secret_connection/init-corpus/main.go new file mode 100644 index 000000000..635f2d99f --- /dev/null +++ b/test/fuzz/p2p/secret_connection/init-corpus/main.go @@ -0,0 +1,48 @@ +// nolint: gosec +package main + +import ( + "flag" + "fmt" + "io/ioutil" + "log" + "os" + "path/filepath" +) + +func main() { + baseDir := flag.String("base", ".", `where the "corpus" directory will live`) + flag.Parse() + + initCorpus(*baseDir) +} + +func initCorpus(baseDir string) { + log.SetFlags(0) + + corpusDir := filepath.Join(baseDir, "corpus") + if err := os.MkdirAll(corpusDir, 0755); err != nil { + log.Fatal(err) + } + + data := []string{ + "dadc04c2-cfb1-4aa9-a92a-c0bf780ec8b6", + "", + " ", + " a ", + `{"a": 12, "tsp": 999, k: "blue"}`, + `9999.999`, + `""`, + `Tendermint fuzzing`, + } + + for i, datum := range data { + filename := filepath.Join(corpusDir, fmt.Sprintf("%d", i)) + + if err := ioutil.WriteFile(filename, []byte(datum), 0644); err != nil { + log.Fatalf("can't write %v to %q: %v", datum, filename, err) + } + + log.Printf("wrote %q", filename) + } +} diff --git a/test/fuzz/p2p/secret_connection/read_write.go b/test/fuzz/p2p/secret_connection/read_write.go new file mode 100644 index 000000000..632790002 --- /dev/null +++ b/test/fuzz/p2p/secret_connection/read_write.go @@ -0,0 +1,107 @@ +package secretconnection + +import ( + "bytes" + "fmt" + "io" + "log" + + "github.com/tendermint/tendermint/crypto/ed25519" + "github.com/tendermint/tendermint/libs/async" + sc "github.com/tendermint/tendermint/p2p/conn" +) + +func Fuzz(data []byte) int { + if len(data) == 0 { + return -1 + } + + 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) + } + if !bytes.Equal(data[:n], dataRead[:m]) { + panic(fmt.Sprintf("bytes written %X != read %X", data[:n], dataRead[:m])) + } + return 1 +} + +type kvstoreConn struct { + *io.PipeReader + *io.PipeWriter +} + +func (drw kvstoreConn) Close() (err error) { + err2 := drw.PipeWriter.CloseWithError(io.EOF) + err1 := drw.PipeReader.Close() + if err2 != nil { + return err + } + return err1 +} + +// Each returned ReadWriteCloser is akin to a net.Connection +func makeKVStoreConnPair() (fooConn, barConn kvstoreConn) { + barReader, fooWriter := io.Pipe() + fooReader, barWriter := io.Pipe() + return kvstoreConn{fooReader, fooWriter}, kvstoreConn{barReader, barWriter} +} + +func makeSecretConnPair() (fooSecConn, barSecConn *sc.SecretConnection) { + var ( + fooConn, barConn = makeKVStoreConnPair() + fooPrvKey = ed25519.GenPrivKey() + fooPubKey = fooPrvKey.PubKey() + barPrvKey = ed25519.GenPrivKey() + barPubKey = barPrvKey.PubKey() + ) + + // Make connections from both sides in parallel. + var trs, ok = async.Parallel( + func(_ int) (val interface{}, abort bool, err error) { + fooSecConn, err = sc.MakeSecretConnection(fooConn, fooPrvKey) + if err != nil { + log.Printf("failed to establish SecretConnection for foo: %v", err) + return nil, true, err + } + remotePubBytes := fooSecConn.RemotePubKey() + if !remotePubBytes.Equals(barPubKey) { + err = fmt.Errorf("unexpected fooSecConn.RemotePubKey. Expected %v, got %v", + barPubKey, fooSecConn.RemotePubKey()) + log.Print(err) + return nil, true, err + } + return nil, false, nil + }, + func(_ int) (val interface{}, abort bool, err error) { + barSecConn, err = sc.MakeSecretConnection(barConn, barPrvKey) + if barSecConn == nil { + log.Printf("failed to establish SecretConnection for bar: %v", err) + return nil, true, err + } + remotePubBytes := barSecConn.RemotePubKey() + if !remotePubBytes.Equals(fooPubKey) { + err = fmt.Errorf("unexpected barSecConn.RemotePubKey. Expected %v, got %v", + fooPubKey, barSecConn.RemotePubKey()) + log.Print(err) + return nil, true, err + } + return nil, false, nil + }, + ) + + if trs.FirstError() != nil { + log.Fatalf("unexpected error: %v", trs.FirstError()) + } + if !ok { + log.Fatal("Unexpected task abortion") + } + + return fooSecConn, barSecConn +} diff --git a/test/fuzz/rpc/jsonrpc/server/handler.go b/test/fuzz/rpc/jsonrpc/server/handler.go new file mode 100644 index 000000000..98c75d511 --- /dev/null +++ b/test/fuzz/rpc/jsonrpc/server/handler.go @@ -0,0 +1,44 @@ +package handler + +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"), +} +var mux *http.ServeMux + +func init() { + mux := http.NewServeMux() + buf := new(bytes.Buffer) + lgr := log.NewTMLogger(buf) + rs.RegisterRPCFuncs(mux, rpcFuncMap, lgr) +} + +func Fuzz(data []byte) int { + 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) + } + recv := new(types.RPCResponse) + if err := json.Unmarshal(blob, recv); err != nil { + panic(err) + } + return 1 +}