Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package weechat for openSUSE:Factory checked in at 2026-06-09 14:22:41 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/weechat (Old) and /work/SRC/openSUSE:Factory/.weechat.new.2375 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "weechat" Tue Jun 9 14:22:41 2026 rev:94 rq:1358018 version:4.9.2 Changes: -------- --- /work/SRC/openSUSE:Factory/weechat/weechat.changes 2026-06-01 18:09:14.935351525 +0200 +++ /work/SRC/openSUSE:Factory/.weechat.new.2375/weechat.changes 2026-06-09 14:26:51.232814132 +0200 @@ -1,0 +2,21 @@ +Mon Jun 8 14:32:55 UTC 2026 - Hunter Wardlaw <[email protected]> + +- Update to 4.9.2: + * api: fix infinite loop in function string_replace when the search + string is empty + * irc: limit size of data received from the server to prevent + memory exhaustion + * irc: fix out-of-bounds read on incoming DCC command with a quoted + filename ending the message (#2322) + * relay: limit size of received websocket frame and HTTP body to + prevent memory exhaustion + * relay: limit size of partial message received while reading an + HTTP request to prevent memory exhaustion + * relay: fix out-of-bounds read in dump of data (#2324) + * xfer: replace directory separator in remote nick by underscore in + download filename to prevent writing the file outside the download + directory (#2321) + * xfer: fix out-of-bounds read when receiving empty line in DCC + chat (#2323) + +------------------------------------------------------------------- Old: ---- weechat-4.9.1.tar.xz weechat-4.9.1.tar.xz.asc New: ---- weechat-4.9.2.tar.xz weechat-4.9.2.tar.xz.asc ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ weechat.spec ++++++ --- /var/tmp/diff_new_pack.m1ZLRk/_old 2026-06-09 14:26:52.396862247 +0200 +++ /var/tmp/diff_new_pack.m1ZLRk/_new 2026-06-09 14:26:52.396862247 +0200 @@ -17,7 +17,7 @@ Name: weechat -Version: 4.9.1 +Version: 4.9.2 Release: 0 Summary: Multi-protocol extensible Chat Client License: GPL-3.0-or-later ++++++ weechat-4.9.1.tar.xz -> weechat-4.9.2.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weechat-4.9.1/CHANGELOG.md new/weechat-4.9.2/CHANGELOG.md --- old/weechat-4.9.1/CHANGELOG.md 2026-05-31 13:46:04.000000000 +0200 +++ new/weechat-4.9.2/CHANGELOG.md 2026-06-07 09:25:09.000000000 +0200 @@ -6,6 +6,19 @@ # WeeChat ChangeLog +## Version 4.9.2 (2026-06-07) + +### Fixed + +- api: fix infinite loop in function string_replace when the search string is empty +- irc: limit size of data received from the server to prevent memory exhaustion +- irc: fix out-of-bounds read on incoming DCC command with a quoted filename ending the message ([#2322](https://github.com/weechat/weechat/issues/2322)) +- relay: limit size of received websocket frame and HTTP body to prevent memory exhaustion +- relay: limit size of partial message received while reading an HTTP request to prevent memory exhaustion +- relay: fix out-of-bounds read in dump of data ([#2324](https://github.com/weechat/weechat/issues/2324)) +- xfer: replace directory separator in remote nick by underscore in download filename to prevent writing the file outside the download directory ([#2321](https://github.com/weechat/weechat/issues/2321)) +- xfer: fix out-of-bounds read when receiving empty line in DCC chat ([#2323](https://github.com/weechat/weechat/issues/2323)) + ## Version 4.9.1 (2026-05-31) ### Fixed diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weechat-4.9.1/src/core/core-string.c new/weechat-4.9.2/src/core/core-string.c --- old/weechat-4.9.1/src/core/core-string.c 2026-05-31 13:46:04.000000000 +0200 +++ new/weechat-4.9.2/src/core/core-string.c 2026-06-07 09:25:09.000000000 +0200 @@ -1965,6 +1965,9 @@ if (!string || !search || !replace) return NULL; + if (!search[0]) + return strdup (string); + length1 = strlen (search); length2 = strlen (replace); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weechat-4.9.1/src/plugins/irc/irc-ctcp.c new/weechat-4.9.2/src/plugins/irc/irc-ctcp.c --- old/weechat-4.9.1/src/plugins/irc/irc-ctcp.c 2026-05-31 13:46:04.000000000 +0200 +++ new/weechat-4.9.2/src/plugins/irc/irc-ctcp.c 2026-06-07 09:25:09.000000000 +0200 @@ -857,7 +857,7 @@ * double-quote */ pos = strrchr (pos_file, '"'); - if (!pos || (pos == pos_file)) + if (!pos || (pos == pos_file) || !pos[1]) { weechat_printf ( ctxt->server->buffer, @@ -1032,7 +1032,7 @@ * double-quote */ pos = strrchr (pos_file, '"'); - if (!pos || (pos == pos_file)) + if (!pos || (pos == pos_file) || !pos[1]) { weechat_printf ( ctxt->server->buffer, @@ -1176,7 +1176,7 @@ * double-quote */ pos = strrchr (pos_file, '"'); - if (!pos || (pos == pos_file)) + if (!pos || (pos == pos_file) || !pos[1]) { weechat_printf ( ctxt->server->buffer, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weechat-4.9.1/src/plugins/irc/irc-protocol.c new/weechat-4.9.2/src/plugins/irc/irc-protocol.c --- old/weechat-4.9.1/src/plugins/irc/irc-protocol.c 2026-05-31 13:46:04.000000000 +0200 +++ new/weechat-4.9.2/src/plugins/irc/irc-protocol.c 2026-06-07 09:25:09.000000000 +0200 @@ -4164,16 +4164,25 @@ if (ctxt->server->isupport) { length_isupport = strlen (ctxt->server->isupport); - isupport2 = realloc (ctxt->server->isupport, - length_isupport + /* existing */ - 1 + /* space */ - length + /* new */ - 1); - if (isupport2) + /* + * limit the size of the accumulated ISUPPORT data: once the + * maximum is reached, ignore the extra data (protection against a + * server flooding "005" messages, which would consume all the + * memory) + */ + if (length_isupport + 1 + length < IRC_SERVER_ISUPPORT_MAX_LENGTH) { - ctxt->server->isupport = isupport2; - strcat (ctxt->server->isupport, " "); - strcat (ctxt->server->isupport, str_info); + isupport2 = realloc (ctxt->server->isupport, + length_isupport + /* existing */ + 1 + /* space */ + length + /* new */ + 1); + if (isupport2) + { + ctxt->server->isupport = isupport2; + strcat (ctxt->server->isupport, " "); + strcat (ctxt->server->isupport, str_info); + } } } else diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weechat-4.9.1/src/plugins/irc/irc-server.c new/weechat-4.9.2/src/plugins/irc/irc-server.c --- old/weechat-4.9.1/src/plugins/irc/irc-server.c 2026-05-31 13:46:04.000000000 +0200 +++ new/weechat-4.9.2/src/plugins/irc/irc-server.c 2026-06-07 09:25:09.000000000 +0200 @@ -3409,6 +3409,14 @@ if (server->unterminated_message) { + /* + * limit the size of the unterminated message: once the maximum is + * reached, ignore the extra data (protection against a server sending + * a very long line without end-of-line, which would consume all the + * memory) + */ + if (strlen (server->unterminated_message) >= IRC_SERVER_RECV_MSG_MAX_LENGTH) + return; unterminated_message2 = realloc (server->unterminated_message, (strlen (server->unterminated_message) + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weechat-4.9.1/src/plugins/irc/irc-server.h new/weechat-4.9.2/src/plugins/irc/irc-server.h --- old/weechat-4.9.1/src/plugins/irc/irc-server.h 2026-05-31 13:46:04.000000000 +0200 +++ new/weechat-4.9.2/src/plugins/irc/irc-server.h 2026-06-07 09:25:09.000000000 +0200 @@ -144,6 +144,15 @@ #define IRC_SERVER_MULTILINE_DEFAULT_MAX_BYTES 4096 #define IRC_SERVER_MULTILINE_DEFAULT_MAX_LINES 24 +/* + * maximum length of an unterminated message (a received line without + * end-of-line) and of the accumulated "005" (ISUPPORT) data; these limits + * protect against a server sending a huge amount of data without end-of-line + * (or a flood of "005" messages), which would consume all the memory + */ +#define IRC_SERVER_RECV_MSG_MAX_LENGTH (64 * 1024) +#define IRC_SERVER_ISUPPORT_MAX_LENGTH (64 * 1024) + /* casemapping (string comparisons for nicks/channels) */ enum t_irc_server_casemapping { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weechat-4.9.1/src/plugins/relay/relay-http.c new/weechat-4.9.2/src/plugins/relay/relay-http.c --- old/weechat-4.9.1/src/plugins/relay/relay-http.c 2026-05-31 13:46:04.000000000 +0200 +++ new/weechat-4.9.2/src/plugins/relay/relay-http.c 2026-06-07 09:25:09.000000000 +0200 @@ -513,6 +513,19 @@ if (!partial_message || !*partial_message) return; + /* + * reject the body if its announced length is too big: this prevents a + * client from forcing an unbounded allocation by announcing a huge + * "Content-Length" + */ + if (request->content_length > RELAY_HTTP_BODY_MAX_LENGTH) + { + free (*partial_message); + *partial_message = NULL; + request->status = RELAY_HTTP_END; + return; + } + num_bytes_missing = request->content_length - request->body_size; if (num_bytes_missing <= 0) @@ -993,6 +1006,14 @@ if (client->partial_message) { + /* + * limit the size of the partial message: once the maximum is reached, + * ignore the extra data (protection against a client sending a huge + * amount of data without any end-of-line and dribbling it, which would + * consume all the memory) + */ + if (strlen (client->partial_message) >= RELAY_HTTP_PARTIAL_MESSAGE_MAX_LENGTH) + return; new_partial = realloc (client->partial_message, strlen (client->partial_message) + strlen (data) + 1); @@ -1695,7 +1716,7 @@ weechat_log_printf (" path_items. . . . . . . : %p", request->path_items); if (request->path_items) { - for (i = 0; request->path_items[0]; i++) + for (i = 0; request->path_items[i]; i++) { weechat_log_printf (" '%s'", request->path_items[i]); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weechat-4.9.1/src/plugins/relay/relay-http.h new/weechat-4.9.2/src/plugins/relay/relay-http.h --- old/weechat-4.9.1/src/plugins/relay/relay-http.h 2026-05-31 13:46:04.000000000 +0200 +++ new/weechat-4.9.2/src/plugins/relay/relay-http.h 2026-06-07 09:25:09.000000000 +0200 @@ -57,6 +57,22 @@ #define RELAY_HTTP_ERROR_METHOD_NOT_ALLOWED "Method Not Allowed" #define RELAY_HTTP_ERROR_OUT_OF_MEMORY "Out of memory" +/* + * maximum length of an HTTP request body: used as an upper bound on the + * "Content-Length" accepted from a client, to prevent a client from forcing + * an unbounded allocation by announcing a huge body + */ +#define RELAY_HTTP_BODY_MAX_LENGTH (8 * 1024 * 1024) + +/* + * maximum length of the partial message accumulated while reading an HTTP + * request: once this limit is reached, the extra data is ignored; this + * protects against a client sending a huge amount of data without any + * end-of-line (an unterminated method or header line), which would consume + * all the memory + */ +#define RELAY_HTTP_PARTIAL_MESSAGE_MAX_LENGTH (8 * 1024 * 1024) + struct t_relay_http_request { enum t_relay_client_http_status status; /* HTTP status */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weechat-4.9.1/src/plugins/relay/relay-websocket.c new/weechat-4.9.2/src/plugins/relay/relay-websocket.c --- old/weechat-4.9.1/src/plugins/relay/relay-websocket.c 2026-05-31 13:46:04.000000000 +0200 +++ new/weechat-4.9.2/src/plugins/relay/relay-websocket.c 2026-06-07 09:25:09.000000000 +0200 @@ -703,6 +703,14 @@ index_buffer += length_frame_size; } + /* + * reject the frame if its announced length is too big: this prevents + * a client from forcing an unbounded allocation (and unbounded + * accumulation of partial frames) by announcing a huge frame + */ + if (length_frame > WEBSOCKET_FRAME_MAX_LENGTH) + return 0; + if (masked_frame) { /* read mask (4 bytes) */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weechat-4.9.1/src/plugins/relay/relay-websocket.h new/weechat-4.9.2/src/plugins/relay/relay-websocket.h --- old/weechat-4.9.1/src/plugins/relay/relay-websocket.h 2026-05-31 13:46:04.000000000 +0200 +++ new/weechat-4.9.2/src/plugins/relay/relay-websocket.h 2026-06-07 09:25:09.000000000 +0200 @@ -42,6 +42,14 @@ #define WEBSOCKET_SUB_PROTOCOL_API_WEECHAT "api.weechat" /* + * maximum length of a websocket frame received from a client (or a remote + * WeeChat): used as an upper bound on the announced frame payload length, to + * prevent a client from forcing an unbounded allocation by announcing a huge + * frame and dribbling its payload + */ +#define WEBSOCKET_FRAME_MAX_LENGTH (8 * 1024 * 1024) + +/* * maximum size of a decompressed websocket frame (with "permessage-deflate"): * used as an upper bound when inflating, to prevent a small compressed frame * from decompressing to an unbounded amount of data ("deflate bomb") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weechat-4.9.1/src/plugins/xfer/xfer-chat.c new/weechat-4.9.2/src/plugins/xfer/xfer-chat.c --- old/weechat-4.9.1/src/plugins/xfer/xfer-chat.c 2026-05-31 13:46:04.000000000 +0200 +++ new/weechat-4.9.2/src/plugins/xfer/xfer-chat.c 2026-06-07 09:25:09.000000000 +0200 @@ -162,7 +162,7 @@ { ctcp_action = 0; length = strlen (ptr_buf); - if (ptr_buf[length - 1] == '\r') + if ((length > 0) && (ptr_buf[length - 1] == '\r')) { ptr_buf[length - 1] = '\0'; length--; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weechat-4.9.1/src/plugins/xfer/xfer-file.c new/weechat-4.9.2/src/plugins/xfer/xfer-file.c --- old/weechat-4.9.1/src/plugins/xfer/xfer-file.c 2026-05-31 13:46:04.000000000 +0200 +++ new/weechat-4.9.2/src/plugins/xfer/xfer-file.c 2026-06-07 09:25:09.000000000 +0200 @@ -251,7 +251,7 @@ void xfer_file_find_filename (struct t_xfer *xfer) { - char *dir_separator, *path; + char *dir_separator, *path, *nick; struct t_hashtable *options; if (!XFER_IS_FILE(xfer->type)) @@ -287,12 +287,20 @@ { strcat (xfer->local_filename, dir_separator); } - free (dir_separator); if (weechat_config_boolean (xfer_config_file_use_nick_in_filename)) { - strcat (xfer->local_filename, xfer->remote_nick); + /* + * the remote nick comes from the server and can contain a directory + * separator: replace it so the nick cannot make the file be written + * outside the download directory + */ + nick = (dir_separator) ? + weechat_string_replace (xfer->remote_nick, dir_separator, "_") : NULL; + strcat (xfer->local_filename, (nick) ? nick : xfer->remote_nick); + free (nick); strcat (xfer->local_filename, "."); } + free (dir_separator); strcat (xfer->local_filename, xfer->filename); free (path); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weechat-4.9.1/tests/unit/core/test-core-string.cpp new/weechat-4.9.2/tests/unit/core/test-core-string.cpp --- old/weechat-4.9.1/tests/unit/core/test-core-string.cpp 2026-05-31 13:46:04.000000000 +0200 +++ new/weechat-4.9.2/tests/unit/core/test-core-string.cpp 2026-06-07 09:25:09.000000000 +0200 @@ -1454,6 +1454,8 @@ WEE_TEST_STR(NULL, string_replace ("string", NULL, "replace")); WEE_TEST_STR(NULL, string_replace (NULL, "search", "replace")); + WEE_TEST_STR("test abc def", string_replace("test abc def", "", "xxx")); + WEE_TEST_STR("test abc def", string_replace("test abc def", "xyz", "xxx")); WEE_TEST_STR("test xxx def", string_replace("test abc def", "abc", "xxx")); WEE_TEST_STR("xxx test xxx def xxx", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weechat-4.9.1/tests/unit/plugins/irc/test-irc-protocol.cpp new/weechat-4.9.2/tests/unit/plugins/irc/test-irc-protocol.cpp --- old/weechat-4.9.1/tests/unit/plugins/irc/test-irc-protocol.cpp 2026-05-31 13:46:04.000000000 +0200 +++ new/weechat-4.9.2/tests/unit/plugins/irc/test-irc-protocol.cpp 2026-06-07 09:25:09.000000000 +0200 @@ -305,7 +305,7 @@ void server_recv (const char *command) { - char str_command[4096]; + char str_command[8192]; record_start (); arraylist_clear (sent_messages); @@ -3867,6 +3867,44 @@ } /* + * Test functions: + * irc_protocol_cb_005 (accumulated ISUPPORT is bounded) + */ + +TEST(IrcProtocolWithServer, 005_limit) +{ + char str_msg[4096], str_value[3500]; + size_t length1, length2; + int i; + + SRV_INIT; + + memset (str_value, 'X', sizeof (str_value) - 1); + str_value[sizeof (str_value) - 1] = '\0'; + snprintf (str_msg, sizeof (str_msg), + ":server 005 alice TEST=%s :are supported", str_value); + + /* flood the server with "005" messages */ + for (i = 0; i < 100; i++) + { + server_recv (str_msg); + } + CHECK(ptr_server->isupport); + length1 = strlen (ptr_server->isupport); + + /* the accumulated ISUPPORT data must be bounded */ + CHECK(length1 <= IRC_SERVER_ISUPPORT_MAX_LENGTH + sizeof (str_value)); + + /* receiving more "005" messages must not grow it any further */ + for (i = 0; i < 100; i++) + { + server_recv (str_msg); + } + length2 = strlen (ptr_server->isupport); + LONGS_EQUAL(length1, length2); +} + +/* * Test functions: * irc_protocol_cb_005 (infos from server, multiple messages) */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weechat-4.9.1/tests/unit/plugins/irc/test-irc-server.cpp new/weechat-4.9.2/tests/unit/plugins/irc/test-irc-server.cpp --- old/weechat-4.9.1/tests/unit/plugins/irc/test-irc-server.cpp 2026-05-31 13:46:04.000000000 +0200 +++ new/weechat-4.9.2/tests/unit/plugins/irc/test-irc-server.cpp 2026-06-07 09:25:09.000000000 +0200 @@ -67,6 +67,49 @@ /* * Test functions: + * irc_server_msgq_add_unterminated (via irc_server_msgq_add_buffer) + * + * Check that data received without any end-of-line does not grow the + * unterminated message buffer without limit. + */ + +TEST(IrcServer, MsgqAddBufferLimit) +{ + struct t_irc_server *server; + char chunk[4097]; + int i; + size_t length1, length2; + + server = irc_server_alloc ("server_msgq"); + CHECK(server); + + memset (chunk, 'a', sizeof (chunk) - 1); + chunk[sizeof (chunk) - 1] = '\0'; + + /* feed a lot of data with no end-of-line */ + for (i = 0; i < 100; i++) + { + irc_server_msgq_add_buffer (server, chunk); + } + CHECK(server->unterminated_message); + length1 = strlen (server->unterminated_message); + + /* the buffer must be bounded (not ~400 KB) */ + CHECK(length1 <= IRC_SERVER_RECV_MSG_MAX_LENGTH + sizeof (chunk)); + + /* feeding more data must not grow the buffer any further */ + for (i = 0; i < 100; i++) + { + irc_server_msgq_add_buffer (server, chunk); + } + length2 = strlen (server->unterminated_message); + LONGS_EQUAL(length1, length2); + + irc_server_free (server); +} + +/* + * Test functions: * irc_server_search */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weechat-4.9.1/tests/unit/plugins/relay/test-relay-http.cpp new/weechat-4.9.2/tests/unit/plugins/relay/test-relay-http.cpp --- old/weechat-4.9.1/tests/unit/plugins/relay/test-relay-http.cpp 2026-05-31 13:46:04.000000000 +0200 +++ new/weechat-4.9.2/tests/unit/plugins/relay/test-relay-http.cpp 2026-06-07 09:25:09.000000000 +0200 @@ -41,6 +41,7 @@ #include "src/plugins/relay/relay-client.h" #include "src/plugins/relay/relay-config.h" #include "src/plugins/relay/relay-http.h" +#include "src/plugins/relay/relay-server.h" #include "src/plugins/relay/relay-websocket.h" #include "src/plugins/weechat-plugin.h" @@ -163,6 +164,35 @@ /* * Test functions: + * relay_http_add_to_body (body too large is rejected) + */ + +TEST(RelayHttp, AddToBodyLimit) +{ + struct t_relay_http_request *request; + char *partial; + + request = relay_http_request_alloc (); + CHECK(request); + + /* announce a body larger than the maximum allowed */ + request->status = RELAY_HTTP_BODY; + request->content_length = RELAY_HTTP_BODY_MAX_LENGTH + 1; + partial = strdup ("some body data"); + + relay_http_add_to_body (request, &partial); + + /* the body must be rejected: nothing allocated, request ended */ + POINTERS_EQUAL(NULL, request->body); + LONGS_EQUAL(0, request->body_size); + POINTERS_EQUAL(NULL, partial); + LONGS_EQUAL(RELAY_HTTP_END, request->status); + + relay_http_request_free (request); +} + +/* + * Test functions: * relay_http_url_decode */ @@ -993,6 +1023,69 @@ } /* + * Test functions: + * relay_http_recv (partial message accumulated is bounded) + * + * Check that data received without any end-of-line does not grow the partial + * message buffer without limit. + */ + +TEST(RelayHttp, RecvLimit) +{ + struct t_relay_server *server; + struct t_relay_client *client; + char *chunk; + int chunk_size, i; + size_t length1, length2; + + /* disable auto-open of relay buffer (it would pollute other tests) */ + config_file_option_set (relay_config_look_auto_open_buffer, "off", 1); + + server = relay_server_new ("weechat", RELAY_PROTOCOL_WEECHAT, NULL, + 9000, + NULL, /* path */ + 1, /* ipv4 */ + 0, /* ipv6 */ + 0, /* tls */ + 0); /* unix_socket */ + CHECK(server); + client = relay_client_new (-1, "test", server); + CHECK(client); + + chunk_size = 1024 * 1024; + chunk = (char *)malloc (chunk_size + 1); + CHECK(chunk); + memset (chunk, 'a', chunk_size); + chunk[chunk_size] = '\0'; + + /* feed more than the maximum, with no end-of-line (16 MB) */ + for (i = 0; i < 16; i++) + { + relay_http_recv (client, chunk, chunk_size); + } + CHECK(client->partial_message); + length1 = strlen (client->partial_message); + + /* the partial message must be bounded (not ~16 MB) */ + CHECK(length1 <= RELAY_HTTP_PARTIAL_MESSAGE_MAX_LENGTH + (size_t)chunk_size); + + /* feeding more data must not grow it any further */ + for (i = 0; i < 16; i++) + { + relay_http_recv (client, chunk, chunk_size); + } + length2 = strlen (client->partial_message); + LONGS_EQUAL(length1, length2); + + free (chunk); + relay_client_free (client); + relay_server_free (server); + + /* restore auto-open of relay buffer */ + config_file_option_reset (relay_config_look_auto_open_buffer, 1); +} + +/* * Test functions: * relay_http_compress */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weechat-4.9.1/tests/unit/plugins/relay/test-relay-websocket.cpp new/weechat-4.9.2/tests/unit/plugins/relay/test-relay-websocket.cpp --- old/weechat-4.9.1/tests/unit/plugins/relay/test-relay-websocket.cpp 2026-05-31 13:46:04.000000000 +0200 +++ new/weechat-4.9.2/tests/unit/plugins/relay/test-relay-websocket.cpp 2026-06-07 09:25:09.000000000 +0200 @@ -510,7 +510,44 @@ TEST(RelayWebsocket, DecodeFrame) { - /* TODO: write tests */ + struct t_relay_websocket_frame *frames; + char *partial_ws_frame; + int num_frames, partial_ws_frame_size; + /* small unmasked binary frame with payload "hello" */ + unsigned char frame_ok[7] = { 0x82, 0x05, 'h', 'e', 'l', 'l', 'o' }; + /* masked frame announcing a 1 GB payload (64-bit length field) */ + unsigned char frame_too_big[10] = { + 0x82, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + }; + + /* a valid small frame is decoded */ + frames = NULL; + num_frames = 0; + partial_ws_frame = NULL; + partial_ws_frame_size = 0; + LONGS_EQUAL(1, relay_websocket_decode_frame ( + frame_ok, sizeof (frame_ok), 0, NULL, + &frames, &num_frames, &partial_ws_frame, + &partial_ws_frame_size)); + LONGS_EQUAL(1, num_frames); + CHECK(frames); + LONGS_EQUAL(5, frames[0].payload_size); + MEMCMP_EQUAL("hello", frames[0].payload, 5); + free (frames[0].payload); + free (frames); + free (partial_ws_frame); + + /* a frame announcing an oversized payload is rejected (return 0) */ + frames = NULL; + num_frames = 0; + partial_ws_frame = NULL; + partial_ws_frame_size = 0; + LONGS_EQUAL(0, relay_websocket_decode_frame ( + frame_too_big, sizeof (frame_too_big), 1, NULL, + &frames, &num_frames, &partial_ws_frame, + &partial_ws_frame_size)); + free (frames); + free (partial_ws_frame); } /* diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weechat-4.9.1/tests/unit/plugins/xfer/test-xfer-file.cpp new/weechat-4.9.2/tests/unit/plugins/xfer/test-xfer-file.cpp --- old/weechat-4.9.1/tests/unit/plugins/xfer/test-xfer-file.cpp 2026-05-31 13:46:04.000000000 +0200 +++ new/weechat-4.9.2/tests/unit/plugins/xfer/test-xfer-file.cpp 2026-06-07 09:25:09.000000000 +0200 @@ -25,6 +25,11 @@ extern "C" { +#include <stdlib.h> +#include <string.h> +#include "src/core/core-config-file.h" +#include "src/plugins/xfer/xfer.h" +#include "src/plugins/xfer/xfer-config.h" #include "src/plugins/xfer/xfer-file.h" } @@ -33,6 +38,42 @@ }; /* + * Build a "file recv" xfer with the given remote nick (and a fixed filename), + * call xfer_file_find_filename and return a copy of the basename of the local + * filename (the part after the last directory separator). + * + * Note: result must be freed after use. + */ + +static char * +test_find_filename_basename (const char *remote_nick) +{ + struct t_xfer xfer; + char *pos, *result; + + memset (&xfer, 0, sizeof (xfer)); + xfer.type = XFER_TYPE_FILE_RECV_ACTIVE; + xfer.remote_nick = strdup (remote_nick); + xfer.filename = strdup ("test.txt"); + + xfer_file_find_filename (&xfer); + + result = NULL; + if (xfer.local_filename) + { + pos = strrchr (xfer.local_filename, DIR_SEPARATOR_CHAR); + result = strdup ((pos) ? pos + 1 : xfer.local_filename); + } + + free (xfer.remote_nick); + free (xfer.filename); + free (xfer.local_filename); + free (xfer.temp_local_filename); + + return result; +} + +/* * Test functions: * xfer_file_search_crc32 */ @@ -91,7 +132,30 @@ TEST(XferFile, FindFilename) { - /* TODO: write tests */ + char *basename; + + config_file_option_set (xfer_config_file_download_path, "/tmp/weechat_test_xfer", 1); + + /* remote nick without directory separator: used as-is */ + basename = test_find_filename_basename ("alice"); + STRCMP_EQUAL("alice.test.txt", basename); + free (basename); + + /* + * remote nick with a directory separator: the separator is replaced by + * "_" so the nick cannot make the file be written outside the download + * directory + */ + basename = test_find_filename_basename ("../foo"); + STRCMP_EQUAL(".._foo.test.txt", basename); + free (basename); + + /* all directory separators in the nick are replaced */ + basename = test_find_filename_basename ("a/b/c"); + STRCMP_EQUAL("a_b_c.test.txt", basename); + free (basename); + + config_file_option_unset (xfer_config_file_download_path); } /* diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weechat-4.9.1/version.sh new/weechat-4.9.2/version.sh --- old/weechat-4.9.1/version.sh 2026-05-31 13:46:04.000000000 +0200 +++ new/weechat-4.9.2/version.sh 2026-06-07 09:25:09.000000000 +0200 @@ -41,8 +41,8 @@ # devel-number the devel version as hex number ("0x04010000" for "4.1.0-dev") # -weechat_stable="4.9.1" -weechat_devel="4.9.1" +weechat_stable="4.9.2" +weechat_devel="4.9.2" stable_major=$(echo "${weechat_stable}" | cut -d"." -f1) stable_minor=$(echo "${weechat_stable}" | cut -d"." -f2)
