From 202c4c9067b5855295895eed8c06fcb64c54e260 Mon Sep 17 00:00:00 2001 From: Adam Scott Date: Thu, 24 Apr 2025 22:46:52 -0400 Subject: [PATCH] Fix `sendmsg()` implementation --- src/lib/libsockfs.js | 2 +- .../test_sockets_sendmsg_to_invalid_dest.c | 68 +++++++++++++++++++ test/test_sockets.py | 4 ++ 3 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 test/sockets/test_sockets_sendmsg_to_invalid_dest.c diff --git a/src/lib/libsockfs.js b/src/lib/libsockfs.js index 786606c3c39bc..203088fbaa489 100644 --- a/src/lib/libsockfs.js +++ b/src/lib/libsockfs.js @@ -632,7 +632,7 @@ addToLibrary({ // connect, and lie, saying the data was sent now. if (!dest || dest.socket.readyState !== dest.socket.OPEN) { // if we're not connected, open a new connection - if (sock.type === {{{ cDefs.SOCK_DGRAM }}}) { + if (!dest || sock.type === {{{ cDefs.SOCK_DGRAM }}}) { if (!dest || dest.socket.readyState === dest.socket.CLOSING || dest.socket.readyState === dest.socket.CLOSED) { dest = SOCKFS.websocket_sock_ops.createPeer(sock, addr, port); } diff --git a/test/sockets/test_sockets_sendmsg_to_invalid_dest.c b/test/sockets/test_sockets_sendmsg_to_invalid_dest.c new file mode 100644 index 0000000000000..57120edfdb604 --- /dev/null +++ b/test/sockets/test_sockets_sendmsg_to_invalid_dest.c @@ -0,0 +1,68 @@ +// Copyright 2025 The Emscripten Authors. All rights reserved. +// Emscripten is available under two separate licenses, the MIT license and the +// University of Illinois/NCSA Open Source License. Both these licenses can be +// found in the LICENSE file. + +#include +#include +#include +#include +#include +#include +#include +#include + +int sock; + +bool wait_for_recv(double d, void* u) { + // Poll read from the socket to see what we have received + char buf[1024] = {}; + recv(sock, buf, sizeof(buf) - 1, 0); + if (strlen(buf) > 0) { + printf("%s\n", buf); + if (!strcmp(buf, "Hello")) { + printf("Got hello, test finished.\n"); +#ifdef REPORT_RESULT + REPORT_RESULT(0); +#endif + } + } + return EM_TRUE; +} + +int main() { + // Connect socket to a WebSocket echo server + struct sockaddr_in addr = {.sin_family = AF_INET, .sin_port = htons(8089)}; + inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr); + sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + if (sock < 0) { + printf("socket() failed to error %d\n", sock); + return sock; + } + + // Connect to echo server. + int error = connect(sock, (struct sockaddr*)&addr, sizeof(addr)); + if (error) { + printf("connect() failed to error %d\n", error); + return error; + } + + // Immediately send a message back-to-back from connecting to the socket + const char* msg = "Hello"; + ssize_t bytes = send(sock, msg, strlen(msg), 0); + if (bytes != strlen(msg)) { + printf("send() failed to send %d bytes. Return value: %d\n", + (int)strlen(msg), + (int)bytes); + return bytes; + } + + // This shouldn't throw an exception in `sendmsg` implementation. + // [see GH-23046] + struct ifaddrs* ifaddrs = NULL; + getifaddrs(&ifaddrs); + + // Asynchronously wait until we get the message echoed back + emscripten_set_timeout_loop(wait_for_recv, 0, 0); + return 0; +} diff --git a/test/test_sockets.py b/test/test_sockets.py index 9f21a4f870463..e23e6094b2379 100644 --- a/test/test_sockets.py +++ b/test/test_sockets.py @@ -359,6 +359,10 @@ def test_sockets_send_while_connecting(self): with NodeJsWebSocketEchoServerProcess(): self.btest('sockets/test_sockets_send_while_connecting.c', emcc_args=['-DSOCKET_DEBUG'], expected='0') + def test_sockets_sendmsg_to_invalid_dest(self): + with NodeJsWebSocketEchoServerProcess(): + self.btest('sockets/test_sockets_sendmsg_to_invalid_dest.c', emcc_args=['-DSOCKET_DEBUG', '-lsockfs.js'], expected='0') + class sockets64(sockets): def setUp(self):