Skip to content

Commit 875dd75

Browse files
rcseacordmanhatsu
authored andcommitted
Revise uninitialized memory guidelines and examples
Updated guidelines on uninitialized memory usage and added examples of compliant and non-compliant code.
1 parent fd48690 commit 875dd75

File tree

1 file changed

+79
-10
lines changed

1 file changed

+79
-10
lines changed

src/coding-guidelines/values.rst

Lines changed: 79 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,43 +14,92 @@ Values
1414
:fls: fls_6lg0oaaopc26
1515
:decidability: undecidable
1616
:scope: system
17-
:tags: undefined-behavior
17+
:tags: undefined-behavior, unsafe
1818

19-
A program shall not create a value of any type from uninitialized memory, except when accessing a field of a union type, where such reads are explicitly defined to be permitted even if the bytes of that field are uninitialized.
20-
It is prohibited to interpret uninitialized memory as a value of any Rust type (primitive, aggregate, reference, pointer, struct, enum, array, tuple, etc.)
19+
A program shall not create a value of any type from uninitialized memory,
20+
except when accessing a field of a union type,
21+
where such reads are explicitly defined to be permitted even if the bytes of that field are uninitialized.
22+
It is prohibited to interpret uninitialized memory as a value of any Rust type such as a
23+
primitive, aggregate, reference, pointer, struct, enum, array, or tuple.
2124

2225
**Exception:** You can access a field of a union even when the backing bytes of that field are uninitialized provided that:
2326

2427
- The resulting value has an unspecified but well-defined bit pattern.
25-
- Interpreting that value must still comply with the requirements of the accessed type (e.g., no invalid enum discriminants, no invalid pointer values, etc.).
28+
- Interpreting that value must still comply with the requirements of the accessed type
29+
(e.g., no invalid enum discriminants, no invalid pointer values, etc.).
2630

27-
For example, reading an uninitialized u32 field of a union is allowed; reading an uninitialized bool field is disallowed because not all bit patterns are valid.
31+
For example, reading an uninitialized u32 field of a union is allowed;
32+
reading an uninitialized bool field is disallowed because not all bit patterns are valid.
2833

2934
.. rationale::
3035
:id: rat_kjFRrhpS8Wu6
3136
:status: draft
3237

33-
Rust’s memory model treats all types except unions as having an invariant that all bytes must be initialized before a value may be constructed. Reading uninitialized memory:
38+
Rust’s memory model treats all types except unions as having an invariant that all bytes must be initialized before a value may be constructed.
39+
Reading uninitialized memory:
3440

3541
- creates undefined behavior for most types,
3642
- may violate niche or discriminant validity,
37-
- may create invalid pointer values,
38-
- or may produce values that violate type invariants.
43+
- may create invalid pointer values, or
44+
- may produce values that violate type invariants.
3945

40-
The sole exception is that unions work like C unions: any union field may be read, even if it was never written. The resulting bytes must, however, form a valid representation for the field’s type, which is not guaranteed if the union contains arbitrary data.
46+
The sole exception is that unions work like C unions: any union field may be read, even if it was never written.
47+
The resulting bytes must, however, form a valid representation for the field’s type,
48+
which is not guaranteed if the union contains arbitrary data.
4149

4250
.. non_compliant_example::
4351
:id: non_compl_ex_Qb5GqYTP6db1
4452
:status: draft
4553

46-
The following code creates a value from uninitialized memory via assume_init:
54+
This noncompliant example creates a value from uninitialized memory via ``assume_init``:
4755

4856
.. code-block:: rust
4957
5058
use std::mem::MaybeUninit;
5159
5260
let x: u32 = unsafe { MaybeUninit::uninit().assume_init() }; // UB
5361
62+
.. non_compliant_example::
63+
:id: non_compl_ex_Qb5GqYTP6db2
64+
:status: draft
65+
66+
Creating a reference from arbitrary or uninitialized bytes is always undefined behavior.
67+
References must be valid, aligned, properly dereferenceable, and non-null.
68+
Uninitialized memory cannot satisfy these invariants.
69+
70+
.. code-block:: rust
71+
72+
use std::mem::MaybeUninit;
73+
74+
let r: &u32 = unsafe { MaybeUninit::uninit().assume_init() }; // UB — invalid reference
75+
76+
.. non_compliant_example::
77+
:id: non_compl_ex_Qb5GqYTP6db4
78+
:status: draft
79+
80+
Not all bit patterns are valid pointers for all operations (e.g., provenance rules).
81+
You cannot create a pointer from unspecified bytes.
82+
Even a raw pointer type (e.g., ``*const T``) has validity rules.
83+
84+
.. code-block:: rust
85+
86+
use std::mem::MaybeUninit;
87+
88+
let p: *const u32 = unsafe { MaybeUninit::uninit().assume_init() }; // UB
89+
90+
.. non_compliant_example::
91+
:id: non_compl_ex_Qb5GqYTP6db5
92+
:status: draft
93+
94+
Array elements must individually be valid values.
95+
96+
.. code-block:: rust
97+
98+
use std::mem::MaybeUninit;
99+
100+
let mut arr: [MaybeUninit<u8>; 4] = unsafe { MaybeUninit::uninit().assume_init() };
101+
let a = unsafe { std::mem::transmute::<_, [u8; 4]>(arr) }; // UB — not all elements initialized
102+
54103
.. compliant_example::
55104
:id: compl_ex_Ke869nSXuShT
56105
:status: draft
@@ -66,3 +115,23 @@ Values
66115
67116
let u = U { x: 123 }; // write to one field
68117
let f = unsafe { u.y }; // reading the other field is allowed
118+
119+
.. non_compliant_example::
120+
:id: non_compl_ex_Qb5GqYTP6db3
121+
:status: draft
122+
123+
Even though unions allow reads of any field, not all bit patterns are valid for a ``bool``.
124+
Unions do not relax type validity requirements.
125+
Only the read itself is allowed;
126+
the resulting bytes must still be a valid bool.
127+
128+
.. code-block:: rust
129+
130+
union U {
131+
b: bool,
132+
x: u8,
133+
}
134+
135+
let u = U { x: 255 }; // 255 is not a valid bool representation
136+
let b = unsafe { u.b }; // UB — invalid bool
137+

0 commit comments

Comments
 (0)