|
3 | 3 |
|
4 | 4 | .. default-domain:: coding-guidelines |
5 | 5 |
|
6 | | -.. guideline:: Do not create values from uninitialized memory except for union fields |
| 6 | +.. guideline:: Do not create values from uninitialized memory |
7 | 7 | :id: gui_uyp3mCj77FS8 |
8 | 8 | :category: mandatory |
9 | 9 | :status: draft |
|
13 | 13 | :scope: system |
14 | 14 | :tags: undefined-behavior, unsafe |
15 | 15 |
|
16 | | - A program shall not create a value of any type from uninitialized memory, |
17 | | - except when accessing a field of a union type, |
18 | | - where such reads are explicitly defined to be permitted even if the bytes of that field are uninitialized. |
| 16 | + A program shall not create a value of any non-``union`` type from uninitialized memory. |
| 17 | + Reading from a union is covered by a separate rule, "Do not read from union fields that may contain uninitialized bytes". |
19 | 18 | It is prohibited to interpret uninitialized memory as a value of any Rust type such as a |
20 | 19 | primitive, aggregate, reference, pointer, struct, enum, array, or tuple. |
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 |
26 | | - (e.g., no invalid enum discriminants, no invalid pointer values, etc.). |
27 | | - |
28 | | - For example, reading an uninitialized u32 field of a union is allowed; |
29 | | - reading an uninitialized bool field is disallowed because not all bit patterns are valid. |
30 | | - |
| 20 | + |
31 | 21 | .. rationale:: |
32 | 22 | :id: rat_kjFRrhpS8Wu6 |
33 | 23 | :status: draft |
|
39 | 29 | - may violate niche or discriminant validity, |
40 | 30 | - may create invalid pointer values, or |
41 | 31 | - may produce values that violate type invariants. |
42 | | -
|
43 | | - The sole exception is that unions work like C unions: any union field may be read, even if it was never written. |
44 | | - The resulting bytes must, however, form a valid representation for the field's type, |
45 | | - which is not guaranteed if the union contains arbitrary data. |
46 | | - |
| 32 | + |
47 | 33 | .. non_compliant_example:: |
48 | 34 | :id: non_compl_ex_Qb5GqYTP6db1 |
49 | 35 | :status: draft |
|
59 | 45 | let x: u32 = unsafe { MaybeUninit::uninit().assume_init() }; // UB |
60 | 46 | # } |
61 | 47 |
|
62 | | - .. compliant_example:: |
63 | | - :id: compl_ex_Ke869nSXuShU |
64 | | - :status: draft |
65 | | - |
66 | | - Types such as ``u8``, ``u16``, ``u32``, and ``i128`` allow all possible bit patterns. |
67 | | - Provided the memory is initialized, there is no undefined behavior. |
68 | | - |
69 | | - .. rust-example:: |
70 | | - |
71 | | - union U { |
72 | | - n: u32, |
73 | | - bytes: [u8; 4], |
74 | | - } |
75 | | - |
76 | | - # fn main() { |
77 | | - let u = U { bytes: [0xFF, 0xEE, 0xDD, 0xCC] }; |
78 | | - let n = unsafe { u.n }; // OK — all bit patterns valid for u32 |
79 | | - # } |
80 | | - |
81 | 48 | .. compliant_example:: |
82 | 49 | :id: compl_ex_Ke869nSXuShV |
83 | 50 | :status: draft |
|
140 | 107 | let a = unsafe { std::mem::transmute::<_, [u8; 4]>(arr) }; // UB — not all elements initialized |
141 | 108 | # } |
142 | 109 |
|
143 | | - .. compliant_example:: |
144 | | - :id: compl_ex_Ke869nSXuShT |
145 | | - :status: draft |
146 | | - |
147 | | - The following code reads a union field: |
148 | | - |
149 | | - .. rust-example:: |
150 | | - |
151 | | - union U { |
152 | | - x: u32, |
153 | | - y: f32, |
154 | | - } |
155 | | - |
156 | | - # fn main() { |
157 | | - let u = U { x: 123 }; // write to one field |
158 | | - let f = unsafe { u.y }; // reading the other field is allowed |
159 | | - # } |
160 | | - |
161 | | - .. non_compliant_example:: |
162 | | - :id: non_compl_ex_Qb5GqYTP6db3 |
163 | | - :status: draft |
164 | | - |
165 | | - Even though unions allow reads of any field, not all bit patterns are valid for a ``bool``. |
166 | | - Unions do not relax type validity requirements. |
167 | | - Only the read itself is allowed; |
168 | | - the resulting bytes must still be a valid bool. |
169 | | - |
170 | | - .. rust-example:: |
171 | | - |
172 | | - union U { |
173 | | - b: bool, |
174 | | - x: u8, |
175 | | - } |
176 | | - |
177 | | - # fn main() { |
178 | | - let u = U { x: 255 }; // 255 is not a valid bool representation |
179 | | - let b = unsafe { u.b }; // UB — invalid bool |
180 | | - # } |
181 | | - |
182 | 110 | .. compliant_example:: |
183 | 111 | :id: compl_ex_Ke869nSXuShW |
184 | 112 | :status: draft |
|
0 commit comments