Skip to content

Commit dbea549

Browse files
committed
move exposed-provenance APIs into separate feature gate and explain the relationship of Exposed Provenance and Strict Provenance
1 parent 0079625 commit dbea549

File tree

11 files changed

+70
-55
lines changed

11 files changed

+70
-55
lines changed

library/core/src/ptr/const_ptr.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -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

+6-5
Original file line numberDiff line numberDiff line change
@@ -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)