aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorThijs Schreijer <thijs@thijsschreijer.nl>2026-08-30 12:58:43 +0200
committerThijs Schreijer <thijs@thijsschreijer.nl>2026-08-30 13:46:21 +0200
commit75d638ac9cc613f39ec4513d3dc2e43a6f909da1 (patch)
treee883e854605945a839f208d1ab36c2ae9d20cc1d /src
parente21720da69f2a505bcd1405cc7e8b52d5649df55 (diff)
downloadluasocket-75d638ac9cc613f39ec4513d3dc2e43a6f909da1.tar.gz
luasocket-75d638ac9cc613f39ec4513d3dc2e43a6f909da1.tar.bz2
luasocket-75d638ac9cc613f39ec4513d3dc2e43a6f909da1.zip
fix(udp): receive(0) tests and bad call to getnameinfo
Diffstat (limited to 'src')
-rw-r--r--src/udp.c12
-rw-r--r--src/wsocket.c8
2 files changed, 20 insertions, 0 deletions
diff --git a/src/udp.c b/src/udp.c
index 712ad50..a782699 100644
--- a/src/udp.c
+++ b/src/udp.c
@@ -277,6 +277,7 @@ static int meth_receivefrom(lua_State *L) {
277 lua_pushliteral(L, "out of memory"); 277 lua_pushliteral(L, "out of memory");
278 return 2; 278 return 2;
279 } 279 }
280 memset(&addr, 0, sizeof(addr));
280 err = socket_recvfrom(&udp->sock, dgram, wanted, &got, (SA *) &addr, 281 err = socket_recvfrom(&udp->sock, dgram, wanted, &got, (SA *) &addr,
281 &addr_len, tm); 282 &addr_len, tm);
282 /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */ 283 /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */
@@ -286,6 +287,17 @@ static int meth_receivefrom(lua_State *L) {
286 if (wanted > sizeof(buf)) free(dgram); 287 if (wanted > sizeof(buf)) free(dgram);
287 return 2; 288 return 2;
288 } 289 }
290 /* a zero-length request may be satisfied by some kernels (notably
291 * Darwin/BSD) without ever touching the sender's address -- only
292 * resolve it when the OS actually reported one, instead of feeding
293 * getnameinfo() a garbage/zeroed sockaddr. */
294 if (addr.ss_family != AF_INET && addr.ss_family != AF_INET6) {
295 lua_pushlstring(L, dgram, got);
296 lua_pushnil(L);
297 lua_pushnil(L);
298 if (wanted > sizeof(buf)) free(dgram);
299 return 3;
300 }
289 err = getnameinfo((struct sockaddr *)&addr, addr_len, addrstr, 301 err = getnameinfo((struct sockaddr *)&addr, addr_len, addrstr,
290 INET6_ADDRSTRLEN, portstr, 6, NI_NUMERICHOST | NI_NUMERICSERV); 302 INET6_ADDRSTRLEN, portstr, 6, NI_NUMERICHOST | NI_NUMERICSERV);
291 if (err) { 303 if (err) {
diff --git a/src/wsocket.c b/src/wsocket.c
index 86c6994..b2b668c 100644
--- a/src/wsocket.c
+++ b/src/wsocket.c
@@ -286,6 +286,14 @@ int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got,
286 } 286 }
287 if (taken == 0) return IO_CLOSED; 287 if (taken == 0) return IO_CLOSED;
288 err = WSAGetLastError(); 288 err = WSAGetLastError();
289 /* a zero-length request is trivially "too small" for any
290 * non-empty datagram; unlike POSIX, which truncates and succeeds
291 * silently, Windows reports this as WSAEMSGSIZE even though the
292 * datagram -- and its sender's address, already written to addr/
293 * len above -- was still consumed. Normalize it to match POSIX's
294 * silent-truncation instead of surfacing a platform-specific
295 * error for what is otherwise a successful, if empty, receive. */
296 if (count == 0 && err == WSAEMSGSIZE) return IO_DONE;
289 /* On UDP, a connreset simply means the previous send failed. 297 /* On UDP, a connreset simply means the previous send failed.
290 * So we try again. 298 * So we try again.
291 * On TCP, it means our socket is now useless, so the error passes. 299 * On TCP, it means our socket is now useless, so the error passes.