@@ -165,9 +165,19 @@ mod io_extras {
165
165
mod prelude {
166
166
#[ cfg( feature = "hashbrown" ) ]
167
167
extern crate hashbrown;
168
+ #[ cfg( feature = "ahash" ) ]
169
+ extern crate ahash;
168
170
169
171
pub use alloc:: { vec, vec:: Vec , string:: String , collections:: VecDeque , boxed:: Box } ;
170
172
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
+
171
181
#[ cfg( not( feature = "hashbrown" ) ) ]
172
182
mod std_hashtables {
173
183
pub ( crate ) use std:: collections:: { HashMap , HashSet , hash_map} ;
@@ -181,35 +191,85 @@ mod prelude {
181
191
pub ( crate ) use std_hashtables:: * ;
182
192
183
193
#[ 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 } ;
186
199
187
200
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 > ;
189
202
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 > ;
191
204
}
192
- #[ cfg( feature = "hashbrown" ) ]
193
- pub ( crate ) use hashbrown_tables :: * ;
205
+ #[ cfg( all ( feature = "hashbrown" , fuzzing ) ) ]
206
+ pub ( crate ) use nonrandomized_hashbrown :: * ;
194
207
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
- }
202
208
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
+ }
206
249
}
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
+ }
209
270
}
210
271
211
- pub use alloc:: borrow:: ToOwned ;
212
- pub use alloc:: string:: ToString ;
272
+ pub ( crate ) use randomized_hashtables:: * ;
213
273
}
214
274
215
275
#[ cfg( all( not( ldk_bench) , feature = "backtrace" , feature = "std" , test) ) ]
0 commit comments