@@ -167,9 +167,19 @@ mod io_extras {
167167mod prelude {
168168 #[ cfg( feature = "hashbrown" ) ]
169169 extern crate hashbrown;
170+ #[ cfg( feature = "ahash" ) ]
171+ extern crate ahash;
170172
171173 pub use alloc:: { vec, vec:: Vec , string:: String , collections:: VecDeque , boxed:: Box } ;
172174
175+ pub use alloc:: borrow:: ToOwned ;
176+ pub use alloc:: string:: ToString ;
177+
178+ // For no-std builds, we need to use hashbrown, however, by default, it doesn't randomize the
179+ // hashing and is vulnerable to HashDoS attacks. Thus, when not fuzzing, we use its default
180+ // ahash hashing algorithm but randomize, opting to not randomize when fuzzing to avoid false
181+ // positive branch coverage.
182+
173183 #[ cfg( not( feature = "hashbrown" ) ) ]
174184 mod std_hashtables {
175185 pub ( crate ) use std:: collections:: { HashMap , HashSet , hash_map} ;
@@ -183,35 +193,85 @@ mod prelude {
183193 pub ( crate ) use std_hashtables:: * ;
184194
185195 #[ cfg( feature = "hashbrown" ) ]
186- mod hashbrown_tables {
187- pub ( crate ) use hashbrown:: { HashMap , HashSet , hash_map} ;
196+ pub ( crate ) use self :: hashbrown:: hash_map;
197+
198+ #[ cfg( all( feature = "hashbrown" , fuzzing) ) ]
199+ mod nonrandomized_hashbrown {
200+ pub ( crate ) use hashbrown:: { HashMap , HashSet } ;
188201
189202 pub ( crate ) type OccupiedHashMapEntry < ' a , K , V > =
190- hashbrown:: hash_map:: OccupiedEntry < ' a , K , V , hash_map:: DefaultHashBuilder > ;
203+ hashbrown:: hash_map:: OccupiedEntry < ' a , K , V , hashbrown :: hash_map:: DefaultHashBuilder > ;
191204 pub ( crate ) type VacantHashMapEntry < ' a , K , V > =
192- hashbrown:: hash_map:: VacantEntry < ' a , K , V , hash_map:: DefaultHashBuilder > ;
205+ hashbrown:: hash_map:: VacantEntry < ' a , K , V , hashbrown :: hash_map:: DefaultHashBuilder > ;
193206 }
194- #[ cfg( feature = "hashbrown" ) ]
195- pub ( crate ) use hashbrown_tables :: * ;
207+ #[ cfg( all ( feature = "hashbrown" , fuzzing ) ) ]
208+ pub ( crate ) use nonrandomized_hashbrown :: * ;
196209
197- pub ( crate ) fn new_hash_map < K : core:: hash:: Hash + Eq , V > ( ) -> HashMap < K , V > { HashMap :: new ( ) }
198- pub ( crate ) fn hash_map_with_capacity < K : core:: hash:: Hash + Eq , V > ( cap : usize ) -> HashMap < K , V > {
199- HashMap :: with_capacity ( cap)
200- }
201- pub ( crate ) fn hash_map_from_iter < K : core:: hash:: Hash + Eq , V , I : IntoIterator < Item = ( K , V ) > > ( iter : I ) -> HashMap < K , V > {
202- HashMap :: from_iter ( iter)
203- }
204210
205- pub ( crate ) fn new_hash_set < K : core:: hash:: Hash + Eq > ( ) -> HashSet < K > { HashSet :: new ( ) }
206- pub ( crate ) fn hash_set_with_capacity < K : core:: hash:: Hash + Eq > ( cap : usize ) -> HashSet < K > {
207- HashSet :: with_capacity ( cap)
211+ #[ cfg( all( feature = "hashbrown" , not( fuzzing) ) ) ]
212+ mod randomized_hashtables {
213+ use super :: * ;
214+ use ahash:: RandomState ;
215+
216+ pub ( crate ) type HashMap < K , V > = hashbrown:: HashMap < K , V , RandomState > ;
217+ pub ( crate ) type HashSet < K > = hashbrown:: HashSet < K , RandomState > ;
218+
219+ pub ( crate ) type OccupiedHashMapEntry < ' a , K , V > =
220+ hashbrown:: hash_map:: OccupiedEntry < ' a , K , V , RandomState > ;
221+ pub ( crate ) type VacantHashMapEntry < ' a , K , V > =
222+ hashbrown:: hash_map:: VacantEntry < ' a , K , V , RandomState > ;
223+
224+ pub ( crate ) fn new_hash_map < K , V > ( ) -> HashMap < K , V > {
225+ HashMap :: with_hasher ( RandomState :: new ( ) )
226+ }
227+ pub ( crate ) fn hash_map_with_capacity < K , V > ( cap : usize ) -> HashMap < K , V > {
228+ HashMap :: with_capacity_and_hasher ( cap, RandomState :: new ( ) )
229+ }
230+ pub ( crate ) fn hash_map_from_iter < K : core:: hash:: Hash + Eq , V , I : IntoIterator < Item =( K , V ) > > ( iter : I ) -> HashMap < K , V > {
231+ let iter = iter. into_iter ( ) ;
232+ let min_size = iter. size_hint ( ) . 0 ;
233+ let mut res = HashMap :: with_capacity_and_hasher ( min_size, RandomState :: new ( ) ) ;
234+ res. extend ( iter) ;
235+ res
236+ }
237+
238+ pub ( crate ) fn new_hash_set < K > ( ) -> HashSet < K > {
239+ HashSet :: with_hasher ( RandomState :: new ( ) )
240+ }
241+ pub ( crate ) fn hash_set_with_capacity < K > ( cap : usize ) -> HashSet < K > {
242+ HashSet :: with_capacity_and_hasher ( cap, RandomState :: new ( ) )
243+ }
244+ pub ( crate ) fn hash_set_from_iter < K : core:: hash:: Hash + Eq , I : IntoIterator < Item =K > > ( iter : I ) -> HashSet < K > {
245+ let iter = iter. into_iter ( ) ;
246+ let min_size = iter. size_hint ( ) . 0 ;
247+ let mut res = HashSet :: with_capacity_and_hasher ( min_size, RandomState :: new ( ) ) ;
248+ res. extend ( iter) ;
249+ res
250+ }
208251 }
209- pub ( crate ) fn hash_set_from_iter < K : core:: hash:: Hash + Eq , I : IntoIterator < Item = K > > ( iter : I ) -> HashSet < K > {
210- HashSet :: from_iter ( iter)
252+
253+ #[ cfg( any( not( feature = "hashbrown" ) , fuzzing) ) ]
254+ mod randomized_hashtables {
255+ use super :: * ;
256+
257+ pub ( crate ) fn new_hash_map < K , V > ( ) -> HashMap < K , V > { HashMap :: new ( ) }
258+ pub ( crate ) fn hash_map_with_capacity < K , V > ( cap : usize ) -> HashMap < K , V > {
259+ HashMap :: with_capacity ( cap)
260+ }
261+ pub ( crate ) fn hash_map_from_iter < K : core:: hash:: Hash + Eq , V , I : IntoIterator < Item =( K , V ) > > ( iter : I ) -> HashMap < K , V > {
262+ HashMap :: from_iter ( iter)
263+ }
264+
265+ pub ( crate ) fn new_hash_set < K > ( ) -> HashSet < K > { HashSet :: new ( ) }
266+ pub ( crate ) fn hash_set_with_capacity < K > ( cap : usize ) -> HashSet < K > {
267+ HashSet :: with_capacity ( cap)
268+ }
269+ pub ( crate ) fn hash_set_from_iter < K : core:: hash:: Hash + Eq , I : IntoIterator < Item =K > > ( iter : I ) -> HashSet < K > {
270+ HashSet :: from_iter ( iter)
271+ }
211272 }
212273
213- pub use alloc:: borrow:: ToOwned ;
214- pub use alloc:: string:: ToString ;
274+ pub ( crate ) use randomized_hashtables:: * ;
215275}
216276
217277#[ cfg( all( not( ldk_bench) , feature = "backtrace" , feature = "std" , test) ) ]
0 commit comments