diff options
Diffstat (limited to 'library/std/src')
| -rw-r--r-- | library/std/src/path/tests.rs | 1 | ||||
| -rw-r--r-- | library/std/src/process.rs | 2 | ||||
| -rw-r--r-- | library/std/src/sys/windows/c.rs | 4 | ||||
| -rw-r--r-- | library/std/src/sys/windows/rand.rs | 74 |
4 files changed, 76 insertions, 5 deletions
diff --git a/library/std/src/path/tests.rs b/library/std/src/path/tests.rs index 0d8ea29c2be..351cf698810 100644 --- a/library/std/src/path/tests.rs +++ b/library/std/src/path/tests.rs @@ -7,6 +7,7 @@ use crate::rc::Rc; use crate::sync::Arc; use core::hint::black_box; +#[allow(unknown_lints, unused_macro_rules)] macro_rules! t ( ($path:expr, iter: $iter:expr) => ( { diff --git a/library/std/src/process.rs b/library/std/src/process.rs index 6c5c08d0bea..e253f46406f 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -1764,7 +1764,7 @@ impl ExitCode { /// code.exit_process() /// } /// ``` - #[unstable(feature = "exitcode_exit_method", issue = "none")] + #[unstable(feature = "exitcode_exit_method", issue = "97100")] pub fn exit_process(self) -> ! { exit(self.to_i32()) } diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs index 0692da1d795..0bb6fee60c9 100644 --- a/library/std/src/sys/windows/c.rs +++ b/library/std/src/sys/windows/c.rs @@ -788,6 +788,10 @@ if #[cfg(not(target_vendor = "uwp"))] { #[link(name = "advapi32")] extern "system" { + // Forbidden when targeting UWP + #[link_name = "SystemFunction036"] + pub fn RtlGenRandom(RandomBuffer: *mut u8, RandomBufferLength: ULONG) -> BOOLEAN; + // Allowed but unused by UWP pub fn OpenProcessToken( ProcessHandle: HANDLE, diff --git a/library/std/src/sys/windows/rand.rs b/library/std/src/sys/windows/rand.rs index de73e9154b4..22e024d8552 100644 --- a/library/std/src/sys/windows/rand.rs +++ b/library/std/src/sys/windows/rand.rs @@ -1,8 +1,60 @@ use crate::io; +use crate::lazy; use crate::mem; use crate::sys::c; +/// The kinds of HashMap RNG that may be available +#[derive(Clone, Copy, Debug, PartialEq)] +enum HashMapRng { + Preferred, + Fallback, +} + pub fn hashmap_random_keys() -> (u64, u64) { + match get_hashmap_rng() { + HashMapRng::Preferred => { + preferred_rng().expect("couldn't generate random bytes with preferred RNG") + } + HashMapRng::Fallback => { + fallback_rng().expect("couldn't generate random bytes with fallback RNG") + } + } +} + +/// Returns the HashMap RNG that should be used +/// +/// Panics if they are both broken +fn get_hashmap_rng() -> HashMapRng { + // Assume that if the preferred RNG is broken the first time we use it, it likely means + // that: the DLL has failed to load, there is no point to calling it over-and-over again, + // and we should cache the result + static VALUE: lazy::SyncOnceCell<HashMapRng> = lazy::SyncOnceCell::new(); + *VALUE.get_or_init(choose_hashmap_rng) +} + +/// Test whether we should use the preferred or fallback RNG +/// +/// If the preferred RNG is successful, we choose it. Otherwise, if the fallback RNG is successful, +/// we choose that +/// +/// Panics if both the preferred and the fallback RNG are both non-functional +fn choose_hashmap_rng() -> HashMapRng { + let preferred_error = match preferred_rng() { + Ok(_) => return HashMapRng::Preferred, + Err(e) => e, + }; + + match fallback_rng() { + Ok(_) => return HashMapRng::Fallback, + Err(fallback_error) => panic!( + "preferred RNG broken: `{}`, fallback RNG broken: `{}`", + preferred_error, fallback_error + ), + } +} + +/// Generate random numbers using the preferred RNG function (BCryptGenRandom) +fn preferred_rng() -> Result<(u64, u64), io::Error> { use crate::ptr; let mut v = (0, 0); @@ -14,8 +66,22 @@ pub fn hashmap_random_keys() -> (u64, u64) { c::BCRYPT_USE_SYSTEM_PREFERRED_RNG, ) }; - if ret != 0 { - panic!("couldn't generate random bytes: {}", io::Error::last_os_error()); - } - return v; + + if ret == 0 { Ok(v) } else { Err(io::Error::last_os_error()) } +} + +/// Generate random numbers using the fallback RNG function (RtlGenRandom) +#[cfg(not(target_vendor = "uwp"))] +fn fallback_rng() -> Result<(u64, u64), io::Error> { + let mut v = (0, 0); + let ret = + unsafe { c::RtlGenRandom(&mut v as *mut _ as *mut u8, mem::size_of_val(&v) as c::ULONG) }; + + if ret != 0 { Ok(v) } else { Err(io::Error::last_os_error()) } +} + +/// We can't use RtlGenRandom with UWP, so there is no fallback +#[cfg(target_vendor = "uwp")] +fn fallback_rng() -> Result<(u64, u64), io::Error> { + Err(io::const_io_error!(io::ErrorKind::Unsupported, "RtlGenRandom() not supported on UWP")) } |
