svn commit: r261454 - head/lib/libc/net

Bruce Evans brde at optusnet.com.au
Tue Feb 4 07:02:27 UTC 2014


On Tue, 4 Feb 2014, Eitan Adler wrote:

> Log:
>  libc/net: Fix some issues in inet6_opt_init() (from RFC 3542):
>
>  * The RFC says (in section 10.1) that only when extbuf is not NULL,
>  extlen shall be checked, so don't perform this check when NULL is
>  passed.
>
>  * socklen_t is unsigned, so checking extlen for less than zero is
>  not needed.

Why be so unportable?  socklen_t is not necessarily unsigned.  It
should be signed, and was signed int in BSD, but was broken during
development of POSIX.1-2001.  FreeBSD apparently tracked the buggy
development version and changed from int to u_int32_t in 1999.

>From POSIX.1-2001-draft7:

12409               The <sys/socket.h> header shall define the type socklen_t, which is an integer type of width of
12410               at least 32 bits; see APPLICATION USAGE.

[APPLICATION USAGE "recommends" that values stored in socklen_t not be larger
than 2**31-1.  It doesn't spell out that this is because socklen_t might be
a signed type.  Note that "width" is a technical tyem for integer types, and
is satisfied by signed 32-bit ints although these have only 31 useful bits.]

7456 B.2.10.6 Socket Types
7457            The type socklen_t was invented to cover the range of implementations seen in the field. The
7458            intent of socklen_t is to be the type for all lengths that are naturally bounded in size; that is, that
7459            they are the length of a buffer which cannot sensibly become of massive size: network addresses,
7460            host names, string representations of these, ancillary data, control messages, and socket options

[2**31-1 is massive.  2**16-1 would just be a bit too small.]

7461            are examples. Truly boundless sizes are represented by size_t as in read( ), write( ), and so on.

[Nonsense.  2**31-1 is massive for read/write buffer sizes too, and size_t is
far from being able to represent truly boundless sizes.]

7462            All socklen_t types were originally (in BSD UNIX) of type int. During the development of
7463            IEEE Std 1003.1-200x, it was decided to change all buffer lengths to size_t, which appears at face
7464            value to make sense. When dual mode 32/64-bit systems came along, this choice unnecessarily
7465            complicated system interfaces because size_t (with long) was a different size under ILP32 and
7466            LP64 models. Reverting to int would have happened except that some implementations had
7467            already shipped 64-bit-only interfaces. The compromise was a type which could be defined to be
7468            any size by the implementation: socklen_t.

It was too late to fix the breakage for read/write.  It was not too
late to require plain int again for socklen_t.  POSIX.1 requires 32-bit
ints, so int for socklen_t was large enough.  Strangely, POSIX only
requires 16 bits for size_t and ssize_t.  This makes some sense since
it allows API's burdened by using typedefed types to use the best
machine-dependent type (portable applications have the burden of using
the typedefed types no matter what the implementation chooses).  OTOH,
if the API uses a basic type like int, then it has to be large enough
to work for all implementations, so int can't be 16 bits.

Bruce


More information about the svn-src-head mailing list