Repository navigation
Do the bytes of a pointer have to stay in the same order? #558
Description
Activity
- addedA-provenanceTopic: Related to when which values have which provenance (but not which alias restrictions follow)Topic: Related to when which values have which provenance (but not which alias restrictions follow)
on Feb 20, 2025 I'd certainly agree that ruling out pointer crimes is an upside 😛.
In a more serious argument, I think it shouldn't be difficult to track this along with the
Pointer. The only thing would be thatPointerwould need to be something more likePointerFragmentand be different between bytes (but this is really only anu8 is 0..size_of::<usize>()extra state). We could then say that if a pointer is computed from provenance, where the provenance isn't coherent (different provenances, wrong place, or some having no provenance) you get a pointer without provenance.No, it's not difficult, but it is extra complexity.
Since you mention XOR linked lists: I recently read the paper Garbage Collection for Rust: The Finalizer Frontier which implements a fork of Rust, and which also do not support such types.
They implement GC by stopping the world and scanning the process memory, which is fraught with peril for many reasons, but still thought I'd note it as a possible use-case for restricting the bytes of pointers.
- added a commit that references this issue
on Jul 17, 2025 - added a commit that references this issue
on Aug 17, 2025 - added 4 commits that reference this issue
on Aug 18, 2025 - added a commit that references this issue
on Aug 20, 2025 - added a commit that references this issue
on Aug 28, 2025 - added a commit that references this issue
on Sep 25, 2025 7 remaining items
@RalfJung has proposed to merge this. The next step is review by the rest of the tagged team members:
No concerns currently listed.
Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!
See this document for info about what commands tagged team members can give me.
🔔 This is now entering its final comment period, as per the review above. 🔔
This was talked about today in the T-opsem meeting. The meeting was fine with the FCP going ahead, with a clarification.
The rules proposed here will be enforced on typed copy - doing a typed load of a pointer with "broken" pointer bytes (not all bytes from one allocation, or not in the right order) produces a pointer with no provenance (similar to what you get with
core::ptr::without_provenance). This is as opposed to allowing pointer values to carry arround a broken provenance state, and only be checked (causing UB) on dereference/add.
Pointer "values" in a broken state can still be carried usingMaybeUninit.Reacted by Ralf Jung and opaleThis was talked about today in the T-opsem meeting. The meeting was fine with the FCP going ahead, with a clarification.
The rules proposed here will be enforced on typed copy - doing a typed load of a pointer with "broken" pointer bytes (not all bytes from one allocation, or not in the right order) produces a pointer with no provenance (similar to what you get with
core::ptr::without_provenance). This is as opposed to allowing pointer values to carry arround a broken provenance state, and only be checked (causing UB) on dereference/add. Pointer "values" in a broken state can still be carried usingMaybeUninit.To clarify: While the rules proposed here will be enforced on typed copy, they will not be enforced on byte copy (e.g. when copying via
[MaybeUninit<u8>; N]). Thus, it will remain sound to do things like convert a raw pointer type,P, to a[MaybeUninit<u8>; size_of::<P>()], mix the bytes around, store them in various places, etc, as long as they end up back in their original order before being converted back to aP- in this case, thePwill retain its original provenance.Reacted by Ralf Jung and matthieu-mThe final comment period, with a disposition to merge, as per the review above, is now complete.
As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed.
There's another aspect of provenance that we haven't officially decided yet and that is implicitly answered by the current wording in rust-lang/reference#1664: do the individual bytes in a pointer "remember" where in the pointer they are, and have to be put back in the same order? Some formal models require this, and if we ever allow "taking apart" the bytes of a pointer in const-eval (rust-lang/const-eval#72) we'll also have to require this, but for runtime semantics we could decide either way.
The one example of code that I am aware of that breaks this requirement is XOR linked lists, which can be implemented in the semantics sketched in MiniRust right now but can't be implemented if bytes with provenance remember their position in the pointer. That's not exactly realistic code, but it is somewhat satisfying that (on architectures where pointers have at least 2 bytes), XOR linked lists can be implemented.
The main upside of requiring the same bytes in the same order is that it rules out pointer crimes like XOR linked lists so if there's some unexpected interactions there, we'd not be affected. It would also make the runtime semantics more consistent with the const-eval semantics. I am not aware of an optimization that would benefit from this UB, it's mostly a case of "ruling out some rather cursed programs to avoid locking ourselves into an unexpected corner". In some sense the model becomes a bit simpler since we can just say, pointer bytes must be put back together in the same order they started out as before they can be treated as a pointer again, but the actual op.sem would become more complicated because of the extra bookkeeping required to enforce this.