-
Notifications
You must be signed in to change notification settings - Fork 13.6k
Description
Fingerprint::combine
is not a cryptographic hash, so when we use it we might lose the "cryptographic" guarantee of collision safety. Potentially even worse, Fingerprint::combine
is associative: Fingerprint::combine(Fingerprint::combine(a, b), c) = Fingerprint::combine(a, Fingerprint::combine(b, c))
, and that might cause "algebraic" collisions in some cases.
For example:
rust/src/librustc/dep_graph/dep_node.rs
Line 595 in 2f1ef9e
def_path_hash_0.0.combine(def_path_hash_1.0) |
rust/src/librustc/dep_graph/dep_node.rs
Lines 614 to 623 in 2f1ef9e
fn to_fingerprint(&self, tcx: TyCtxt) -> Fingerprint { | |
let mut fingerprint = Fingerprint::zero(); | |
for &def_id in self.0.iter() { | |
let def_path_hash = tcx.def_path_hash(def_id); | |
fingerprint = fingerprint.combine(def_path_hash.0); | |
} | |
fingerprint | |
} |
And another case added by my PR:
https://github.com/arielb1/rust/blob/d14ed92f6b5aa23fd06f8affe4554f2c370bc79d/src/librustc/dep_graph/dep_node.rs#L647-L657
I believe the only requirement for DepNode
is that the map from QueryKey -> (DepKind, Fingerprint)
is injective. It might be a good idea to have a good sense of the requirements there to avoid accidental collisions.