Skip to content

Commit

Permalink
Fix bitsize of some msghdr and cmsghdr fields on Linux
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
zeldin committed Aug 24, 2022
1 parent 53519f0 commit b5a2547
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 12 deletions.
12 changes: 8 additions & 4 deletions Network/Socket/Posix/CmsgHdr.hsc
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
12 changes: 10 additions & 2 deletions Network/Socket/Posix/MsgHdr.hsc
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down
4 changes: 2 additions & 2 deletions cbits/cmsg.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
8 changes: 4 additions & 4 deletions include/HsNet.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit b5a2547

Please sign in to comment.