mirror of
https://github.com/tailscale/tailscale.git
synced 2024-11-25 19:15:34 +00:00
util/deephash: fix collisions between different types
Updates #4883 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
parent
4f6fa3d63a
commit
8c5c87be26
@ -127,7 +127,18 @@ func Hash(v any) (s Sum) {
|
||||
h.reset()
|
||||
seedOnce.Do(initSeed)
|
||||
h.hashUint64(seed)
|
||||
h.hashValue(reflect.ValueOf(v), false)
|
||||
|
||||
rv := reflect.ValueOf(v)
|
||||
if rv.IsValid() {
|
||||
// Always treat the Hash input as an interface (it is), including hashing
|
||||
// its type, otherwise two Hash calls of different types could hash to the
|
||||
// same bytes off the different types and get equivalent Sum values. This is
|
||||
// the same thing that we do for reflect.Kind Interface in hashValue, but
|
||||
// the initial reflect.ValueOf from an interface value effectively strips
|
||||
// the interface box off so we have to do it at the top level by hand.
|
||||
h.hashType(rv.Type())
|
||||
h.hashValue(rv, false)
|
||||
}
|
||||
return h.sum()
|
||||
}
|
||||
|
||||
|
@ -61,6 +61,7 @@ type scalars struct {
|
||||
}
|
||||
type MyBool bool
|
||||
type MyHeader tar.Header
|
||||
var zeroFloat64 float64
|
||||
tests := []struct {
|
||||
in tuple
|
||||
wantEq bool
|
||||
@ -102,6 +103,10 @@ type scalars struct {
|
||||
{in: tuple{iface{&MyHeader{}}, iface{&tar.Header{}}}, wantEq: false},
|
||||
{in: tuple{iface{[]map[string]MyBool{}}, iface{[]map[string]MyBool{}}}, wantEq: true},
|
||||
{in: tuple{iface{[]map[string]bool{}}, iface{[]map[string]MyBool{}}}, wantEq: false},
|
||||
{in: tuple{zeroFloat64, -zeroFloat64}, wantEq: false}, // Issue 4883 (false alarm)
|
||||
{in: tuple{[]any(nil), 0.0}, wantEq: false}, // Issue 4883
|
||||
{in: tuple{[]any(nil), uint8(0)}, wantEq: false}, // Issue 4883
|
||||
{in: tuple{nil, nil}, wantEq: true}, // Issue 4883
|
||||
{
|
||||
in: func() tuple {
|
||||
i1 := 1
|
||||
@ -117,7 +122,7 @@ type scalars struct {
|
||||
for _, tt := range tests {
|
||||
gotEq := Hash(tt.in[0]) == Hash(tt.in[1])
|
||||
if gotEq != tt.wantEq {
|
||||
t.Errorf("(Hash(%v) == Hash(%v)) = %v, want %v", tt.in[0], tt.in[1], gotEq, tt.wantEq)
|
||||
t.Errorf("(Hash(%T %v) == Hash(%T %v)) = %v, want %v", tt.in[0], tt.in[0], tt.in[1], tt.in[1], gotEq, tt.wantEq)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user