Skip to content

Types of CMSG_LEN and CMSG_SPACE don't match libc on many platforms #3240

Open
@jmillikin

Description

@jmillikin

The CMSG_LEN and CMSG_SPACE macros defined in <sys/socket.h> on most UNIX platforms do not have well-defined types, but they generally (not always[0]) operate on size_t:

/* Linux (GNU libc, musl) */
#define CMSG_LEN(len)   (CMSG_ALIGN (sizeof (struct cmsghdr)) + (len))
#define CMSG_SPACE(len) (CMSG_ALIGN (len) + CMSG_ALIGN (sizeof (struct cmsghdr)))

/* macOS */
#define CMSG_SPACE(l)           (__DARWIN_ALIGN32(sizeof(struct cmsghdr)) + __DARWIN_ALIGN32(l))
#define CMSG_LEN(l)             (__DARWIN_ALIGN32(sizeof(struct cmsghdr)) + (l))

/* FreeBSD */
#define	CMSG_SPACE(l)		(_ALIGN(sizeof(struct cmsghdr)) + _ALIGN(l))
#define	CMSG_LEN(l)		(_ALIGN(sizeof(struct cmsghdr)) + (l))

/* OpenBSD */
#define	CMSG_LEN(len)	(_ALIGN(sizeof(struct cmsghdr)) + (len))
#define	CMSG_SPACE(len)	(_ALIGN(sizeof(struct cmsghdr)) + _ALIGN(len))

However, the libc crate uses c_uint for the functions that mimic those macros, so the values end up getting bounced back and forth between usize and c_uint with failable as conversions.

The libc crate would ideally use c_size when appropriate to match the platform libc. This would be a breaking change, though most users of those functions follow a CMSG_LEN(some_slice.len() as _) pattern that might reduce the ecosystem impact.

[0] An example platform that does not use size_t is Solaris and its descendants, which use unsigned int: https://github.com/illumos/illumos-gate/blob/118b2dbf1f4a745a7e35a5054a777c09bd90fff7/usr/src/uts/common/sys/socket.h#L499-L505

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions