swarm/network: fix data race in stream.(*Peer).handleOfferedHashesMsg() (#18468)

* swarm/network: fix data race in stream.(*Peer).handleOfferedHashesMsg()

handleOfferedHashesMsg() contained a data race:
- read => in a goroutine, call to c.batchDone()
- write => in the main thread, write to c.sessionAt

c.batchDone() contained a call to c.AddInterval(). Client was a value
receiver for AddInterval. So on c.AddInterval() call the whole client
struct got copied (read) while one of its field was modified in
handleOfferedHashesMsg() (write).

fixes ethersphere/go-ethereum#1086

* swarm/network: simplify some trivial statements
This commit is contained in:
Ferenc Szabo 2019-01-17 14:44:29 +01:00 committed by Anton Evangelatov
parent 81e26d5a48
commit 4f8ec44565
1 changed files with 4 additions and 9 deletions

View File

@ -666,17 +666,16 @@ func peerStreamIntervalsKey(p *Peer, s Stream) string {
return p.ID().String() + s.String() return p.ID().String() + s.String()
} }
func (c client) AddInterval(start, end uint64) (err error) { func (c *client) AddInterval(start, end uint64) (err error) {
i := &intervals.Intervals{} i := &intervals.Intervals{}
err = c.intervalsStore.Get(c.intervalsKey, i) if err = c.intervalsStore.Get(c.intervalsKey, i); err != nil {
if err != nil {
return err return err
} }
i.Add(start, end) i.Add(start, end)
return c.intervalsStore.Put(c.intervalsKey, i) return c.intervalsStore.Put(c.intervalsKey, i)
} }
func (c client) NextInterval() (start, end uint64, err error) { func (c *client) NextInterval() (start, end uint64, err error) {
i := &intervals.Intervals{} i := &intervals.Intervals{}
err = c.intervalsStore.Get(c.intervalsKey, i) err = c.intervalsStore.Get(c.intervalsKey, i)
if err != nil { if err != nil {
@ -733,11 +732,7 @@ func (c *client) batchDone(p *Peer, req *OfferedHashesMsg, hashes []byte) error
} }
return nil return nil
} }
// TODO: make a test case for testing if the interval is added when the batch is done return c.AddInterval(req.From, req.To)
if err := c.AddInterval(req.From, req.To); err != nil {
return err
}
return nil
} }
func (c *client) close() { func (c *client) close() {