1313 :scope: system
1414 :tags: defect, safety, undefined-behavior
1515
16- When reading from a union field, ensure that the underlying bytes constitute a valid value for that field' s type.
16+ Ensure that the underlying bytes constitute a valid value for that field' s type when reading from a union field .
1717 Reading a union field whose bytes do not represent a valid value for the field' s type is undefined behavior.
1818
19- Before accessing a union field:
19+ Before accessing a union field, verify that that the union was either :
2020
21- * Verify that the union was last written through that field, or
22- * Verify that the union was written through a field whose bytes are valid when reinterpreted as the target field' s type, or
23- * Use explicit validity checks when the active field is uncertain
21+ * last written through that field, or
22+ * written through a field whose bytes are valid when reinterpreted as the target field' s type
23+
24+ If the active field is uncertain, use explicit validity checks.
2425
2526 .. rationale::
2627 :id: rat_UnionFieldValidityReason
2728 :status: draft
2829
29- Unions allow multiple fields to occupy the same memory, similar to C unions .
30+ Similar to C, unions allow multiple fields to occupy the same memory.
3031 Unlike enumeration types, unions do not track which field is currently active.
31- You must ensure that when a field is read,
32+ You must ensure that when a field is read that
3233 the underlying bytes are valid for that field' s type [RUST-REF-UNION]_.
3334
3435 Every type has a *validity invariant* — a set of constraints that all values of
3940 Examples of validity requirements for common types:
4041
4142 * **bool**: Must be ``0`` (false) or ``1`` (true). Any other value (e.g., ``3``) is invalid.
42- * **char**: Must be a valid Unicode scalar value (0x0 to 0xD7FF or 0xE000 to 0x10FFFF).
43+ * **char**: Must be a valid Unicode scalar value (`` 0x0`` to `` 0xD7FF`` or `` 0xE000`` to `` 0x10FFFF`` ).
4344 * **References**: Must be non-null and properly aligned.
4445 * **Enums**: Must hold a valid discriminant value.
4546 * **Floating point**: All bit patterns are valid for the ``f32`` or ``f64``.type
8283 }
8384
8485 fn main() {
85- // 0xD800 is a surrogate and not a valid Unicode scalar value
86+ // ' 0xD800' is a surrogate and not a valid Unicode scalar value
8687 let u = IntOrChar { i: 0xD800 };
8788
88- // Noncompliant: reading an invalid Unicode value from a union field of type ' char '
89+ // Reading an invalid Unicode value from a union field of type 'char'
8990 unsafe { u.c }; // Noncompliant
9091 }
9192
9293 .. non_compliant_example::
9394 :id: non_compl_ex_UnionEnum
9495 :status: draft
9596
96- This noncompliant example reads an invalid discriminant from a `` union`` field of ' Color' enumeration type.
97+ This noncompliant example reads an invalid discriminant from a union field of ' Color' enumeration type.
9798
9899 .. code-block:: rust
99100
121122 :id: non_compl_ex_UnionRef
122123 :status: draft
123124
124- This noncompliant example reads a reference from a `` union`` containing a null pointer.
125+ This noncompliant example reads a reference from a union containing a null pointer.
125126 A similar problem occurs when reading a misaligned pointer.
126127
127128 .. code-block:: rust
209210 fn main() {
210211 let u = IntOrBool { b: true };
211212
212- // Compliant: reading the same field that was written
213- let valid_bool = unsafe { u.b };
214- println!(" bool value: {}" , valid_bool);
213+ // Read the same field that was written
214+ println!("bool value: {}", unsafe { u.b }); // compliant
215215 }
216216
217217 .. compliant_example::
230230 fn main() {
231231 let u = IntBytes { i: 0x12345678 };
232232
233- // Compliant: all bit patterns are valid for [u8; 4]
234- let bytes = unsafe { u.bytes };
235- println!(" bytes: {:?}" , bytes);
233+ // All bit patterns are valid for [u8; 4]
234+ println!("bytes: {:?}", unsafe { u.bytes }); // compliant
236235
237236 let u2 = IntBytes { bytes: [0x11, 0x22, 0x33, 0x44] };
238237
239- // Compliant: all bit patterns are valid for u32
240- let int_value = unsafe { u2.i };
241- println!(" integer: 0x{:08X}" , int_value);
238+ // All bit patterns are valid for ' u32 '
239+ println!("integer: 0x{:08X}", unsafe { u2.i }); // compliant
242240 }
243241
244242 .. compliant_example::
245243 :id: compl_ex_UnionValidateBool
246244 :status: draft
247245
248- This compliant solution validates bytes before reading as a constrained type.
246+ This compliant example validates bytes before reading as a constrained type.
249247
250248 .. code-block:: rust
251249
255253 }
256254
257255 fn try_read_bool(u: &IntOrBool) -> Option<bool> {
258- // Read as integer first (always valid for u8 )
256+ // Read as integer (always valid for ' u8 ' )
259257 let raw = unsafe { u.i };
260258
261- // Validate before interpreting as bool
259+ // Validate before interpreting as a value of type ' bool '
262260 match raw {
263261 0 => Some(false),
264262 1 => Some(true),
265- _ => None, // Invalid bool value
263+ _ => None, // Invalid Boolean value
266264 }
267265 }
268266
269267 fn main() {
270268 let u1 = IntOrBool { i: 1 };
271269 let u2 = IntOrBool { i: 3 };
272270
273- // Compliant: validates before reading as bool
271+ // Validates before reading as value of type ' bool '
274272 println!("u1 as bool: {:?}", try_read_bool(&u1)); // Some(true)
275273 println!("u2 as bool: {:?}", try_read_bool(&u2)); // None
276274 }
294292 | *Rust Unsafe Code Guidelines*, n.d.
295293 | https://rust-lang.github.io/unsafe-code-guidelines/glossary.html#validity-and-safety-invariant.
296294
297- >>>>>>> c93b2cb (Update types-and -traits.rst):src/coding-guidelines/types-and-traits.rst
295+ >>>>>>> c93b2cb (Update types-and-traits.rst):src/coding-guidelines/types-and-traits.rst
0 commit comments