@@ -165,9 +165,19 @@ mod io_extras {
165165mod prelude {
166166 #[ cfg( feature = "hashbrown" ) ]
167167 extern crate hashbrown;
168+ #[ cfg( feature = "ahash" ) ]
169+ extern crate ahash;
168170
169171 pub use alloc:: { vec, vec:: Vec , string:: String , collections:: VecDeque , boxed:: Box } ;
170172
173+ pub use alloc:: borrow:: ToOwned ;
174+ pub use alloc:: string:: ToString ;
175+
176+ // For no-std builds, we need to use hashbrown, however, by default, it doesn't randomize the
177+ // hashing and is vulnerable to HashDoS attacks. Thus, when not fuzzing, we use its default
178+ // ahash hashing algorithm but randomize, opting to not randomize when fuzzing to avoid false
179+ // positive branch coverage.
180+
171181 #[ cfg( not( feature = "hashbrown" ) ) ]
172182 mod std_hashtables {
173183 pub ( crate ) use std:: collections:: { HashMap , HashSet , hash_map} ;
@@ -181,35 +191,85 @@ mod prelude {
181191 pub ( crate ) use std_hashtables:: * ;
182192
183193 #[ cfg( feature = "hashbrown" ) ]
184- mod hashbrown_tables {
185- pub ( crate ) use hashbrown:: { HashMap , HashSet , hash_map} ;
194+ pub ( crate ) use self :: hashbrown:: hash_map;
195+
196+ #[ cfg( all( feature = "hashbrown" , fuzzing) ) ]
197+ mod nonrandomized_hashbrown {
198+ pub ( crate ) use hashbrown:: { HashMap , HashSet } ;
186199
187200 pub ( crate ) type OccupiedHashMapEntry < ' a , K , V > =
188- hashbrown:: hash_map:: OccupiedEntry < ' a , K , V , hash_map:: DefaultHashBuilder > ;
201+ hashbrown:: hash_map:: OccupiedEntry < ' a , K , V , hashbrown :: hash_map:: DefaultHashBuilder > ;
189202 pub ( crate ) type VacantHashMapEntry < ' a , K , V > =
190- hashbrown:: hash_map:: VacantEntry < ' a , K , V , hash_map:: DefaultHashBuilder > ;
203+ hashbrown:: hash_map:: VacantEntry < ' a , K , V , hashbrown :: hash_map:: DefaultHashBuilder > ;
191204 }
192- #[ cfg( feature = "hashbrown" ) ]
193- pub ( crate ) use hashbrown_tables :: * ;
205+ #[ cfg( all ( feature = "hashbrown" , fuzzing ) ) ]
206+ pub ( crate ) use nonrandomized_hashbrown :: * ;
194207
195- pub ( crate ) fn new_hash_map < K : core:: hash:: Hash + Eq , V > ( ) -> HashMap < K , V > { HashMap :: new ( ) }
196- pub ( crate ) fn hash_map_with_capacity < K : core:: hash:: Hash + Eq , V > ( cap : usize ) -> HashMap < K , V > {
197- HashMap :: with_capacity ( cap)
198- }
199- pub ( crate ) fn hash_map_from_iter < K : core:: hash:: Hash + Eq , V , I : IntoIterator < Item = ( K , V ) > > ( iter : I ) -> HashMap < K , V > {
200- HashMap :: from_iter ( iter)
201- }
202208
203- pub ( crate ) fn new_hash_set < K : core:: hash:: Hash + Eq > ( ) -> HashSet < K > { HashSet :: new ( ) }
204- pub ( crate ) fn hash_set_with_capacity < K : core:: hash:: Hash + Eq > ( cap : usize ) -> HashSet < K > {
205- HashSet :: with_capacity ( cap)
209+ #[ cfg( all( feature = "hashbrown" , not( fuzzing) ) ) ]
210+ mod randomized_hashtables {
211+ use super :: * ;
212+ use ahash:: RandomState ;
213+
214+ pub ( crate ) type HashMap < K , V > = hashbrown:: HashMap < K , V , RandomState > ;
215+ pub ( crate ) type HashSet < K > = hashbrown:: HashSet < K , RandomState > ;
216+
217+ pub ( crate ) type OccupiedHashMapEntry < ' a , K , V > =
218+ hashbrown:: hash_map:: OccupiedEntry < ' a , K , V , RandomState > ;
219+ pub ( crate ) type VacantHashMapEntry < ' a , K , V > =
220+ hashbrown:: hash_map:: VacantEntry < ' a , K , V , RandomState > ;
221+
222+ pub ( crate ) fn new_hash_map < K , V > ( ) -> HashMap < K , V > {
223+ HashMap :: with_hasher ( RandomState :: new ( ) )
224+ }
225+ pub ( crate ) fn hash_map_with_capacity < K , V > ( cap : usize ) -> HashMap < K , V > {
226+ HashMap :: with_capacity_and_hasher ( cap, RandomState :: new ( ) )
227+ }
228+ pub ( crate ) fn hash_map_from_iter < K : core:: hash:: Hash + Eq , V , I : IntoIterator < Item =( K , V ) > > ( iter : I ) -> HashMap < K , V > {
229+ let iter = iter. into_iter ( ) ;
230+ let min_size = iter. size_hint ( ) . 0 ;
231+ let mut res = HashMap :: with_capacity_and_hasher ( min_size, RandomState :: new ( ) ) ;
232+ res. extend ( iter) ;
233+ res
234+ }
235+
236+ pub ( crate ) fn new_hash_set < K > ( ) -> HashSet < K > {
237+ HashSet :: with_hasher ( RandomState :: new ( ) )
238+ }
239+ pub ( crate ) fn hash_set_with_capacity < K > ( cap : usize ) -> HashSet < K > {
240+ HashSet :: with_capacity_and_hasher ( cap, RandomState :: new ( ) )
241+ }
242+ pub ( crate ) fn hash_set_from_iter < K : core:: hash:: Hash + Eq , I : IntoIterator < Item =K > > ( iter : I ) -> HashSet < K > {
243+ let iter = iter. into_iter ( ) ;
244+ let min_size = iter. size_hint ( ) . 0 ;
245+ let mut res = HashSet :: with_capacity_and_hasher ( min_size, RandomState :: new ( ) ) ;
246+ res. extend ( iter) ;
247+ res
248+ }
206249 }
207- pub ( crate ) fn hash_set_from_iter < K : core:: hash:: Hash + Eq , I : IntoIterator < Item = K > > ( iter : I ) -> HashSet < K > {
208- HashSet :: from_iter ( iter)
250+
251+ #[ cfg( any( not( feature = "hashbrown" ) , fuzzing) ) ]
252+ mod randomized_hashtables {
253+ use super :: * ;
254+
255+ pub ( crate ) fn new_hash_map < K , V > ( ) -> HashMap < K , V > { HashMap :: new ( ) }
256+ pub ( crate ) fn hash_map_with_capacity < K , V > ( cap : usize ) -> HashMap < K , V > {
257+ HashMap :: with_capacity ( cap)
258+ }
259+ pub ( crate ) fn hash_map_from_iter < K : core:: hash:: Hash + Eq , V , I : IntoIterator < Item =( K , V ) > > ( iter : I ) -> HashMap < K , V > {
260+ HashMap :: from_iter ( iter)
261+ }
262+
263+ pub ( crate ) fn new_hash_set < K > ( ) -> HashSet < K > { HashSet :: new ( ) }
264+ pub ( crate ) fn hash_set_with_capacity < K > ( cap : usize ) -> HashSet < K > {
265+ HashSet :: with_capacity ( cap)
266+ }
267+ pub ( crate ) fn hash_set_from_iter < K : core:: hash:: Hash + Eq , I : IntoIterator < Item =K > > ( iter : I ) -> HashSet < K > {
268+ HashSet :: from_iter ( iter)
269+ }
209270 }
210271
211- pub use alloc:: borrow:: ToOwned ;
212- pub use alloc:: string:: ToString ;
272+ pub ( crate ) use randomized_hashtables:: * ;
213273}
214274
215275#[ cfg( all( not( ldk_bench) , feature = "backtrace" , feature = "std" , test) ) ]
0 commit comments