Skip to content

Commit 0cd09e9

Browse files
committed
Fix soundness issues and improve safety comments
1 parent 9dcaffe commit 0cd09e9

File tree

4 files changed

+32
-17
lines changed

4 files changed

+32
-17
lines changed

src/distr/integer.rs

+3-3
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

+2
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ impl Distribution<char> for StandardUniform {
118118
if n <= 0xDFFF {
119119
n -= GAP_SIZE;
120120
}
121+
// SAFETY: The representation of `n` is a valid representation of `u32`.
121122
unsafe { char::from_u32_unchecked(n) }
122123
}
123124
}
@@ -166,6 +167,7 @@ impl Distribution<u8> for Alphabetic {
166167
#[cfg(feature = "alloc")]
167168
impl SampleString for Alphanumeric {
168169
fn append_string<R: Rng + ?Sized>(&self, rng: &mut R, string: &mut String, len: usize) {
170+
// SAFETY: `self` only samples alphanumeric characters, which are valid UTF-8.
169171
unsafe {
170172
let v = string.as_mut_vec();
171173
v.extend(self.sample_iter(rng).take(len));

src/lib.rs

+1
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

+26-14
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)