For libc 1.0, we should consider whether all C enums should be exposed as a newtype struct rather than an integer typedef. For example, the header file on my laptop declares idtype_t like this:
/* The following values are used by the `waitid' function. */
typedef enum
{
P_ALL, /* Wait for any child. */
P_PID, /* Wait for specified process. */
P_PGID, /* Wait for members of process group. */
P_PIDFD, /* Wait for the child referred by the PID file
descriptor. */
} idtype_t;
whereas libc declares the above type as:
|
pub type idtype_t = c_uint; |
Defining a C enum as a typedef for an integer has consequences for the CFI (Control Flow Integrity) sanitizer. When using that sanitizer, enums do not have the same ABI as the underlying integer type. Using a newtype struct allows libc to declare a type with an ABI that actually matches what CFI expects.
#[repr(transparent)]
#[cfi_encoding="8idtype_t"]
pub struct idtype_t(pub c_uint);
impl idtype_t {
pub const P_ALL: Self = Self(0);
pub const P_PID: Self = Self(1);
pub const P_PGID: Self = Self(2);
pub const P_PIDFD: Self = Self(3);
}
The consequence of calling a method with an enum declared as a typedefd integer is that the program will crash if the call is dynamic. Static function calls work like normal.
For libc 1.0, we should consider whether all C enums should be exposed as a newtype struct rather than an integer typedef. For example, the header file on my laptop declares
idtype_tlike this:whereas libc declares the above type as:
libc/src/unix/linux_like/linux/mod.rs
Line 21 in 088a284
Defining a C enum as a typedef for an integer has consequences for the CFI (Control Flow Integrity) sanitizer. When using that sanitizer, enums do not have the same ABI as the underlying integer type. Using a newtype struct allows libc to declare a type with an ABI that actually matches what CFI expects.
The consequence of calling a method with an enum declared as a typedefd integer is that the program will crash if the call is dynamic. Static function calls work like normal.