diff options
| author | Thijs Schreijer <thijs@thijsschreijer.nl> | 2026-08-30 12:58:43 +0200 |
|---|---|---|
| committer | Thijs Schreijer <thijs@thijsschreijer.nl> | 2026-08-30 13:46:21 +0200 |
| commit | 75d638ac9cc613f39ec4513d3dc2e43a6f909da1 (patch) | |
| tree | e883e854605945a839f208d1ab36c2ae9d20cc1d /src | |
| parent | e21720da69f2a505bcd1405cc7e8b52d5649df55 (diff) | |
| download | luasocket-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.c | 12 | ||||
| -rw-r--r-- | src/wsocket.c | 8 |
2 files changed, 20 insertions, 0 deletions
| @@ -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. |
