Skip to content

Commit 9b3cf57

Browse files
MariusVanDerWijdenholiman
authored andcommitted
eth/protocols/eth: add ETH68 protocol handler fuzzers (#30417)
Adds a protocol handler fuzzer to fuzz the ETH68 protocol handlers
1 parent ba882b6 commit 9b3cf57

File tree

2 files changed

+84
-2
lines changed

2 files changed

+84
-2
lines changed

eth/protocols/eth/handler_test.go

Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,12 @@
1717
package eth
1818

1919
import (
20+
"bytes"
2021
"math"
2122
"math/big"
2223
"math/rand"
2324
"testing"
25+
"time"
2426

2527
"github.com/ethereum/go-ethereum/common"
2628
"github.com/ethereum/go-ethereum/consensus"
@@ -37,6 +39,7 @@ import (
3739
"github.com/ethereum/go-ethereum/p2p"
3840
"github.com/ethereum/go-ethereum/p2p/enode"
3941
"github.com/ethereum/go-ethereum/params"
42+
"github.com/ethereum/go-ethereum/rlp"
4043
)
4144

4245
var (
@@ -142,10 +145,12 @@ func (b *testBackend) RunPeer(peer *Peer, handler Handler) error {
142145
func (b *testBackend) PeerInfo(enode.ID) interface{} { panic("not implemented") }
143146

144147
func (b *testBackend) AcceptTxs() bool {
145-
panic("data processing tests should be done in the handler package")
148+
return true
149+
//panic("data processing tests should be done in the handler package")
146150
}
147151
func (b *testBackend) Handle(*Peer, Packet) error {
148-
panic("data processing tests should be done in the handler package")
152+
return nil
153+
//panic("data processing tests should be done in the handler package")
149154
}
150155

151156
// 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) {
498503
t.Errorf("receipts mismatch: %v", err)
499504
}
500505
}
506+
507+
type decoder struct {
508+
msg []byte
509+
}
510+
511+
func (d decoder) Decode(val interface{}) error {
512+
buffer := bytes.NewBuffer(d.msg)
513+
s := rlp.NewStream(buffer, uint64(len(d.msg)))
514+
return s.Decode(val)
515+
}
516+
517+
func (d decoder) Time() time.Time {
518+
return time.Now()
519+
}
520+
521+
func setup() (*testBackend, *testPeer) {
522+
// Generate some transactions etc.
523+
acc1Key, _ := crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
524+
acc2Key, _ := crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee")
525+
acc1Addr := crypto.PubkeyToAddress(acc1Key.PublicKey)
526+
acc2Addr := crypto.PubkeyToAddress(acc2Key.PublicKey)
527+
signer := types.HomesteadSigner{}
528+
gen := func(n int, block *core.BlockGen) {
529+
if n%2 == 0 {
530+
w := &types.Withdrawal{
531+
Address: common.Address{0xaa},
532+
Amount: 42,
533+
}
534+
block.AddWithdrawal(w)
535+
}
536+
switch n {
537+
case 0:
538+
// In block 1, the test bank sends account #1 some ether.
539+
tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testAddr), acc1Addr, big.NewInt(10_000_000_000_000_000), params.TxGas, block.BaseFee(), nil), signer, testKey)
540+
block.AddTx(tx)
541+
case 1:
542+
// In block 2, the test bank sends some more ether to account #1.
543+
// acc1Addr passes it on to account #2.
544+
tx1, _ := types.SignTx(types.NewTransaction(block.TxNonce(testAddr), acc1Addr, big.NewInt(1_000_000_000_000_000), params.TxGas, block.BaseFee(), nil), signer, testKey)
545+
tx2, _ := types.SignTx(types.NewTransaction(block.TxNonce(acc1Addr), acc2Addr, big.NewInt(1_000_000_000_000_000), params.TxGas, block.BaseFee(), nil), signer, acc1Key)
546+
block.AddTx(tx1)
547+
block.AddTx(tx2)
548+
case 2:
549+
// Block 3 is empty but was mined by account #2.
550+
block.SetCoinbase(acc2Addr)
551+
block.SetExtra([]byte("yeehaw"))
552+
}
553+
}
554+
backend := newTestBackendWithGenerator(maxBodiesServe+15, true, gen)
555+
peer, _ := newTestPeer("peer", ETH68, backend)
556+
// Discard all messages
557+
go func() {
558+
for {
559+
msg, err := peer.app.ReadMsg()
560+
if err == nil {
561+
msg.Discard()
562+
}
563+
}
564+
}()
565+
return backend, peer
566+
}
567+
568+
func FuzzEthProtocolHandlers(f *testing.F) {
569+
handlers := eth68
570+
backend, peer := setup()
571+
f.Fuzz(func(t *testing.T, code byte, msg []byte) {
572+
handler := handlers[uint64(code)%protocolLengths[ETH68]]
573+
if handler == nil {
574+
return
575+
}
576+
handler(backend, decoder{msg: msg}, peer.Peer)
577+
})
578+
}

oss-fuzz.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,10 @@ compile_fuzzer github.com/ethereum/go-ethereum/tests/fuzzers/secp256k1 \
220220
Fuzz fuzzSecp256k1\
221221
$repo/tests/fuzzers/secp256k1/secp_test.go
222222

223+
compile_fuzzer github.com/ethereum/go-ethereum/eth/protocols/eth \
224+
FuzzEthProtocolHandlers fuzz_eth_protocol_handlers \
225+
$repo/eth/protocols/eth/handler_test.go
226+
223227

224228
#compile_fuzzer tests/fuzzers/vflux FuzzClientPool fuzzClientPool
225229
#compile_fuzzer tests/fuzzers/difficulty Fuzz fuzzDifficulty

0 commit comments

Comments
 (0)