From 7197ad3c4006fc26a6438c9ec062c450dd2ea4a2 Mon Sep 17 00:00:00 2001 From: Emmanuel Fleury Date: Tue, 12 Jan 2021 00:11:20 +0100 Subject: [PATCH] Fix possible integer overflow of g_socket_send_message() The explanation of this bug has been mentioned in !1823, basically it fixes some possible integer overflow when message buffer size is more than G_MAXSSIZE. --- gio/gsocket.c | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/gio/gsocket.c b/gio/gsocket.c index 69fc72825..b86eaab60 100644 --- a/gio/gsocket.c +++ b/gio/gsocket.c @@ -4754,6 +4754,11 @@ input_message_from_msghdr (const struct msghdr *msg, * notified of a %G_IO_OUT condition. (On Windows in particular, this is * very common due to the way the underlying APIs work.) * + * Finally, it must be mentioned that the whole message buffer cannot + * exceed %G_MAXSSIZE, if the message can be more than this, then it + * is mandatory to use the g_socket_send_message_with_timeout() + * function. + * * On error -1 is returned and @error is set accordingly. * * Returns: Number of bytes written (which may be less than @size), or -1 @@ -4774,6 +4779,29 @@ g_socket_send_message (GSocket *socket, { GPollableReturn res; gsize bytes_written = 0; + gsize vectors_size = 0; + + for (gsize i = 0; i < num_vectors; i++) + { + /* No wrap-around for vectors_size */ + if (vectors_size > vectors_size + vectors[i].size) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, + _("Unable to send message: %s"), + _("Message too large")); + return -1; + } + + vectors_size += vectors[i].size; + } + /* Check if vectors buffers are too big for gssize */ + if (vectors_size > G_MAXSSIZE) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, + _("Unable to send message: %s"), + _("Message too large")); + return -1; + } res = g_socket_send_message_with_timeout (socket, address, vectors, num_vectors, @@ -4782,6 +4810,8 @@ g_socket_send_message (GSocket *socket, &bytes_written, cancellable, error); + g_assert (res != G_POLLABLE_RETURN_OK || bytes_written <= G_MAXSSIZE); + if (res == G_POLLABLE_RETURN_WOULD_BLOCK) { #ifndef G_OS_WIN32 @@ -4791,7 +4821,7 @@ g_socket_send_message (GSocket *socket, #endif } - return res == G_POLLABLE_RETURN_OK ? bytes_written : -1; + return res == G_POLLABLE_RETURN_OK ? (gssize) bytes_written : -1; } /**