Skip to content

Commit 13339c7

Browse files
randall77cagedmantis
authored andcommitted
[release-branch.go1.21] runtime: fix maps.Clone bug when cloning a map mid-grow
Fixes #62204 Change-Id: I0459d3f481b0cd20102f6d9fd3ea84335a7739a8 Reviewed-on: https://go-review.googlesource.com/c/go/+/522317 Reviewed-by: Cuong Manh Le <[email protected]> Reviewed-by: Keith Randall <[email protected]> Reviewed-by: Bryan Mills <[email protected]> Run-TryBot: Keith Randall <[email protected]> TryBot-Result: Gopher Robot <[email protected]> (cherry picked from commit b303fb4) Reviewed-on: https://go-review.googlesource.com/c/go/+/522936 Reviewed-by: Carlos Amedee <[email protected]>
1 parent 2977709 commit 13339c7

File tree

2 files changed

+33
-1
lines changed

2 files changed

+33
-1
lines changed

src/runtime/map.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1553,7 +1553,7 @@ func mapclone2(t *maptype, src *hmap) *hmap {
15531553
}
15541554

15551555
if oldB >= dst.B { // main bucket bits in dst is less than oldB bits in src
1556-
dstBmap := (*bmap)(add(dst.buckets, uintptr(i)&bucketMask(dst.B)))
1556+
dstBmap := (*bmap)(add(dst.buckets, (uintptr(i)&bucketMask(dst.B))*uintptr(t.BucketSize)))
15571557
for dstBmap.overflow(t) != nil {
15581558
dstBmap = dstBmap.overflow(t)
15591559
}

test/fixedbugs/issue62203.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// run
2+
3+
// Copyright 2023 The Go Authors. All rights reserved.
4+
// Use of this source code is governed by a BSD-style
5+
// license that can be found in the LICENSE file.
6+
7+
package main
8+
9+
import (
10+
"fmt"
11+
"maps"
12+
)
13+
14+
func main() {
15+
m := map[string]struct{}{}
16+
17+
// Fill m up to the max for 4 buckets = 48 entries.
18+
for i := 0; i < 48; i++ {
19+
m[fmt.Sprintf("%d", i)] = struct{}{}
20+
}
21+
22+
// Add a 49th entry, to start a grow to 8 buckets.
23+
m["foo"] = struct{}{}
24+
25+
// Remove that 49th entry. m is still growing to 8 buckets,
26+
// but a clone of m will only have 4 buckets because it
27+
// only needs to fit 48 entries.
28+
delete(m, "foo")
29+
30+
// Clone an 8-bucket map to a 4-bucket map.
31+
_ = maps.Clone(m)
32+
}

0 commit comments

Comments
 (0)