From f79dc484deb87ade283342507356397ef2cc61e4 Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Thu, 18 Jun 2026 07:42:56 +0000 Subject: [PATCH] Avoid unsafe where safety depends on non-local values --- CHANGELOG.md | 2 ++ src/distr/slice.rs | 15 +++------------ src/distr/uniform_other.rs | 7 +++---- 3 files changed, 8 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e0e189f60..0d9f126945 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,8 +12,10 @@ You may also find the [Upgrade Guide](https://rust-random.github.io/book/update. ### Changes - Document required output order of fn `partial_shuffle` and apply `#[must_use]` ([#1769]) +- Avoid usage of `unsafe` in contexts where non-local memory corruption could invalidate contract ([#1791]) [#1769]: https://github.com/rust-random/rand/pull/1769 +[#1791]: https://github.com/rust-random/rand/pull/1791 ## [0.10.1] — 2026-02-11 This release includes a fix for a soundness bug; see [#1763]. diff --git a/src/distr/slice.rs b/src/distr/slice.rs index bbe7840e47..dc5853566f 100644 --- a/src/distr/slice.rs +++ b/src/distr/slice.rs @@ -86,18 +86,9 @@ impl<'a, T> Choose<'a, T> { impl<'a, T> Distribution<&'a T> for Choose<'a, T> { fn sample(&self, rng: &mut R) -> &'a T { let idx = self.range.sample(rng); - - debug_assert!( - idx < self.slice.len(), - "Uniform::new(0, {}) somehow returned {}", - self.slice.len(), - idx - ); - - // Safety: at construction time, it was ensured that the slice was - // non-empty, and that the `Uniform` range produces values in range - // for the slice - unsafe { self.slice.get_unchecked(idx) } + self.slice + .get(idx) + .expect("rand::distr::slice::Choose: index out-of-range (likely memory corruption)") } } diff --git a/src/distr/uniform_other.rs b/src/distr/uniform_other.rs index a1813b761a..25b4d9b83e 100644 --- a/src/distr/uniform_other.rs +++ b/src/distr/uniform_other.rs @@ -83,10 +83,9 @@ impl UniformSampler for UniformChar { if x >= CHAR_SURROGATE_START { x += CHAR_SURROGATE_LEN; } - // SAFETY: x must not be in surrogate range or greater than char::MAX. - // This relies on range constructors which accept char arguments. - // Validity of input char values is assumed. - unsafe { core::char::from_u32_unchecked(x) } + + char::from_u32(x) + .expect("rand::distr::uniform::UniformChar: invalid Unicode scalar value (likely memory corruption)") } }