|
153 | 153 | //! integers is very useful, so what can we do?
|
154 | 154 | //!
|
155 | 155 | //! Strict Provenance attempts to square this circle by decoupling Rust's traditional conflation
|
156 |
| -//! of pointers and `usize` (and `isize`), defining a pointer to semantically contain the following |
157 |
| -//! information: |
| 156 | +//! of pointers and `usize` (and `isize`), and defining a pointer to semantically contain the |
| 157 | +//! following information: |
158 | 158 | //!
|
159 | 159 | //! * The **address-space** it is part of.
|
160 | 160 | //! * The **address** it points to, which can be represented by a `usize`.
|
|
235 | 235 | //! }
|
236 | 236 | //! ```
|
237 | 237 | //!
|
| 238 | +//! (Yes, if you've been using AtomicUsize for pointers in concurrent datastructures, you should |
| 239 | +//! be using AtomicPtr instead. If that messes up the way you atomically manipulate pointers, |
| 240 | +//! we would like to know why, and what needs to be done to fix it.) |
| 241 | +//! |
238 | 242 | //! Something more complicated and just generally *evil* like a XOR-List requires more significant
|
239 | 243 | //! changes like allocating all nodes in a pre-allocated Vec or Arena and using a pointer
|
240 | 244 | //! to the whole allocation to reconstitute the XORed addresses.
|
|
258 | 262 | //!
|
259 | 263 | //! * Create an invalid pointer from just an address (see [`ptr::invalid`][]). This can
|
260 | 264 | //! be used for sentinel values like `null` *or* to represent a tagged pointer that will
|
261 |
| -//! never be dereferencable. |
| 265 | +//! never be dereferencable. In general, it is always sound for an integer to pretend |
| 266 | +//! to be a pointer "for fun" as long as you don't use operations on it which require |
| 267 | +//! it to be valid (offset, read, write, etc). |
262 | 268 | //!
|
263 | 269 | //! * Forge an allocation of size zero at any sufficiently aligned non-null address.
|
264 | 270 | //! i.e. the usual "ZSTs are fake, do what you want" rules apply *but* this only applies
|
265 |
| -//! for actual forgery (integers cast to pointers). If you borrow some structs subfield |
| 271 | +//! for actual forgery (integers cast to pointers). If you borrow some struct's field |
266 | 272 | //! that *happens* to be zero-sized, the resulting pointer will have provenance tied to
|
267 | 273 | //! that allocation and it will still get invalidated if the allocation gets deallocated.
|
268 | 274 | //! In the future we may introduce an API to make such a forged allocation explicit.
|
|
277 | 283 | //! and based on alignment, but the buffer on either side of the pointer's range is pretty
|
278 | 284 | //! generous (think kilobytes, not bytes).
|
279 | 285 | //!
|
| 286 | +//! * Compare arbitrary pointers by address. Addresses *are* just integers and so there is |
| 287 | +//! always a coherent answer, even if the pointers are invalid or from different |
| 288 | +//! address-spaces/provenances. Of course, comparing addresses from different address-spaces |
| 289 | +//! is generally going to be *meaningless*, but so is comparing Kilograms to Meters, and Rust |
| 290 | +//! doesn't prevent that either. Similarly, if you get "lucky" and notice that a pointer |
| 291 | +//! one-past-the-end is the "same" address as the start of an unrelated allocation, anything |
| 292 | +//! you do with that fact is *probably* going to be gibberish. The scope of that gibberish |
| 293 | +//! is kept under control by the fact that the two pointers *still* aren't allowed to access |
| 294 | +//! the other's allocation (bytes), because they still have different provenance. |
| 295 | +//! |
280 | 296 | //! * Perform pointer tagging tricks. This falls out of [`wrapping_offset`] but is worth
|
281 | 297 | //! mentioning in more detail because of the limitations of [CHERI][]. Low-bit tagging
|
282 | 298 | //! is very robust, and often doesn't even go out of bounds because types have a
|
|
0 commit comments