Skip to content

Commit 2d62bd0

Browse files
authored
Rollup merge of rust-lang#93615 - Kobzol:stable-hash-opt-endianness, r=the8472
Fix `isize` optimization in `StableHasher` for big-endian architectures This PR fixes a problem with the stable hash optimization introduced in rust-lang#93432. As `@michaelwoerister` has [found out](rust-lang#93432 (comment)), the original implementation wouldn't produce the same hash on little/big architectures. r? `@the8472`
2 parents 9ba09f9 + c21b8e1 commit 2d62bd0

File tree

2 files changed

+8
-3
lines changed

2 files changed

+8
-3
lines changed

compiler/rustc_data_structures/src/stable_hasher.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -133,18 +133,18 @@ impl Hasher for StableHasher {
133133

134134
#[inline]
135135
fn write_isize(&mut self, i: isize) {
136-
// Always treat isize as i64 so we get the same results on 32 and 64 bit
136+
// Always treat isize as a 64-bit number so we get the same results on 32 and 64 bit
137137
// platforms. This is important for symbol hashes when cross compiling,
138138
// for example. Sign extending here is preferable as it means that the
139139
// same negative number hashes the same on both 32 and 64 bit platforms.
140-
let value = (i as i64).to_le() as u64;
140+
let value = i as u64;
141141

142142
// Cold path
143143
#[cold]
144144
#[inline(never)]
145145
fn hash_value(state: &mut SipHasher128, value: u64) {
146146
state.write_u8(0xFF);
147-
state.write_u64(value);
147+
state.write_u64(value.to_le());
148148
}
149149

150150
// `isize` values often seem to have a small (positive) numeric value in practice.
@@ -161,6 +161,10 @@ impl Hasher for StableHasher {
161161
// 8 bytes. Since this prefix cannot occur when we hash a single byte, when we hash two
162162
// `isize`s that fit within a different amount of bytes, they should always produce a different
163163
// byte stream for the hasher.
164+
//
165+
// To ensure that this optimization hashes the exact same bytes on both little-endian and
166+
// big-endian architectures, we compare the value with 0xFF before we convert the number
167+
// into a unified representation (little-endian).
164168
if value < 0xFF {
165169
self.state.write_u8(value as u8);
166170
} else {

compiler/rustc_data_structures/src/stable_hasher/tests.rs

+1
Original file line numberDiff line numberDiff line change
@@ -159,4 +159,5 @@ fn test_isize_compression() {
159159
check_hash(0xAAAA, 0xAAAAAA);
160160
check_hash(0xAAAAAA, 0xAAAAAAAA);
161161
check_hash(0xFF, 0xFFFFFFFFFFFFFFFF);
162+
check_hash(u64::MAX /* -1 */, 1);
162163
}

0 commit comments

Comments
 (0)