Skip to content

[Coding Guideline]: Do not create values from uninitialized memory #235

@rcseacord

Description

@rcseacord

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

category: mandatoryA coding guideline with category mandatorychapter: valuescoding guidelineAn issue related to a suggestion for a coding guidelinedecidability: undecidableA coding guideline which cannot be checked automaticallyscope: systemA coding guideline that can be determined applied only when entire source is inspectedstatus: draft

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions