From 2a2d5c869aeee6792209abc24874e57cd0e23e00 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Thu, 2 Apr 2026 13:10:20 +0000 Subject: [PATCH] types/change: fix slice aliasing in Change.Merge Merge copies the receiver by value, but the slice headers share the backing array with the original. When append has spare capacity, it writes through to the original's memory, and uniqueNodeIDs then sorts that shared data in place. Replace append with slices.Concat which always allocates a fresh backing array, preventing mutation of the receiver's slices. --- hscontrol/types/change/change.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hscontrol/types/change/change.go b/hscontrol/types/change/change.go index 37a63e80..c6ab9daa 100644 --- a/hscontrol/types/change/change.go +++ b/hscontrol/types/change/change.go @@ -66,9 +66,9 @@ func (r Change) Merge(other Change) Change { merged.SendAllPeers = r.SendAllPeers || other.SendAllPeers merged.RequiresRuntimePeerComputation = r.RequiresRuntimePeerComputation || other.RequiresRuntimePeerComputation - merged.PeersChanged = uniqueNodeIDs(append(r.PeersChanged, other.PeersChanged...)) - merged.PeersRemoved = uniqueNodeIDs(append(r.PeersRemoved, other.PeersRemoved...)) - merged.PeerPatches = append(r.PeerPatches, other.PeerPatches...) + merged.PeersChanged = uniqueNodeIDs(slices.Concat(r.PeersChanged, other.PeersChanged)) + merged.PeersRemoved = uniqueNodeIDs(slices.Concat(r.PeersRemoved, other.PeersRemoved)) + merged.PeerPatches = slices.Concat(r.PeerPatches, other.PeerPatches) // Preserve OriginNode for self-update detection. // If either change has OriginNode set, keep it so the mapper