about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDylan DPC <dylan.dpc@gmail.com>2020-04-24 02:47:30 +0200
committerGitHub <noreply@github.com>2020-04-24 02:47:30 +0200
commit9ff020e0dd73cd8a64711bf999f69970ec608718 (patch)
tree28831f6e8ce759d9d2f8dcb9c506cdc0f3e6fc8d
parent45e04feb1d25103127beb5f34c126a64e959cff6 (diff)
parenta694315ed1943496149980dd80a0da2b1d71ff1c (diff)
downloadrust-9ff020e0dd73cd8a64711bf999f69970ec608718.tar.gz
rust-9ff020e0dd73cd8a64711bf999f69970ec608718.zip
Rollup merge of #71063 - LeSeulArtichaut:document-unsafe, r=Mark-Simulacrum
Document unsafety in core::{option, hash}

Helps with #66219.
I think that the part that will need reviewing the most is the `hash/sip.rs` file.
r? @LukasKalbertodt (or someone else from the libs team)
-rw-r--r--src/libcore/hash/mod.rs16
-rw-r--r--src/libcore/hash/sip.rs11
-rw-r--r--src/libcore/option.rs8
3 files changed, 28 insertions, 7 deletions
diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs
index 2a7fa58dd30..d80101753cb 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,10 @@ mod impls {
                 fn hash_slice<H: Hasher>(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, 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) })
                 }
             }
@@ -691,6 +693,11 @@ 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.
+                // 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);
@@ -706,6 +713,11 @@ 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.
+                // 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);
diff --git a/src/libcore/hash/sip.rs b/src/libcore/hash/sip.rs
index adfbe243512..ac058609f45 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<S: Sip> super::Hasher for Hasher<S> {
 
         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<S: Sip> super::Hasher for Hasher<S> {
 
         // 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<S: Sip> super::Hasher for Hasher<S> {
             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;
     }
diff --git a/src/libcore/option.rs b/src/libcore/option.rs
index 3aab8b1b333..63a5277100f 100644
--- a/src/libcore/option.rs
+++ b/src/libcore/option.rs
@@ -133,8 +133,6 @@
 //! [`Box<T>`]: ../../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<T> Option<T> {
     #[inline]
     #[stable(feature = "pin", since = "1.33.0")]
     pub fn as_pin_ref(self: Pin<&Self>) -> Option<Pin<&T>> {
+        // 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<T> Option<T> {
     #[inline]
     #[stable(feature = "pin", since = "1.33.0")]
     pub fn as_pin_mut(self: Pin<&mut Self>) -> Option<Pin<&mut T>> {
+        // 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<T> Option<T> {
 
         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() },
         }
     }