Skip to content

Commit 71940e0

Browse files
committed
Auto merge of #118487 - RalfJung:exposed-provenance, r=thomcc
move exposed-provenance APIs into separate feature gate We have already stated explicitly for all the 'exposed' functions that > Using this method means that code is *not* following strict provenance rules. However, they were part of the same feature gate and still described as part of the strict provenance experiment. Unfortunately, their semantics are much less clear and certainly nowhere near stabilization, so in preparation for an attempt to stabilize the strict provenance APIs, I suggest we split the things related to "exposed" into their own feature gate. I also used this opportunity to better explain how Exposed Provenance fits into the larger plan here: this is *one possible candidate* for `as` semantics, but we don't know if it is actually viable, so we can't really promise that it is equivalent to `as`. If it works out we probably want to make `as` equivalent to the 'exposed' APIs; if it doesn't, we will remove them again and try to find some other semantics for `as`.
2 parents 2f1ba4a + f2dc18d commit 71940e0

File tree

11 files changed

+78
-63
lines changed

11 files changed

+78
-63
lines changed

library/core/src/ptr/const_ptr.rs

+9-8
Original file line numberDiff line numberDiff line change
@@ -186,10 +186,10 @@ impl<T: ?Sized> *const T {
186186
/// [`with_addr`][pointer::with_addr] or [`map_addr`][pointer::map_addr].
187187
///
188188
/// If using those APIs is not possible because there is no way to preserve a pointer with the
189-
/// required provenance, use [`expose_addr`][pointer::expose_addr] and
190-
/// [`from_exposed_addr`][from_exposed_addr] instead. However, note that this makes
191-
/// your code less portable and less amenable to tools that check for compliance with the Rust
192-
/// memory model.
189+
/// required provenance, then Strict Provenance might not be for you. Use pointer-integer casts
190+
/// or [`expose_addr`][pointer::expose_addr] and [`from_exposed_addr`][from_exposed_addr]
191+
/// instead. However, note that this makes your code less portable and less amenable to tools
192+
/// that check for compliance with the Rust memory model.
193193
///
194194
/// On most platforms this will produce a value with the same bytes as the original
195195
/// pointer, because all the bytes are dedicated to describing the address.
@@ -219,7 +219,8 @@ impl<T: ?Sized> *const T {
219219
/// later call [`from_exposed_addr`][] to reconstitute the original pointer including its
220220
/// provenance. (Reconstructing address space information, if required, is your responsibility.)
221221
///
222-
/// Using this method means that code is *not* following Strict Provenance rules. Supporting
222+
/// Using this method means that code is *not* following [Strict
223+
/// Provenance][../index.html#strict-provenance] rules. Supporting
223224
/// [`from_exposed_addr`][] complicates specification and reasoning and may not be supported by
224225
/// tools that help you to stay conformant with the Rust memory model, so it is recommended to
225226
/// use [`addr`][pointer::addr] wherever possible.
@@ -230,13 +231,13 @@ impl<T: ?Sized> *const T {
230231
/// side-effect which is required for [`from_exposed_addr`][] to work is typically not
231232
/// available.
232233
///
233-
/// This API and its claimed semantics are part of the Strict Provenance experiment, see the
234-
/// [module documentation][crate::ptr] for details.
234+
/// It is unclear whether this method can be given a satisfying unambiguous specification. This
235+
/// API and its claimed semantics are part of [Exposed Provenance][../index.html#exposed-provenance].
235236
///
236237
/// [`from_exposed_addr`]: from_exposed_addr
237238
#[must_use]
238239
#[inline(always)]
239-
#[unstable(feature = "strict_provenance", issue = "95228")]
240+
#[unstable(feature = "exposed_provenance", issue = "95228")]
240241
pub fn expose_addr(self) -> usize {
241242
// FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic.
242243
self.cast::<()>() as usize

library/core/src/ptr/mod.rs

+51-39
Original file line numberDiff line numberDiff line change
@@ -312,22 +312,30 @@
312312
//! For instance, ARM explicitly supports high-bit tagging, and so CHERI on ARM inherits
313313
//! that and should support it.
314314
//!
315-
//! ## Pointer-usize-pointer roundtrips and 'exposed' provenance
315+
//! ## Exposed Provenance
316316
//!
317-
//! **This section is *non-normative* and is part of the [Strict Provenance] experiment.**
317+
//! **This section is *non-normative* and is an extension to the [Strict Provenance] experiment.**
318318
//!
319319
//! As discussed above, pointer-usize-pointer roundtrips are not possible under [Strict Provenance].
320-
//! However, there exists legacy Rust code that is full of such roundtrips, and legacy platform APIs
321-
//! regularly assume that `usize` can capture all the information that makes up a pointer. There
322-
//! also might be code that cannot be ported to Strict Provenance (which is something we would [like
323-
//! to hear about][Strict Provenance]).
324-
//!
325-
//! For situations like this, there is a fallback plan, a way to 'opt out' of Strict Provenance.
326-
//! However, note that this makes your code a lot harder to specify, and the code will not work
327-
//! (well) with tools like [Miri] and [CHERI].
328-
//!
329-
//! This fallback plan is provided by the [`expose_addr`] and [`from_exposed_addr`] methods (which
330-
//! are equivalent to `as` casts between pointers and integers). [`expose_addr`] is a lot like
320+
//! This is by design: the goal of Strict Provenance is to provide a clear specification that we are
321+
//! confident can be formalized unambiguously and can be subject to precise formal reasoning.
322+
//!
323+
//! However, there exist situations where pointer-usize-pointer roundtrips cannot be avoided, or
324+
//! where avoiding them would require major refactoring. Legacy platform APIs also regularly assume
325+
//! that `usize` can capture all the information that makes up a pointer. The goal of Strict
326+
//! Provenance is not to rule out such code; the goal is to put all the *other* pointer-manipulating
327+
//! code onto a more solid foundation. Strict Provenance is about improving the situation where
328+
//! possible (all the code that can be written with Strict Provenance) without making things worse
329+
//! for situations where Strict Provenance is insufficient.
330+
//!
331+
//! For these situations, there is a highly experimental extension to Strict Provenance called
332+
//! *Exposed Provenance*. This extension permits pointer-usize-pointer roundtrips. However, its
333+
//! semantics are on much less solid footing than Strict Provenance, and at this point it is not yet
334+
//! clear where a satisfying unambiguous semantics can be defined for Exposed Provenance.
335+
//! Furthermore, Exposed Provenance will not work (well) with tools like [Miri] and [CHERI].
336+
//!
337+
//! Exposed Provenance is provided by the [`expose_addr`] and [`from_exposed_addr`] methods, which
338+
//! are meant to replace `as` casts between pointers and integers. [`expose_addr`] is a lot like
331339
//! [`addr`], but additionally adds the provenance of the pointer to a global list of 'exposed'
332340
//! provenances. (This list is purely conceptual, it exists for the purpose of specifying Rust but
333341
//! is not materialized in actual executions, except in tools like [Miri].) [`from_exposed_addr`]
@@ -341,10 +349,11 @@
341349
//! there is *no* previously 'exposed' provenance that justifies the way the returned pointer will
342350
//! be used, the program has undefined behavior.
343351
//!
344-
//! Using [`expose_addr`] or [`from_exposed_addr`] (or the equivalent `as` casts) means that code is
352+
//! Using [`expose_addr`] or [`from_exposed_addr`] (or the `as` casts) means that code is
345353
//! *not* following Strict Provenance rules. The goal of the Strict Provenance experiment is to
346-
//! determine whether it is possible to use Rust without [`expose_addr`] and [`from_exposed_addr`].
347-
//! If this is successful, it would be a major win for avoiding specification complexity and to
354+
//! determine how far one can get in Rust without the use of [`expose_addr`] and
355+
//! [`from_exposed_addr`], and to encourage code to be written with Strict Provenance APIs only.
356+
//! Maximizing the amount of such code is a major win for avoiding specification complexity and to
348357
//! facilitate adoption of tools like [CHERI] and [Miri] that can be a big help in increasing the
349358
//! confidence in (unsafe) Rust code.
350359
//!
@@ -619,12 +628,12 @@ pub const fn invalid_mut<T>(addr: usize) -> *mut T {
619628

620629
/// Convert an address back to a pointer, picking up a previously 'exposed' provenance.
621630
///
622-
/// This is equivalent to `addr as *const T`. The provenance of the returned pointer is that of *any*
623-
/// pointer that was previously exposed by passing it to [`expose_addr`][pointer::expose_addr],
624-
/// or a `ptr as usize` cast. In addition, memory which is outside the control of the Rust abstract
625-
/// machine (MMIO registers, for example) is always considered to be exposed, so long as this memory
626-
/// is disjoint from memory that will be used by the abstract machine such as the stack, heap,
627-
/// and statics.
631+
/// This is a more rigorously specified alternative to `addr as *const T`. The provenance of the
632+
/// returned pointer is that of *any* pointer that was previously exposed by passing it to
633+
/// [`expose_addr`][pointer::expose_addr], or a `ptr as usize` cast. In addition, memory which is
634+
/// outside the control of the Rust abstract machine (MMIO registers, for example) is always
635+
/// considered to be exposed, so long as this memory is disjoint from memory that will be used by
636+
/// the abstract machine such as the stack, heap, and statics.
628637
///
629638
/// If there is no 'exposed' provenance that justifies the way this pointer will be used,
630639
/// the program has undefined behavior. In particular, the aliasing rules still apply: pointers
@@ -639,7 +648,8 @@ pub const fn invalid_mut<T>(addr: usize) -> *mut T {
639648
/// On platforms with multiple address spaces, it is your responsibility to ensure that the
640649
/// address makes sense in the address space that this pointer will be used with.
641650
///
642-
/// Using this method means that code is *not* following strict provenance rules. "Guessing" a
651+
/// Using this function means that code is *not* following [Strict
652+
/// Provenance][../index.html#strict-provenance] rules. "Guessing" a
643653
/// suitable provenance complicates specification and reasoning and may not be supported by
644654
/// tools that help you to stay conformant with the Rust memory model, so it is recommended to
645655
/// use [`with_addr`][pointer::with_addr] wherever possible.
@@ -649,13 +659,13 @@ pub const fn invalid_mut<T>(addr: usize) -> *mut T {
649659
/// since it is generally not possible to actually *compute* which provenance the returned
650660
/// pointer has to pick up.
651661
///
652-
/// This API and its claimed semantics are part of the Strict Provenance experiment, see the
653-
/// [module documentation][crate::ptr] for details.
662+
/// It is unclear whether this function can be given a satisfying unambiguous specification. This
663+
/// API and its claimed semantics are part of [Exposed Provenance][../index.html#exposed-provenance].
654664
#[must_use]
655665
#[inline(always)]
656-
#[unstable(feature = "strict_provenance", issue = "95228")]
666+
#[unstable(feature = "exposed_provenance", issue = "95228")]
657667
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
658-
#[allow(fuzzy_provenance_casts)] // this *is* the strict provenance API one should use instead
668+
#[allow(fuzzy_provenance_casts)] // this *is* the explicit provenance API one should use instead
659669
pub fn from_exposed_addr<T>(addr: usize) -> *const T
660670
where
661671
T: Sized,
@@ -666,18 +676,20 @@ where
666676

667677
/// Convert an address back to a mutable pointer, picking up a previously 'exposed' provenance.
668678
///
669-
/// This is equivalent to `addr as *mut T`. The provenance of the returned pointer is that of *any*
670-
/// pointer that was previously passed to [`expose_addr`][pointer::expose_addr] or a `ptr as usize`
671-
/// cast. If there is no previously 'exposed' provenance that justifies the way this pointer will be
672-
/// used, the program has undefined behavior. Note that there is no algorithm that decides which
673-
/// provenance will be used. You can think of this as "guessing" the right provenance, and the guess
674-
/// will be "maximally in your favor", in the sense that if there is any way to avoid undefined
675-
/// behavior, then that is the guess that will be taken.
679+
/// This is a more rigorously specified alternative to `addr as *mut T`. The provenance of the
680+
/// returned pointer is that of *any* pointer that was previously passed to
681+
/// [`expose_addr`][pointer::expose_addr] or a `ptr as usize` cast. If there is no previously
682+
/// 'exposed' provenance that justifies the way this pointer will be used, the program has undefined
683+
/// behavior. Note that there is no algorithm that decides which provenance will be used. You can
684+
/// think of this as "guessing" the right provenance, and the guess will be "maximally in your
685+
/// favor", in the sense that if there is any way to avoid undefined behavior, then that is the
686+
/// guess that will be taken.
676687
///
677688
/// On platforms with multiple address spaces, it is your responsibility to ensure that the
678689
/// address makes sense in the address space that this pointer will be used with.
679690
///
680-
/// Using this method means that code is *not* following strict provenance rules. "Guessing" a
691+
/// Using this function means that code is *not* following [Strict
692+
/// Provenance][../index.html#strict-provenance] rules. "Guessing" a
681693
/// suitable provenance complicates specification and reasoning and may not be supported by
682694
/// tools that help you to stay conformant with the Rust memory model, so it is recommended to
683695
/// use [`with_addr`][pointer::with_addr] wherever possible.
@@ -687,13 +699,13 @@ where
687699
/// since it is generally not possible to actually *compute* which provenance the returned
688700
/// pointer has to pick up.
689701
///
690-
/// This API and its claimed semantics are part of the Strict Provenance experiment, see the
691-
/// [module documentation][crate::ptr] for details.
702+
/// It is unclear whether this function can be given a satisfying unambiguous specification. This
703+
/// API and its claimed semantics are part of [Exposed Provenance][../index.html#exposed-provenance].
692704
#[must_use]
693705
#[inline(always)]
694-
#[unstable(feature = "strict_provenance", issue = "95228")]
706+
#[unstable(feature = "exposed_provenance", issue = "95228")]
695707
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
696-
#[allow(fuzzy_provenance_casts)] // this *is* the strict provenance API one should use instead
708+
#[allow(fuzzy_provenance_casts)] // this *is* the explicit provenance API one should use instead
697709
pub fn from_exposed_addr_mut<T>(addr: usize) -> *mut T
698710
where
699711
T: Sized,

library/core/src/ptr/mut_ptr.rs

+10-9
Original file line numberDiff line numberDiff line change
@@ -193,10 +193,10 @@ impl<T: ?Sized> *mut T {
193193
/// [`with_addr`][pointer::with_addr] or [`map_addr`][pointer::map_addr].
194194
///
195195
/// If using those APIs is not possible because there is no way to preserve a pointer with the
196-
/// required provenance, use [`expose_addr`][pointer::expose_addr] and
197-
/// [`from_exposed_addr_mut`][from_exposed_addr_mut] instead. However, note that this makes
198-
/// your code less portable and less amenable to tools that check for compliance with the Rust
199-
/// memory model.
196+
/// required provenance, then Strict Provenance might not be for you. Use pointer-integer casts
197+
/// or [`expose_addr`][pointer::expose_addr] and [`from_exposed_addr`][from_exposed_addr]
198+
/// instead. However, note that this makes your code less portable and less amenable to tools
199+
/// that check for compliance with the Rust memory model.
200200
///
201201
/// On most platforms this will produce a value with the same bytes as the original
202202
/// pointer, because all the bytes are dedicated to describing the address.
@@ -226,7 +226,8 @@ impl<T: ?Sized> *mut T {
226226
/// later call [`from_exposed_addr_mut`][] to reconstitute the original pointer including its
227227
/// provenance. (Reconstructing address space information, if required, is your responsibility.)
228228
///
229-
/// Using this method means that code is *not* following Strict Provenance rules. Supporting
229+
/// Using this method means that code is *not* following [Strict
230+
/// Provenance][../index.html#strict-provenance] rules. Supporting
230231
/// [`from_exposed_addr_mut`][] complicates specification and reasoning and may not be supported
231232
/// by tools that help you to stay conformant with the Rust memory model, so it is recommended
232233
/// to use [`addr`][pointer::addr] wherever possible.
@@ -237,13 +238,13 @@ impl<T: ?Sized> *mut T {
237238
/// side-effect which is required for [`from_exposed_addr_mut`][] to work is typically not
238239
/// available.
239240
///
240-
/// This API and its claimed semantics are part of the Strict Provenance experiment, see the
241-
/// [module documentation][crate::ptr] for details.
241+
/// It is unclear whether this method can be given a satisfying unambiguous specification. This
242+
/// API and its claimed semantics are part of [Exposed Provenance][../index.html#exposed-provenance].
242243
///
243244
/// [`from_exposed_addr_mut`]: from_exposed_addr_mut
244245
#[must_use]
245246
#[inline(always)]
246-
#[unstable(feature = "strict_provenance", issue = "95228")]
247+
#[unstable(feature = "exposed_provenance", issue = "95228")]
247248
pub fn expose_addr(self) -> usize {
248249
// FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic.
249250
self.cast::<()>() as usize
@@ -259,7 +260,7 @@ impl<T: ?Sized> *mut T {
259260
/// This is equivalent to using [`wrapping_offset`][pointer::wrapping_offset] to offset
260261
/// `self` to the given address, and therefore has all the same capabilities and restrictions.
261262
///
262-
/// This API and its claimed semantics are part of the Strict Provenance experiment,
263+
/// This API and its claimed semantics are an extension to the Strict Provenance experiment,
263264
/// see the [module documentation][crate::ptr] for details.
264265
#[must_use]
265266
#[inline]

library/std/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,7 @@
317317
#![feature(error_iter)]
318318
#![feature(exact_size_is_empty)]
319319
#![feature(exclusive_wrapper)]
320+
#![feature(exposed_provenance)]
320321
#![feature(extend_one)]
321322
#![feature(float_gamma)]
322323
#![feature(float_minimum_maximum)]

src/tools/miri/tests/fail/provenance/ptr_int_unexposed.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//@compile-flags: -Zmiri-permissive-provenance
2-
#![feature(strict_provenance)]
2+
#![feature(strict_provenance, exposed_provenance)]
33

44
fn main() {
55
let x: i32 = 3;

src/tools/miri/tests/fail/provenance/ptr_invalid.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#![feature(strict_provenance)]
1+
#![feature(strict_provenance, exposed_provenance)]
22

33
// Ensure that a `ptr::invalid` ptr is truly invalid.
44
fn main() {

src/tools/miri/tests/fail/provenance/strict_provenance_cast.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//@compile-flags: -Zmiri-strict-provenance
2-
#![feature(strict_provenance)]
2+
#![feature(exposed_provenance)]
33

44
fn main() {
55
let addr = &0 as *const i32 as usize;

src/tools/miri/tests/fail/stacked_borrows/exposed_only_ro.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//@compile-flags: -Zmiri-permissive-provenance
2-
#![feature(strict_provenance)]
2+
#![feature(exposed_provenance)]
33

44
// If we have only exposed read-only pointers, doing a write through a wildcard ptr should fail.
55

src/tools/miri/tests/pass/ptr_int_from_exposed.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//@revisions: stack tree
22
//@[tree]compile-flags: -Zmiri-tree-borrows
33
//@compile-flags: -Zmiri-permissive-provenance
4-
#![feature(strict_provenance)]
4+
#![feature(strict_provenance, exposed_provenance)]
55

66
use std::ptr;
77

src/tools/miri/tests/pass/stacked-borrows/int-to-ptr.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//@compile-flags: -Zmiri-permissive-provenance
2-
#![feature(strict_provenance)]
2+
#![feature(exposed_provenance)]
33
use std::ptr;
44

55
// Just to make sure that casting a ref to raw, to int and back to raw

src/tools/miri/tests/pass/stacked-borrows/unknown-bottom-gc.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//@compile-flags: -Zmiri-permissive-provenance
2-
#![feature(strict_provenance)]
2+
#![feature(exposed_provenance)]
33

44
use std::ptr;
55

0 commit comments

Comments
 (0)