fix(routing): defensive clone of AddrInfo from provider channel (#11120)
Belt-and-suspenders defense against data races where routing subsystem (DHT or delegated routing) may reuse backing array. Clones AddrInfo before publishing to QueryEvent to ensure isolated copy. Closes https://github.com/ipfs/kubo/issues/11116
Marcin Rataj committed
Jan 9, 2026 at 21:40 UTC
de20a78a1f8005afea0f8268ac74038a001e808a
2 files changed
+14
-1
core/commands/cmdutils/utils.go
+12
@@ -2,12 +2,14 @@ package cmdutils
2
3
import (
4
"fmt"
5
+ "slices"
6
7
cmds "github.com/ipfs/go-ipfs-cmds"
8
9
"github.com/ipfs/boxo/path"
10
"github.com/ipfs/go-cid"
11
coreiface "github.com/ipfs/kubo/core/coreiface"
12
+ "github.com/libp2p/go-libp2p/core/peer"
13
)
14
15
const (
@@ -84,3 +86,13 @@ func PathOrCidPath(str string) (path.Path, error) {
86
// Send back original err.
87
return nil, originalErr
88
}
89
+
90
+// CloneAddrInfo returns a copy of the AddrInfo with a cloned Addrs slice.
91
+// This prevents data races if the sender reuses the backing array.
92
+// See: https://github.com/ipfs/kubo/issues/11116
93
+func CloneAddrInfo(ai peer.AddrInfo) peer.AddrInfo {
94
+ return peer.AddrInfo{
95
+ ID: ai.ID,
96
+ Addrs: slices.Clone(ai.Addrs),
97
+ }
98
+}
core/commands/routing.go
+2
-1
@@ -11,6 +11,7 @@ import (
11
12
"github.com/ipfs/kubo/config"
13
cmdenv "github.com/ipfs/kubo/core/commands/cmdenv"
14
+ "github.com/ipfs/kubo/core/commands/cmdutils"
15
"github.com/ipfs/kubo/core/node"
16
mh "github.com/multiformats/go-multihash"
17
@@ -89,7 +90,7 @@ var findProvidersRoutingCmd = &cmds.Command{
90
defer cancel()
91
pchan := n.Routing.FindProvidersAsync(ctx, c, numProviders)
92
for p := range pchan {
92
- np := p
93
+ np := cmdutils.CloneAddrInfo(p)
94
routing.PublishQueryEvent(ctx, &routing.QueryEvent{
95
Type: routing.Provider,
96
Responses: []*peer.AddrInfo{&np},