Apple “Feedback” #12149675.
Some netmasks returned by getifaddrs
have family of AF_INET
yet a length less than sizeof(sockaddr_in)
, e.g. 5, 6, 7, or 8. On macOS Ventura 13.3.1, at least.
It looks like it’s actually allocating only eight bytes for the ifa_netmask
(not the 16 that is the size of sockaddr_in
per MacOSX13.3.sdk/usr/include/netinet/in.h
), as it clearly has a different sockaddr_in
immediately after it, e.g.:
sockaddr - sa_len : 5 - sa_family : 2 ▿ sa_data : 14 elements - .0 : 0 - .1 : 0 - .2 : 255 - .3 : 0 - .4 : 0 - .5 : 0 - .6 : 16 // This is obviously the start of the next sockaddr_in; a correct entry with length of 16. - .7 : 2 - .8 : 0 - .9 : 0 - .10 : 127 - .11 : 0 - .12 : 0 - .13 : 1
It’s thus clear that it’s both wrong about the actual length in memory and it is indeed truncating the sockaddr_in
structure, although it looks like it’s actually including the full address (the lo0 netmask in the above example is indeed 255.0.0.0).
Here’s another example, where the netmask is 255.255.255.0:
▿ sockaddr - sa_len : 7 - sa_family : 2 ▿ sa_data : 14 elements - .0 : 0 - .1 : 0 - .2 : 255 - .3 : 255 - .4 : 255 - .5 : 0 - .6 : 16 // Again, clearly the start of the next sockaddr_in. - .7 : 2 - .8 : 0 - .9 : 0 - .10 : 192 - .11 : 168 - .12 : 0 - .13 : 24
So you can see it’s:
- Only allocating up to the address of
sockaddr_in
, not counting the padding (sosizeof(sockaddr_in)
,MemoryLayout<sockaddr_in>.size
, etc disagree with whatgetifaddrs
is doing), and - Weirdly truncating the stated length (
sin_len
) to the end of the non-zero bytes in the netmask.
This is undocumented (well, all these data structures are completely undocumented 😔) and is all very messy. getifaddrs
should just provide the full sockaddr_in
without any of this weirdness, so that users which blindly cast to sockaddr_in
(without checking sin_len
) don’t risk segmentation faults or reading corrupt data.
I have no idea why it does this only for ifa_netmask
, not ifa_addr
or ifa_dstaddr
. That discrepancy just makes it even more troublesome.
As far as I can tell there are no similar issues with AF_INET6
netmasks, although without knowing under what criteria it’s truncating, I can’t be sure I have all relevant examples covered on the happenstance networks of my laptop.
For these systems, there’s seemingly not much you can do… it seems you have to hard-code the assumption that ifa_netmask
contains exactly & only the first eight bytes of the sockaddr_in
. You have to completely ignore sin_len
(at least if it’s less than eight).