Skip to content

Commit c0aa7dc

Browse files
committed
Fix soundness issues and improve safety comments
1 parent b81c644 commit c0aa7dc

File tree

4 files changed

+35
-19
lines changed

4 files changed

+35
-19
lines changed

src/distr/integer.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ impl Distribution<__m128i> for StandardUniform {
119119
rng.fill_bytes(&mut buf);
120120
// x86 is little endian so no need for conversion
121121

122-
// SAFETY: both source and result types are valid for all values.
122+
// SAFETY: All representations of the source are also representations of the target.
123123
unsafe { core::mem::transmute(buf) }
124124
}
125125
}
@@ -132,7 +132,7 @@ impl Distribution<__m256i> for StandardUniform {
132132
rng.fill_bytes(&mut buf);
133133
// x86 is little endian so no need for conversion
134134

135-
// SAFETY: both source and result types are valid for all values.
135+
// SAFETY: All representations of the source are also representations of the target.
136136
unsafe { core::mem::transmute(buf) }
137137
}
138138
}
@@ -148,7 +148,7 @@ impl Distribution<__m512i> for StandardUniform {
148148
rng.fill_bytes(&mut buf);
149149
// x86 is little endian so no need for conversion
150150

151-
// SAFETY: both source and result types are valid for all values.
151+
// SAFETY: All representations of the source are also representations of the target.
152152
unsafe { core::mem::transmute(buf) }
153153
}
154154
}

src/distr/other.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ impl Distribution<char> for StandardUniform {
8989
if n <= 0xDFFF {
9090
n -= GAP_SIZE;
9191
}
92+
// SAFETY: The representation of `n` is a valid representation of `u32`.
9293
unsafe { char::from_u32_unchecked(n) }
9394
}
9495
}
@@ -126,6 +127,7 @@ impl Distribution<u8> for Alphanumeric {
126127
#[cfg(feature = "alloc")]
127128
impl SampleString for Alphanumeric {
128129
fn append_string<R: Rng + ?Sized>(&self, rng: &mut R, string: &mut String, len: usize) {
130+
// SAFETY: `self` only samples alphanumeric characters, which are valid UTF-8.
129131
unsafe {
130132
let v = string.as_mut_vec();
131133
v.extend(self.sample_iter(rng).take(len));
@@ -238,12 +240,13 @@ where
238240
{
239241
#[inline]
240242
fn sample<R: Rng + ?Sized>(&self, _rng: &mut R) -> [T; N] {
241-
let mut buff: [MaybeUninit<T>; N] = unsafe { MaybeUninit::uninit().assume_init() };
243+
let mut buff: [MaybeUninit<T>; N] = [const { MaybeUninit::uninit() }; N];
242244

243245
for elem in &mut buff {
244-
*elem = MaybeUninit::new(_rng.random());
246+
elem.write(_rng.random());
245247
}
246248

249+
// SAFETY: All values of the array are initialized.
247250
unsafe { mem::transmute_copy::<_, _>(&buff) }
248251
}
249252
}

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
clippy::neg_cmp_op_on_partial_ord,
6060
clippy::nonminimal_bool
6161
)]
62+
#![deny(clippy::undocumented_unsafe_blocks)]
6263

6364
#[cfg(feature = "alloc")]
6465
extern crate alloc;

src/rng.rs

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -393,20 +393,26 @@ impl Fill for [u8] {
393393
}
394394
}
395395

396-
// This macro is unsafe to call: target types must support transmute from
397-
// random bits (i.e. all bit representations are valid).
396+
/// Implement `Fill` for given type `T`.
397+
///
398+
/// # Safety
399+
/// All representations of `[u8; size_of::<T>()]` are also representations of `T`.
398400
macro_rules! unsafe_impl_fill {
399401
() => {};
400402
($t:ty) => {
401403
impl Fill for [$t] {
402404
fn fill<R: Rng + ?Sized>(&mut self, rng: &mut R) {
403405
if self.len() > 0 {
404-
rng.fill_bytes(unsafe {
405-
slice::from_raw_parts_mut(self.as_mut_ptr()
406-
as *mut u8,
407-
mem::size_of_val(self)
408-
)
409-
});
406+
let size = mem::size_of_val(self);
407+
rng.fill_bytes(
408+
// SAFETY: `self` is not borrowed and all byte sequences are representations of `T`.
409+
unsafe {
410+
slice::from_raw_parts_mut(self.as_mut_ptr()
411+
as *mut u8,
412+
size
413+
)
414+
}
415+
);
410416
for x in self {
411417
*x = x.to_le();
412418
}
@@ -417,12 +423,16 @@ macro_rules! unsafe_impl_fill {
417423
impl Fill for [Wrapping<$t>] {
418424
fn fill<R: Rng + ?Sized>(&mut self, rng: &mut R) {
419425
if self.len() > 0 {
420-
rng.fill_bytes(unsafe {
421-
slice::from_raw_parts_mut(self.as_mut_ptr()
422-
as *mut u8,
423-
self.len() * mem::size_of::<$t>()
424-
)
425-
});
426+
let size = self.len() * mem::size_of::<$t>();
427+
rng.fill_bytes(
428+
// SAFETY: `self` is not borrowed and all byte sequences are representations of `T`.
429+
unsafe {
430+
slice::from_raw_parts_mut(self.as_mut_ptr()
431+
as *mut u8,
432+
size
433+
)
434+
}
435+
);
426436
for x in self {
427437
*x = Wrapping(x.0.to_le());
428438
}
@@ -438,7 +448,9 @@ macro_rules! unsafe_impl_fill {
438448
}
439449
}
440450

451+
// SAFETY: All representations of `[u8; size_of::<u*>()]` are representations of `u*`.
441452
unsafe_impl_fill!(u16, u32, u64, u128,);
453+
// SAFETY: All representations of `[u8; size_of::<i*>()]` are representations of `i*`.
442454
unsafe_impl_fill!(i8, i16, i32, i64, i128,);
443455

444456
impl<T, const N: usize> Fill for [T; N]

0 commit comments

Comments
 (0)