Uninitialized data from external functions

⚓ rust    📅 2025-05-19    👤 surdeus    👁️ 5      

surdeus

Warning

This post was published 42 days ago. The information described in this article may have changed.

A lot of compound types in the libc crate contain initialized types which variables of it are assumed to be init. But sometimes we call external functions returning (usually by outpointer) these types and in their program, and those functions may not initialize every byte that rust requires to be initialized.
For example, the ifreq type's ifr_name field is represented as an array of c_char (type alias for i8 usually, and i8 is a type variables of which rust requires to be initialized). But ifr_name should be a c-style string representing the name of the network interface on which this ifreq is requesting operations, and if I obtained an ifreq from some external library, say:

// libfoo
struct ifreq foo()
{
    struct ifreq r;
    strlcpy(r.ifr_name, "en0", sizeof(r.ifr_name));
    /* initalizing other fields */
    return r;
}
#[link(name = "foo")]
unsafe extern "C"
{
    fn foo() -> libc::ifreq;
}

In the libfoo code, as we can see, only the first 4 c_chars are properly initialized. So calling foo in rust invokes undefined behavior?
So my main query is, can we call foo in rust anyway, even though the program's outcome is, in theory, unpredictable? Or do we have to instead write the ffi declaration of foo as:

#[link(name = "foo")]
unsafe extern "C"
{
    fn foo() -> MaybeUninit<libc::ifreq>;
}

Will the compiler actually care about whether data from external functions are "initialized"? Maybe it only cares about bit patterns for those?

1 post - 1 participant

Read full topic

🏷️ rust_feed