2 files changed +44
-4
lines changed Original file line number Diff line number Diff line change @@ -3192,15 +3192,19 @@ impl Hash for Path {
3192
3192
let bytes = & bytes[ prefix_len..] ;
3193
3193
3194
3194
let mut component_start = 0 ;
3195
- let mut bytes_hashed = 0 ;
3195
+ // track some extra state to avoid prefix collisions.
3196
+ // ["foo", "bar"] and ["foobar"], will have the same payload bytes
3197
+ // but result in different chunk_bits
3198
+ let mut chunk_bits: usize = 0 ;
3196
3199
3197
3200
for i in 0 ..bytes. len ( ) {
3198
3201
let is_sep = if verbatim { is_verbatim_sep ( bytes[ i] ) } else { is_sep_byte ( bytes[ i] ) } ;
3199
3202
if is_sep {
3200
3203
if i > component_start {
3201
3204
let to_hash = & bytes[ component_start..i] ;
3205
+ chunk_bits = chunk_bits. wrapping_add ( to_hash. len ( ) ) ;
3206
+ chunk_bits = chunk_bits. rotate_right ( 2 ) ;
3202
3207
h. write ( to_hash) ;
3203
- bytes_hashed += to_hash. len ( ) ;
3204
3208
}
3205
3209
3206
3210
// skip over separator and optionally a following CurDir item
@@ -3221,11 +3225,12 @@ impl Hash for Path {
3221
3225
3222
3226
if component_start < bytes. len ( ) {
3223
3227
let to_hash = & bytes[ component_start..] ;
3228
+ chunk_bits = chunk_bits. wrapping_add ( to_hash. len ( ) ) ;
3229
+ chunk_bits = chunk_bits. rotate_right ( 2 ) ;
3224
3230
h. write ( to_hash) ;
3225
- bytes_hashed += to_hash. len ( ) ;
3226
3231
}
3227
3232
3228
- h. write_usize ( bytes_hashed ) ;
3233
+ h. write_usize ( chunk_bits ) ;
3229
3234
}
3230
3235
}
3231
3236
Original file line number Diff line number Diff line change @@ -1619,6 +1619,20 @@ pub fn test_compare() {
1619
1619
relative_from: Some ( "" )
1620
1620
) ;
1621
1621
1622
+ tc ! ( "foo//" , "foo" ,
1623
+ eq: true ,
1624
+ starts_with: true ,
1625
+ ends_with: true ,
1626
+ relative_from: Some ( "" )
1627
+ ) ;
1628
+
1629
+ tc ! ( "foo///" , "foo" ,
1630
+ eq: true ,
1631
+ starts_with: true ,
1632
+ ends_with: true ,
1633
+ relative_from: Some ( "" )
1634
+ ) ;
1635
+
1622
1636
tc ! ( "foo/." , "foo" ,
1623
1637
eq: true ,
1624
1638
starts_with: true ,
@@ -1633,13 +1647,34 @@ pub fn test_compare() {
1633
1647
relative_from: Some ( "" )
1634
1648
) ;
1635
1649
1650
+ tc ! ( "foo/.//bar" , "foo/bar" ,
1651
+ eq: true ,
1652
+ starts_with: true ,
1653
+ ends_with: true ,
1654
+ relative_from: Some ( "" )
1655
+ ) ;
1656
+
1657
+ tc ! ( "foo//./bar" , "foo/bar" ,
1658
+ eq: true ,
1659
+ starts_with: true ,
1660
+ ends_with: true ,
1661
+ relative_from: Some ( "" )
1662
+ ) ;
1663
+
1636
1664
tc ! ( "foo/bar" , "foo" ,
1637
1665
eq: false ,
1638
1666
starts_with: true ,
1639
1667
ends_with: false ,
1640
1668
relative_from: Some ( "bar" )
1641
1669
) ;
1642
1670
1671
+ tc ! ( "foo/bar" , "foobar" ,
1672
+ eq: false ,
1673
+ starts_with: false ,
1674
+ ends_with: false ,
1675
+ relative_from: None
1676
+ ) ;
1677
+
1643
1678
tc ! ( "foo/bar/baz" , "foo/bar" ,
1644
1679
eq: false ,
1645
1680
starts_with: true ,
0 commit comments