diff --git a/src/slices/slices.go b/src/slices/slices.go index 25c124d291..f53c93be52 100644 --- a/src/slices/slices.go +++ b/src/slices/slices.go @@ -346,8 +346,13 @@ func Replace[S ~[]E, E any](s S, i, j int, v ...E) S { // The elements are copied using assignment, so this is a shallow clone. // The result may have additional unused capacity. func Clone[S ~[]E, E any](s S) S { - // The s[:0:0] preserves nil in case it matters. - return append(s[:0:0], s...) + // Preserve nilness in case it matters. + if s == nil { + return nil + } + // Avoid s[:0:0] as it leads to unwanted liveness when cloning a + // zero-length slice of a large array; see https://go.dev/issue/68488. + return append(S{}, s...) } // Compact replaces consecutive runs of equal elements with a single copy. diff --git a/src/slices/slices_test.go b/src/slices/slices_test.go index 68c8a3adc2..26cbb87fcd 100644 --- a/src/slices/slices_test.go +++ b/src/slices/slices_test.go @@ -12,6 +12,7 @@ import ( . "slices" "strings" "testing" + "unsafe" ) var equalIntTests = []struct { @@ -1450,3 +1451,12 @@ func TestRepeatPanics(t *testing.T) { } } } + +func TestIssue68488(t *testing.T) { + s := make([]int, 3) + clone := Clone(s[1:1]) + switch unsafe.SliceData(clone) { + case &s[0], &s[1], &s[2]: + t.Error("clone keeps alive s due to array overlap") + } +}