Skip to content

Commit

Permalink
Seed thread_rng with the current time if OsRng fails. Fixes #180.
Browse files Browse the repository at this point in the history
  • Loading branch information
cpeterso committed Oct 25, 2017
1 parent 807b142 commit 6d297d5
Showing 1 changed file with 16 additions and 6 deletions.
22 changes: 16 additions & 6 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ use std::mem;
use std::io;
use std::rc::Rc;
use std::num::Wrapping as w;
use std::time;

pub use os::OsRng;

Expand Down Expand Up @@ -902,9 +903,9 @@ struct ThreadRngReseeder;

impl reseeding::Reseeder<StdRng> for ThreadRngReseeder {
fn reseed(&mut self, rng: &mut StdRng) {
*rng = match StdRng::new() {
Ok(r) => r,
Err(e) => panic!("could not reseed thread_rng: {}", e)
match StdRng::new() {
Ok(r) => *rng = r,
Err(_) => rng.reseed(&weak_seed())
}
}
}
Expand All @@ -921,8 +922,9 @@ pub struct ThreadRng {
/// generator, seeded by the system. Intended to be used in method
/// chaining style, e.g. `thread_rng().gen::<i32>()`.
///
/// The RNG provided will reseed itself from the operating system
/// after generating a certain amount of randomness.
/// After generating a certain amount of randomness, the RNG will reseed itself
/// from the operating system or, if the operating system RNG returns an error,
/// a seed based on the current system time.
///
/// The internal RNG used is platform and architecture dependent, even
/// if the operating system random number generator is rigged to give
Expand All @@ -933,7 +935,7 @@ pub fn thread_rng() -> ThreadRng {
thread_local!(static THREAD_RNG_KEY: Rc<RefCell<ThreadRngInner>> = {
let r = match StdRng::new() {
Ok(r) => r,
Err(e) => panic!("could not initialize thread_rng: {}", e)
Err(_) => StdRng::from_seed(&weak_seed())
};
let rng = reseeding::ReseedingRng::new(r,
THREAD_RNG_RESEED_THRESHOLD,
Expand All @@ -944,6 +946,14 @@ pub fn thread_rng() -> ThreadRng {
ThreadRng { rng: THREAD_RNG_KEY.with(|t| t.clone()) }
}

fn weak_seed() -> [usize; 2] {
let now = time::SystemTime::now();
let unix_time = now.duration_since(time::UNIX_EPOCH).unwrap();
let seconds = unix_time.as_secs() as usize;
let nanoseconds = unix_time.subsec_nanos() as usize;
[seconds, nanoseconds]
}

impl Rng for ThreadRng {
fn next_u32(&mut self) -> u32 {
self.rng.borrow_mut().next_u32()
Expand Down

0 comments on commit 6d297d5

Please sign in to comment.