diff --git a/core/commands/cmdutils/utils.go b/core/commands/cmdutils/utils.go index c793f516e..30249d016 100644 --- a/core/commands/cmdutils/utils.go +++ b/core/commands/cmdutils/utils.go @@ -2,12 +2,14 @@ package cmdutils import ( "fmt" + "slices" cmds "github.com/ipfs/go-ipfs-cmds" "github.com/ipfs/boxo/path" "github.com/ipfs/go-cid" coreiface "github.com/ipfs/kubo/core/coreiface" + "github.com/libp2p/go-libp2p/core/peer" ) const ( @@ -84,3 +86,13 @@ func PathOrCidPath(str string) (path.Path, error) { // Send back original err. return nil, originalErr } + +// CloneAddrInfo returns a copy of the AddrInfo with a cloned Addrs slice. +// This prevents data races if the sender reuses the backing array. +// See: https://github.com/ipfs/kubo/issues/11116 +func CloneAddrInfo(ai peer.AddrInfo) peer.AddrInfo { + return peer.AddrInfo{ + ID: ai.ID, + Addrs: slices.Clone(ai.Addrs), + } +} diff --git a/core/commands/routing.go b/core/commands/routing.go index a49e5dd32..5e1d5334d 100644 --- a/core/commands/routing.go +++ b/core/commands/routing.go @@ -11,6 +11,7 @@ import ( "github.com/ipfs/kubo/config" cmdenv "github.com/ipfs/kubo/core/commands/cmdenv" + "github.com/ipfs/kubo/core/commands/cmdutils" "github.com/ipfs/kubo/core/node" mh "github.com/multiformats/go-multihash" @@ -89,7 +90,7 @@ var findProvidersRoutingCmd = &cmds.Command{ defer cancel() pchan := n.Routing.FindProvidersAsync(ctx, c, numProviders) for p := range pchan { - np := p + np := cmdutils.CloneAddrInfo(p) routing.PublishQueryEvent(ctx, &routing.QueryEvent{ Type: routing.Provider, Responses: []*peer.AddrInfo{&np},