diff options
| author | Jorropo <jorropo.pgm@gmail.com> | 2024-07-17 14:15:32 +0200 |
|---|---|---|
| committer | Gopher Robot <gobot@golang.org> | 2024-09-29 05:04:42 +0000 |
| commit | 2bffb8b3fb2d9137ccfa87fc35137371b86a2e96 (patch) | |
| tree | cee4b43bad8c21f567a4c377482eb38267e2f24c /src | |
| parent | eb6f2c24cd17c0ca1df7e343f8d9187eef7d6e13 (diff) | |
| download | go-2bffb8b3fb2d9137ccfa87fc35137371b86a2e96.tar.xz | |
slices: prevent Clone keeping alive the array when cloning empty slices
Fixes #68488
Change-Id: I39aba22cdfe8ca0bbe69db7c64f1bca75fa067fa
Reviewed-on: https://go-review.googlesource.com/c/go/+/598875
Reviewed-by: Keith Randall <khr@golang.org>
Commit-Queue: Ian Lance Taylor <iant@google.com>
Reviewed-by: Keith Randall <khr@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Ian Lance Taylor <iant@google.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Diffstat (limited to 'src')
| -rw-r--r-- | src/slices/slices.go | 9 | ||||
| -rw-r--r-- | src/slices/slices_test.go | 10 |
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") + } +} |
