From a81e9a781b19153d19898c421c80d713dc739d8e Mon Sep 17 00:00:00 2001 From: Daniel Henry-Mantilla Date: Tue, 19 May 2020 15:37:06 +0200 Subject: [PATCH 1/2] Improve documentation of `slice::from_raw_parts` This is to provide a more explicit statement against a code pattern that many people end up coming with, since the reason of it being unsound comes from the badly known single-allocation validity rule. Providing that very pattern as a counter-example could help mitigate that. Co-authored-by: Ralf Jung --- src/libcore/slice/mod.rs | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 9582ac33ff6b7..2e1dd89433d9e 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -5740,7 +5740,8 @@ unsafe impl<'a, T> TrustedRandomAccess for RChunksExactMut<'a, T> { /// and it must be properly aligned. This means in particular: /// /// * The entire memory range of this slice must be contained within a single allocated object! -/// Slices can never span across multiple allocated objects. +/// Slices can never span across multiple allocated objects. See [below](#incorrect-usage) +/// for an example incorrectly not taking this into account. /// * `data` must be non-null and aligned even for zero-length slices. One /// reason for this is that enum layout optimizations may rely on references /// (including slices of any length) being aligned and non-null to distinguish @@ -5773,6 +5774,34 @@ unsafe impl<'a, T> TrustedRandomAccess for RChunksExactMut<'a, T> { /// assert_eq!(slice[0], 42); /// ``` /// +/// ### Incorrect usage +/// +/// The following `join_slices` function is **unsound** ⚠️ +/// +/// ```rust,no_run +/// use std::slice; +/// +/// fn join_slices<'a, T>(fst: &'a [T], snd: &'a [T]) -> &'a [T] { +/// let fst_end = fst.as_ptr().wrapping_add(fst.len()); +/// let snd_start = snd.as_ptr(); +/// assert_eq!(fst_end, snd_start, "Slices must be contiguous!"); +/// unsafe { +/// // The assertion above ensures `fst` and `snd` are contiguous, but they might +/// // still be contained within _different allocated objects_, in which case +/// // creating this slice is undefined behavior. +/// slice::from_raw_parts(fst.as_ptr(), fst.len() + snd.len()) +/// } +/// } +/// +/// fn main() { +/// // `a` and `b` are different allocated objects... +/// let a = 42; +/// let b = 27; +/// // ... which may nevertheless be laid out contiguous in memory: | a | b | +/// let _ = join_slices(slice::from_ref(&a), slice::from_ref(&b)); // UB +/// } +/// ``` +/// /// [valid]: ../../std/ptr/index.html#safety /// [`NonNull::dangling()`]: ../../std/ptr/struct.NonNull.html#method.dangling /// [`pointer::offset`]: ../../std/primitive.pointer.html#method.offset From 67e075589b7e19a87130a700b7e59015a1b80f11 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 21 May 2020 19:07:59 +0200 Subject: [PATCH 2/2] Typo --- src/libcore/slice/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 2e1dd89433d9e..b5ce165cb43db 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -5797,7 +5797,7 @@ unsafe impl<'a, T> TrustedRandomAccess for RChunksExactMut<'a, T> { /// // `a` and `b` are different allocated objects... /// let a = 42; /// let b = 27; -/// // ... which may nevertheless be laid out contiguous in memory: | a | b | +/// // ... which may nevertheless be laid out contiguously in memory: | a | b | /// let _ = join_slices(slice::from_ref(&a), slice::from_ref(&b)); // UB /// } /// ```