|
| 1 | +// Copyright 2023 The Fuchsia Authors |
| 2 | +// |
| 3 | +// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0 |
| 4 | +// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT |
| 5 | +// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option. |
| 6 | +// This file may not be copied, modified, or distributed except according to |
| 7 | +// those terms. |
| 8 | + |
| 9 | +//! This module exists to hold this doc comment, which provides lemmas which can |
| 10 | +//! be used in soundness proofs. |
| 11 | +//! |
| 12 | +//! # Definitions |
| 13 | +//! |
| 14 | +//! ## transparent-layout-validity |
| 15 | +//! |
| 16 | +//! A type, `T`, has the property `transparent-layout-validity(U)` if the |
| 17 | +//! following all hold: |
| 18 | +//! - `T` and `U` have the same alignment |
| 19 | +//! - For all `t: *const T`, `let u = t as *const U` is valid and |
| 20 | +//! `size_of_val_raw(t) == size_of_val_raw(u)`. |
| 21 | +//! - For all `u: *const U`, `let t = *const T` is valid and `size_of_val_raw(u) |
| 22 | +//! == size_of_val_raw(t)`. |
| 23 | +//! - For all `(t, u): (*const T, *const U)` where `size_of_val_raw(t) == |
| 24 | +//! size_of_val_raw(u)`: |
| 25 | +//! - `t` and `u` refer to `UnsafeCell`s at the same byte ranges. |
| 26 | +//! - If `*t` contains a valid `T`, that implies that `*u` contains a valid |
| 27 | +//! `U`. |
| 28 | +//! - If `*u` contains a valid `U`, that implies that `*t` contains a valid |
| 29 | +//! `T`. |
| 30 | +//! |
| 31 | +//! # Axioms |
| 32 | +//! |
| 33 | +//! These are statements which are not technically logically bulletproof, but |
| 34 | +//! capture the way that language is used in practice in the Rust Reference and |
| 35 | +//! standard library documentation. |
| 36 | +//! |
| 37 | +//! ## axiom-transparent-layout-validity |
| 38 | +//! |
| 39 | +//! Given types `T` and `U`, the phrase "`T` is guaranteed to have the same |
| 40 | +//! layout and bit validity as `U`" is taken to imply that `T` has the property |
| 41 | +//! `transparent-layout-validity(U)`. |
| 42 | +//! |
| 43 | +//! The term "layout" is used in Rust documentation to refer to a type's size |
| 44 | +//! and alignment and the sizes, alignments, and byte offsets of each of the |
| 45 | +//! type's fields. In practice, phrases like the above are only ever used in |
| 46 | +//! contexts where the following additional properties also hold: |
| 47 | +//! - `T` and `U` have the same vtable kinds. `T`'s and `U`'s pointer metadata |
| 48 | +//! is such that raw pointer casts preserve size and field placement. |
| 49 | +//! - `T` and `U` have `UnsafeCell`s at the same byte ranges. |
| 50 | +//! |
| 51 | +//! ## axiom-repr-transparent-layout-validity |
| 52 | +//! |
| 53 | +//! Given types `T` and `U`, if `T` is a `#[repr(transparent)]` struct with a |
| 54 | +//! `pub` field of type `U`, and `T` does not contain any other fields, then |
| 55 | +//! `T` has the property `transparent-layout-validity(U)`. |
| 56 | +//! |
| 57 | +//! Per the [Rust Reference][repr-transparent]: |
| 58 | +//! |
| 59 | +//! > \[`repr(transparent)`\] is only considered part of the public ABI of a |
| 60 | +//! > type if either its single field is `pub`, or if its layout is documented |
| 61 | +//! > in prose. |
| 62 | +//! |
| 63 | +//! [repr-transparent] https://doc.rust-lang.org/nomicon/other-reprs.html#reprtransparent |
| 64 | +//! |
| 65 | +//! # Lemmas |
| 66 | +//! |
| 67 | +//! ## lemma-repr-transparent-zerocopy-traits |
| 68 | +//! |
| 69 | +//! - Lemma: Given types `T` and `U` where `T` is |
| 70 | +//! `transparent-layout-validity(U)`, for each `Trait` in `FromZeroes`, |
| 71 | +//! `FromBytes`, `AsBytes`, and `Unaligned`, if `U` satisfies the safety |
| 72 | +//! preconditions of `Trait`, then `T` does as well. |
| 73 | +//! - Proof: |
| 74 | +//! - `FromZeroes`, `FromBytes`, and `AsBytes` all require that a type not |
| 75 | +//! contain any `UnsafeCell`s. `T: transparent-layout-validity(U)` |
| 76 | +//! guarantees that, for all pairs of `t: *const T` and `u: *const U` of |
| 77 | +//! equal size, `t` and `u` refer to `UnsafeCell`s at the same byte ranges. |
| 78 | +//! If `U: FromZeroes`, `U: FromBytes`, or `U: AsBytes`, no instance of `U` |
| 79 | +//! contains `UnsafeCell`s at any byte ranges. Thus, no instance of `T` |
| 80 | +//! contains `UnsafeCell`s at any byte ranges. |
| 81 | +//! - `U: FromZeroes` additionally requires that, given `u: *const U`, it is |
| 82 | +//! sound to initialize `*u` to contain all zero bytes. Since, for all `t: |
| 83 | +//! *const T` and `u: *const U` of equal size, `*t` and `*u` have equal bit |
| 84 | +//! validity, then it must also be the case that, given `t: *const T`, it is |
| 85 | +//! sound to initialize `*t` to contain all zero bytes. |
| 86 | +//! - `U: FromBytes` additionally requires that, given `u: *const U`, it is |
| 87 | +//! sound to initialize `*u` to contain any sequence of `u8`s. Since, for |
| 88 | +//! all `t: *const T` and `u: *const U` of equal size, `*t` and `*u` have |
| 89 | +//! equal bit validity, then it must also be the case that, given `t: *const |
| 90 | +//! T`, it is sound to initialize `*t` to contain any sequence of `u8`s. |
| 91 | +//! - `U: AsBytes` additionally requires that, given `u: &U`, it is sound to |
| 92 | +//! treat `t` as an immutable `[u8]` of length `size_of_val(u)`. This is |
| 93 | +//! equivalent to saying that no instance of `U` can contain bytes which are |
| 94 | +//! invalid for `u8`. Since, for all `t: *const T` and `u: *const U` of |
| 95 | +//! equal size, `*t` and `*u` have equal bit validity, then it must also be |
| 96 | +//! the case that no instance of `T` can contain bytes which are invalid for |
| 97 | +//! `u8`. |
| 98 | +//! - `U: Unaligned` requires that `U`'s alignment is 1. `T: |
| 99 | +//! transparent-layout-validity(U)` guarantees that `T`'s alignment is equal |
| 100 | +//! to `U`'s, and is thus also 1. |
0 commit comments