From 37514dedabd58f8146afcac6680dc0d77ef2193d Mon Sep 17 00:00:00 2001 From: LeSeulArtichaut Date: Sat, 11 Apr 2020 20:11:59 +0200 Subject: [PATCH 1/5] Document unsafety in `core::option` --- src/libcore/option.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 3aab8b1b3337c..63a5277100fa8 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -133,8 +133,6 @@ //! [`Box`]: ../../std/boxed/struct.Box.html //! [`i32`]: ../../std/primitive.i32.html -// ignore-tidy-undocumented-unsafe - #![stable(feature = "rust1", since = "1.0.0")] use crate::iter::{FromIterator, FusedIterator, TrustedLen}; @@ -301,6 +299,8 @@ impl Option { #[inline] #[stable(feature = "pin", since = "1.33.0")] pub fn as_pin_ref(self: Pin<&Self>) -> Option> { + // SAFETY: `x` is guaranteed to be pinned because it comes from `self` + // which is pinned. unsafe { Pin::get_ref(self).as_ref().map(|x| Pin::new_unchecked(x)) } } @@ -310,6 +310,8 @@ impl Option { #[inline] #[stable(feature = "pin", since = "1.33.0")] pub fn as_pin_mut(self: Pin<&mut Self>) -> Option> { + // SAFETY: `get_unchecked_mut` is never used to move the `Option` inside `self`. + // `x` is guaranteed to be pinned because it comes from `self` which is pinned. unsafe { Pin::get_unchecked_mut(self).as_mut().map(|x| Pin::new_unchecked(x)) } } @@ -858,6 +860,8 @@ impl Option { match *self { Some(ref mut v) => v, + // SAFETY: a `None` variant for `self` would have been replaced by a `Some` + // variant in the code above. None => unsafe { hint::unreachable_unchecked() }, } } From d1ce7ff84ec94d8d5d18368dc8c18560f327c9a1 Mon Sep 17 00:00:00 2001 From: LeSeulArtichaut Date: Sat, 11 Apr 2020 22:00:34 +0200 Subject: [PATCH 2/5] Document unsafety in `src/libcore/hash/mod.rs` --- src/libcore/hash/mod.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs index 2a7fa58dd30ec..14ca0826733c0 100644 --- a/src/libcore/hash/mod.rs +++ b/src/libcore/hash/mod.rs @@ -79,8 +79,6 @@ //! } //! ``` -// ignore-tidy-undocumented-unsafe - #![stable(feature = "rust1", since = "1.0.0")] use crate::fmt; @@ -572,6 +570,9 @@ mod impls { fn hash_slice(data: &[$ty], state: &mut H) { let newlen = data.len() * mem::size_of::<$ty>(); let ptr = data.as_ptr() as *const u8; + // SAFETY: `ptr` is valid and aligned, the new slice only spans + // across `data` and is never mutated, and its total size is the + // same as the original `data` so it can't be over `isize::MAX`. state.write(unsafe { slice::from_raw_parts(ptr, newlen) }) } } @@ -691,6 +692,8 @@ mod impls { state.write_usize(*self as *const () as usize); } else { // Fat pointer + // SAFETY: we are accessing the memory occupied by `self` + // which is guaranteed to be valid. let (a, b) = unsafe { *(self as *const Self as *const (usize, usize)) }; state.write_usize(a); state.write_usize(b); @@ -706,6 +709,8 @@ mod impls { state.write_usize(*self as *const () as usize); } else { // Fat pointer + // SAFETY: we are accessing the memory occupied by `self` + // which is guaranteed to be valid. let (a, b) = unsafe { *(self as *const Self as *const (usize, usize)) }; state.write_usize(a); state.write_usize(b); From b84f9813618e6d8de68e91022e942562940a83cc Mon Sep 17 00:00:00 2001 From: LeSeulArtichaut Date: Sun, 12 Apr 2020 16:47:57 +0200 Subject: [PATCH 3/5] Document unsafety in `src/libcore/hash/sip.rs` --- src/libcore/hash/sip.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/libcore/hash/sip.rs b/src/libcore/hash/sip.rs index adfbe243512bd..ac058609f45ed 100644 --- a/src/libcore/hash/sip.rs +++ b/src/libcore/hash/sip.rs @@ -1,7 +1,5 @@ //! An implementation of SipHash. -// ignore-tidy-undocumented-unsafe - #![allow(deprecated)] // the types in this module are deprecated use crate::cmp; @@ -265,6 +263,7 @@ impl super::Hasher for Hasher { if self.ntail != 0 { needed = 8 - self.ntail; + // SAFETY: `cmp::min(length, needed)` is guaranteed to not be over `length` self.tail |= unsafe { u8to64_le(msg, 0, cmp::min(length, needed)) } << (8 * self.ntail); if length < needed { self.ntail += length; @@ -279,10 +278,13 @@ impl super::Hasher for Hasher { // Buffered tail is now flushed, process new input. let len = length - needed; - let left = len & 0x7; + let left = len & 0x7; // len % 8 let mut i = needed; while i < len - left { + // SAFETY: because `len - left` is the biggest multiple of 8 under + // `len`, and because `i` starts at `needed` where `len` is `length - needed`, + // `i + 8` is guaranteed to be less than or equal to `length`. let mi = unsafe { load_int_le!(msg, i, u64) }; self.state.v3 ^= mi; @@ -292,6 +294,9 @@ impl super::Hasher for Hasher { i += 8; } + // SAFETY: `i` is now `needed + len.div_euclid(8) * 8`, + // so `i + left` = `needed + len` = `length`, which is by + // definition equal to `msg.len()`. self.tail = unsafe { u8to64_le(msg, i, left) }; self.ntail = left; } From 3029e9e9e476337b9e2c71de669e87839bb19ed5 Mon Sep 17 00:00:00 2001 From: LeSeulArtichaut Date: Thu, 23 Apr 2020 18:32:41 +0200 Subject: [PATCH 4/5] Add note about padding Co-authored-by: Mark-Simulacrum --- src/libcore/hash/mod.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs index 14ca0826733c0..4f66b00b2796b 100644 --- a/src/libcore/hash/mod.rs +++ b/src/libcore/hash/mod.rs @@ -570,8 +570,9 @@ mod impls { fn hash_slice(data: &[$ty], state: &mut H) { let newlen = data.len() * mem::size_of::<$ty>(); let ptr = data.as_ptr() as *const u8; - // SAFETY: `ptr` is valid and aligned, the new slice only spans - // across `data` and is never mutated, and its total size is the + // SAFETY: `ptr` is valid and aligned, as this macro is only used + // for numeric primitives which have no padding. The new slice only + // spans across `data` and is never mutated, and its total size is the // same as the original `data` so it can't be over `isize::MAX`. state.write(unsafe { slice::from_raw_parts(ptr, newlen) }) } From a694315ed1943496149980dd80a0da2b1d71ff1c Mon Sep 17 00:00:00 2001 From: LeSeulArtichaut Date: Thu, 23 Apr 2020 23:05:37 +0200 Subject: [PATCH 5/5] Add a note about fat pointers Co-Authored-By: Mark-Simulacrum --- src/libcore/hash/mod.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs index 4f66b00b2796b..d80101753cbef 100644 --- a/src/libcore/hash/mod.rs +++ b/src/libcore/hash/mod.rs @@ -695,6 +695,9 @@ mod impls { // Fat pointer // SAFETY: we are accessing the memory occupied by `self` // which is guaranteed to be valid. + // This assumes a fat pointer can be represented by a `(usize, usize)`, + // which is safe to do in `std` because it is shipped and kept in sync + // with the implementation of fat pointers in `rustc`. let (a, b) = unsafe { *(self as *const Self as *const (usize, usize)) }; state.write_usize(a); state.write_usize(b); @@ -712,6 +715,9 @@ mod impls { // Fat pointer // SAFETY: we are accessing the memory occupied by `self` // which is guaranteed to be valid. + // This assumes a fat pointer can be represented by a `(usize, usize)`, + // which is safe to do in `std` because it is shipped and kept in sync + // with the implementation of fat pointers in `rustc`. let (a, b) = unsafe { *(self as *const Self as *const (usize, usize)) }; state.write_usize(a); state.write_usize(b);