mirror of
https://github.com/tailscale/tailscale.git
synced 2025-02-19 19:38:40 +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()
|
h.reset()
|
||||||
seedOnce.Do(initSeed)
|
seedOnce.Do(initSeed)
|
||||||
h.hashUint64(seed)
|
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()
|
return h.sum()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,6 +61,7 @@ func TestHash(t *testing.T) {
|
|||||||
}
|
}
|
||||||
type MyBool bool
|
type MyBool bool
|
||||||
type MyHeader tar.Header
|
type MyHeader tar.Header
|
||||||
|
var zeroFloat64 float64
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
in tuple
|
in tuple
|
||||||
wantEq bool
|
wantEq bool
|
||||||
@ -102,6 +103,10 @@ func TestHash(t *testing.T) {
|
|||||||
{in: tuple{iface{&MyHeader{}}, iface{&tar.Header{}}}, wantEq: false},
|
{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]MyBool{}}, iface{[]map[string]MyBool{}}}, wantEq: true},
|
||||||
{in: tuple{iface{[]map[string]bool{}}, iface{[]map[string]MyBool{}}}, wantEq: false},
|
{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 {
|
in: func() tuple {
|
||||||
i1 := 1
|
i1 := 1
|
||||||
@ -117,7 +122,7 @@ func TestHash(t *testing.T) {
|
|||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
gotEq := Hash(tt.in[0]) == Hash(tt.in[1])
|
gotEq := Hash(tt.in[0]) == Hash(tt.in[1])
|
||||||
if gotEq != tt.wantEq {
|
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…
x
Reference in New Issue
Block a user