diff --git a/src/bsd_arandom.rs b/src/bsd_arandom.rs index 96099a39..3539dd5d 100644 --- a/src/bsd_arandom.rs +++ b/src/bsd_arandom.rs @@ -34,7 +34,7 @@ pub fn getrandom_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { // getrandom(2) was introduced in FreeBSD 12.0 and NetBSD 10.0 #[cfg(target_os = "freebsd")] { - use crate::{util::uninit_slice_as_mut_ptr, util_libc::Weak}; + use crate::util_libc::Weak; static GETRANDOM: Weak = unsafe { Weak::new("getrandom\0") }; type GetRandomFn = unsafe extern "C" fn(*mut u8, libc::size_t, libc::c_uint) -> libc::ssize_t; @@ -42,7 +42,7 @@ pub fn getrandom_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { if let Some(fptr) = GETRANDOM.ptr() { let func: GetRandomFn = unsafe { core::mem::transmute(fptr) }; return sys_fill_exact(dest, |buf| unsafe { - func(uninit_slice_as_mut_ptr(buf), buf.len(), 0) + func(buf.as_mut_ptr() as *mut u8, buf.len(), 0) }); } } diff --git a/src/fuchsia.rs b/src/fuchsia.rs index 8e2412bc..5a135f34 100644 --- a/src/fuchsia.rs +++ b/src/fuchsia.rs @@ -7,7 +7,7 @@ // except according to those terms. //! Implementation for Fuchsia Zircon -use crate::{util::uninit_slice_as_mut_ptr, Error}; +use crate::Error; use core::mem::MaybeUninit; #[link(name = "zircon")] @@ -16,6 +16,6 @@ extern "C" { } pub fn getrandom_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { - unsafe { zx_cprng_draw(uninit_slice_as_mut_ptr(dest), dest.len()) } + unsafe { zx_cprng_draw(dest.as_mut_ptr() as *mut u8, dest.len()) } Ok(()) } diff --git a/src/ios.rs b/src/ios.rs index f4379ed9..8f904859 100644 --- a/src/ios.rs +++ b/src/ios.rs @@ -7,7 +7,7 @@ // except according to those terms. //! Implementation for iOS -use crate::{util::uninit_slice_as_mut_ptr, Error}; +use crate::Error; use core::{ffi::c_void, mem::MaybeUninit, ptr::null}; #[link(name = "Security", kind = "framework")] @@ -17,7 +17,7 @@ extern "C" { pub fn getrandom_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { // Apple's documentation guarantees kSecRandomDefault is a synonym for NULL. - let ret = unsafe { SecRandomCopyBytes(null(), dest.len(), uninit_slice_as_mut_ptr(dest)) }; + let ret = unsafe { SecRandomCopyBytes(null(), dest.len(), dest.as_mut_ptr() as *mut u8) }; // errSecSuccess (from SecBase.h) is always zero. if ret != 0 { Err(Error::IOS_SEC_RANDOM) diff --git a/src/js.rs b/src/js.rs index 44f75809..7b9ae313 100644 --- a/src/js.rs +++ b/src/js.rs @@ -5,10 +5,7 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::{ - util::{uninit_slice_as_mut_ptr, uninit_slice_fill_zero}, - Error, -}; +use crate::{util::uninit_slice_fill_zero, Error}; extern crate std; use std::{mem::MaybeUninit, thread_local}; @@ -58,7 +55,7 @@ pub(crate) fn getrandom_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> } // SAFETY: `sub_buf`'s length is the same length as `chunk` - unsafe { sub_buf.raw_copy_to_ptr(uninit_slice_as_mut_ptr(chunk)) }; + unsafe { sub_buf.raw_copy_to_ptr(chunk.as_mut_ptr() as *mut u8) }; } } }; diff --git a/src/lib.rs b/src/lib.rs index 2ef97778..08453a10 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -205,6 +205,9 @@ pub use crate::error::Error; // // These should all provide getrandom_inner with the signature // `fn getrandom_inner(dest: &mut [MaybeUninit]) -> Result<(), Error>`. +// The function MUST fully initialize `dest` when `Ok(())` is returned. +// The function MUST NOT ever write uninitialized bytes into `dest`, +// regardless of what value it returns. cfg_if! { if #[cfg(any(target_os = "emscripten", target_os = "haiku", target_os = "redox"))] { @@ -290,8 +293,11 @@ cfg_if! { /// [`rand::thread_rng`](https://docs.rs/rand/*/rand/fn.thread_rng.html). #[inline] pub fn getrandom(dest: &mut [u8]) -> Result<(), Error> { - // SAFETY: The `&mut MaybeUninit<_>` reference doesn't escape. - getrandom_uninit_slice(unsafe { slice_as_uninit_mut(dest) }).map(|_| ()) + // SAFETY: The `&mut MaybeUninit<_>` reference doesn't escape, and + // `getrandom_uninit_slice` guarantees it will never de-initialize any + // part of `dest`. + getrandom_uninit_slice(unsafe { slice_as_uninit_mut(dest) })?; + Ok(()) } /// Version of the `getrandom` function which fills `dest` with random bytes @@ -302,6 +308,9 @@ pub fn getrandom(dest: &mut [u8]) -> Result<(), Error> { /// In other words, it's safe to assume that `dest` is initialized after /// this function has returned `Ok`. /// +/// No part of `dest` will ever be de-initialized at any point, regardless +/// of what is returned. +/// /// # Examples /// /// ```ignore diff --git a/src/macos.rs b/src/macos.rs index d1a6bb78..312f9b27 100644 --- a/src/macos.rs +++ b/src/macos.rs @@ -9,7 +9,6 @@ //! Implementation for macOS use crate::{ use_file, - util::uninit_slice_as_mut_ptr, util_libc::{last_os_error, Weak}, Error, }; @@ -23,7 +22,7 @@ pub fn getrandom_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { if let Some(fptr) = GETENTROPY.ptr() { let func: GetEntropyFn = unsafe { mem::transmute(fptr) }; for chunk in dest.chunks_mut(256) { - let ret = unsafe { func(uninit_slice_as_mut_ptr(chunk), chunk.len()) }; + let ret = unsafe { func(chunk.as_mut_ptr() as *mut u8, chunk.len()) }; if ret != 0 { return Err(last_os_error()); } diff --git a/src/solid.rs b/src/solid.rs index 2750833c..aeccc4e2 100644 --- a/src/solid.rs +++ b/src/solid.rs @@ -7,7 +7,7 @@ // except according to those terms. //! Implementation for SOLID -use crate::{util::uninit_slice_as_mut_ptr, Error}; +use crate::Error; use core::{mem::MaybeUninit, num::NonZeroU32}; extern "C" { @@ -15,7 +15,7 @@ extern "C" { } pub fn getrandom_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { - let ret = unsafe { SOLID_RNG_SampleRandomBytes(uninit_slice_as_mut_ptr(dest), dest.len()) }; + let ret = unsafe { SOLID_RNG_SampleRandomBytes(dest.as_mut_ptr() as *mut u8, dest.len()) }; if ret >= 0 { Ok(()) } else { diff --git a/src/util.rs b/src/util.rs index ac073ce9..655d16de 100644 --- a/src/util.rs +++ b/src/util.rs @@ -75,13 +75,6 @@ pub unsafe fn slice_assume_init_mut(slice: &mut [MaybeUninit]) -> &mut [T] mem::transmute(slice) } -/// Polyfill for the unstable `maybe_uninit_slice` feature's -/// `MaybeUninit::slice_as_mut_ptr`. -#[inline(always)] -pub fn uninit_slice_as_mut_ptr(slice: &mut [MaybeUninit]) -> *mut T { - slice.as_mut_ptr() as *mut T -} - #[inline] pub fn uninit_slice_fill_zero(slice: &mut [MaybeUninit]) -> &mut [u8] { slice.iter_mut().for_each(|b| *b = MaybeUninit::zeroed()); diff --git a/src/vxworks.rs b/src/vxworks.rs index caecca28..9b2090fb 100644 --- a/src/vxworks.rs +++ b/src/vxworks.rs @@ -7,7 +7,7 @@ // except according to those terms. //! Implementation for VxWorks -use crate::{util::uninit_slice_as_mut_ptr, util_libc::last_os_error, Error}; +use crate::{util_libc::last_os_error, Error}; use core::{ mem::MaybeUninit, sync::atomic::{AtomicBool, Ordering::Relaxed}, @@ -28,7 +28,7 @@ pub fn getrandom_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { // Prevent overflow of i32 for chunk in dest.chunks_mut(i32::max_value() as usize) { - let ret = unsafe { libc::randABytes(uninit_slice_as_mut_ptr(chunk), chunk.len() as i32) }; + let ret = unsafe { libc::randABytes(chunk.as_mut_ptr() as *mut u8, chunk.len() as i32) }; if ret != 0 { return Err(last_os_error()); } diff --git a/src/windows.rs b/src/windows.rs index 7d31be48..e5a626c0 100644 --- a/src/windows.rs +++ b/src/windows.rs @@ -6,7 +6,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::{util::uninit_slice_as_mut_ptr, Error}; +use crate::Error; use core::{ffi::c_void, mem::MaybeUninit, num::NonZeroU32, ptr}; const BCRYPT_USE_SYSTEM_PREFERRED_RNG: u32 = 0x00000002; @@ -28,7 +28,7 @@ pub fn getrandom_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { let ret = unsafe { BCryptGenRandom( ptr::null_mut(), - uninit_slice_as_mut_ptr(chunk), + chunk.as_mut_ptr() as *mut u8, chunk.len() as u32, BCRYPT_USE_SYSTEM_PREFERRED_RNG, )