aboutsummaryrefslogtreecommitdiff
path: root/src/maps
diff options
context:
space:
mode:
authorKeith Randall <khr@golang.org>2023-11-30 22:59:04 -0800
committerKeith Randall <khr@golang.org>2023-12-05 17:05:56 +0000
commit16d3040a84be821d801b75bd1a3d8ab4cc89ee36 (patch)
tree68d04d9721fac23f811f34200c150385d0b948e6 /src/maps
parent098f059d077d01d9151e2e76901f62a7f2d52fec (diff)
downloadgo-16d3040a84be821d801b75bd1a3d8ab4cc89ee36.tar.gz
go-16d3040a84be821d801b75bd1a3d8ab4cc89ee36.zip
maps: fix aliasing problems with Clone
Make sure to alloc+copy large keys and values instead of aliasing them, when they might be updated by a future assignment. Fixes #64474 Change-Id: Ie2226a81cf3897e4e2ee24472f2966d397ace53f Reviewed-on: https://go-review.googlesource.com/c/go/+/546515 Reviewed-by: Cherry Mui <cherryyz@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Keith Randall <khr@google.com> Reviewed-by: Mauri de Souza Meneguzzo <mauri870@gmail.com>
Diffstat (limited to 'src/maps')
-rw-r--r--src/maps/maps_test.go58
1 files changed, 58 insertions, 0 deletions
diff --git a/src/maps/maps_test.go b/src/maps/maps_test.go
index 5e3f9ca03b..fa30fe8c2b 100644
--- a/src/maps/maps_test.go
+++ b/src/maps/maps_test.go
@@ -182,3 +182,61 @@ func TestCloneWithMapAssign(t *testing.T) {
}
}
}
+
+func TestCloneLarge(t *testing.T) {
+ // See issue 64474.
+ type K [17]float64 // > 128 bytes
+ type V [17]float64
+
+ var zero float64
+ negZero := -zero
+
+ for tst := 0; tst < 3; tst++ {
+ // Initialize m with a key and value.
+ m := map[K]V{}
+ var k1 K
+ var v1 V
+ m[k1] = v1
+
+ switch tst {
+ case 0: // nothing, just a 1-entry map
+ case 1:
+ // Add more entries to make it 2 buckets
+ // 1 entry already
+ // 7 more fill up 1 bucket
+ // 1 more to grow to 2 buckets
+ for i := 0; i < 7+1; i++ {
+ m[K{float64(i) + 1}] = V{}
+ }
+ case 2:
+ // Capture the map mid-grow
+ // 1 entry already
+ // 7 more fill up 1 bucket
+ // 5 more (13 total) fill up 2 buckets
+ // 13 more (26 total) fill up 4 buckets
+ // 1 more to start the 4->8 bucket grow
+ for i := 0; i < 7+5+13+1; i++ {
+ m[K{float64(i) + 1}] = V{}
+ }
+ }
+
+ // Clone m, which should freeze the map's contents.
+ c := Clone(m)
+
+ // Update m with new key and value.
+ k2, v2 := k1, v1
+ k2[0] = negZero
+ v2[0] = 1.0
+ m[k2] = v2
+
+ // Make sure c still has its old key and value.
+ for k, v := range c {
+ if math.Signbit(k[0]) {
+ t.Errorf("tst%d: sign bit of key changed; got %v want %v", tst, k, k1)
+ }
+ if v != v1 {
+ t.Errorf("tst%d: value changed; got %v want %v", tst, v, v1)
+ }
+ }
+ }
+}