stir the hash state a little to avoid prefix collisions · model-checking/verify-rust-std@ed3d487 (original) (raw)

Original file line number Diff line number Diff line change
@@ -3098,15 +3098,19 @@ impl Hash for Path {
3098 3098 let bytes = &bytes[prefix_len..];
3099 3099
3100 3100 let mut component_start = 0;
3101 -let mut bytes_hashed = 0;
3101 +// track some extra state to avoid prefix collisions.
3102 +// ["foo", "bar"] and ["foobar"], will have the same payload bytes
3103 +// but result in different chunk_bits
3104 +let mut chunk_bits: usize = 0;
3102 3105
3103 3106 for i in 0..bytes.len() {
3104 3107 let is_sep = if verbatim { is_verbatim_sep(bytes[i]) } else { is_sep_byte(bytes[i]) };
3105 3108 if is_sep {
3106 3109 if i > component_start {
3107 3110 let to_hash = &bytes[component_start..i];
3111 + chunk_bits = chunk_bits.wrapping_add(to_hash.len());
3112 + chunk_bits = chunk_bits.rotate_right(2);
3108 3113 h.write(to_hash);
3109 - bytes_hashed += to_hash.len();
3110 3114 }
3111 3115
3112 3116 // skip over separator and optionally a following CurDir item
@@ -3127,11 +3131,12 @@ impl Hash for Path {
3127 3131
3128 3132 if component_start < bytes.len() {
3129 3133 let to_hash = &bytes[component_start..];
3134 + chunk_bits = chunk_bits.wrapping_add(to_hash.len());
3135 + chunk_bits = chunk_bits.rotate_right(2);
3130 3136 h.write(to_hash);
3131 - bytes_hashed += to_hash.len();
3132 3137 }
3133 3138
3134 - h.write_usize(bytes_hashed);
3139 + h.write_usize(chunk_bits);
3135 3140 }
3136 3141 }
3137 3142