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)
This commit is contained in:
commit
9ff020e0dd
3 changed files with 28 additions and 7 deletions
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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() },
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue