Skip to content

Commit 590a0c0

Browse files
committed
doc: prohibit creating value from uninitialized memory
1 parent 1b00276 commit 590a0c0

File tree

1 file changed

+61
-0
lines changed

1 file changed

+61
-0
lines changed

src/coding-guidelines/values.rst

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,64 @@
55

66
Values
77
======
8+
9+
.. guideline:: Do not create values from uninitialized memory except for union fields
10+
:id: gui_uyp3mCj77FS8
11+
:category: mandatory
12+
:status: draft
13+
:release: <TODO>
14+
:fls: fls_6lg0oaaopc26
15+
:decidability: undecidable
16+
:scope: system
17+
:tags: undefined-behavior
18+
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.)
21+
22+
**Exception:** You can access a field of a union even when the backing bytes of that field are uninitialized provided that:
23+
24+
- 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.).
26+
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.
28+
29+
.. rationale::
30+
:id: rat_kjFRrhpS8Wu6
31+
:status: draft
32+
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:
34+
35+
- creates undefined behavior for most types,
36+
- may violate niche or discriminant validity,
37+
- may create invalid pointer values,
38+
- or may produce values that violate type invariants.
39+
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.
41+
42+
.. non_compliant_example::
43+
:id: non_compl_ex_Qb5GqYTP6db1
44+
:status: draft
45+
46+
The following code creates a value from uninitialized memory via assume_init:
47+
48+
.. code-block:: rust
49+
50+
use std::mem::MaybeUninit;
51+
52+
let x: u32 = unsafe { MaybeUninit::uninit().assume_init() }; // UB
53+
54+
.. compliant_example::
55+
:id: compl_ex_Ke869nSXuShT
56+
:status: draft
57+
58+
The following code reads a union field:
59+
60+
.. code-block:: rust
61+
62+
union U {
63+
x: u32,
64+
y: f32,
65+
}
66+
67+
let u = U { x: 123 }; // write to one field
68+
let f = unsafe { u.y }; // reading the other field is allowed

0 commit comments

Comments
 (0)