internal/deephash: 8 bits of output is not enough

Running hex.Encode(b, b) is a bad idea.
The first byte of input will overwrite the first two bytes of output.
Subsequent bytes have no impact on the output.

Not related to today's IPv6 bug, but...wh::ps.

This caused us to spuriously ignore some wireguard config updates.

Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
crawshaw/deephash
Josh Bleecher Snyder 3 years ago committed by Josh Bleecher Snyder
parent c35a832de6
commit 7f095617f2

@ -24,8 +24,12 @@ func calcHash(v interface{}) string {
printTo(b, v, scratch) printTo(b, v, scratch)
b.Flush() b.Flush()
scratch = h.Sum(scratch[:0]) scratch = h.Sum(scratch[:0])
hex.Encode(scratch[:cap(scratch)], scratch[:sha256.Size]) // The first sha256.Size bytes contain the hash.
return string(scratch[:sha256.Size*2]) // Hex-encode that into the next sha256.Size*2 bytes.
src := scratch[:sha256.Size]
dst := scratch[sha256.Size:cap(scratch)]
n := hex.Encode(dst, src)
return string(dst[:n])
} }
// UpdateHash sets last to the hash of v and reports whether its value changed. // UpdateHash sets last to the hash of v and reports whether its value changed.

@ -134,3 +134,14 @@ func BenchmarkHashMapAcyclic(b *testing.B) {
} }
} }
} }
func TestExhaustive(t *testing.T) {
seen := make(map[string]bool)
for i := 0; i < 100000; i++ {
s := calcHash(i)
if seen[s] {
t.Fatalf("hash collision %v", i)
}
seen[s] = true
}
}

Loading…
Cancel
Save