Clippy says: "call for this type may be undefined behavior" - is it?

This question is about the rusty way to pass OUT pointers to C functions. From other examples I've gathered that MaybeUninit could be the way to initialize the struct that contains the result of the call. However, clippy complains about the following playground:

    unsafe {
        let cttyname = std::ffi::CString::new("/dev/tty").unwrap(); 
        let ctty = libc::open(cttyname.as_ptr(), libc::O_RDONLY | libc::O_CLOEXEC);
        let mut state: libc::termios = MaybeUninit::<libc::termios>::uninit().assume_init();
        libc::tcgetattr(ctty, &mut state); 
    }

with:

error: this call for this type may be undefined behavior
 --> src/main.rs:8:40
  |
8 |         let mut state: libc::termios = MaybeUninit::<libc::termios>::uninit().assume_init();
  |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: `#[deny(clippy::uninit_assumed_init)]` on by default
  = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#uninit_assumed_init

Is Clippy correct and if so, what's the Rusty way of passing a struct termios * pointer to tcgetattr()? (libc::tcgetattr, C signature).

Don't assume it's initialized before it's actually initialized.

    let cttyname = std::ffi::CString::new("/dev/tty").unwrap(); 
    let mut state = MaybeUninit::<libc::termios>::uninit();
    let state = unsafe {
        let ctty = libc::open(cttyname.as_ptr(), libc::O_RDONLY | libc::O_CLOEXEC);
        // Assumption: this call writes all fields of `state`
        // without/before reading any fields of `state`
        libc::tcgetattr(ctty, state.as_mut_ptr()); 
        state.assume_init()
    };

See here.

5 Likes

Thanks. I think I had blindly followed advice given by the rustc compiler (maybe)

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.