Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deriving default for a struct with a rustified enum member that isn't representable by 0 generates undefined behavior #2974

Open
Supreeeme opened this issue Nov 11, 2024 · 2 comments

Comments

@Supreeeme
Copy link

// header.h
enum E { A = 1, B, C };

struct S {
	enum E e;
};

bindgen invocation:

bindgen header.h --rustified-enum '.*' --with-derive-default 

bindgen output:

/* automatically generated by rust-bindgen 0.70.1 */

#[repr(u32)]
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub enum E {
    A = 1,
    B = 2,
    C = 3,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct S {
    pub e: E,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
    ["Size of S"][::std::mem::size_of::<S>() - 4usize];
    ["Alignment of S"][::std::mem::align_of::<S>() - 4usize];
    ["Offset of field: S::e"][::std::mem::offset_of!(S, e) - 0usize];
};
impl Default for S {
    fn default() -> Self {
        let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
        unsafe {
            ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
            s.assume_init()
        }
    }
}

This implementation of Default is UB, since it generates an E with an invalid tag.

@pvdrz
Copy link
Contributor

pvdrz commented Nov 12, 2024

I'm slightly annoyed by the behaviour of rustified_enum in general. Given that there is no sane way to pick a default value for the enum in this case, I'm not sure how a proper fix for this looks like. Maybe we could just avoid deriving default for rustified enums unconditionally

@Supreeeme
Copy link
Author

I think if a struct has a rustified enum member it'd be best to just avoid generating Default, yeah. Or even better, only avoid generating default if a rustified enum doesn't have a variant equal to 0, although I don't know if that special case would be worth the hassle.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants