@@ -167,9 +167,19 @@ mod io_extras {
167
167
mod prelude {
168
168
#[ cfg( feature = "hashbrown" ) ]
169
169
extern crate hashbrown;
170
+ #[ cfg( feature = "ahash" ) ]
171
+ extern crate ahash;
170
172
171
173
pub use alloc:: { vec, vec:: Vec , string:: String , collections:: VecDeque , boxed:: Box } ;
172
174
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
+
173
183
#[ cfg( not( feature = "hashbrown" ) ) ]
174
184
mod std_hashtables {
175
185
pub ( crate ) use std:: collections:: { HashMap , HashSet , hash_map} ;
@@ -183,35 +193,85 @@ mod prelude {
183
193
pub ( crate ) use std_hashtables:: * ;
184
194
185
195
#[ 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 } ;
188
201
189
202
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 > ;
191
204
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 > ;
193
206
}
194
- #[ cfg( feature = "hashbrown" ) ]
195
- pub ( crate ) use hashbrown_tables :: * ;
207
+ #[ cfg( all ( feature = "hashbrown" , fuzzing ) ) ]
208
+ pub ( crate ) use nonrandomized_hashbrown :: * ;
196
209
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
- }
204
210
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
+ }
208
251
}
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
+ }
211
272
}
212
273
213
- pub use alloc:: borrow:: ToOwned ;
214
- pub use alloc:: string:: ToString ;
274
+ pub ( crate ) use randomized_hashtables:: * ;
215
275
}
216
276
217
277
#[ cfg( all( not( ldk_bench) , feature = "backtrace" , feature = "std" , test) ) ]
0 commit comments