-
Notifications
You must be signed in to change notification settings - Fork 17.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
runtime: make typehash match compiler generated hashes exactly
If typehash (used by reflect) does not match the built-in map's hash, then problems occur. If a map is built using reflect, and then assigned to a variable of map type, the hash function can change. That causes very bad things. This issue is rare. MapOf consults a cache of all types that occur in the binary before making a new one. To make a true new map type (with a hash function derived from typehash) that map type must not occur in the binary anywhere. But to cause the bug, we need a variable of that type in order to assign to it. The only way to make that work is to use a named map type for the variable, so it is distinct from the unnamed version that MapOf looks for. Fixes #37716 Change-Id: I3537bfceca8cbfa1af84202f432f3c06953fe0ed Reviewed-on: https://go-review.googlesource.com/c/go/+/222357 Run-TryBot: Keith Randall <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Cherry Zhang <[email protected]>
- Loading branch information
Showing
5 changed files
with
127 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
// run | ||
|
||
// Copyright 2020 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 "reflect" | ||
|
||
// complicated enough to require a compile-generated hash function | ||
type K struct { | ||
a, b int32 // these get merged by the compiler into a single field, something typehash doesn't do | ||
c float64 | ||
} | ||
|
||
func main() { | ||
k := K{a: 1, b: 2, c: 3} | ||
|
||
// Make a reflect map. | ||
m := reflect.MakeMap(reflect.MapOf(reflect.TypeOf(K{}), reflect.TypeOf(true))) | ||
m.SetMapIndex(reflect.ValueOf(k), reflect.ValueOf(true)) | ||
|
||
// The binary must not contain the type map[K]bool anywhere, or reflect.MapOf | ||
// will use that type instead of making a new one. So use an equivalent named type. | ||
type M map[K]bool | ||
var x M | ||
reflect.ValueOf(&x).Elem().Set(m) | ||
if !x[k] { | ||
panic("key not found") | ||
} | ||
} |