Skip to content

Commit c7de289

Browse files
committed
Make the stdlib largely conform to strict provenance.
Some things like the unwinders and system APIs are not fully conformant, this only covers a lot of low-hanging fruit.
1 parent 5167b68 commit c7de289

File tree

30 files changed

+100
-81
lines changed

30 files changed

+100
-81
lines changed

library/alloc/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@
158158
#![feature(rustc_allow_const_fn_unstable)]
159159
#![feature(rustc_attrs)]
160160
#![feature(staged_api)]
161+
#![feature(strict_provenance)]
161162
#![cfg_attr(test, feature(test))]
162163
#![feature(unboxed_closures)]
163164
#![feature(unsized_fn_params)]

library/alloc/src/rc.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2115,13 +2115,12 @@ impl<T> Weak<T> {
21152115
#[rustc_const_unstable(feature = "const_weak_new", issue = "95091", reason = "recently added")]
21162116
#[must_use]
21172117
pub const fn new() -> Weak<T> {
2118-
Weak { ptr: unsafe { NonNull::new_unchecked(usize::MAX as *mut RcBox<T>) } }
2118+
Weak { ptr: unsafe { NonNull::new_unchecked(ptr::invalid_mut::<RcBox<T>>(usize::MAX)) } }
21192119
}
21202120
}
21212121

21222122
pub(crate) fn is_dangling<T: ?Sized>(ptr: *mut T) -> bool {
2123-
let address = ptr as *mut () as usize;
2124-
address == usize::MAX
2123+
(ptr as *mut ()).addr() == usize::MAX
21252124
}
21262125

21272126
/// Helper type to allow accessing the reference counts without

