Skip to content

Commit 701aa6c

Browse files
committed
WIP PROOF-OF-CONCEPT: handle all the fallout in the libs
Still working on this, but it seems to largely be a lot of `as usize` -> `.addr()`
1 parent 93f7f06 commit 701aa6c

File tree

32 files changed

+119
-83
lines changed

32 files changed

+119
-83
lines changed

library/alloc/src/lib.rs

+1
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

+2-3
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

+1-1
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

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

library/alloc/src/vec/into_iter.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ impl<T, A: Allocator> Iterator for IntoIter<T, A> {
154154
#[inline]
155155
fn size_hint(&self) -> (usize, Option<usize>) {
156156
let exact = if mem::size_of::<T>() == 0 {
157-
(self.end as usize).wrapping_sub(self.ptr as usize)
157+
self.end.addr().wrapping_sub(self.ptr.addr())
158158
} else {
159159
unsafe { self.end.offset_from(self.ptr) as usize }
160160
};

library/core/src/alloc/layout.rs

+1-1
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

+6-2
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

+2-2
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

+5-5
Original file line numberDiff line numberDiff line change
@@ -987,8 +987,8 @@ extern "rust-intrinsic" {
987987
/// std::mem::transmute::<&i32, usize>(ptr)
988988
/// };
989989
///
990-
/// // Use an `as` cast instead
991-
/// let ptr_num_cast = ptr as *const i32 as usize;
990+
/// // Use `.addr()` instead
991+
/// let ptr_num_cast = (ptr as *const i32).addr();
992992
/// ```
993993
///
994994
/// Turning a `*mut T` into an `&mut T`:
@@ -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

+3-3
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());
493493
/// ```
494494
#[inline]
495495
#[must_use]

library/core/src/ptr/unique.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ impl<T: Sized> Unique<T> {
7373
pub const fn dangling() -> Self {
7474
// SAFETY: mem::align_of() returns a valid, non-null pointer. The
7575
// conditions to call new_unchecked() are thus respected.
76-
unsafe { Unique::new_unchecked(mem::align_of::<T>() as *mut T) }
76+
unsafe { Unique::new_unchecked(crate::ptr::invalid_mut::<T>(mem::align_of::<T>())) }
7777
}
7878
}
7979

library/core/src/slice/ascii.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -293,17 +293,17 @@ fn is_ascii(s: &[u8]) -> bool {
293293
// Paranoia check about alignment, since we're about to do a bunch of
294294
// unaligned loads. In practice this should be impossible barring a bug in
295295
// `align_offset` though.
296-
debug_assert_eq!((word_ptr as usize) % mem::align_of::<usize>(), 0);
296+
debug_assert_eq!((word_ptr.addr()) % mem::align_of::<usize>(), 0);
297297

298298
// Read subsequent words until the last aligned word, excluding the last
299299
// aligned word by itself to be done in tail check later, to ensure that
300300
// tail is always one `usize` at most to extra branch `byte_pos == len`.
301301
while byte_pos < len - USIZE_SIZE {
302302
debug_assert!(
303303
// Sanity check that the read is in bounds
304-
(word_ptr as usize + USIZE_SIZE) <= (start.wrapping_add(len) as usize) &&
304+
(word_ptr.addr() + USIZE_SIZE) <= (start.wrapping_add(len).addr()) &&
305305
// And that our assumptions about `byte_pos` hold.
306-
(word_ptr as usize) - (start as usize) == byte_pos
306+
(word_ptr.addr()) - (start.addr()) == byte_pos
307307
);
308308

309309
// SAFETY: We know `word_ptr` is properly aligned (because of

library/core/src/slice/iter/macros.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,13 @@ macro_rules! len {
2020
if size == 0 {
2121
// This _cannot_ use `unchecked_sub` because we depend on wrapping
2222
// to represent the length of long ZST slice iterators.
23-
($self.end as usize).wrapping_sub(start.as_ptr() as usize)
23+
($self.end.addr()).wrapping_sub(start.as_ptr().addr())
2424
} else {
2525
// We know that `start <= end`, so can do better than `offset_from`,
2626
// which needs to deal in signed. By setting appropriate flags here
2727
// we can tell LLVM this, which helps it remove bounds checks.
2828
// SAFETY: By the type invariant, `start <= end`
29-
let diff = unsafe { unchecked_sub($self.end as usize, start.as_ptr() as usize) };
29+
let diff = unsafe { unchecked_sub($self.end.addr(), start.as_ptr().addr()) };
3030
// By also telling LLVM that the pointers are apart by an exact
3131
// multiple of the type size, it can optimize `len() == 0` down to
3232
// `start == end` instead of `(end - start) < size`.

library/core/src/slice/sort.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ where
269269
// Returns the number of elements between pointers `l` (inclusive) and `r` (exclusive).
270270
fn width<T>(l: *mut T, r: *mut T) -> usize {
271271
assert!(mem::size_of::<T>() > 0);
272-
(r as usize - l as usize) / mem::size_of::<T>()
272+
(r.addr() - l.addr()) / mem::size_of::<T>()
273273
}
274274

275275
loop {

library/panic_unwind/src/dwarf/eh.rs

+10
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,16 @@
1010
1111
#![allow(non_upper_case_globals)]
1212
#![allow(unused)]
13+
// FIXME(strict_provenance_magic): the unwinder has special permissions and semantics.
14+
//
15+
// This is at worst an Interesting Case Study that is worth doing a deep dive on.
16+
//
17+
// This implementation pretty aggressively puns *offsets* and actual addresses. It can
18+
// probably be made "strict" but requires a lot of very careful thinking about the
19+
// precise semantics of this format (I think it's basically shoe-horning a bunch of
20+
// things into a common path for simplicity, when in reality there are many impossible
21+
// combinations).
22+
#![cfg_attr(not(bootstrap), allow(fuzzy_provenance_casts))]
1323

1424
use crate::dwarf::DwarfReader;
1525
use core::mem;

library/panic_unwind/src/seh.rs

+6
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,12 @@
4545
//! [llvm]: https://llvm.org/docs/ExceptionHandling.html#background-on-windows-exceptions
4646
4747
#![allow(nonstandard_style)]
48+
// FIXME(strict_provenance_magic): the unwinder has special permissions and semantics.
49+
//
50+
// This is at worst an Interesting Case Study that is worth doing a deep dive on.
51+
//
52+
// I haven't looked closely at this implementation yet.
53+
#![cfg_attr(not(bootstrap), allow(fuzzy_provenance_casts))]
4854

4955
use alloc::boxed::Box;
5056
use core::any::Any;

library/std/src/backtrace.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ impl Backtrace {
293293
if !Backtrace::enabled() {
294294
return Backtrace { inner: Inner::Disabled };
295295
}
296-
Backtrace::create(Backtrace::capture as usize)
296+
Backtrace::create((Backtrace::capture as *mut ()).addr())
297297
}
298298

299299
/// Forcibly captures a full backtrace, regardless of environment variable
@@ -308,7 +308,7 @@ impl Backtrace {
308308
/// parts of code.
309309
#[inline(never)] // want to make sure there's a frame here to remove
310310
pub fn force_capture() -> Backtrace {
311-
Backtrace::create(Backtrace::force_capture as usize)
311+
Backtrace::create((Backtrace::force_capture as *mut ()).addr())
312312
}
313313

314314
/// Forcibly captures a disabled backtrace, regardless of environment
@@ -330,7 +330,7 @@ impl Backtrace {
330330
frame: RawFrame::Actual(frame.clone()),
331331
symbols: Vec::new(),
332332
});
333-
if frame.symbol_address() as usize == ip && actual_start.is_none() {
333+
if frame.symbol_address().addr() == ip && actual_start.is_none() {
334334
actual_start = Some(frames.len());
335335
}
336336
true
@@ -493,7 +493,7 @@ impl RawFrame {
493493
match self {
494494
RawFrame::Actual(frame) => frame.ip(),
495495
#[cfg(test)]
496-
RawFrame::Fake => 1 as *mut c_void,
496+
RawFrame::Fake => ptr::invalid_mut(1),
497497
}
498498
}
499499
}

library/std/src/io/error/repr_bitpacked.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@
105105
use super::{Custom, ErrorData, ErrorKind, SimpleMessage};
106106
use alloc::boxed::Box;
107107
use core::mem::{align_of, size_of};
108-
use core::ptr::NonNull;
108+
use core::ptr::{self, NonNull};
109109

110110
// The 2 least-significant bits are used as tag.
111111
const TAG_MASK: usize = 0b11;
@@ -126,7 +126,7 @@ impl Repr {
126126
let p = Box::into_raw(b).cast::<u8>();
127127
// Should only be possible if an allocator handed out a pointer with
128128
// wrong alignment.
129-
debug_assert_eq!((p as usize & TAG_MASK), 0);
129+
debug_assert_eq!((p.addr() & TAG_MASK), 0);
130130
// Note: We know `TAG_CUSTOM <= size_of::<Custom>()` (static_assert at
131131
// end of file), and both the start and end of the expression must be
132132
// valid without address space wraparound due to `Box`'s semantics.
@@ -156,7 +156,7 @@ impl Repr {
156156
pub(super) fn new_os(code: i32) -> Self {
157157
let utagged = ((code as usize) << 32) | TAG_OS;
158158
// Safety: `TAG_OS` is not zero, so the result of the `|` is not 0.
159-
let res = Self(unsafe { NonNull::new_unchecked(utagged as *mut ()) });
159+
let res = Self(unsafe { NonNull::new_unchecked(ptr::invalid_mut(utagged)) });
160160
// quickly smoke-check we encoded the right thing (This generally will
161161
// only run in libstd's tests, unless the user uses -Zbuild-std)
162162
debug_assert!(
@@ -170,7 +170,7 @@ impl Repr {
170170
pub(super) fn new_simple(kind: ErrorKind) -> Self {
171171
let utagged = ((kind as usize) << 32) | TAG_SIMPLE;
172172
// Safety: `TAG_SIMPLE` is not zero, so the result of the `|` is not 0.
173-
let res = Self(unsafe { NonNull::new_unchecked(utagged as *mut ()) });
173+
let res = Self(unsafe { NonNull::new_unchecked(ptr::invalid_mut(utagged)) });
174174
// quickly smoke-check we encoded the right thing (This generally will
175175
// only run in libstd's tests, unless the user uses -Zbuild-std)
176176
debug_assert!(
@@ -228,7 +228,7 @@ unsafe fn decode_repr<C, F>(ptr: NonNull<()>, make_custom: F) -> ErrorData<C>
228228
where
229229
F: FnOnce(*mut Custom) -> C,
230230
{
231-
let bits = ptr.as_ptr() as usize;
231+
let bits = ptr.as_ptr().addr();
232232
match bits & TAG_MASK {
233233
TAG_OS => {
234234
let code = ((bits as i64) >> 32) as i32;

library/std/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,7 @@
275275
#![feature(extend_one)]
276276
#![feature(float_minimum_maximum)]
277277
#![feature(format_args_nl)]
278+
#![feature(strict_provenance)]
278279
#![feature(get_mut_unchecked)]
279280
#![feature(hashmap_internals)]
280281
#![feature(int_error_internals)]

library/std/src/os/windows/io/handle.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use crate::fs;
99
use crate::io;
1010
use crate::marker::PhantomData;
1111
use crate::mem::forget;
12+
use crate::ptr;
1213
use crate::sys::c;
1314
use crate::sys::cvt;
1415
use crate::sys_common::{AsInner, FromInner, IntoInner};
@@ -174,7 +175,7 @@ impl OwnedHandle {
174175
return unsafe { Ok(Self::from_raw_handle(handle)) };
175176
}
176177

177-
let mut ret = 0 as c::HANDLE;
178+
let mut ret = ptr::null_mut();
178179
cvt(unsafe {
179180
let cur_proc = c::GetCurrentProcess();
180181
c::DuplicateHandle(

library/std/src/os/windows/io/socket.rs

+2
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,8 @@ impl OwnedSocket {
129129
}
130130
}
131131

132+
// FIXME(strict_provenance_magic): we defined RawSocket to be a u64 ;-;
133+
#[cfg_attr(not(bootstrap), allow(fuzzy_provenance_casts))]
132134
#[cfg(not(target_vendor = "uwp"))]
133135
pub(crate) fn set_no_inherit(&self) -> io::Result<()> {
134136
cvt(unsafe {

library/std/src/path.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1449,8 +1449,8 @@ impl PathBuf {
14491449
};
14501450

14511451
// truncate until right after the file stem
1452-
let end_file_stem = file_stem[file_stem.len()..].as_ptr() as usize;
1453-
let start = os_str_as_u8_slice(&self.inner).as_ptr() as usize;
1452+
let end_file_stem = file_stem[file_stem.len()..].as_ptr().addr();
1453+
let start = os_str_as_u8_slice(&self.inner).as_ptr().addr();
14541454
let v = self.as_mut_vec();
14551455
v.truncate(end_file_stem.wrapping_sub(start));
14561456

0 commit comments

Comments
 (0)