From b5a254720edfb892124a424a9f062d7bfc2088ae Mon Sep 17 00:00:00 2001 From: Marcus Comstedt Date: Mon, 22 Aug 2022 11:05:46 +0200 Subject: [PATCH] Fix bitsize of some msghdr and cmsghdr fields on Linux These fields are size_t on Linux, so using CInt on LP64 only accesses 32 bits of the total 64. This is especially noticable on big endian, where the lower 32 bits of the number are written to the upper 32 bits of the field. Also use #type socklen_t instead of CUInt/CInt where applicable, since POSIX does not specify the size of this type. --- Network/Socket/Posix/CmsgHdr.hsc | 12 ++++++++---- Network/Socket/Posix/MsgHdr.hsc | 12 ++++++++++-- cbits/cmsg.c | 4 ++-- include/HsNet.h | 8 ++++---- 4 files changed, 24 insertions(+), 12 deletions(-) diff --git a/Network/Socket/Posix/CmsgHdr.hsc b/Network/Socket/Posix/CmsgHdr.hsc index f122ea3b..fe827bf3 100644 --- a/Network/Socket/Posix/CmsgHdr.hsc +++ b/Network/Socket/Posix/CmsgHdr.hsc @@ -22,7 +22,11 @@ import Network.Socket.Posix.MsgHdr import Network.Socket.Types data CmsgHdr = CmsgHdr { - cmsgHdrLen :: !CInt +#ifdef __linux__ + cmsgHdrLen :: !CSize +#else + cmsgHdrLen :: !(#type socklen_t) +#endif , cmsgHdrLevel :: !CInt , cmsgHdrType :: !CInt } deriving (Eq, Show) @@ -61,7 +65,7 @@ withCmsgs cmsgs0 action toCmsgHdr :: Cmsg -> Ptr CmsgHdr -> IO () toCmsgHdr (Cmsg (CmsgId lvl typ) (PS fptr off len)) ctrlPtr = do - poke ctrlPtr $ CmsgHdr (c_cmsg_len (fromIntegral len)) lvl typ + poke ctrlPtr $ CmsgHdr (fromIntegral $ c_cmsg_len (fromIntegral len)) lvl typ withForeignPtr fptr $ \src0 -> do let src = src0 `plusPtr` off dst <- c_cmsg_data ctrlPtr @@ -96,7 +100,7 @@ foreign import ccall unsafe "cmsg_data" c_cmsg_data :: Ptr CmsgHdr -> IO (Ptr Word8) foreign import ccall unsafe "cmsg_space" - c_cmsg_space :: CInt -> CInt + c_cmsg_space :: CSize -> CSize foreign import ccall unsafe "cmsg_len" - c_cmsg_len :: CInt -> CInt + c_cmsg_len :: CSize -> CSize diff --git a/Network/Socket/Posix/MsgHdr.hsc b/Network/Socket/Posix/MsgHdr.hsc index 40b1c7a5..9d072be2 100644 --- a/Network/Socket/Posix/MsgHdr.hsc +++ b/Network/Socket/Posix/MsgHdr.hsc @@ -15,11 +15,19 @@ import Network.Socket.Posix.IOVec (IOVec) data MsgHdr sa = MsgHdr { msgName :: !(Ptr sa) - , msgNameLen :: !CUInt + , msgNameLen :: !(#type socklen_t) , msgIov :: !(Ptr IOVec) +#ifdef __linux__ , msgIovLen :: !CSize +#else + , msgIovLen :: !CInt +#endif , msgCtrl :: !(Ptr Word8) - , msgCtrlLen :: !CInt +#ifdef __linux__ + , msgCtrlLen :: !CSize +#else + , msgCtrlLen :: !(#type socklen_t) +#endif , msgFlags :: !CInt } diff --git a/cbits/cmsg.c b/cbits/cmsg.c index c532f5ad..105dd197 100644 --- a/cbits/cmsg.c +++ b/cbits/cmsg.c @@ -87,11 +87,11 @@ unsigned char *cmsg_data(struct cmsghdr *cmsg) { return (CMSG_DATA(cmsg)); } -int cmsg_space(int l) { +size_t cmsg_space(size_t l) { return (CMSG_SPACE(l)); } -int cmsg_len(int l) { +size_t cmsg_len(size_t l) { return (CMSG_LEN(l)); } #endif /* _WIN32 */ diff --git a/include/HsNet.h b/include/HsNet.h index ba016148..b623a97e 100644 --- a/include/HsNet.h +++ b/include/HsNet.h @@ -126,11 +126,11 @@ cmsg_nxthdr(struct msghdr *mhdr, struct cmsghdr *cmsg); extern unsigned char * cmsg_data(struct cmsghdr *cmsg); -extern int -cmsg_space(int l); +extern size_t +cmsg_space(size_t l); -extern int -cmsg_len(int l); +extern size_t +cmsg_len(size_t l); #endif /* _WIN32 */ INLINE int