aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/slices/slices.go9
-rw-r--r--src/slices/slices_test.go10
2 files changed, 17 insertions, 2 deletions
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")
+ }
+}