Skip to content

Commit 8ebcec0

Browse files
authored
Merge pull request #9 from Manishearth/shallow-deep
Mention shallow vs deep validity
2 parents d35f558 + 4c4e831 commit 8ebcec0

File tree

1 file changed

+11
-2
lines changed

1 file changed

+11
-2
lines changed

src/advanced_unsafety/invalid_values.md

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,12 @@ It's also currently invalid for `Vec<T>` to have a null pointer for its buffer!
3434

3535
There are a lot of other reasons that a pointer type may not be valid, but these are the ones where the bit pattern is statically known to be invalid regardless of context. We'll be covering these in more depth in other chapters (@@note: where?), but, for example, all of these pointers must not only be non-null, they must also point to an actual valid instance of that type at all times (except `Vec<T>`, which is allowed to refer to invalid-but-aligned-and-non-null memory when it is empty)
3636

37+
#### "shallow" vs "deep" validity
38+
39+
40+
An open question in Rust's model is whether references and reference-like types have "shallow" validity (roughly, the rules above), or "deep" validity (where a reference is valid only when the pointed-to data is valid, and that applies transitively). This issue is tracked upstream as [UGC #77](https://github.com/rust-lang/unsafe-code-guidelines/issues/77). The current discussion seems to skew towards shallow validity as opposed to deep validity, but this may change.
41+
42+
For the purposes of _writing_ unsafe code, it is convenient to imagine the boundary as being such that `&`/`&mut` references should never point to invalid memory. However, when auditing existing unsafe code it may be okay to allow scenarios that assume only shallow validity is required, depending on your risk appetite.
3743

3844
### Enums with invalid values
3945

@@ -90,9 +96,11 @@ As a library user you may not assume anything about the representation of a libr
9096
## When you might end up making an invalid value
9197

9298

93-
Invalid values have a chance to crop up when you're reinterpreting a chunk of memory as a value of a different type. This can happen when calling [`mem::transmute()`], [`mem::transmute_copy()`], or [`mem::zeroed()`], when casting a reference to a region of memory into one of a different type, or when accessing the wrong variant of a `union`. The value need not be on the stack to be considered invalid: if you gin up an `&bool` that points to a bit pattern that is not a valid `bool`, that is instantly UB even if you don't read from the reference.
99+
Invalid values have a chance to crop up when you're reinterpreting a chunk of memory as a value of a different type. This can happen when calling [`mem::transmute()`], [`mem::transmute_copy()`], or [`mem::zeroed()`], when casting a reference to a region of memory into one of a different type, or when accessing the wrong variant of a `union`. The value need not be on the stack to be considered invalid: if you gin up an `&bool` that points to a bit pattern that is not a valid `bool`, that can instantly be UB (in a "deep validity" world) even if you don't read from the reference.
100+
101+
Note that since [uninitialized memory][uninit-chapter] is a type of invalid value, any way to produce uninitialized memory (including [`mem::uninitialized()`]) is also a way of producing invalid values.
94102

95-
They can also happen when receiving values over FFI where either the signature of the function is incorrect (e.g. saying an FFI function accepts `bool` when the other side thinks it accepts a `u8`), or where there are differences in notions of validity across languages.
103+
Invalid values can also be created when receiving values over FFI where either the signature of the function is incorrect (e.g. saying an FFI function accepts `bool` when the other side thinks it accepts a `u8`), or where there are differences in notions of validity across languages.
96104

97105
A subtle case of this comes up occasionally in FFI code due to differences in expectations between how enums are used in Rust and C.
98106

@@ -131,6 +139,7 @@ This is not an exhaustive list: ultimately, having an invalid value is UB and it
131139
[unaligned]: ../core_unsafety/dangling_and_unaligned_pointers.md
132140
[uninit-chapter]: ../undef_memory.md
133141
[`mem::transmute()`]: https://doc.rust-lang.org/stable/std/mem/fn.transmute.html
142+
[`mem::uninitialized()`]: https://doc.rust-lang.org/stable/std/mem/fn.uninitialized.html
134143
[`mem::transmute_copy()`]: https://doc.rust-lang.org/stable/std/mem/fn.transmute_copy.html
135144
[`mem::zeroed()`]: https://doc.rust-lang.org/stable/std/mem/fn.zeroed.html
136145
[`NonNull<T>`]: https://doc.rust-lang.org/stable/std/ptr/struct.NonNull.html

0 commit comments

Comments
 (0)