eth/protocols/eth: add ETH68 protocol handler fuzzers (#30417)

Adds a protocol handler fuzzer to fuzz the ETH68 protocol handlers
pull/30740/head
Marius van der Wijden 2 weeks ago committed by GitHub
parent 74ef47462f
commit 3f5f2efccb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 82
      eth/protocols/eth/handler_test.go
  2. 4
      oss-fuzz.sh

@ -17,10 +17,12 @@
package eth package eth
import ( import (
"bytes"
"math" "math"
"math/big" "math/big"
"math/rand" "math/rand"
"testing" "testing"
"time"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/consensus"
@ -37,6 +39,7 @@ import (
"github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
) )
var ( var (
@ -142,10 +145,12 @@ func (b *testBackend) RunPeer(peer *Peer, handler Handler) error {
func (b *testBackend) PeerInfo(enode.ID) interface{} { panic("not implemented") } func (b *testBackend) PeerInfo(enode.ID) interface{} { panic("not implemented") }
func (b *testBackend) AcceptTxs() bool { func (b *testBackend) AcceptTxs() bool {
panic("data processing tests should be done in the handler package") return true
//panic("data processing tests should be done in the handler package")
} }
func (b *testBackend) Handle(*Peer, Packet) error { func (b *testBackend) Handle(*Peer, Packet) error {
panic("data processing tests should be done in the handler package") return nil
//panic("data processing tests should be done in the handler package")
} }
// Tests that block headers can be retrieved from a remote chain based on user queries. // Tests that block headers can be retrieved from a remote chain based on user queries.
@ -498,3 +503,76 @@ func testGetBlockReceipts(t *testing.T, protocol uint) {
t.Errorf("receipts mismatch: %v", err) t.Errorf("receipts mismatch: %v", err)
} }
} }
type decoder struct {
msg []byte
}
func (d decoder) Decode(val interface{}) error {
buffer := bytes.NewBuffer(d.msg)
s := rlp.NewStream(buffer, uint64(len(d.msg)))
return s.Decode(val)
}
func (d decoder) Time() time.Time {
return time.Now()
}
func setup() (*testBackend, *testPeer) {
// Generate some transactions etc.
acc1Key, _ := crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
acc2Key, _ := crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee")
acc1Addr := crypto.PubkeyToAddress(acc1Key.PublicKey)
acc2Addr := crypto.PubkeyToAddress(acc2Key.PublicKey)
signer := types.HomesteadSigner{}
gen := func(n int, block *core.BlockGen) {
if n%2 == 0 {
w := &types.Withdrawal{
Address: common.Address{0xaa},
Amount: 42,
}
block.AddWithdrawal(w)
}
switch n {
case 0:
// In block 1, the test bank sends account #1 some ether.
tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testAddr), acc1Addr, big.NewInt(10_000_000_000_000_000), params.TxGas, block.BaseFee(), nil), signer, testKey)
block.AddTx(tx)
case 1:
// In block 2, the test bank sends some more ether to account #1.
// acc1Addr passes it on to account #2.
tx1, _ := types.SignTx(types.NewTransaction(block.TxNonce(testAddr), acc1Addr, big.NewInt(1_000_000_000_000_000), params.TxGas, block.BaseFee(), nil), signer, testKey)
tx2, _ := types.SignTx(types.NewTransaction(block.TxNonce(acc1Addr), acc2Addr, big.NewInt(1_000_000_000_000_000), params.TxGas, block.BaseFee(), nil), signer, acc1Key)
block.AddTx(tx1)
block.AddTx(tx2)
case 2:
// Block 3 is empty but was mined by account #2.
block.SetCoinbase(acc2Addr)
block.SetExtra([]byte("yeehaw"))
}
}
backend := newTestBackendWithGenerator(maxBodiesServe+15, true, gen)
peer, _ := newTestPeer("peer", ETH68, backend)
// Discard all messages
go func() {
for {
msg, err := peer.app.ReadMsg()
if err == nil {
msg.Discard()
}
}
}()
return backend, peer
}
func FuzzEthProtocolHandlers(f *testing.F) {
handlers := eth68
backend, peer := setup()
f.Fuzz(func(t *testing.T, code byte, msg []byte) {
handler := handlers[uint64(code)%protocolLengths[ETH68]]
if handler == nil {
return
}
handler(backend, decoder{msg: msg}, peer.Peer)
})
}

@ -220,6 +220,10 @@ compile_fuzzer github.com/ethereum/go-ethereum/tests/fuzzers/secp256k1 \
Fuzz fuzzSecp256k1\ Fuzz fuzzSecp256k1\
$repo/tests/fuzzers/secp256k1/secp_test.go $repo/tests/fuzzers/secp256k1/secp_test.go
compile_fuzzer github.com/ethereum/go-ethereum/eth/protocols/eth \
FuzzEthProtocolHandlers fuzz_eth_protocol_handlers \
$repo/eth/protocols/eth/handler_test.go
#compile_fuzzer tests/fuzzers/vflux FuzzClientPool fuzzClientPool #compile_fuzzer tests/fuzzers/vflux FuzzClientPool fuzzClientPool
#compile_fuzzer tests/fuzzers/difficulty Fuzz fuzzDifficulty #compile_fuzzer tests/fuzzers/difficulty Fuzz fuzzDifficulty

Loading…
Cancel
Save