about summary refs log tree commit diff
diff options
context:
space:
mode:
authorarthurprs <arthurprs@gmail.com>2016-10-29 23:12:12 +0200
committerarthurprs <arthurprs@gmail.com>2016-10-31 21:12:27 +0100
commiteba93c3a0f7cf8a0b7447ab22081ccd20824d9e6 (patch)
treefdd8efbbb7e3438cb9758081781af66ac7faac3b
parenta319d13a9beba484a5c7e4e9c674ef905fd3d6f4 (diff)
downloadrust-eba93c3a0f7cf8a0b7447ab22081ccd20824d9e6.tar.gz
rust-eba93c3a0f7cf8a0b7447ab22081ccd20824d9e6.zip
Don't reuse RandomState seeds
-rw-r--r--src/libstd/collections/hash/map.rs26
1 files changed, 12 insertions, 14 deletions
diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs
index fb8a0c3c265..ece51d6d826 100644
--- a/src/libstd/collections/hash/map.rs
+++ b/src/libstd/collections/hash/map.rs
@@ -11,6 +11,7 @@
 use self::Entry::*;
 use self::VacantEntryState::*;
 
+use cell::Cell;
 use borrow::Borrow;
 use cmp::max;
 use fmt::{self, Debug};
@@ -2049,24 +2050,21 @@ impl RandomState {
         // many hash maps are created on a thread. To solve this performance
         // trap we cache the first set of randomly generated keys per-thread.
         //
-        // In doing this, however, we lose the property that all hash maps have
-        // nondeterministic iteration order as all of those created on the same
-        // thread would have the same hash keys. This property has been nice in
-        // the past as it allows for maximal flexibility in the implementation
-        // of `HashMap` itself.
-        //
-        // The constraint here (if there even is one) is just that maps created
-        // on the same thread have the same iteration order, and that *may* be
-        // relied upon even though it is not a documented guarantee at all of
-        // the `HashMap` type. In any case we've decided that this is reasonable
-        // for now, so caching keys thread-locally seems fine.
-        thread_local!(static KEYS: (u64, u64) = {
+        // Later in #36481 it was discovered that exposing a deterministic
+        // iteration order allows a form of DOS attack. To counter that we
+        // increment one of the seeds on every RandomState creation, giving
+        // every corresponding HashMap a different iteration order.
+        thread_local!(static KEYS: Cell<(u64, u64)> = {
             let r = rand::OsRng::new();
             let mut r = r.expect("failed to create an OS RNG");
-            (r.gen(), r.gen())
+            Cell::new((r.gen(), r.gen()))
         });
 
-        KEYS.with(|&(k0, k1)| RandomState { k0: k0, k1: k1 })
+        KEYS.with(|keys| {
+            let (k0, k1) = keys.get();
+            keys.set((k0.wrapping_add(1), k1));
+            RandomState { k0: k0, k1: k1 }
+        })
     }
 }