1
0
mirror of https://github.com/weechat/weechat.git synced 2026-06-14 07:04:46 +02:00

Compare commits

..

18 Commits

Author SHA1 Message Date
aizu-m 12c4170fbf core: fix buffer overflow in function network_pass_socks5proxy (#2325)
bound the configured proxy username and password before they are copied into the fixed stack buffer in network_pass_socks5proxy, otherwise a login longer than the buffer (a long password or token) overruns it while building the SOCKS5 auth request.
2026-06-12 13:03:20 +02:00
Sébastien Helleu e9138c5d55 core: add CVE IDs in ChangeLog 2026-06-09 22:12:25 +02:00
Sébastien Helleu eb8c8641ea Version 4.9.3-dev 2026-06-07 09:28:03 +02:00
Sébastien Helleu bd6455d07f Version 4.9.2 2026-06-07 09:25:09 +02:00
Sébastien Helleu 8d3180fa78 tests: increase buffer size for injection of fake IRC message 2026-06-07 08:48:47 +02:00
aizu-m 519ab4e7bb relay: fix out-of-bounds read in relay_http_print_log_request (#2324) 2026-06-06 11:20:05 +02:00
Sébastien Helleu 3c36fd7412 relay: limit size of partial message received while reading an HTTP request to prevent memory exhaustion
A relay client could send data with no end-of-line (an unterminated method
or header line) and dribble its payload, making WeeChat accumulate it in the
partial message buffer that grew without limit, until all memory was
exhausted. This path is reachable before authentication during websocket
initialization with the "weechat" and "irc" protocols.

The accumulated partial message is now bounded by
RELAY_HTTP_PARTIAL_MESSAGE_MAX_LENGTH: once the limit is reached, the extra
data is ignored.
2026-06-06 09:38:55 +02:00
Sébastien Helleu b62c97dbe3 core: add links to issues in ChangeLog (#2321, #2322) 2026-06-06 07:25:19 +02:00
aizu-m f91f92b48f xfer: fix out-of-bounds read in xfer_chat_recv_cb on empty line (#2323) 2026-06-06 07:21:55 +02:00
aizu-m 30529057c8 irc: fix out-of-bounds read in DCC command with quoted filename 2026-06-04 23:20:59 +02:00
Sébastien Helleu a69f356182 tests: add tests on function xfer_file_find_filename 2026-06-04 23:20:26 +02:00
aizu-m 1438255a87 xfer: replace directory separator in remote nick by underscore in download filename 2026-06-04 23:20:08 +02:00
Sébastien Helleu d15ce789a0 api: fix infinite loop in function string_replace when the search string is empty 2026-06-03 21:17:32 +02:00
Sébastien Helleu 377b6da43d relay: limit size of received websocket frame and HTTP body to prevent memory exhaustion
A relay client could announce a huge websocket frame (or HTTP body via
"Content-Length") and dribble its payload, making WeeChat accumulate it
in a buffer that grew without limit, until all memory was exhausted. The
websocket frame path is reachable before authentication with the
"weechat" and "irc" protocols.

The announced websocket frame length and HTTP "Content-Length" are now
bounded by WEBSOCKET_FRAME_MAX_LENGTH and RELAY_HTTP_BODY_MAX_LENGTH: an
oversized websocket frame closes the connection, and an oversized body is
rejected.
2026-06-01 22:09:27 +02:00
Sébastien Helleu 8b1b06a407 irc: limit size of data received from the server to prevent memory exhaustion
A malicious or compromised IRC server could send data with no end-of-line
(or a flood of "005" messages), making WeeChat accumulate it in a buffer
that grew without limit, until all memory was exhausted.

The unterminated received message and the accumulated "005" (ISUPPORT)
data are now bounded by IRC_SERVER_RECV_MSG_MAX_LENGTH and
IRC_SERVER_ISUPPORT_MAX_LENGTH: extra data is ignored once the limit is
reached.
2026-06-01 22:08:39 +02:00
Sébastien Helleu c09c1bf2fc ci: enable ruby 3.3 module on Rocky Linux 9 2026-05-31 15:19:37 +02:00
Sébastien Helleu c83afb9a06 ci: install dnf-plugins-core on Rocky Linux 9 for dnf config-manager 2026-05-31 15:18:42 +02:00
Sébastien Helleu ed9535a43f Version 4.9.2-dev 2026-05-31 13:50:17 +02:00
21 changed files with 433 additions and 27 deletions
+3 -1
View File
@@ -280,8 +280,10 @@ jobs:
- name: Install dependencies
run: |
dnf install -y epel-release
dnf install -y epel-release dnf-plugins-core
dnf config-manager --set-enabled crb
# pin a working ruby stream (ruby:4.0 has broken module metadata on Rocky 9.8)
dnf module enable -y ruby:3.3
dnf install -y ${{ env.WEECHAT_DEPS_ROCKYLINUX }}
- name: Build and run tests
+22 -3
View File
@@ -6,15 +6,34 @@ SPDX-License-Identifier: GPL-3.0-or-later
# WeeChat ChangeLog
## Version 4.9.3 (under dev)
### Fixed
- core: fix buffer overflow in connection to SOCKS5 proxy ([#2325](https://github.com/weechat/weechat/issues/2325))
## 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
- core: fix option weechat.look.color_real_white not applied when color is "white" on 16+ colors terminals ([#1742](https://github.com/weechat/weechat/issues/1742))
- irc: fix tag in message with list of names when joining a channel
- relay: limit size of decompressed websocket frame with permessage-deflate to prevent memory exhaustion ([GHSA-v2v4-45wm-5cr3](https://github.com/weechat/weechat/security/advisories/GHSA-v2v4-45wm-5cr3))
- relay: fix timing attack on password authentication ([GHSA-vhv8-g2r9-cwcc](https://github.com/weechat/weechat/security/advisories/GHSA-vhv8-g2r9-cwcc))
- api, relay: fix timing attack on TOTP validation ([GHSA-vhv8-g2r9-cwcc](https://github.com/weechat/weechat/security/advisories/GHSA-vhv8-g2r9-cwcc))
- relay: limit size of decompressed websocket frame with permessage-deflate to prevent memory exhaustion ([GHSA-v2v4-45wm-5cr3](https://github.com/weechat/weechat/security/advisories/GHSA-v2v4-45wm-5cr3), [CVE-2026-53524](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2026-53524))
- relay: fix timing attack on password authentication ([GHSA-vhv8-g2r9-cwcc](https://github.com/weechat/weechat/security/advisories/GHSA-vhv8-g2r9-cwcc), [CVE-2026-53525](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2026-53525))
- api, relay: fix timing attack on TOTP validation ([GHSA-vhv8-g2r9-cwcc](https://github.com/weechat/weechat/security/advisories/GHSA-vhv8-g2r9-cwcc), [CVE-2026-53525](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2026-53525))
## Version 4.9.0 (2026-03-29)
+19 -1
View File
@@ -581,7 +581,13 @@ network_pass_socks5proxy (struct t_proxy *proxy, int sock, const char *address,
int port)
{
struct t_network_socks5 socks5;
unsigned char buffer[288];
/*
* buffer must be large enough for the username/password authentication
* request, which is the longest message sent/received here; according to
* RFC 1929 it is: version (1) + username length (1) + username (max 255)
* + password length (1) + password (max 255)
*/
unsigned char buffer[2 + 255 + 1 + 255];
int username_len, password_len, addr_len, addr_buffer_len;
unsigned char *addr_buffer;
char *username, *password;
@@ -630,6 +636,18 @@ network_pass_socks5proxy (struct t_proxy *proxy, int sock, const char *address,
username_len = strlen (username);
password_len = strlen (password);
/*
* username and password length are each stored on a single byte
* (RFC 1929), so they cannot exceed 255 bytes: reject longer values,
* otherwise the memcpy calls below would overflow the buffer
*/
if ((username_len > 255) || (password_len > 255))
{
free (username);
free (password);
return 0;
}
/* make username/password buffer */
buffer[0] = 1;
buffer[1] = (unsigned char) username_len;
+3
View File
@@ -1965,6 +1965,9 @@ string_replace (const char *string, const char *search, const char *replace)
if (!string || !search || !replace)
return NULL;
if (!search[0])
return strdup (string);
length1 = strlen (search);
length2 = strlen (replace);
+3 -3
View File
@@ -857,7 +857,7 @@ irc_ctcp_recv_dcc (struct t_irc_protocol_ctxt *ctxt, const char *arguments)
* 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 @@ irc_ctcp_recv_dcc (struct t_irc_protocol_ctxt *ctxt, const char *arguments)
* 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 @@ irc_ctcp_recv_dcc (struct t_irc_protocol_ctxt *ctxt, const char *arguments)
* double-quote
*/
pos = strrchr (pos_file, '"');
if (!pos || (pos == pos_file))
if (!pos || (pos == pos_file) || !pos[1])
{
weechat_printf (
ctxt->server->buffer,
+18 -9
View File
@@ -4164,16 +4164,25 @@ IRC_PROTOCOL_CALLBACK(005)
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
+8
View File
@@ -3409,6 +3409,14 @@ irc_server_msgq_add_unterminated (struct t_irc_server *server,
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) +
+9
View File
@@ -144,6 +144,15 @@ enum t_irc_server_option
#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
{
+22 -1
View File
@@ -513,6 +513,19 @@ relay_http_add_to_body (struct t_relay_http_request *request,
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 @@ relay_http_recv (struct t_relay_client *client, const char *data, int size)
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 @@ relay_http_print_log_request (struct t_relay_http_request *request)
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]);
}
+16
View File
@@ -57,6 +57,22 @@ enum t_relay_client_http_status
#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 */
+8
View File
@@ -703,6 +703,14 @@ relay_websocket_decode_frame (const unsigned char *buffer,
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) */
+8
View File
@@ -41,6 +41,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
+1 -1
View File
@@ -162,7 +162,7 @@ xfer_chat_recv_cb (const void *pointer, void *data, int fd)
{
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--;
+11 -3
View File
@@ -251,7 +251,7 @@ xfer_file_find_suffix (struct t_xfer *xfer)
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 @@ xfer_file_find_filename (struct t_xfer *xfer)
{
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);
+2
View File
@@ -1454,6 +1454,8 @@ TEST(CoreString, Replace)
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",
+39 -1
View File
@@ -305,7 +305,7 @@ TEST_GROUP(IrcProtocolWithServer)
void server_recv (const char *command)
{
char str_command[4096];
char str_command[8192];
record_start ();
arraylist_clear (sent_messages);
@@ -3866,6 +3866,44 @@ TEST(IrcProtocolWithServer, 005_full)
STRCMP_EQUAL(IRC_MSG_005 " " IRC_MSG_005, ptr_server->isupport);
}
/*
* 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)
@@ -65,6 +65,49 @@ TEST(IrcServer, Valid)
irc_server_free (server);
}
/*
* 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
@@ -41,6 +41,7 @@ extern "C"
#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"
@@ -161,6 +162,35 @@ TEST(RelayHttp, RequestAllocReinitFree)
relay_http_request_free (request);
}
/*
* 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
@@ -992,6 +1022,69 @@ TEST(RelayHttp, Recv)
/* TODO: write tests */
}
/*
* 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
@@ -510,7 +510,44 @@ TEST(RelayWebsocket, Inflate)
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);
}
/*
+65 -1
View File
@@ -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"
}
@@ -32,6 +37,42 @@ TEST_GROUP(XferFile)
{
};
/*
* 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, FindSuffix)
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);
}
/*
+2 -2
View File
@@ -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.3-dev"
stable_major=$(echo "${weechat_stable}" | cut -d"." -f1)
stable_minor=$(echo "${weechat_stable}" | cut -d"." -f2)