From 0bfc66f1082f5d47df99b6fc03f742ef7fa1051e Mon Sep 17 00:00:00 2001
From: Changqing Li <changqing.li@windriver.com>
Date: Thu, 5 Feb 2026 17:19:51 +0800
Subject: [PATCH] Set message size limit in SoupServer rather than 
 SoupWebsocketConnection

We're not sure about the compatibility implications of having a default
size limit for clients.

Also not sure whether the server limit is actually set appropriately,
but there is probably very little server usage of
SoupWebsocketConnection in the wild, so it's not so likely to break
things.

Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/libsoup/-/commit/2df34d9544cabdbfdedd3b36f098cf69233b1df7]
CVE: CVE-2025-32049

Signed-off-by: Changqing Li <changqing.li@windriver.com>
---
 libsoup/soup-server.c               | 24 +++++++++++++++++++-----
 libsoup/soup-websocket-connection.c | 23 ++++++++++++++++-------
 2 files changed, 35 insertions(+), 12 deletions(-)

diff --git a/libsoup/soup-server.c b/libsoup/soup-server.c
index 63875f3..a3f8597 100644
--- a/libsoup/soup-server.c
+++ b/libsoup/soup-server.c
@@ -216,6 +216,16 @@ enum {
 
 G_DEFINE_TYPE_WITH_PRIVATE (SoupServer, soup_server, G_TYPE_OBJECT)
 
+/* SoupWebsocketConnection by default limits only maximum packet size. But a
+ * message may consist of multiple packets, so SoupServer additionally restricts
+ * total message size to mitigate denial of service attacks on the server.
+ * SoupWebsocketConnection does not do this by default because I don't know
+ * whether that would or would not cause compatibility problems for websites.
+ *
+ * This size is in bytes and it is arbitrary.
+ */
+#define MAX_TOTAL_MESSAGE_SIZE_DEFAULT   128 * 1024
+
 static SoupClientContext *soup_client_context_ref (SoupClientContext *client);
 static void soup_client_context_unref (SoupClientContext *client);
 
@@ -1445,11 +1455,15 @@ complete_websocket_upgrade (SoupMessage *msg, gpointer user_data)
 
 	soup_client_context_ref (client);
 	stream = soup_client_context_steal_connection (client);
-	conn = soup_websocket_connection_new_with_extensions (stream, uri,
-							      SOUP_WEBSOCKET_CONNECTION_SERVER,
-							      soup_message_headers_get_one (msg->request_headers, "Origin"),
-							      soup_message_headers_get_one (msg->response_headers, "Sec-WebSocket-Protocol"),
-							      handler->websocket_extensions);
+	conn = SOUP_WEBSOCKET_CONNECTION (g_object_new (SOUP_TYPE_WEBSOCKET_CONNECTION,
+						          "io-stream", stream,
+						          "uri", uri,
+						          "connection-type", SOUP_WEBSOCKET_CONNECTION_SERVER,
+						          "origin", soup_message_headers_get_one (msg->request_headers, "Origin"),
+						          "protocol", soup_message_headers_get_one (msg->response_headers, "Sec-WebSocket-Protocol"),
+						          "extensions", handler->websocket_extensions,
+						          "max-total-message-size", (guint64)MAX_TOTAL_MESSAGE_SIZE_DEFAULT,
+                                 NULL));
 	handler->websocket_extensions = NULL;
 	g_object_unref (stream);
 	soup_client_context_unref (client);
diff --git a/libsoup/soup-websocket-connection.c b/libsoup/soup-websocket-connection.c
index 3dad477..e7fa9b7 100644
--- a/libsoup/soup-websocket-connection.c
+++ b/libsoup/soup-websocket-connection.c
@@ -154,7 +154,6 @@ struct _SoupWebsocketConnectionPrivate {
 };
 
 #define MAX_INCOMING_PAYLOAD_SIZE_DEFAULT   128 * 1024
-#define MAX_TOTAL_MESSAGE_SIZE_DEFAULT   128 * 1024
 #define READ_BUFFER_SIZE 1024
 #define MASK_LENGTH 4
 
@@ -1615,8 +1614,9 @@ soup_websocket_connection_class_init (SoupWebsocketConnectionClass *klass)
 	/**
 	 * SoupWebsocketConnection:max-incoming-payload-size:
 	 *
-	 * The maximum payload size for incoming packets the protocol expects
-	 * or 0 to not limit it.
+	 * The maximum payload size for incoming packets, or 0 to not limit it.
+	 * Each message may consist of multiple packets, so also refer to
+	 * [property@WebSocketConnection:max-total-message-size].
 	 *
 	 * Since: 2.56
 	 */
@@ -1668,9 +1668,18 @@ soup_websocket_connection_class_init (SoupWebsocketConnectionClass *klass)
 	/**
 	 * SoupWebsocketConnection:max-total-message-size:
 	 *
-	 * The total message size for incoming packets.
+	 * The maximum size for incoming messages.
+	 * Set to a value to limit the total message size, or 0 to not
+	 * limit it.
 	 *
-	 * The protocol expects or 0 to not limit it.
+	 * [method@Server.add_websocket_handler] will set this to a nonzero
+	 * default value to mitigate denial of service attacks. Clients must
+	 * choose their own default if they need to mitigate denial of service
+	 * attacks. You also need to set your own default if creating your own
+	 * server SoupWebsocketConnection without using SoupServer.
+	 *
+	 * Each message may consist of multiple packets, so also refer to
+	 *[property@WebSocketConnection:max-incoming-payload-size].
 	 *
 	 */
 	g_object_class_install_property (gobject_class, PROP_MAX_TOTAL_MESSAGE_SIZE,
@@ -1679,7 +1688,7 @@ soup_websocket_connection_class_init (SoupWebsocketConnectionClass *klass)
 					                     "Max total message size ",
 					                     0,
 					                     G_MAXUINT64,
-					                     MAX_TOTAL_MESSAGE_SIZE_DEFAULT,
+					                     0,
 					                     G_PARAM_READWRITE |
 					                     G_PARAM_CONSTRUCT |
 					                     G_PARAM_STATIC_STRINGS));
@@ -2210,7 +2219,7 @@ soup_websocket_connection_get_max_total_message_size (SoupWebsocketConnection *s
 {
    SoupWebsocketConnectionPrivate *pv;
 
-   g_return_val_if_fail (SOUP_IS_WEBSOCKET_CONNECTION (self), MAX_TOTAL_MESSAGE_SIZE_DEFAULT);
+   g_return_val_if_fail (SOUP_IS_WEBSOCKET_CONNECTION (self), 0);
    pv = self->pv;
 
    return pv->max_total_message_size;
-- 
2.34.1

