1 | //! Utilities for hashmap initialization based on random sources. |
2 | |
3 | use core::hash::{BuildHasher, Hasher}; |
4 | |
5 | /// Wasmparser's hashing state stored per-map. |
6 | /// |
7 | /// This is DoS-resistant when the `std` feature is activated and still somewhat |
8 | /// resistant when it's not active but not as secure. |
9 | #[derive (Clone, Debug)] |
10 | pub struct RandomState(RandomStateImpl); |
11 | |
12 | impl Default for RandomState { |
13 | #[inline ] |
14 | fn default() -> RandomState { |
15 | RandomState(RandomStateImpl::default()) |
16 | } |
17 | } |
18 | |
19 | impl BuildHasher for RandomState { |
20 | type Hasher = RandomStateHasher; |
21 | |
22 | #[inline ] |
23 | fn build_hasher(&self) -> RandomStateHasher { |
24 | RandomStateHasher(self.0.build_hasher()) |
25 | } |
26 | } |
27 | |
28 | /// Wasmparser's hasher type used with [`RandomState`]. |
29 | pub struct RandomStateHasher(<RandomStateImpl as BuildHasher>::Hasher); |
30 | |
31 | impl Hasher for RandomStateHasher { |
32 | #[inline ] |
33 | fn finish(&self) -> u64 { |
34 | self.0.finish() |
35 | } |
36 | #[inline ] |
37 | fn write(&mut self, bytes: &[u8]) { |
38 | self.0.write(bytes) |
39 | } |
40 | #[inline ] |
41 | fn write_u8(&mut self, i: u8) { |
42 | self.0.write_u8(i) |
43 | } |
44 | #[inline ] |
45 | fn write_u16(&mut self, i: u16) { |
46 | self.0.write_u16(i) |
47 | } |
48 | #[inline ] |
49 | fn write_u32(&mut self, i: u32) { |
50 | self.0.write_u32(i) |
51 | } |
52 | #[inline ] |
53 | fn write_u64(&mut self, i: u64) { |
54 | self.0.write_u64(i) |
55 | } |
56 | #[inline ] |
57 | fn write_u128(&mut self, i: u128) { |
58 | self.0.write_u128(i) |
59 | } |
60 | #[inline ] |
61 | fn write_usize(&mut self, i: usize) { |
62 | self.0.write_usize(i) |
63 | } |
64 | #[inline ] |
65 | fn write_i8(&mut self, i: i8) { |
66 | self.0.write_i8(i) |
67 | } |
68 | #[inline ] |
69 | fn write_i16(&mut self, i: i16) { |
70 | self.0.write_i16(i) |
71 | } |
72 | #[inline ] |
73 | fn write_i32(&mut self, i: i32) { |
74 | self.0.write_i32(i) |
75 | } |
76 | #[inline ] |
77 | fn write_i64(&mut self, i: i64) { |
78 | self.0.write_i64(i) |
79 | } |
80 | #[inline ] |
81 | fn write_i128(&mut self, i: i128) { |
82 | self.0.write_i128(i) |
83 | } |
84 | #[inline ] |
85 | fn write_isize(&mut self, i: isize) { |
86 | self.0.write_isize(i) |
87 | } |
88 | } |
89 | |
90 | // When the `std` feature is active reuse the standard library's implementation |
91 | // of hash state and hasher. |
92 | #[cfg (feature = "std" )] |
93 | use std::collections::hash_map::RandomState as RandomStateImpl; |
94 | |
95 | // When the `std` feature is NOT active then rely on `ahash::RandomState`. That |
96 | // relies on ASLR by default for randomness. |
97 | #[derive (Clone, Debug)] |
98 | #[cfg (not(feature = "std" ))] |
99 | struct RandomStateImpl { |
100 | state: hashbrown::DefaultHashBuilder, |
101 | } |
102 | |
103 | #[cfg (not(feature = "std" ))] |
104 | impl Default for RandomStateImpl { |
105 | fn default() -> RandomStateImpl { |
106 | RandomStateImpl { |
107 | state: hashbrown::DefaultHashBuilder::default(), |
108 | } |
109 | } |
110 | } |
111 | |
112 | #[cfg (not(feature = "std" ))] |
113 | impl BuildHasher for RandomStateImpl { |
114 | type Hasher = <hashbrown::DefaultHashBuilder as BuildHasher>::Hasher; |
115 | |
116 | #[inline ] |
117 | fn build_hasher(&self) -> Self::Hasher { |
118 | self.state.build_hasher() |
119 | } |
120 | } |
121 | |