library/alloc/src/slice.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1044,7 +1044,7 @@ where
10441044
impl<T> Drop for MergeHole<T> {
10451045
fn drop(&mut self) {
10461046
// `T` is not a zero-sized type, so it's okay to divide by its size.
1047-
let len = (self.end as usize - self.start as usize) / mem::size_of::<T>();
1047+
let len = (self.end.addr() - self.start.addr()) / mem::size_of::<T>();
10481048
unsafe {
10491049
ptr::copy_nonoverlapping(self.start, self.dest, len);
10501050
}

library/alloc/src/sync.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1746,7 +1746,7 @@ impl<T> Weak<T> {
17461746
#[rustc_const_unstable(feature = "const_weak_new", issue = "95091", reason = "recently added")]
17471747
#[must_use]
17481748
pub const fn new() -> Weak<T> {
1749-
Weak { ptr: unsafe { NonNull::new_unchecked(usize::MAX as *mut ArcInner<T>) } }
1749+
Weak { ptr: unsafe { NonNull::new_unchecked(ptr::invalid_mut::<ArcInner<T>>(usize::MAX)) } }
17501750
}
17511751
}
17521752

library/alloc/src/vec/into_iter.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ impl<T, A: Allocator> Iterator for IntoIter<T, A> {
159159
#[inline]
160160
fn size_hint(&self) -> (usize, Option<usize>) {
161161
let exact = if mem::size_of::<T>() == 0 {
162-
(self.end as usize).wrapping_sub(self.ptr as usize)
162+
self.end.addr().wrapping_sub(self.ptr.addr())
163163
} else {
164164
unsafe { self.end.offset_from(self.ptr) as usize }
165165
};

library/core/src/alloc/layout.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ impl Layout {
194194
#[inline]
195195
pub const fn dangling(&self) -> NonNull<u8> {
196196
// SAFETY: align is guaranteed to be non-zero
197-
unsafe { NonNull::new_unchecked(self.align() as *mut u8) }
197+
unsafe { NonNull::new_unchecked(crate::ptr::invalid_mut::<u8>(self.align())) }
198198
}
199199

200200
/// Creates a layout describing the record that can hold a value

library/core/src/fmt/mod.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,11 @@ impl<'a> ArgumentV1<'a> {
352352
}
353353

354354
fn as_usize(&self) -> Option<usize> {
355-
if self.formatter as usize == USIZE_MARKER as usize {
355+
// We are type punning a bit here: USIZE_MARKER only takes an &usize but
356+
// formatter takes an &Opaque. Rust understandably doesn't think we should compare
357+
// the function pointers if they don't have the same signature, so we cast to
358+
// pointers to convince it that we know what we're doing.
359+
if self.formatter as *mut u8 == USIZE_MARKER as *mut u8 {
356360
// SAFETY: The `formatter` field is only set to USIZE_MARKER if
357361
// the value is a usize, so this is safe
358362
Some(unsafe { *(self.value as *const _ as *const usize) })
@@ -2246,7 +2250,7 @@ impl<T: ?Sized> Pointer for *const T {
22462250
}
22472251
f.flags |= 1 << (FlagV1::Alternate as u32);
22482252

2249-
let ret = LowerHex::fmt(&(ptr as usize), f);
2253+
let ret = LowerHex::fmt(&(ptr.addr()), f);
22502254

22512255
f.width = old_width;
22522256
f.flags = old_flags;

library/core/src/hash/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -793,7 +793,7 @@ mod impls {
793793
#[inline]
794794
fn hash<H: Hasher>(&self, state: &mut H) {
795795
let (address, metadata) = self.to_raw_parts();
796-
state.write_usize(address as usize);
796+
state.write_usize(address.addr());
797797
metadata.hash(state);
798798
}
799799
}
@@ -803,7 +803,7 @@ mod impls {
803803
#[inline]
804804
fn hash<H: Hasher>(&self, state: &mut H) {
805805
let (address, metadata) = self.to_raw_parts();
806-
state.write_usize(address as usize);
806+
state.write_usize(address.addr());
807807
metadata.hash(state);
808808
}
809809
}

library/core/src/intrinsics.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1972,15 +1972,15 @@ extern "rust-intrinsic" {
19721972
/// Checks whether `ptr` is properly aligned with respect to
19731973
/// `align_of::<T>()`.
19741974
pub(crate) fn is_aligned_and_not_null<T>(ptr: *const T) -> bool {
1975-
!ptr.is_null() && ptr as usize % mem::align_of::<T>() == 0
1975+
!ptr.is_null() && ptr.addr() % mem::align_of::<T>() == 0
19761976
}
19771977

19781978
/// Checks whether the regions of memory starting at `src` and `dst` of size
19791979
/// `count * size_of::<T>()` do *not* overlap.
19801980
#[cfg(debug_assertions)]
19811981
pub(crate) fn is_nonoverlapping<T>(src: *const T, dst: *const T, count: usize) -> bool {
1982-
let src_usize = src as usize;
1983-
let dst_usize = dst as usize;
1982+
let src_usize = src.addr();
1983+
let dst_usize = dst.addr();
19841984
let size = mem::size_of::<T>().checked_mul(count).unwrap();
19851985
let diff = if src_usize > dst_usize { src_usize - dst_usize } else { dst_usize - src_usize };
19861986
// If the absolute distance between the ptrs is at least as big as the size of the buffer,

library/core/src/ptr/non_null.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ impl<T: Sized> NonNull<T> {
9090
// to a *mut T. Therefore, `ptr` is not null and the conditions for
9191
// calling new_unchecked() are respected.
9292
unsafe {
93-
let ptr = mem::align_of::<T>() as *mut T;
93+
let ptr = crate::ptr::invalid_mut::<T>(mem::align_of::<T>());
9494
NonNull::new_unchecked(ptr)
9595
}
9696
}
@@ -469,7 +469,7 @@ impl<T> NonNull<[T]> {
469469
/// use std::ptr::NonNull;
470470
///
471471
/// let slice: NonNull<[i8]> = NonNull::slice_from_raw_parts(NonNull::dangling(), 3);
472-
/// assert_eq!(slice.as_non_null_ptr(), NonNull::new(1 as *mut i8).unwrap());
472+
/// assert_eq!(slice.as_non_null_ptr(), NonNull::<i8>::dangling());
473473
/// ```
474474
#[inline]
475475
#[must_use]
@@ -489,7 +489,7 @@ impl<T> NonNull<[T]> {
489489
/// use std::ptr::NonNull;
490490
///
491491
/// let slice: NonNull<[i8]> = NonNull::slice_from_raw_parts(NonNull::dangling(), 3);
492-
/// assert_eq!(slice.as_mut_ptr(), 1 as *mut i8);
492+
/// assert_eq!(slice.as_mut_ptr(), NonNull::<i8>::dangling().as_ptr());
493493
/// ```
494494
#[inline]
495495
#[must_use]

0 commit comments

Comments
 (0)