Skip to content

Newtypes for all C enums #5066

@Darksonn

Description

@Darksonn

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions