mirror of
https://github.com/golang/go
synced 2024-09-05 07:54:46 +00:00
![Keith Randall](/assets/img/avatar_default.png)
The signature of the mapassign_fast* routines need to distinguish the pointerness of their key argument. If the affected routines suspend part way through, the object pointed to by the key might get garbage collected because the key is typed as a uint{32,64}. This is not a problem for mapaccess or mapdelete because the key in those situations do not live beyond the call involved. If the object referenced by the key is garbage collected prematurely, the code still works fine. Even if that object is subsequently reallocated, it can't be written to the map in time to affect the lookup/delete. Fixes #22781 Change-Id: I0bbbc5e9883d5ce702faf4e655348be1191ee439 Reviewed-on: https://go-review.googlesource.com/79018 Run-TryBot: Keith Randall <khr@golang.org> Reviewed-by: Austin Clements <austin@google.com> Reviewed-by: Martin Möhrmann <moehrmann@google.com>
30 lines
680 B
Go
30 lines
680 B
Go
// run
|
|
|
|
// Copyright 2017 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 "runtime/debug"
|
|
|
|
type T struct {
|
|
// >= 16 bytes to avoid tiny alloc.
|
|
a, b int
|
|
}
|
|
|
|
func main() {
|
|
debug.SetGCPercent(1)
|
|
for i := 0; i < 100000; i++ {
|
|
m := make(map[*T]struct{}, 0)
|
|
for j := 0; j < 20; j++ {
|
|
// During the call to mapassign_fast64, the key argument
|
|
// was incorrectly treated as a uint64. If the stack was
|
|
// scanned during that call, the only pointer to k was
|
|
// missed, leading to *k being collected prematurely.
|
|
k := new(T)
|
|
m[k] = struct{}{}
|
|
}
|
|
}
|
|
}
|