github.com/unicornultrafoundation/go-u2u@v1.0.0-rc1.0.20240205080301-e74a83d3fadc/gossip/handler_fuzz.go (about) 1 //go:build gofuzz 2 // +build gofuzz 3 4 package gossip 5 6 import ( 7 "bytes" 8 "errors" 9 "math/rand" 10 "sync" 11 12 _ "github.com/dvyukov/go-fuzz/go-fuzz-defs" 13 "github.com/unicornultrafoundation/go-helios/utils/cachescale" 14 "github.com/unicornultrafoundation/go-u2u/core/types" 15 "github.com/unicornultrafoundation/go-u2u/p2p" 16 "github.com/unicornultrafoundation/go-u2u/p2p/enode" 17 18 "github.com/unicornultrafoundation/go-u2u/evmcore" 19 "github.com/unicornultrafoundation/go-u2u/integration/makefakegenesis" 20 "github.com/unicornultrafoundation/go-u2u/native" 21 "github.com/unicornultrafoundation/go-u2u/u2u" 22 "github.com/unicornultrafoundation/go-u2u/utils" 23 "github.com/unicornultrafoundation/go-u2u/utils/signers/gsignercache" 24 ) 25 26 const ( 27 fuzzHot int = 1 // if the fuzzer should increase priority of the given input during subsequent fuzzing; 28 fuzzCold int = -1 // if the input must not be added to corpus even if gives new coverage; 29 fuzzNoMatter int = 0 // otherwise. 30 ) 31 32 var ( 33 fuzzedHandler *handler 34 ) 35 36 func FuzzHandler(data []byte) int { 37 var err error 38 if fuzzedHandler == nil { 39 fuzzedHandler, err = makeFuzzedHandler() 40 if err != nil { 41 panic(err) 42 } 43 } 44 45 msg, err := newFuzzMsg(data) 46 if err != nil { 47 return fuzzCold 48 } 49 input := &fuzzMsgReadWriter{msg} 50 other := &peer{ 51 version: ProtocolVersion, 52 Peer: p2p.NewPeer(randomID(), "fake-node-1", []p2p.Cap{}), 53 rw: input, 54 } 55 56 err = fuzzedHandler.handleMsg(other) 57 if err != nil { 58 return fuzzNoMatter 59 } 60 61 return fuzzHot 62 } 63 64 func makeFuzzedHandler() (h *handler, err error) { 65 const ( 66 genesisStakers = 3 67 genesisBalance = 1e18 68 genesisStake = 2 * 4e6 69 ) 70 71 genStore := makefakegenesis.FakeGenesisStore(genesisStakers, utils.ToU2U(genesisBalance), utils.ToU2U(genesisStake)) 72 genesis := genStore.Genesis() 73 74 config := DefaultConfig(cachescale.Identity) 75 store := NewMemStore() 76 _, err = store.ApplyGenesis(genesis) 77 if err != nil { 78 return 79 } 80 81 var ( 82 network = u2u.FakeNetRules() 83 heavyCheckReader HeavyCheckReader 84 gasPowerCheckReader GasPowerCheckReader 85 // TODO: init 86 ) 87 88 mu := new(sync.RWMutex) 89 feed := new(ServiceFeed) 90 net := store.GetRules() 91 txSigner := gsignercache.Wrap(types.LatestSignerForChainID(net.EvmChainConfig().ChainID)) 92 checkers := makeCheckers(config.HeavyCheck, txSigner, &heavyCheckReader, &gasPowerCheckReader, store) 93 94 txpool := evmcore.NewTxPool(evmcore.DefaultTxPoolConfig, network.EvmChainConfig(), &EvmStateReader{ 95 ServiceFeed: feed, 96 store: store, 97 }) 98 99 h, err = newHandler( 100 handlerConfig{ 101 config: config, 102 notifier: feed, 103 txpool: txpool, 104 engineMu: mu, 105 checkers: checkers, 106 s: store, 107 process: processCallback{ 108 Event: func(event *native.EventPayload) error { 109 return nil 110 }, 111 }, 112 }) 113 if err != nil { 114 return 115 } 116 117 h.Start(3) 118 return 119 } 120 121 func randomID() (id enode.ID) { 122 for i := range id { 123 id[i] = byte(rand.Intn(255)) 124 } 125 return id 126 } 127 128 type fuzzMsgReadWriter struct { 129 msg *p2p.Msg 130 } 131 132 func newFuzzMsg(data []byte) (*p2p.Msg, error) { 133 if len(data) < 1 { 134 return nil, errors.New("empty data") 135 } 136 137 var ( 138 codes = []uint64{ 139 HandshakeMsg, 140 EvmTxsMsg, 141 ProgressMsg, 142 NewEventIDsMsg, 143 GetEventsMsg, 144 EventsMsg, 145 RequestEventsStream, 146 EventsStreamResponse, 147 } 148 code = codes[int(data[0])%len(codes)] 149 ) 150 data = data[1:] 151 152 return &p2p.Msg{ 153 Code: code, 154 Size: uint32(len(data)), 155 Payload: bytes.NewReader(data), 156 }, nil 157 } 158 159 func (rw *fuzzMsgReadWriter) ReadMsg() (p2p.Msg, error) { 160 return *rw.msg, nil 161 } 162 163 func (rw *fuzzMsgReadWriter) WriteMsg(p2p.Msg) error { 164 return nil 165 }