-
Notifications
You must be signed in to change notification settings - Fork 28
Description
Chapter
Values
Guideline Title
Do not create values from uninitialized memory except for union fields
Category
Mandatory
Status
Draft
Release Begin
unclear
Release End
latest
FLS Paragraph ID
fls_6lg0oaaopc26
Decidability
Undecidable
Scope
System
Tags
undefined-behavior
Amplification
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.
It is prohibited to interpret uninitialized memory as a value of any Rust type (primitive, aggregate, reference, pointer, struct, enum, array, tuple, etc.)
Exception(s)
You can access a field of a union even when the backing bytes of that field are uninitialized provided that:
- The resulting value has an unspecified but well-defined bit pattern.
- Interpreting that value must still comply with the requirements of the accessed type (e.g., no invalid enum discriminants, no invalid pointer values, etc.).
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.
Rationale
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:
- creates undefined behavior for most types,
- may violate niche or discriminant validity,
- may create invalid pointer values,
- or may produce values that violate type invariants.
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.
Non-Compliant Example - Prose
This noncompliant code example creates a value from uninitialized memory via assume_init:
Non-Compliant Example - Code
use std::mem::MaybeUninit;
let x: u32 = unsafe { MaybeUninit::uninit().assume_init() }; // UB
Compliant Example - Prose
This compliant solution reads a union field:
Compliant Example - Code
union U {
x: u32,
y: f32,
}
let u = U { x: 123 }; // write to one field
let f = unsafe { u.y }; // reading the other field is allowed
Metadata
Metadata
Assignees
Labels
Type
Projects
Status