mirror of
https://github.com/golang/go
synced 2024-11-23 06:40:05 -07:00
1b4cf43e42
In rare situations, like during same-sized grows, the source map for maps.Clone may be overloaded (has more than 6.5 entries per bucket). This causes the runtime to allocate a larger bucket array for the destination map than for the source map. The maps.Clone code walks off the end of the source array if it is smaller than the destination array. This is a pretty simple fix, ensuring that the destination bucket array is never longer than the source bucket array. Maybe a better fix is to make the Clone code handle shorter source arrays correctly, but this fix is deliberately simple to reduce the risk of backporting this fix. Fixes #69110 Change-Id: I824c93d1db690999f25a3c43b2816fc28ace7509 Reviewed-on: https://go-review.googlesource.com/c/go/+/609757 Reviewed-by: Keith Randall <khr@google.com> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
58 lines
1.1 KiB
Go
58 lines
1.1 KiB
Go
// run
|
|
|
|
// Copyright 2024 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package main
|
|
|
|
import (
|
|
"maps"
|
|
_ "unsafe"
|
|
)
|
|
|
|
func main() {
|
|
for i := 0; i < 100; i++ {
|
|
f()
|
|
}
|
|
}
|
|
|
|
const NB = 4
|
|
|
|
func f() {
|
|
// Make a map with NB buckets, at max capacity.
|
|
// 6.5 entries/bucket.
|
|
ne := NB * 13 / 2
|
|
m := map[int]int{}
|
|
for i := 0; i < ne; i++ {
|
|
m[i] = i
|
|
}
|
|
|
|
// delete/insert a lot, to hopefully get lots of overflow buckets
|
|
// and trigger a same-size grow.
|
|
ssg := false
|
|
for i := ne; i < ne+1000; i++ {
|
|
delete(m, i-ne)
|
|
m[i] = i
|
|
if sameSizeGrow(m) {
|
|
ssg = true
|
|
break
|
|
}
|
|
}
|
|
if !ssg {
|
|
return
|
|
}
|
|
|
|
// Insert 1 more entry, which would ordinarily trigger a growth.
|
|
// We can't grow while growing, so we instead go over our
|
|
// target capacity.
|
|
m[-1] = -1
|
|
|
|
// Cloning in this state will make a map with a destination bucket
|
|
// array twice the size of the source.
|
|
_ = maps.Clone(m)
|
|
}
|
|
|
|
//go:linkname sameSizeGrow runtime.sameSizeGrowForIssue69110Test
|
|
func sameSizeGrow(m map[int]int) bool
|