Skip to content

macOS 26 arm64: vec![None; N] with Option<NonZero<…>> can cause libc abort on free #150898

@venhelhardt

Description

@venhelhardt

View all comments

On macOS Tahoe (arm64), using the vec![T; N] initializer or std::vec::from_elem(T, N) for certain data structure patterns can lead to a libc abort on free (pointer being freed was not allocated).

Affected pattern

The issue reproduces reliably with types involving niche optimization, in particular:
Option<(NonZero<u32>, u64, u64)>

Using:

let v = vec![None; 16];
// or
let v = std::vec::from_elem(None, 16);

may cause the resulting allocation to be rejected by libc during free.

In contrast, constructing the same vector via:

let mut v = Vec::with_capacity(16);
v.resize(16, None);

does not reproduce the issue.

Environment sensitivity

The issue is highly sensitive to compiler and codegen settings and appears only under specific optimization configurations:

  • lto = off
  • incremental = true
  • opt-level = 2
  • codegen-units > 1 (e.g. 16 or 256)

Observed behavior

  • The allocation is valid immediately after allocation.
  • During initialization via Vec::from_elem / vec![T; N], the buffer may be filled with non-deterministic bit patterns (likely coming from padding / unused bytes in niche-optimized Option<NonZero<...>>).
  • After this initialization, libc (via xzm_free) treats the pointer as not allocated and aborts on free.

Investigation notes

  • The allocation is valid immediately after allocation (the pointer, size, and zone are correct according to malloc_size/malloc_zone_from_ptr)
  • After initialization (after Vec::extend_with), malloc_size and malloc_zone_from_ptr report the pointer as invalid (no zone, size = 0).
  • ASan / gmalloc change behavior or mask the issue

I tried this code: https://github.com/venhelhardt/r92-memory-corruption

I expected to see this happen: vec![T; N] / std::vec::from_elem(T, N) should always produce a Vec that can be safely dropped.

Instead, this happened: On macOS Tahoe (arm64), initializing certain niche-optimized types with vec![None; N] causes the allocation to be treated as invalid, leading to a libc abort on free.

Meta

rustc --version --verbose:

rustc 1.92.0 (ded5c06cf 2025-12-08)
binary: rustc
commit-hash: ded5c06cf21d2b93bffd5d884aa6e96934ee4234
commit-date: 2025-12-08
host: aarch64-apple-darwin
release: 1.92.0
LLVM version: 21.1.3
rustc 1.94.0-nightly (fecb335cb 2026-01-07)
binary: rustc
commit-hash: fecb335cbad3d84ef3da39191ba094e6c726a5b4
commit-date: 2026-01-07
host: aarch64-apple-darwin
release: 1.94.0-nightly
LLVM version: 21.1.8
Backtrace

RUST_BACKTRACE=1 cargo run --release
    Finished `release` profile [optimized] target(s) in 0.18s
     Running `target/release/r92-mem-corruption`
========= [0]
v0 ptr=0x1056261a0, len=16, cap=16, malloc_zone=0x1ee7e0000, malloc_size=384, first_u64=0x0000000000000088
v1 ptr=0x105626320, len=16, cap=16, malloc_zone=0x1ee7e0000, malloc_size=384, first_u64=0x0000000000000000
v2 ptr=0x1056264a0, len=16, cap=16, malloc_zone=0x1ee7e0000, malloc_size=384, first_u64=0x0000000000000098
drop v0
drop v1
drop v2
========= [1]
v0 ptr=0x1056261a0, len=16, cap=16, malloc_zone=0x1ee7e0000, malloc_size=384, first_u64=0x000400023a000000
v1 ptr=0x105626320, len=16, cap=16, malloc_zone=0x1ee7e0000, malloc_size=384, first_u64=0x0000000000000006
v2 ptr=0x105626a20, len=16, cap=16, malloc_zone=0x1ee7e0000, malloc_size=384, first_u64=0x00000000000000a8
drop v0
drop v1
drop v2
========= [2]
v0 ptr=0x1056261a0, len=16, cap=16, malloc_zone=0x1ee7e0000, malloc_size=384, first_u64=0x000400023a000000
v1 ptr=0x105626320, len=16, cap=16, malloc_zone=0x1ee7e0000, malloc_size=384, first_u64=0x0000000000000003
v2 ptr=0x105626a20, len=16, cap=16, malloc_zone=0x1ee7e0000, malloc_size=384, first_u64=0x00000000000000a8
drop v0
drop v1
drop v2
========= [3]
v0 ptr=0x1056261a0, len=16, cap=16, malloc_zone=0x1ee7e0000, malloc_size=384, first_u64=0x000400023a000000
v1 ptr=0x808c08000, len=16, cap=16, malloc_zone=0x1ee7e0000, malloc_size=384, first_u64=0x0000000000000030
v2 ptr=0x808c08180, len=16, cap=16, malloc_zone=0x1ee7e0000, malloc_size=384, first_u64=0x0000000000000000
drop v0
drop v1
drop v2
========= [4]
v0 ptr=0x808c08000, len=16, cap=16, malloc_zone=0x1ee7e0000, malloc_size=384, first_u64=0x02010001053f4898
v1 ptr=0x808c08180, len=16, cap=16, malloc_zone=0x1ee7e0000, malloc_size=384, first_u64=0x0000000000000000
v2 ptr=0x808c08300, len=16, cap=16, malloc_zone=0x1ee7e0000, malloc_size=384, first_u64=0x0000000000000000
drop v0
drop v1
drop v2
========= [5]
v0 ptr=0x808c08300, len=16, cap=16, malloc_zone=0x1ee7e0000, malloc_size=384, first_u64=0x0000000000001818
v1 ptr=0x808c08180, len=16, cap=16, malloc_zone=0x0, malloc_size=0, first_u64=0xa02febcde5c4fe47
v2 ptr=0x808c08000, len=16, cap=16, malloc_zone=0x1ee7e0000, malloc_size=384, first_u64=0x0000000000000400
drop v0
drop v1
r92-mem-corruption(3233,0x1edb66c40) malloc: *** error for object 0x808c08180: pointer being freed was not allocated
r92-mem-corruption(3233,0x1edb66c40) malloc: *** set a breakpoint in malloc_error_break to debug
Abort trap: 6              RUST_BACKTRACE=1 cargo run --release

Pinned by dianqk

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: This is a bug.C-external-bugCategory: issue that is caused by bugs in software beyond our controlO-AArch64Armv8-A or later processors in AArch64 modeO-appleOperating system: Apple / Darwin (macOS, iOS, tvOS, visionOS, watchOS)O-macosOperating system: macOSP-highHigh priorityS-has-mcveStatus: A Minimal Complete and Verifiable Example has been found for this issueT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type
    No fields configured for issues without a type.

    Projects

    Status

    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions