Skip to content

Unexpected undefined behavior when assigning a function pointer to std::mem::zeroed() #51615

Closed
@archshift

Description

@archshift

Note: the following behavior only exists when compiling with optimizations (a.k.a. release mode).

Example 1:

pub fn bar() -> usize {
    let foo: fn() = unsafe { ::std::mem::zeroed() };
    foo as usize
}

This emits (as of 1.26.0):

  push rbp
  mov rbp, rsp
  ud2

Whereas it used to have expected behavior up until 1.19.0:

  push rbp
  mov rbp, rsp
  xor eax, eax
  pop rbp
  ret

Example 2:

A bit of an odd case I discovered, which results in what seems to be some stack corruption:

pub struct Foo<T: Copy> {
    map_keys: [u64; 64],
    map_vals: T,
}

impl<T: Copy> Foo<T> {
    pub fn new() -> Self {
        Foo {
            map_keys: [!0; 64],
            map_vals: unsafe { ::std::mem::zeroed() }
        }
    }
}

fn main() {
    Foo::<fn()>::new();
}

Playground link


What I think is striking here is that this behavior occurs while never even dereferencing the pointer!. This allows one to shoot oneself in the foot when trying to, for example, set a default value for a function pointer member.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-docsArea: Documentation for any part of the project, including the compiler, standard library, and toolsC-enhancementCategory: An issue proposing an enhancement or a PR with one.P-mediumMedium priorityT-libs-apiRelevant to the library API team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions