diff options
Diffstat (limited to 'src/custom.rs')
-rw-r--r-- | src/custom.rs | 46 |
1 files changed, 25 insertions, 21 deletions
diff --git a/src/custom.rs b/src/custom.rs index 8432dfd..8dc9cb7 100644 --- a/src/custom.rs +++ b/src/custom.rs @@ -1,14 +1,6 @@ -// Copyright 2018 Developers of the Rand project. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - //! An implementation which calls out to an externally defined function. -use crate::Error; -use core::num::NonZeroU32; +use crate::{util::uninit_slice_fill_zero, Error}; +use core::{mem::MaybeUninit, num::NonZeroU32}; /// Register a function to be invoked by `getrandom` on unsupported targets. /// @@ -76,24 +68,36 @@ use core::num::NonZeroU32; #[cfg_attr(docsrs, doc(cfg(feature = "custom")))] macro_rules! register_custom_getrandom { ($path:path) => { - // We use an extern "C" function to get the guarantees of a stable ABI. - #[no_mangle] - extern "C" fn __getrandom_custom(dest: *mut u8, len: usize) -> u32 { - let f: fn(&mut [u8]) -> Result<(), $crate::Error> = $path; - let slice = unsafe { ::core::slice::from_raw_parts_mut(dest, len) }; - match f(slice) { - Ok(()) => 0, - Err(e) => e.code().get(), + // TODO(MSRV 1.37): change to unnamed block + const __GETRANDOM_INTERNAL: () = { + // We use Rust ABI to be safe against potential panics in the passed function. + #[no_mangle] + unsafe fn __getrandom_custom(dest: *mut u8, len: usize) -> u32 { + // Make sure the passed function has the type of getrandom::getrandom + type F = fn(&mut [u8]) -> ::core::result::Result<(), $crate::Error>; + let _: F = $crate::getrandom; + let f: F = $path; + let slice = ::core::slice::from_raw_parts_mut(dest, len); + match f(slice) { + Ok(()) => 0, + Err(e) => e.code().get(), + } } - } + }; }; } #[allow(dead_code)] -pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> { - extern "C" { +pub fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> { + extern "Rust" { fn __getrandom_custom(dest: *mut u8, len: usize) -> u32; } + // Previously we always passed a valid, initialized slice to + // `__getrandom_custom`. Ensure `dest` has been initialized for backward + // compatibility with implementations that rely on that (e.g. Rust + // implementations that construct a `&mut [u8]` slice from `dest` and + // `len`). + let dest = uninit_slice_fill_zero(dest); let ret = unsafe { __getrandom_custom(dest.as_mut_ptr(), dest.len()) }; match NonZeroU32::new(ret) { None => Ok(()), |