diff options
| author | Erick Tryzelaar <erick.tryzelaar@gmail.com> | 2014-06-23 19:15:40 -0400 |
|---|---|---|
| committer | Erick Tryzelaar <erick.tryzelaar@gmail.com> | 2014-06-30 06:57:05 -0700 |
| commit | 8284ef63a517690a893ffda1083fb966a76b6fbc (patch) | |
| tree | 7b3dcf1d45223093718e3730e61f4384438f4619 /src/libstd | |
| parent | 287dcb77b34b421256c1d9cf26f3101276d2f486 (diff) | |
| download | rust-8284ef63a517690a893ffda1083fb966a76b6fbc.tar.gz rust-8284ef63a517690a893ffda1083fb966a76b6fbc.zip | |
std: make sure HashMap from_iter uses random initialization by default
It turns out that HashMap's from_iter implementation was being initialized without the sip keys being randomized. This adds a custom default hasher that should avoid this potential vulnerability.
Diffstat (limited to 'src/libstd')
| -rw-r--r-- | src/libstd/collections/hashmap.rs | 25 | ||||
| -rw-r--r-- | src/libstd/hash.rs | 51 | ||||
| -rw-r--r-- | src/libstd/lib.rs | 2 |
3 files changed, 62 insertions, 16 deletions
diff --git a/src/libstd/collections/hashmap.rs b/src/libstd/collections/hashmap.rs index b94141748d5..be5c2e25141 100644 --- a/src/libstd/collections/hashmap.rs +++ b/src/libstd/collections/hashmap.rs @@ -16,15 +16,13 @@ use collections::{Collection, Mutable, Set, MutableSet, Map, MutableMap}; use default::Default; use fmt::Show; use fmt; -use hash::{Hash, Hasher, sip}; +use hash::{Hash, Hasher, RandomSipHasher}; use iter::{Iterator, FilterMap, Chain, Repeat, Zip, Extendable}; use iter::{range, range_inclusive, FromIterator}; use iter; use mem::replace; use num; use option::{Some, None, Option}; -use rand::Rng; -use rand; use result::{Ok, Err}; mod table { @@ -733,7 +731,7 @@ impl DefaultResizePolicy { /// } /// ``` #[deriving(Clone)] -pub struct HashMap<K, V, H = sip::SipHasher> { +pub struct HashMap<K, V, H = RandomSipHasher> { // All hashes are keyed on these values, to prevent hash collision attacks. hasher: H, @@ -1033,18 +1031,15 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> MutableMap<K, V> for HashMap<K, V, H> } -impl<K: Hash + Eq, V> HashMap<K, V, sip::SipHasher> { +impl<K: Hash + Eq, V> HashMap<K, V, RandomSipHasher> { /// Create an empty HashMap. - pub fn new() -> HashMap<K, V, sip::SipHasher> { + pub fn new() -> HashMap<K, V, RandomSipHasher> { HashMap::with_capacity(INITIAL_CAPACITY) } /// Creates an empty hash map with the given initial capacity. - pub fn with_capacity(capacity: uint) -> HashMap<K, V, sip::SipHasher> { - let mut r = rand::task_rng(); - let r0 = r.gen(); - let r1 = r.gen(); - let hasher = sip::SipHasher::new_with_keys(r0, r1); + pub fn with_capacity(capacity: uint) -> HashMap<K, V, RandomSipHasher> { + let hasher = RandomSipHasher::new(); HashMap::with_capacity_and_hasher(capacity, hasher) } } @@ -1489,7 +1484,7 @@ pub type SetMoveItems<K> = /// HashMap where the value is (). As with the `HashMap` type, a `HashSet` /// requires that the elements implement the `Eq` and `Hash` traits. #[deriving(Clone)] -pub struct HashSet<T, H = sip::SipHasher> { +pub struct HashSet<T, H = RandomSipHasher> { map: HashMap<T, (), H> } @@ -1529,15 +1524,15 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> MutableSet<T> for HashSet<T, H> { fn remove(&mut self, value: &T) -> bool { self.map.remove(value) } } -impl<T: Hash + Eq> HashSet<T, sip::SipHasher> { +impl<T: Hash + Eq> HashSet<T, RandomSipHasher> { /// Create an empty HashSet - pub fn new() -> HashSet<T, sip::SipHasher> { + pub fn new() -> HashSet<T, RandomSipHasher> { HashSet::with_capacity(INITIAL_CAPACITY) } /// Create an empty HashSet with space for at least `n` elements in /// the hash table. - pub fn with_capacity(capacity: uint) -> HashSet<T, sip::SipHasher> { + pub fn with_capacity(capacity: uint) -> HashSet<T, RandomSipHasher> { HashSet { map: HashMap::with_capacity(capacity) } } } diff --git a/src/libstd/hash.rs b/src/libstd/hash.rs new file mode 100644 index 00000000000..fd1bab2dd71 --- /dev/null +++ b/src/libstd/hash.rs @@ -0,0 +1,51 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Generic hashing support. + +pub use core_collections::hash::{Hash, Hasher, Writer, hash, sip}; + +use default::Default; +use rand::Rng; +use rand; + +/// `RandomSipHasher` computes the SipHash algorithm from a stream of bytes +/// initialized with random keys. +#[deriving(Clone)] +pub struct RandomSipHasher { + hasher: sip::SipHasher, +} + +impl RandomSipHasher { + /// Construct a new `RandomSipHasher` that is initialized with random keys. + #[inline] + pub fn new() -> RandomSipHasher { + let mut r = rand::task_rng(); + let r0 = r.gen(); + let r1 = r.gen(); + RandomSipHasher { + hasher: sip::SipHasher::new_with_keys(r0, r1), + } + } +} + +impl Hasher<sip::SipState> for RandomSipHasher { + #[inline] + fn hash<T: Hash<sip::SipState>>(&self, value: &T) -> u64 { + self.hasher.hash(value) + } +} + +impl Default for RandomSipHasher { + #[inline] + fn default() -> RandomSipHasher { + RandomSipHasher::new() + } +} diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index f63e69f3cca..12ad1d64344 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -166,7 +166,6 @@ pub use core::option; pub use alloc::owned; pub use alloc::rc; -pub use core_collections::hash; pub use core_collections::slice; pub use core_collections::str; pub use core_collections::string; @@ -236,6 +235,7 @@ pub mod to_str; /* Common data structures */ pub mod collections; +pub mod hash; /* Tasks and communication */ |
