From 682bcc86574b57133bc8a0ae52a75d2fc81db9a9 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Wed, 21 Aug 2019 10:47:31 -0700 Subject: [PATCH] fix listen addrs race Copy the listen address list before returning it. If you're wondering about the syntax: https://github.com/go101/go101/wiki/How-to-perfectly-clone-a-slice%3F --- swarm_addr.go | 6 +++--- swarm_addr_test.go | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/swarm_addr.go b/swarm_addr.go index 6210a4f..650fb79 100644 --- a/swarm_addr.go +++ b/swarm_addr.go @@ -35,8 +35,8 @@ func (s *Swarm) InterfaceListenAddresses() ([]ma.Multiaddr, error) { s.listeners.RUnlock() // RLock end if ifaceListenAddres != nil && !isEOL { - // Cache is valid - return ifaceListenAddres, nil + // Cache is valid, clone the slice + return append(ifaceListenAddres[:0:0], ifaceListenAddres...), nil } // Cache is not valid @@ -64,5 +64,5 @@ func (s *Swarm) InterfaceListenAddresses() ([]ma.Multiaddr, error) { s.listeners.Unlock() // Lock end - return ifaceListenAddres, nil + return append(ifaceListenAddres[:0:0], ifaceListenAddres...), nil } diff --git a/swarm_addr_test.go b/swarm_addr_test.go index e75d660..5009946 100644 --- a/swarm_addr_test.go +++ b/swarm_addr_test.go @@ -35,3 +35,21 @@ func TestDialBadAddrs(t *testing.T) { test(m("/ip6/fe80::100")) // link local test(m("/ip4/127.0.0.1/udp/1234/utp")) // utp } + +func TestAddrRace(t *testing.T) { + ctx := context.Background() + s := makeSwarms(ctx, t, 1)[0] + + a1, err := s.InterfaceListenAddresses() + if err != nil { + t.Fatal(err) + } + a2, err := s.InterfaceListenAddresses() + if err != nil { + t.Fatal(err) + } + + if len(a1) > 0 && len(a2) > 0 && &a1[0] == &a2[0] { + t.Fatal("got the exact same address set twice; this could lead to data races") + } +} -- GitLab