Bug Description

A bug in sb-bsd-sockets:socket-receive was introduced sometime around september 2014. The new code assumes the return value of recvfrom is always the length of the received buffer, but recvfrom can also return -1 on error. This was detected by the older code, but this check no longer seems to be done. I just called socket-receive and got a buffer length of 4294967295 i.e. -1 cast as unsigned int, the buffer itself seemed to be filled with garbage from the heap (contents of malloc'ed buffer).

You can repeat by sending a UDP datagram to a local port not listening for UDP traffic then waiting for a reply with socket-receive. On windows this returns immediately with the above behaviour (I can't comment on other platforms).

I'm using sbcl 1.2.1 on Windows, but looking at the relevant code on github suggests the bug should be on all platforms.

I've done a little bit more investigating and It looks like the -1 check actually is getting performed. The cause of the bug is actually more simple: recvfrom returns a (32-bit) signed int, but the recvfrom ffi definition has a return type of ssize_t, I assume that's a 64bit int on x86_64 systems. This would cause the -1 error status to get marshalled into Lisp incorrectly.

Running this test on x86-64 on linux 3.19 (and other roughly similarly-aged kernels) hangs. portmapper is listening on port 111. Perhaps that's the source of the problem. In any event, this breaks the build for me. Is the right thing to choose a different port and hope we get lucky, automagically determine the right port to use, or, back this test out?

I don't know if this test would even succeed on Linux, does Linux signal an ECONNRESET in the same way Windows does? I used the codes above because I'm writing an NFS and was encountering this bug (that's why I used port 111).