aboutsummaryrefslogtreecommitdiff
path: root/src/custom.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/custom.rs')
-rw-r--r--src/custom.rs46
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(()),