fix(#2050): use stable fnv-1a for avatar idempotency hash

This commit is contained in:
damocles 2026-06-27 20:58:20 +02:00 committed by mara
commit db3249a390

View file

@ -208,12 +208,18 @@ pub async fn sync_avatar(client: &Client, state_dir: &Path, account: &str) {
return;
}
};
// A non-crypto content hash is enough to answer "did the icon change?".
// FNV-1a content hash — enough to answer "did the icon change?" and
// deterministic across Rust/std versions (unlike `DefaultHasher`, whose
// output may change between toolchains, spuriously mismatching the
// persisted hash and re-uploading the same avatar). No crypto strength
// needed here, so no dependency on a hashing crate.
let hash = {
use std::hash::{Hash, Hasher};
let mut h = std::collections::hash_map::DefaultHasher::new();
bytes.hash(&mut h);
format!("{:016x}", h.finish())
let mut h: u64 = 0xcbf2_9ce4_8422_2325;
for &b in &bytes {
h ^= u64::from(b);
h = h.wrapping_mul(0x0000_0100_0000_01b3);
}
format!("{h:016x}")
};
let hash_file = state_dir.join("avatar-icon-hash");
if let Ok(prev) = fs::read_to_string(&hash_file).await