]> Cypherpunks repositories - gostls13.git/commitdiff
slices: prevent Clone keeping alive the array when cloning empty slices
authorJorropo <jorropo.pgm@gmail.com>
Wed, 17 Jul 2024 12:15:32 +0000 (14:15 +0200)
committerGopher Robot <gobot@golang.org>
Sun, 29 Sep 2024 05:04:42 +0000 (05:04 +0000)
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>
src/slices/slices.go
src/slices/slices_test.go

index 25c124d29154001f54d01cc0011831526e681f54..f53c93be52d9aa34ac199133b30cbaed33c2d594 100644 (file)
@@ -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.
index 68c8a3adc252f0e1363bfc16cd134ff6fb16a288..26cbb87fcd6c04e40ab2c44431e263b2427fadf7 100644 (file)
@@ -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")
+       }
+}