Skip to content

Initial value of FxHasher leads to avoidable collisions #17

Open
@eggyal

Description

@eggyal

It's easy to see that FxHasher { hash: 0 }.add_to_hash(0) is a fixed point (i.e. does not result in any change to the internal state self.hash):

rustc-hash/src/lib.rs

Lines 76 to 81 in 5e09ea0

impl FxHasher {
#[inline]
fn add_to_hash(&mut self, i: usize) {
self.hash = self.hash.rotate_left(5).bitxor(i).wrapping_mul(K);
}
}

In particular 0.rotate_left(5).bitxor(0).wrapping_mul(K) == 0.

Therefore initialising FxHasher with a hash value of 0 is a bit undesirable, as sequences of 0s (written to the hash before any non-zero value) cannot be distinguished by their hashes.

rustc-hash/src/lib.rs

Lines 69 to 74 in 5e09ea0

impl Default for FxHasher {
#[inline]
fn default() -> FxHasher {
FxHasher { hash: 0 }
}
}

Of course, there's always the possibility that a value of self.hash.rotate_left(5) could be written to the hasher, which will result in the internal state reaching 0—but in practice writing values of 0 can arise quite often, and choosing some other initial value would be quite beneficial? Perhaps even K?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions