1 use core::hash::Hash;
2 cfg_if::cfg_if! {
3     if #[cfg(any(
4         all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes", not(miri)),
5         all(feature = "nightly-arm-aes", target_arch = "aarch64", target_feature = "aes", not(miri)),
6         all(feature = "nightly-arm-aes", target_arch = "arm", target_feature = "aes", not(miri)),
7     ))] {
8         use crate::aes_hash::*;
9     } else {
10         use crate::fallback_hash::*;
11     }
12 }
13 cfg_if::cfg_if! {
14     if #[cfg(feature = "specialize")]{
15         use crate::BuildHasherExt;
16     }
17 }
18 cfg_if::cfg_if! {
19     if #[cfg(feature = "std")] {
20         extern crate std as alloc;
21     } else {
22         extern crate alloc;
23     }
24 }
25 
26 #[cfg(feature = "atomic-polyfill")]
27 use atomic_polyfill as atomic;
28 #[cfg(not(feature = "atomic-polyfill"))]
29 use core::sync::atomic;
30 
31 use alloc::boxed::Box;
32 use atomic::{AtomicUsize, Ordering};
33 use core::any::{Any, TypeId};
34 use core::fmt;
35 use core::hash::BuildHasher;
36 use core::hash::Hasher;
37 
38 pub(crate) const PI: [u64; 4] = [
39     0x243f_6a88_85a3_08d3,
40     0x1319_8a2e_0370_7344,
41     0xa409_3822_299f_31d0,
42     0x082e_fa98_ec4e_6c89,
43 ];
44 
45 pub(crate) const PI2: [u64; 4] = [
46     0x4528_21e6_38d0_1377,
47     0xbe54_66cf_34e9_0c6c,
48     0xc0ac_29b7_c97c_50dd,
49     0x3f84_d5b5_b547_0917,
50 ];
51 
52 #[cfg(all(feature = "runtime-rng", not(all(feature = "compile-time-rng", test))))]
read_urandom(dest: &mut [u8]) -> Result<(), std::io::Error>53 fn read_urandom(dest: &mut [u8]) -> Result<(), std::io::Error> {
54     use std::fs::File;
55     use std::io::Read;
56 
57     let mut f = File::open("/dev/urandom")?;
58     f.read_exact(dest)
59 }
60 
61 cfg_if::cfg_if! {
62     if #[cfg(all(feature = "compile-time-rng", any(test, fuzzing)))] {
63         #[inline]
64         fn get_fixed_seeds() -> &'static [[u64; 4]; 2] {
65             use const_random::const_random;
66 
67             const RAND: [[u64; 4]; 2] = [
68                 [
69                     const_random!(u64),
70                     const_random!(u64),
71                     const_random!(u64),
72                     const_random!(u64),
73                 ], [
74                     const_random!(u64),
75                     const_random!(u64),
76                     const_random!(u64),
77                     const_random!(u64),
78                 ]
79             ];
80             &RAND
81         }
82     } else if #[cfg(all(feature = "runtime-rng", not(fuzzing)))] {
83         #[inline]
84         fn get_fixed_seeds() -> &'static [[u64; 4]; 2] {
85             use crate::convert::Convert;
86 
87             static SEEDS: OnceBox<[[u64; 4]; 2]> = OnceBox::new();
88 
89             SEEDS.get_or_init(|| {
90                 let mut result: [u8; 64] = [0; 64];
91                 if read_urandom(&mut result).is_err() {
92                     getrandom::getrandom(&mut result).expect("getrandom::getrandom() failed.");
93                 }
94                 Box::new(result.convert())
95             })
96         }
97     } else if #[cfg(feature = "compile-time-rng")] {
98         #[inline]
99         fn get_fixed_seeds() -> &'static [[u64; 4]; 2] {
100             use const_random::const_random;
101 
102             const RAND: [[u64; 4]; 2] = [
103                 [
104                     const_random!(u64),
105                     const_random!(u64),
106                     const_random!(u64),
107                     const_random!(u64),
108                 ], [
109                     const_random!(u64),
110                     const_random!(u64),
111                     const_random!(u64),
112                     const_random!(u64),
113                 ]
114             ];
115             &RAND
116         }
117     } else {
118         #[inline]
119         fn get_fixed_seeds() -> &'static [[u64; 4]; 2] {
120             &[PI, PI2]
121         }
122     }
123 }
124 
125 cfg_if::cfg_if! {
126     if #[cfg(not(all(target_arch = "arm", target_os = "none")))] {
127         use once_cell::race::OnceBox;
128 
129         static RAND_SOURCE: OnceBox<Box<dyn RandomSource + Send + Sync>> = OnceBox::new();
130     }
131 }
132 /// A supplier of Randomness used for different hashers.
133 /// See [set_random_source].
134 ///
135 /// If [set_random_source] aHash will default to the best available source of randomness.
136 /// In order this is:
137 /// 1. OS provided random number generator (available if the `runtime-rng` flag is enabled which it is by default) - This should be very strong.
138 /// 2. Strong compile time random numbers used to permute a static "counter". (available if `compile-time-rng` is enabled.
139 /// __Enabling this is recommended if `runtime-rng` is not possible__)
140 /// 3. A static counter that adds the memory address of each [RandomState] created permuted with fixed constants.
141 /// (Similar to above but with fixed keys) - This is the weakest option. The strength of this heavily depends on whether or not ASLR is enabled.
142 /// (Rust enables ASLR by default)
143 pub trait RandomSource {
gen_hasher_seed(&self) -> usize144     fn gen_hasher_seed(&self) -> usize;
145 }
146 
147 struct DefaultRandomSource {
148     counter: AtomicUsize,
149 }
150 
151 impl DefaultRandomSource {
new() -> DefaultRandomSource152     fn new() -> DefaultRandomSource {
153         DefaultRandomSource {
154             counter: AtomicUsize::new(&PI as *const _ as usize),
155         }
156     }
157 
158     #[cfg(all(target_arch = "arm", target_os = "none"))]
default() -> DefaultRandomSource159     const fn default() -> DefaultRandomSource {
160         DefaultRandomSource {
161             counter: AtomicUsize::new(PI[3] as usize),
162         }
163     }
164 }
165 
166 impl RandomSource for DefaultRandomSource {
167     cfg_if::cfg_if! {
168         if #[cfg(all(target_arch = "arm", target_os = "none"))] {
169             fn gen_hasher_seed(&self) -> usize {
170                 let stack = self as *const _ as usize;
171                 let previous = self.counter.load(Ordering::Relaxed);
172                 let new = previous.wrapping_add(stack);
173                 self.counter.store(new, Ordering::Relaxed);
174                 new
175             }
176         } else {
177             fn gen_hasher_seed(&self) -> usize {
178                 let stack = self as *const _ as usize;
179                 self.counter.fetch_add(stack, Ordering::Relaxed)
180             }
181         }
182     }
183 }
184 
185 cfg_if::cfg_if! {
186         if #[cfg(all(target_arch = "arm", target_os = "none"))] {
187             #[inline]
188             fn get_src() -> &'static dyn RandomSource {
189                 static RAND_SOURCE: DefaultRandomSource = DefaultRandomSource::default();
190                 &RAND_SOURCE
191             }
192         } else {
193             /// Provides an optional way to manually supply a source of randomness for Hasher keys.
194             ///
195             /// The provided [RandomSource] will be used to be used as a source of randomness by [RandomState] to generate new states.
196             /// If this method is not invoked the standard source of randomness is used as described in the Readme.
197             ///
198             /// The source of randomness can only be set once, and must be set before the first RandomState is created.
199             /// If the source has already been specified `Err` is returned with a `bool` indicating if the set failed because
200             /// method was previously invoked (true) or if the default source is already being used (false).
201             #[cfg(not(all(target_arch = "arm", target_os = "none")))]
202             pub fn set_random_source(source: impl RandomSource + Send + Sync + 'static) -> Result<(), bool> {
203                 RAND_SOURCE.set(Box::new(Box::new(source))).map_err(|s| s.as_ref().type_id() != TypeId::of::<&DefaultRandomSource>())
204             }
205 
206             #[inline]
207             fn get_src() -> &'static dyn RandomSource {
208                 RAND_SOURCE.get_or_init(|| Box::new(Box::new(DefaultRandomSource::new()))).as_ref()
209             }
210         }
211 }
212 
213 /// Provides a [Hasher] factory. This is typically used (e.g. by [HashMap]) to create
214 /// [AHasher]s in order to hash the keys of the map. See `build_hasher` below.
215 ///
216 /// [build_hasher]: ahash::
217 /// [Hasher]: std::hash::Hasher
218 /// [BuildHasher]: std::hash::BuildHasher
219 /// [HashMap]: std::collections::HashMap
220 ///
221 /// There are multiple constructors each is documented in more detail below:
222 ///
223 /// | Constructor   | Dynamically random? | Seed |
224 /// |---------------|---------------------|------|
225 /// |`new`          | Each instance unique|_[RandomSource]_|
226 /// |`generate_with`| Each instance unique|`u64` x 4 + [RandomSource]|
227 /// |`with_seed`    | Fixed per process   |`u64` + static random number|
228 /// |`with_seeds`   | Fixed               |`u64` x 4|
229 ///
230 #[derive(Clone)]
231 pub struct RandomState {
232     pub(crate) k0: u64,
233     pub(crate) k1: u64,
234     pub(crate) k2: u64,
235     pub(crate) k3: u64,
236 }
237 
238 impl fmt::Debug for RandomState {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result239     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
240         f.pad("RandomState { .. }")
241     }
242 }
243 
244 impl RandomState {
245     /// Create a new `RandomState` `BuildHasher` using random keys.
246     ///
247     /// Each instance will have a unique set of keys derived from [RandomSource].
248     ///
249     #[inline]
new() -> RandomState250     pub fn new() -> RandomState {
251         let src = get_src();
252         let fixed = get_fixed_seeds();
253         Self::from_keys(&fixed[0], &fixed[1], src.gen_hasher_seed())
254     }
255 
256     /// Create a new `RandomState` `BuildHasher` based on the provided seeds, but in such a way
257     /// that each time it is called the resulting state will be different and of high quality.
258     /// This allows fixed constant or poor quality seeds to be provided without the problem of different
259     /// `BuildHasher`s being identical or weak.
260     ///
261     /// This is done via permuting the provided values with the value of a static counter and memory address.
262     /// (This makes this method somewhat more expensive than `with_seeds` below which does not do this).
263     ///
264     /// The provided values (k0-k3) do not need to be of high quality but they should not all be the same value.
265     #[inline]
generate_with(k0: u64, k1: u64, k2: u64, k3: u64) -> RandomState266     pub fn generate_with(k0: u64, k1: u64, k2: u64, k3: u64) -> RandomState {
267         let src = get_src();
268         let fixed = get_fixed_seeds();
269         RandomState::from_keys(&fixed[0], &[k0, k1, k2, k3], src.gen_hasher_seed())
270     }
271 
from_keys(a: &[u64; 4], b: &[u64; 4], c: usize) -> RandomState272     fn from_keys(a: &[u64; 4], b: &[u64; 4], c: usize) -> RandomState {
273         let &[k0, k1, k2, k3] = a;
274         let mut hasher = AHasher::from_random_state(&RandomState { k0, k1, k2, k3 });
275         hasher.write_usize(c);
276         let mix = |l: u64, r: u64| {
277             let mut h = hasher.clone();
278             h.write_u64(l);
279             h.write_u64(r);
280             h.finish()
281         };
282         RandomState {
283             k0: mix(b[0], b[2]),
284             k1: mix(b[1], b[3]),
285             k2: mix(b[2], b[1]),
286             k3: mix(b[3], b[0]),
287         }
288     }
289 
290     /// Internal. Used by Default.
291     #[inline]
with_fixed_keys() -> RandomState292     pub(crate) fn with_fixed_keys() -> RandomState {
293         let [k0, k1, k2, k3] = get_fixed_seeds()[0];
294         RandomState { k0, k1, k2, k3 }
295     }
296 
297     /// Build a `RandomState` from a single key. The provided key does not need to be of high quality,
298     /// but all `RandomState`s created from the same key will produce identical hashers.
299     /// (In contrast to `generate_with` above)
300     ///
301     /// This allows for explicitly setting the seed to be used.
302     ///
303     /// Note: This method does not require the provided seed to be strong.
304     #[inline]
with_seed(key: usize) -> RandomState305     pub fn with_seed(key: usize) -> RandomState {
306         let fixed = get_fixed_seeds();
307         RandomState::from_keys(&fixed[0], &fixed[1], key)
308     }
309 
310     /// Allows for explicitly setting the seeds to used.
311     /// All `RandomState`s created with the same set of keys key will produce identical hashers.
312     /// (In contrast to `generate_with` above)
313     ///
314     /// Note: If DOS resistance is desired one of these should be a decent quality random number.
315     /// If 4 high quality random number are not cheaply available this method is robust against 0s being passed for
316     /// one or more of the parameters or the same value being passed for more than one parameter.
317     /// It is recommended to pass numbers in order from highest to lowest quality (if there is any difference).
318     #[inline]
with_seeds(k0: u64, k1: u64, k2: u64, k3: u64) -> RandomState319     pub const fn with_seeds(k0: u64, k1: u64, k2: u64, k3: u64) -> RandomState {
320         RandomState {
321             k0: k0 ^ PI2[0],
322             k1: k1 ^ PI2[1],
323             k2: k2 ^ PI2[2],
324             k3: k3 ^ PI2[3],
325         }
326     }
327 
328     /// Calculates the hash of a single value. This provides a more convenient (and faster) way to obtain a hash:
329     /// For example:
330     #[cfg_attr(
331         feature = "std",
332         doc = r##" # Examples
333 ```
334     use std::hash::BuildHasher;
335     use ahash::RandomState;
336 
337     let hash_builder = RandomState::new();
338     let hash = hash_builder.hash_one("Some Data");
339 ```
340     "##
341     )]
342     /// This is similar to:
343     #[cfg_attr(
344         feature = "std",
345         doc = r##" # Examples
346 ```
347     use std::hash::{BuildHasher, Hash, Hasher};
348     use ahash::RandomState;
349 
350     let hash_builder = RandomState::new();
351     let mut hasher = hash_builder.build_hasher();
352     "Some Data".hash(&mut hasher);
353     let hash = hasher.finish();
354 ```
355     "##
356     )]
357     /// (Note that these two ways to get a hash may not produce the same value for the same data)
358     ///
359     /// This is intended as a convenience for code which *consumes* hashes, such
360     /// as the implementation of a hash table or in unit tests that check
361     /// whether a custom [`Hash`] implementation behaves as expected.
362     ///
363     /// This must not be used in any code which *creates* hashes, such as in an
364     /// implementation of [`Hash`].  The way to create a combined hash of
365     /// multiple values is to call [`Hash::hash`] multiple times using the same
366     /// [`Hasher`], not to call this method repeatedly and combine the results.
367     #[inline]
hash_one<T: Hash>(&self, x: T) -> u64 where Self: Sized,368     pub fn hash_one<T: Hash>(&self, x: T) -> u64
369     where
370         Self: Sized,
371     {
372         use crate::specialize::CallHasher;
373         T::get_hash(&x, self)
374     }
375 }
376 
377 /// Creates an instance of RandomState using keys obtained from the random number generator.
378 /// Each instance created in this way will have a unique set of keys. (But the resulting instance
379 /// can be used to create many hashers each or which will have the same keys.)
380 ///
381 /// This is the same as [RandomState::new()]
382 ///
383 /// NOTE: For safety this trait impl is only available available if either of the flags `runtime-rng` (on by default) or
384 /// `compile-time-rng` are enabled. This is to prevent weakly keyed maps from being accidentally created. Instead one of
385 /// constructors for [RandomState] must be used.
386 #[cfg(any(feature = "compile-time-rng", feature = "runtime-rng", feature = "no-rng"))]
387 impl Default for RandomState {
388     #[inline]
default() -> Self389     fn default() -> Self {
390         Self::new()
391     }
392 }
393 
394 impl BuildHasher for RandomState {
395     type Hasher = AHasher;
396 
397     /// Constructs a new [AHasher] with keys based on this [RandomState] object.
398     /// This means that two different [RandomState]s will will generate
399     /// [AHasher]s that will return different hashcodes, but [Hasher]s created from the same [BuildHasher]
400     /// will generate the same hashes for the same input data.
401     ///
402     #[cfg_attr(
403         feature = "std",
404         doc = r##" # Examples
405 ```
406         use ahash::{AHasher, RandomState};
407         use std::hash::{Hasher, BuildHasher};
408 
409         let build_hasher = RandomState::new();
410         let mut hasher_1 = build_hasher.build_hasher();
411         let mut hasher_2 = build_hasher.build_hasher();
412 
413         hasher_1.write_u32(1234);
414         hasher_2.write_u32(1234);
415 
416         assert_eq!(hasher_1.finish(), hasher_2.finish());
417 
418         let other_build_hasher = RandomState::new();
419         let mut different_hasher = other_build_hasher.build_hasher();
420         different_hasher.write_u32(1234);
421         assert_ne!(different_hasher.finish(), hasher_1.finish());
422 ```
423     "##
424     )]
425     /// [Hasher]: std::hash::Hasher
426     /// [BuildHasher]: std::hash::BuildHasher
427     /// [HashMap]: std::collections::HashMap
428     #[inline]
build_hasher(&self) -> AHasher429     fn build_hasher(&self) -> AHasher {
430         AHasher::from_random_state(self)
431     }
432 
433     /// Calculates the hash of a single value. This provides a more convenient (and faster) way to obtain a hash:
434     /// For example:
435     #[cfg_attr(
436         feature = "std",
437         doc = r##" # Examples
438 ```
439     use std::hash::BuildHasher;
440     use ahash::RandomState;
441 
442     let hash_builder = RandomState::new();
443     let hash = hash_builder.hash_one("Some Data");
444 ```
445     "##
446     )]
447     /// This is similar to:
448     #[cfg_attr(
449         feature = "std",
450         doc = r##" # Examples
451 ```
452     use std::hash::{BuildHasher, Hash, Hasher};
453     use ahash::RandomState;
454 
455     let hash_builder = RandomState::new();
456     let mut hasher = hash_builder.build_hasher();
457     "Some Data".hash(&mut hasher);
458     let hash = hasher.finish();
459 ```
460     "##
461     )]
462     /// (Note that these two ways to get a hash may not produce the same value for the same data)
463     ///
464     /// This is intended as a convenience for code which *consumes* hashes, such
465     /// as the implementation of a hash table or in unit tests that check
466     /// whether a custom [`Hash`] implementation behaves as expected.
467     ///
468     /// This must not be used in any code which *creates* hashes, such as in an
469     /// implementation of [`Hash`].  The way to create a combined hash of
470     /// multiple values is to call [`Hash::hash`] multiple times using the same
471     /// [`Hasher`], not to call this method repeatedly and combine the results.
472     #[cfg(feature = "specialize")]
473     #[inline]
hash_one<T: Hash>(&self, x: T) -> u64474     fn hash_one<T: Hash>(&self, x: T) -> u64 {
475         RandomState::hash_one(self, x)
476     }
477 }
478 
479 #[cfg(feature = "specialize")]
480 impl BuildHasherExt for RandomState {
481     #[inline]
hash_as_u64<T: Hash + ?Sized>(&self, value: &T) -> u64482     fn hash_as_u64<T: Hash + ?Sized>(&self, value: &T) -> u64 {
483         let mut hasher = AHasherU64 {
484             buffer: self.k1,
485             pad: self.k0,
486         };
487         value.hash(&mut hasher);
488         hasher.finish()
489     }
490 
491     #[inline]
hash_as_fixed_length<T: Hash + ?Sized>(&self, value: &T) -> u64492     fn hash_as_fixed_length<T: Hash + ?Sized>(&self, value: &T) -> u64 {
493         let mut hasher = AHasherFixed(self.build_hasher());
494         value.hash(&mut hasher);
495         hasher.finish()
496     }
497 
498     #[inline]
hash_as_str<T: Hash + ?Sized>(&self, value: &T) -> u64499     fn hash_as_str<T: Hash + ?Sized>(&self, value: &T) -> u64 {
500         let mut hasher = AHasherStr(self.build_hasher());
501         value.hash(&mut hasher);
502         hasher.finish()
503     }
504 }
505 
506 #[cfg(test)]
507 mod test {
508     use super::*;
509 
510     #[test]
test_unique()511     fn test_unique() {
512         let a = RandomState::generate_with(1, 2, 3, 4);
513         let b = RandomState::generate_with(1, 2, 3, 4);
514         assert_ne!(a.build_hasher().finish(), b.build_hasher().finish());
515     }
516 
517     #[cfg(all(feature = "runtime-rng", not(all(feature = "compile-time-rng", test))))]
518     #[test]
test_not_pi()519     fn test_not_pi() {
520         assert_ne!(PI, get_fixed_seeds()[0]);
521     }
522 
523     #[cfg(all(feature = "compile-time-rng", any(not(feature = "runtime-rng"), test)))]
524     #[test]
test_not_pi_const()525     fn test_not_pi_const() {
526         assert_ne!(PI, get_fixed_seeds()[0]);
527     }
528 
529     #[cfg(all(not(feature = "runtime-rng"), not(feature = "compile-time-rng")))]
530     #[test]
test_pi()531     fn test_pi() {
532         assert_eq!(PI, get_fixed_seeds()[0]);
533     }
534 
535     #[test]
test_with_seeds_const()536     fn test_with_seeds_const() {
537         const _CONST_RANDOM_STATE: RandomState = RandomState::with_seeds(17, 19, 21, 23);
538     }
539 }
540