summaryrefslogtreecommitdiffstats
path: root/meta-oe/recipes-support/libsoup
diff options
context:
space:
mode:
Diffstat (limited to 'meta-oe/recipes-support/libsoup')
-rw-r--r--meta-oe/recipes-support/libsoup/libsoup-2.4/CVE-2025-14523.patch52
-rw-r--r--meta-oe/recipes-support/libsoup/libsoup-2.4/CVE-2025-32049-1.patch229
-rw-r--r--meta-oe/recipes-support/libsoup/libsoup-2.4/CVE-2025-32049-2.patch131
-rw-r--r--meta-oe/recipes-support/libsoup/libsoup-2.4/CVE-2026-1467.patch151
-rw-r--r--meta-oe/recipes-support/libsoup/libsoup-2.4/CVE-2026-1539.patch31
-rw-r--r--meta-oe/recipes-support/libsoup/libsoup-2.4/CVE-2026-1760.patch153
-rw-r--r--meta-oe/recipes-support/libsoup/libsoup-2.4/CVE-2026-1761.patch36
-rw-r--r--meta-oe/recipes-support/libsoup/libsoup-2.4/CVE-2026-1801.patch126
-rw-r--r--meta-oe/recipes-support/libsoup/libsoup-2.4/CVE-2026-2369.patch33
-rw-r--r--meta-oe/recipes-support/libsoup/libsoup-2.4/CVE-2026-2443.patch135
-rw-r--r--meta-oe/recipes-support/libsoup/libsoup-2.4_2.74.3.bb10
11 files changed, 1087 insertions, 0 deletions
diff --git a/meta-oe/recipes-support/libsoup/libsoup-2.4/CVE-2025-14523.patch b/meta-oe/recipes-support/libsoup/libsoup-2.4/CVE-2025-14523.patch
new file mode 100644
index 0000000000..7815dba55a
--- /dev/null
+++ b/meta-oe/recipes-support/libsoup/libsoup-2.4/CVE-2025-14523.patch
@@ -0,0 +1,52 @@
1From d6028a6e6a8417b7fb6c89f6c10fb94781435ee6 Mon Sep 17 00:00:00 2001
2From: Changqing Li <changqing.li@windriver.com>
3Date: Wed, 4 Feb 2026 15:08:50 +0800
4Subject: [PATCH] Reject duplicate Host headers (for libsoup 2)
5
6This is a simplified version of my patch for libsoup 3:
7
8!491
9
10Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/libsoup/-/commit/d3db5a6f8f03e1f0133754872877c92c0284c472]
11CVE: CVE-2025-14523
12
13This patch is a MR for branch 2-74, but not merged yet, maybe it will
14not be merged.
15
16Signed-off-by: Changqing Li <changqing.li@windriver.com>
17---
18 libsoup/soup-headers.c | 3 +++
19 libsoup/soup-message-headers.c | 3 +++
20 2 files changed, 6 insertions(+)
21
22diff --git a/libsoup/soup-headers.c b/libsoup/soup-headers.c
23index ea2f986..6cd3dad 100644
24--- a/libsoup/soup-headers.c
25+++ b/libsoup/soup-headers.c
26@@ -138,6 +138,9 @@ soup_headers_parse (const char *str, int len, SoupMessageHeaders *dest)
27 for (p = strchr (value, '\r'); p; p = strchr (p, '\r'))
28 *p = ' ';
29
30+ if (g_ascii_strcasecmp (name, "Host") == 0 && soup_message_headers_get_one (dest, "Host"))
31+ goto done;
32+
33 soup_message_headers_append (dest, name, value);
34 }
35 success = TRUE;
36diff --git a/libsoup/soup-message-headers.c b/libsoup/soup-message-headers.c
37index f612bff..bb20bbb 100644
38--- a/libsoup/soup-message-headers.c
39+++ b/libsoup/soup-message-headers.c
40@@ -220,6 +220,9 @@ soup_message_headers_append (SoupMessageHeaders *hdrs,
41 }
42 #endif
43
44+ if (g_ascii_strcasecmp (name, "Host") == 0 && soup_message_headers_get_one (hdrs, "Host"))
45+ return;
46+
47 header.name = intern_header_name (name, &setter);
48 header.value = g_strdup (value);
49 g_array_append_val (hdrs->array, header);
50--
512.34.1
52
diff --git a/meta-oe/recipes-support/libsoup/libsoup-2.4/CVE-2025-32049-1.patch b/meta-oe/recipes-support/libsoup/libsoup-2.4/CVE-2025-32049-1.patch
new file mode 100644
index 0000000000..64e87cb1ec
--- /dev/null
+++ b/meta-oe/recipes-support/libsoup/libsoup-2.4/CVE-2025-32049-1.patch
@@ -0,0 +1,229 @@
1From c574e659c41c18fad3973bbaa3b3ec75664b3137 Mon Sep 17 00:00:00 2001
2From: Changqing Li <changqing.li@windriver.com>
3Date: Thu, 5 Feb 2026 16:20:02 +0800
4Subject: [PATCH 1/2] websocket: add a way to restrict the total message size
5
6Otherwise a client could send small packages smaller than
7total-incoming-payload-size but still to break the server
8with a big allocation
9
10Fixes: #390
11
12Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/libsoup/-/commit/db87805ab565d67533dfed2cb409dbfd63c7fdce]
13CVE: CVE-2025-32049
14
15libsoup2 is not maintained, the patch is backported from libsoup3, and
16change accordingly
17
18Signed-off-by: Changqing Li <changqing.li@windriver.com>
19---
20 libsoup/soup-websocket-connection.c | 104 ++++++++++++++++++++++++++--
21 libsoup/soup-websocket-connection.h | 7 ++
22 2 files changed, 107 insertions(+), 4 deletions(-)
23
24diff --git a/libsoup/soup-websocket-connection.c b/libsoup/soup-websocket-connection.c
25index 9d5f4f8..3dad477 100644
26--- a/libsoup/soup-websocket-connection.c
27+++ b/libsoup/soup-websocket-connection.c
28@@ -85,7 +85,8 @@ enum {
29 PROP_STATE,
30 PROP_MAX_INCOMING_PAYLOAD_SIZE,
31 PROP_KEEPALIVE_INTERVAL,
32- PROP_EXTENSIONS
33+ PROP_EXTENSIONS,
34+ PROP_MAX_TOTAL_MESSAGE_SIZE,
35 };
36
37 enum {
38@@ -120,6 +121,7 @@ struct _SoupWebsocketConnectionPrivate {
39 char *origin;
40 char *protocol;
41 guint64 max_incoming_payload_size;
42+ guint64 max_total_message_size;
43 guint keepalive_interval;
44
45 gushort peer_close_code;
46@@ -152,6 +154,7 @@ struct _SoupWebsocketConnectionPrivate {
47 };
48
49 #define MAX_INCOMING_PAYLOAD_SIZE_DEFAULT 128 * 1024
50+#define MAX_TOTAL_MESSAGE_SIZE_DEFAULT 128 * 1024
51 #define READ_BUFFER_SIZE 1024
52 #define MASK_LENGTH 4
53
54@@ -664,7 +667,7 @@ bad_data_error_and_close (SoupWebsocketConnection *self)
55 }
56
57 static void
58-too_big_error_and_close (SoupWebsocketConnection *self,
59+too_big_incoming_payload_error_and_close (SoupWebsocketConnection *self,
60 guint64 payload_len)
61 {
62 GError *error;
63@@ -680,6 +683,23 @@ too_big_error_and_close (SoupWebsocketConnection *self,
64 emit_error_and_close (self, error, TRUE);
65 }
66
67+static void
68+too_big_message_error_and_close (SoupWebsocketConnection *self,
69+ guint64 len)
70+{
71+ GError *error;
72+
73+ error = g_error_new_literal (SOUP_WEBSOCKET_ERROR,
74+ SOUP_WEBSOCKET_CLOSE_TOO_BIG,
75+ self->pv->connection_type == SOUP_WEBSOCKET_CONNECTION_SERVER ?
76+ "Received WebSocket payload from the client larger than configured max-total-message-size" :
77+ "Received WebSocket payload from the server larger than configured max-total-message-size");
78+ g_debug ("%s received message of size %" G_GUINT64_FORMAT " or greater, but max supported size is %" G_GUINT64_FORMAT,
79+ self->pv->connection_type == SOUP_WEBSOCKET_CONNECTION_SERVER ? "server" : "client",
80+ len, self->pv->max_total_message_size);
81+ emit_error_and_close (self, error, TRUE);
82+}
83+
84 static void
85 close_connection (SoupWebsocketConnection *self,
86 gushort code,
87@@ -913,6 +933,12 @@ process_contents (SoupWebsocketConnection *self,
88 switch (pv->message_opcode) {
89 case 0x01:
90 case 0x02:
91+ /* Safety valve */
92+ if (pv->max_total_message_size > 0 &&
93+ (pv->message_data->len + payload_len) > pv->max_total_message_size) {
94+ too_big_message_error_and_close (self, (pv->message_data->len + payload_len));
95+ return;
96+ }
97 g_byte_array_append (pv->message_data, payload, payload_len);
98 break;
99 default:
100@@ -1050,7 +1076,7 @@ process_frame (SoupWebsocketConnection *self)
101 /* Safety valve */
102 if (self->pv->max_incoming_payload_size > 0 &&
103 payload_len >= self->pv->max_incoming_payload_size) {
104- too_big_error_and_close (self, payload_len);
105+ too_big_incoming_payload_error_and_close (self, payload_len);
106 return FALSE;
107 }
108
109@@ -1357,6 +1383,10 @@ soup_websocket_connection_get_property (GObject *object,
110 g_value_set_pointer (value, pv->extensions);
111 break;
112
113+ case PROP_MAX_TOTAL_MESSAGE_SIZE:
114+ g_value_set_uint64 (value, pv->max_total_message_size);
115+ break;
116+
117 default:
118 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
119 break;
120@@ -1410,6 +1440,10 @@ soup_websocket_connection_set_property (GObject *object,
121 pv->extensions = g_value_get_pointer (value);
122 break;
123
124+ case PROP_MAX_TOTAL_MESSAGE_SIZE:
125+ pv->max_total_message_size = g_value_get_uint64 (value);
126+ break;
127+
128 default:
129 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
130 break;
131@@ -1631,7 +1665,24 @@ soup_websocket_connection_class_init (SoupWebsocketConnectionClass *klass)
132 G_PARAM_READWRITE |
133 G_PARAM_CONSTRUCT_ONLY |
134 G_PARAM_STATIC_STRINGS));
135-
136+ /**
137+ * SoupWebsocketConnection:max-total-message-size:
138+ *
139+ * The total message size for incoming packets.
140+ *
141+ * The protocol expects or 0 to not limit it.
142+ *
143+ */
144+ g_object_class_install_property (gobject_class, PROP_MAX_TOTAL_MESSAGE_SIZE,
145+ g_param_spec_uint64 ("max-total-message-size",
146+ "Max total message size",
147+ "Max total message size ",
148+ 0,
149+ G_MAXUINT64,
150+ MAX_TOTAL_MESSAGE_SIZE_DEFAULT,
151+ G_PARAM_READWRITE |
152+ G_PARAM_CONSTRUCT |
153+ G_PARAM_STATIC_STRINGS));
154 /**
155 * SoupWebsocketConnection::message:
156 * @self: the WebSocket
157@@ -2145,6 +2196,51 @@ soup_websocket_connection_set_max_incoming_payload_size (SoupWebsocketConnection
158 }
159 }
160
161+/**
162+ * soup_websocket_connection_get_max_total_message_size:
163+ * @self: the WebSocket
164+ *
165+ * Gets the maximum total message size allowed for packets.
166+ *
167+ * Returns: the maximum total message size.
168+ *
169+ */
170+guint64
171+soup_websocket_connection_get_max_total_message_size (SoupWebsocketConnection *self)
172+{
173+ SoupWebsocketConnectionPrivate *pv;
174+
175+ g_return_val_if_fail (SOUP_IS_WEBSOCKET_CONNECTION (self), MAX_TOTAL_MESSAGE_SIZE_DEFAULT);
176+ pv = self->pv;
177+
178+ return pv->max_total_message_size;
179+}
180+
181+/**
182+ * soup_websocket_connection_set_max_total_message_size:
183+ * @self: the WebSocket
184+ * @max_total_message_size: the maximum total message size
185+ *
186+ * Sets the maximum total message size allowed for packets.
187+ *
188+ * It does not limit the outgoing packet size.
189+ *
190+ */
191+void
192+soup_websocket_connection_set_max_total_message_size (SoupWebsocketConnection *self,
193+ guint64 max_total_message_size)
194+{
195+ SoupWebsocketConnectionPrivate *pv;
196+
197+ g_return_if_fail (SOUP_IS_WEBSOCKET_CONNECTION (self));
198+ pv = self->pv;
199+
200+ if (pv->max_total_message_size != max_total_message_size) {
201+ pv->max_total_message_size = max_total_message_size;
202+ g_object_notify (G_OBJECT (self), "max-total-message-size");
203+ }
204+}
205+
206 /**
207 * soup_websocket_connection_get_keepalive_interval:
208 * @self: the WebSocket
209diff --git a/libsoup/soup-websocket-connection.h b/libsoup/soup-websocket-connection.h
210index f82d723..d2a60e9 100644
211--- a/libsoup/soup-websocket-connection.h
212+++ b/libsoup/soup-websocket-connection.h
213@@ -136,6 +136,13 @@ SOUP_AVAILABLE_IN_2_58
214 void soup_websocket_connection_set_keepalive_interval (SoupWebsocketConnection *self,
215 guint interval);
216
217+SOUP_AVAILABLE_IN_2_72
218+guint64 soup_websocket_connection_get_max_total_message_size (SoupWebsocketConnection *self);
219+
220+SOUP_AVAILABLE_IN_2_72
221+void soup_websocket_connection_set_max_total_message_size (SoupWebsocketConnection *self,
222+ guint64 max_total_message_size);
223+
224 G_END_DECLS
225
226 #endif /* __SOUP_WEBSOCKET_CONNECTION_H__ */
227--
2282.34.1
229
diff --git a/meta-oe/recipes-support/libsoup/libsoup-2.4/CVE-2025-32049-2.patch b/meta-oe/recipes-support/libsoup/libsoup-2.4/CVE-2025-32049-2.patch
new file mode 100644
index 0000000000..f9c894aaec
--- /dev/null
+++ b/meta-oe/recipes-support/libsoup/libsoup-2.4/CVE-2025-32049-2.patch
@@ -0,0 +1,131 @@
1From 0bfc66f1082f5d47df99b6fc03f742ef7fa1051e Mon Sep 17 00:00:00 2001
2From: Changqing Li <changqing.li@windriver.com>
3Date: Thu, 5 Feb 2026 17:19:51 +0800
4Subject: [PATCH] Set message size limit in SoupServer rather than
5 SoupWebsocketConnection
6
7We're not sure about the compatibility implications of having a default
8size limit for clients.
9
10Also not sure whether the server limit is actually set appropriately,
11but there is probably very little server usage of
12SoupWebsocketConnection in the wild, so it's not so likely to break
13things.
14
15Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/libsoup/-/commit/2df34d9544cabdbfdedd3b36f098cf69233b1df7]
16CVE: CVE-2025-32049
17
18Signed-off-by: Changqing Li <changqing.li@windriver.com>
19---
20 libsoup/soup-server.c | 24 +++++++++++++++++++-----
21 libsoup/soup-websocket-connection.c | 23 ++++++++++++++++-------
22 2 files changed, 35 insertions(+), 12 deletions(-)
23
24diff --git a/libsoup/soup-server.c b/libsoup/soup-server.c
25index 63875f3..a3f8597 100644
26--- a/libsoup/soup-server.c
27+++ b/libsoup/soup-server.c
28@@ -216,6 +216,16 @@ enum {
29
30 G_DEFINE_TYPE_WITH_PRIVATE (SoupServer, soup_server, G_TYPE_OBJECT)
31
32+/* SoupWebsocketConnection by default limits only maximum packet size. But a
33+ * message may consist of multiple packets, so SoupServer additionally restricts
34+ * total message size to mitigate denial of service attacks on the server.
35+ * SoupWebsocketConnection does not do this by default because I don't know
36+ * whether that would or would not cause compatibility problems for websites.
37+ *
38+ * This size is in bytes and it is arbitrary.
39+ */
40+#define MAX_TOTAL_MESSAGE_SIZE_DEFAULT 128 * 1024
41+
42 static SoupClientContext *soup_client_context_ref (SoupClientContext *client);
43 static void soup_client_context_unref (SoupClientContext *client);
44
45@@ -1445,11 +1455,15 @@ complete_websocket_upgrade (SoupMessage *msg, gpointer user_data)
46
47 soup_client_context_ref (client);
48 stream = soup_client_context_steal_connection (client);
49- conn = soup_websocket_connection_new_with_extensions (stream, uri,
50- SOUP_WEBSOCKET_CONNECTION_SERVER,
51- soup_message_headers_get_one (msg->request_headers, "Origin"),
52- soup_message_headers_get_one (msg->response_headers, "Sec-WebSocket-Protocol"),
53- handler->websocket_extensions);
54+ conn = SOUP_WEBSOCKET_CONNECTION (g_object_new (SOUP_TYPE_WEBSOCKET_CONNECTION,
55+ "io-stream", stream,
56+ "uri", uri,
57+ "connection-type", SOUP_WEBSOCKET_CONNECTION_SERVER,
58+ "origin", soup_message_headers_get_one (msg->request_headers, "Origin"),
59+ "protocol", soup_message_headers_get_one (msg->response_headers, "Sec-WebSocket-Protocol"),
60+ "extensions", handler->websocket_extensions,
61+ "max-total-message-size", (guint64)MAX_TOTAL_MESSAGE_SIZE_DEFAULT,
62+ NULL));
63 handler->websocket_extensions = NULL;
64 g_object_unref (stream);
65 soup_client_context_unref (client);
66diff --git a/libsoup/soup-websocket-connection.c b/libsoup/soup-websocket-connection.c
67index 3dad477..e7fa9b7 100644
68--- a/libsoup/soup-websocket-connection.c
69+++ b/libsoup/soup-websocket-connection.c
70@@ -154,7 +154,6 @@ struct _SoupWebsocketConnectionPrivate {
71 };
72
73 #define MAX_INCOMING_PAYLOAD_SIZE_DEFAULT 128 * 1024
74-#define MAX_TOTAL_MESSAGE_SIZE_DEFAULT 128 * 1024
75 #define READ_BUFFER_SIZE 1024
76 #define MASK_LENGTH 4
77
78@@ -1615,8 +1614,9 @@ soup_websocket_connection_class_init (SoupWebsocketConnectionClass *klass)
79 /**
80 * SoupWebsocketConnection:max-incoming-payload-size:
81 *
82- * The maximum payload size for incoming packets the protocol expects
83- * or 0 to not limit it.
84+ * The maximum payload size for incoming packets, or 0 to not limit it.
85+ * Each message may consist of multiple packets, so also refer to
86+ * [property@WebSocketConnection:max-total-message-size].
87 *
88 * Since: 2.56
89 */
90@@ -1668,9 +1668,18 @@ soup_websocket_connection_class_init (SoupWebsocketConnectionClass *klass)
91 /**
92 * SoupWebsocketConnection:max-total-message-size:
93 *
94- * The total message size for incoming packets.
95+ * The maximum size for incoming messages.
96+ * Set to a value to limit the total message size, or 0 to not
97+ * limit it.
98 *
99- * The protocol expects or 0 to not limit it.
100+ * [method@Server.add_websocket_handler] will set this to a nonzero
101+ * default value to mitigate denial of service attacks. Clients must
102+ * choose their own default if they need to mitigate denial of service
103+ * attacks. You also need to set your own default if creating your own
104+ * server SoupWebsocketConnection without using SoupServer.
105+ *
106+ * Each message may consist of multiple packets, so also refer to
107+ *[property@WebSocketConnection:max-incoming-payload-size].
108 *
109 */
110 g_object_class_install_property (gobject_class, PROP_MAX_TOTAL_MESSAGE_SIZE,
111@@ -1679,7 +1688,7 @@ soup_websocket_connection_class_init (SoupWebsocketConnectionClass *klass)
112 "Max total message size ",
113 0,
114 G_MAXUINT64,
115- MAX_TOTAL_MESSAGE_SIZE_DEFAULT,
116+ 0,
117 G_PARAM_READWRITE |
118 G_PARAM_CONSTRUCT |
119 G_PARAM_STATIC_STRINGS));
120@@ -2210,7 +2219,7 @@ soup_websocket_connection_get_max_total_message_size (SoupWebsocketConnection *s
121 {
122 SoupWebsocketConnectionPrivate *pv;
123
124- g_return_val_if_fail (SOUP_IS_WEBSOCKET_CONNECTION (self), MAX_TOTAL_MESSAGE_SIZE_DEFAULT);
125+ g_return_val_if_fail (SOUP_IS_WEBSOCKET_CONNECTION (self), 0);
126 pv = self->pv;
127
128 return pv->max_total_message_size;
129--
1302.34.1
131
diff --git a/meta-oe/recipes-support/libsoup/libsoup-2.4/CVE-2026-1467.patch b/meta-oe/recipes-support/libsoup/libsoup-2.4/CVE-2026-1467.patch
new file mode 100644
index 0000000000..a1a130ee3a
--- /dev/null
+++ b/meta-oe/recipes-support/libsoup/libsoup-2.4/CVE-2026-1467.patch
@@ -0,0 +1,151 @@
1From b4f1dcb89a552fc03bfd0e65830b4f76fdc4a232 Mon Sep 17 00:00:00 2001
2From: Changqing Li <changqing.li@windriver.com>
3Date: Tue, 21 Apr 2026 17:10:37 +0800
4Subject: [PATCH] Fix CVE-2026-1467
5
6CVE: CVE-2026-1467
7Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/libsoup/-/commit/6dfe506618d2d5856618e5c0f85bd93386dc8012]
8
9The original backport patch targets libsoup3. This patch has been
10adapted accordingly for libsoup2, refer the openSUSE patch, see [1]
11
12[1] https://www.suse.com/security/cve/CVE-2026-1467.html
13
14Signed-off-by: Changqing Li <changqing.li@windriver.com>
15---
16 libsoup/soup-auth.c | 2 +-
17 libsoup/soup-message.c | 5 +++-
18 libsoup/soup-uri.c | 60 ++++++++++++++++++++++++++++++++++++++++++
19 libsoup/soup-uri.h | 2 ++
20 4 files changed, 67 insertions(+), 2 deletions(-)
21
22diff --git a/libsoup/soup-auth.c b/libsoup/soup-auth.c
23index 1896aab..e205fe3 100644
24--- a/libsoup/soup-auth.c
25+++ b/libsoup/soup-auth.c
26@@ -535,7 +535,7 @@ GSList *
27 soup_auth_get_protection_space (SoupAuth *auth, SoupURI *source_uri)
28 {
29 g_return_val_if_fail (SOUP_IS_AUTH (auth), NULL);
30- g_return_val_if_fail (source_uri != NULL, NULL);
31+ g_return_val_if_fail (soup_uri_is_valid (source_uri), NULL);
32
33 return SOUP_AUTH_GET_CLASS (auth)->get_protection_space (auth, source_uri);
34 }
35diff --git a/libsoup/soup-message.c b/libsoup/soup-message.c
36index da32b42..cc4f22b 100644
37--- a/libsoup/soup-message.c
38+++ b/libsoup/soup-message.c
39@@ -1044,7 +1044,7 @@ soup_message_new (const char *method, const char *uri_string)
40 uri = soup_uri_new (uri_string);
41 if (!uri)
42 return NULL;
43- if (!uri->host) {
44+ if (!soup_uri_is_valid (uri)) {
45 soup_uri_free (uri);
46 return NULL;
47 }
48@@ -1066,6 +1066,8 @@ soup_message_new (const char *method, const char *uri_string)
49 SoupMessage *
50 soup_message_new_from_uri (const char *method, SoupURI *uri)
51 {
52+ g_return_val_if_fail (soup_uri_is_valid (uri), NULL);
53+
54 return g_object_new (SOUP_TYPE_MESSAGE,
55 SOUP_MESSAGE_METHOD, method,
56 SOUP_MESSAGE_URI, uri,
57@@ -1676,6 +1678,7 @@ soup_message_set_uri (SoupMessage *msg, SoupURI *uri)
58 SoupMessagePrivate *priv;
59
60 g_return_if_fail (SOUP_IS_MESSAGE (msg));
61+ g_return_if_fail (soup_uri_is_valid (uri));
62 priv = soup_message_get_instance_private (msg);
63
64 if (priv->uri)
65diff --git a/libsoup/soup-uri.c b/libsoup/soup-uri.c
66index bdb7a17..d781ff1 100644
67--- a/libsoup/soup-uri.c
68+++ b/libsoup/soup-uri.c
69@@ -1342,6 +1342,66 @@ soup_uri_host_equal (gconstpointer v1, gconstpointer v2)
70 return g_ascii_strcasecmp (one->host, two->host) == 0;
71 }
72
73+static gboolean
74+is_valid_character_for_host (char c)
75+{
76+ static const char forbidden_chars[] = { '\t', '\n', '\r', ' ', '#', '/', ':', '<', '>', '?', '@', '[', '\\', ']', '^', '|' };
77+ int i;
78+
79+ for (i = 0; i < G_N_ELEMENTS (forbidden_chars); ++i) {
80+ if (c == forbidden_chars[i])
81+ return FALSE;
82+ }
83+
84+ return TRUE;
85+}
86+
87+static gboolean
88+is_host_valid (const char* host)
89+{
90+ int i;
91+ gboolean is_valid;
92+ char *ascii_host = NULL;
93+
94+ if (!host || !host[0])
95+ return FALSE;
96+
97+ if (g_hostname_is_non_ascii (host)) {
98+ ascii_host = g_hostname_to_ascii (host);
99+ if (!ascii_host)
100+ return FALSE;
101+
102+ host = ascii_host;
103+ }
104+
105+ if ((g_ascii_isdigit (host[0]) || strchr (host, ':')) && g_hostname_is_ip_address (host)) {
106+ g_free (ascii_host);
107+ return TRUE;
108+ }
109+ is_valid = TRUE;
110+ for (i = 0; host[i] && is_valid; i++)
111+ is_valid = is_valid_character_for_host (host[i]);
112+
113+ g_free (ascii_host);
114+
115+ return is_valid;
116+}
117+
118+gboolean
119+soup_uri_is_valid (SoupURI *uri)
120+{
121+ if (!uri)
122+ return FALSE;
123+
124+ if (!is_host_valid (soup_uri_get_host (uri)))
125+ return FALSE;
126+
127+ /* FIXME: validate other URI components? */
128+
129+ return TRUE;
130+}
131+
132+
133 gboolean
134 soup_uri_is_http (SoupURI *uri, char **aliases)
135 {
136diff --git a/libsoup/soup-uri.h b/libsoup/soup-uri.h
137index 8015e4f..64099c3 100644
138--- a/libsoup/soup-uri.h
139+++ b/libsoup/soup-uri.h
140@@ -133,6 +133,8 @@ guint soup_uri_host_hash (gconstpointer key);
141 SOUP_AVAILABLE_IN_2_28
142 gboolean soup_uri_host_equal (gconstpointer v1,
143 gconstpointer v2);
144+SOUP_AVAILABLE_IN_2_68
145+gboolean soup_uri_is_valid (SoupURI *uri);
146
147 #define SOUP_URI_IS_VALID(uri) ((uri) && (uri)->scheme && (uri)->path)
148 #define SOUP_URI_VALID_FOR_HTTP(uri) ((uri) && ((uri)->scheme == SOUP_URI_SCHEME_HTTP || (uri)->scheme == SOUP_URI_SCHEME_HTTPS) && (uri)->host && (uri)->path)
149--
1502.34.1
151
diff --git a/meta-oe/recipes-support/libsoup/libsoup-2.4/CVE-2026-1539.patch b/meta-oe/recipes-support/libsoup/libsoup-2.4/CVE-2026-1539.patch
new file mode 100644
index 0000000000..c6b813a98f
--- /dev/null
+++ b/meta-oe/recipes-support/libsoup/libsoup-2.4/CVE-2026-1539.patch
@@ -0,0 +1,31 @@
1From 285faea567e1e2a95226201175dbf745a64a2439 Mon Sep 17 00:00:00 2001
2From: Changqing Li <changqing.li@windriver.com>
3Date: Fri, 20 Mar 2026 15:04:22 +0800
4Subject: [PATCH 4/4] Also remove Proxy-Authorization header on cross origin
5 redirect
6
7Closes #489
8
9Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/libsoup/-/commit/98c1285d9d78662c38bf14b4a128af01ccfdb446]
10CVE: CVE-2026-1539
11
12Signed-off-by: Changqing Li <changqing.li@windriver.com>
13---
14 libsoup/soup-session.c | 1 +
15 1 file changed, 1 insertion(+)
16
17diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c
18index cc0d04c..0361856 100644
19--- a/libsoup/soup-session.c
20+++ b/libsoup/soup-session.c
21@@ -1190,6 +1190,7 @@ soup_session_redirect_message (SoupSession *session, SoupMessage *msg)
22 /* Strip all credentials on cross-origin redirect. */
23 if (!soup_uri_host_equal (soup_message_get_uri (msg), new_uri)) {
24 soup_message_headers_remove (msg->request_headers, "Authorization");
25+ soup_message_headers_remove (msg->request_headers, "Proxy-Authorization");
26 soup_message_set_auth (msg, NULL);
27 }
28
29--
302.34.1
31
diff --git a/meta-oe/recipes-support/libsoup/libsoup-2.4/CVE-2026-1760.patch b/meta-oe/recipes-support/libsoup/libsoup-2.4/CVE-2026-1760.patch
new file mode 100644
index 0000000000..a5547132a2
--- /dev/null
+++ b/meta-oe/recipes-support/libsoup/libsoup-2.4/CVE-2026-1760.patch
@@ -0,0 +1,153 @@
1From 0fca37e0fce479284e62091ffb9b7d6caff1c7e4 Mon Sep 17 00:00:00 2001
2From: Carlos Garcia Campos <cgarcia@igalia.com>
3Date: Thu, 29 Jan 2026 16:43:28 +0100
4Subject: [PATCH] server: close the connection after responsing a request
5 containing Content-Length and Transfer-Encoding
6
7Closes #475
8
9Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/libsoup/-/commit/6224df5a471e9040a99dd3dc2e91817a701b1bf6]
10CVE: CVE-2026-1760
11
12Signed-off-by: Changqing Li <changqing.li@windriver.com>
13---
14 libsoup/soup-message-headers.c | 86 +++++++++++++++-----------------
15 libsoup/soup-message-server-io.c | 8 +++
16 2 files changed, 49 insertions(+), 45 deletions(-)
17
18diff --git a/libsoup/soup-message-headers.c b/libsoup/soup-message-headers.c
19index 535cf14..06d9600 100644
20--- a/libsoup/soup-message-headers.c
21+++ b/libsoup/soup-message-headers.c
22@@ -666,38 +666,13 @@ clear_special_headers (SoupMessageHeaders *hdrs)
23 static void
24 transfer_encoding_setter (SoupMessageHeaders *hdrs, const char *value)
25 {
26- if (value) {
27- /* "identity" is a wrong value according to RFC errata 408,
28- * and RFC 7230 does not list it as valid transfer-coding.
29- * Nevertheless, the obsolete RFC 2616 stated "identity"
30- * as valid, so we can't handle it as unrecognized here
31- * for compatibility reasons.
32- */
33- if (g_ascii_strcasecmp (value, "chunked") == 0)
34- hdrs->encoding = SOUP_ENCODING_CHUNKED;
35- else if (g_ascii_strcasecmp (value, "identity") != 0)
36- hdrs->encoding = SOUP_ENCODING_UNRECOGNIZED;
37- } else
38- hdrs->encoding = -1;
39+ hdrs->encoding = -1;
40 }
41
42 static void
43 content_length_setter (SoupMessageHeaders *hdrs, const char *value)
44 {
45- /* Transfer-Encoding trumps Content-Length */
46- if (hdrs->encoding == SOUP_ENCODING_CHUNKED)
47- return;
48-
49- if (value) {
50- char *end;
51-
52- hdrs->content_length = g_ascii_strtoull (value, &end, 10);
53- if (*end)
54- hdrs->encoding = SOUP_ENCODING_UNRECOGNIZED;
55- else
56- hdrs->encoding = SOUP_ENCODING_CONTENT_LENGTH;
57- } else
58- hdrs->encoding = -1;
59+ hdrs->encoding = -1;
60 }
61
62 /**
63@@ -730,29 +705,50 @@ SoupEncoding
64 soup_message_headers_get_encoding (SoupMessageHeaders *hdrs)
65 {
66 const char *header;
67+ const char *content_length;
68+ const char *transfer_encoding;
69
70 if (hdrs->encoding != -1)
71 return hdrs->encoding;
72
73- /* If Transfer-Encoding was set, hdrs->encoding would already
74- * be set. So we don't need to check that possibility.
75- */
76- header = soup_message_headers_get_one (hdrs, "Content-Length");
77- if (header) {
78- content_length_setter (hdrs, header);
79- if (hdrs->encoding != -1)
80- return hdrs->encoding;
81- }
82+ /* Transfer-Encoding is checked first because it overrides the Content-Length */
83+ transfer_encoding = soup_message_headers_get_one (hdrs, "Transfer-Encoding");
84+ if (transfer_encoding) {
85+ /* "identity" is a wrong value according to RFC errata 408,
86+ * and RFC 7230 does not list it as valid transfer-coding.
87+ * Nevertheless, the obsolete RFC 2616 stated "identity"
88+ * as valid, so we can't handle it as unrecognized here
89+ * for compatibility reasons.
90+ */
91+ if (g_ascii_strcasecmp (transfer_encoding, "chunked") == 0)
92+ hdrs->encoding = SOUP_ENCODING_CHUNKED;
93+ else if (g_ascii_strcasecmp (transfer_encoding, "identity") != 0)
94+ hdrs->encoding = SOUP_ENCODING_UNRECOGNIZED;
95+ } else {
96+ content_length = soup_message_headers_get_one (hdrs, "Content-Length");
97+ if (content_length) {
98+ char *end;
99+
100+ hdrs->content_length = g_ascii_strtoull (content_length, &end, 10);
101+ if (*end)
102+ hdrs->encoding = SOUP_ENCODING_UNRECOGNIZED;
103+ else
104+ hdrs->encoding = SOUP_ENCODING_CONTENT_LENGTH;
105+ }
106+ }
107+
108+ if (hdrs->encoding == -1) {
109+ /* Per RFC 2616 4.4, a response body that doesn't indicate its
110+ * encoding otherwise is terminated by connection close, and a
111+ * request that doesn't indicate otherwise has no body. Note
112+ * that SoupMessage calls soup_message_headers_set_encoding()
113+ * to override the response body default for our own
114+ * server-side messages.
115+ */
116+ hdrs->encoding = (hdrs->type == SOUP_MESSAGE_HEADERS_RESPONSE) ?
117+ SOUP_ENCODING_EOF : SOUP_ENCODING_NONE;
118+ }
119
120- /* Per RFC 2616 4.4, a response body that doesn't indicate its
121- * encoding otherwise is terminated by connection close, and a
122- * request that doesn't indicate otherwise has no body. Note
123- * that SoupMessage calls soup_message_headers_set_encoding()
124- * to override the response body default for our own
125- * server-side messages.
126- */
127- hdrs->encoding = (hdrs->type == SOUP_MESSAGE_HEADERS_RESPONSE) ?
128- SOUP_ENCODING_EOF : SOUP_ENCODING_NONE;
129 return hdrs->encoding;
130 }
131
132diff --git a/libsoup/soup-message-server-io.c b/libsoup/soup-message-server-io.c
133index 71e943b..df5eafc 100644
134--- a/libsoup/soup-message-server-io.c
135+++ b/libsoup/soup-message-server-io.c
136@@ -80,6 +80,14 @@ parse_request_headers (SoupMessage *msg, char *headers, guint headers_len,
137 return SOUP_STATUS_BAD_REQUEST;
138 }
139
140+ /* A server MAY reject a request that contains both Content-Length and
141+ * Transfer-Encoding or process such a request in accordance with the
142+ * Transfer-Encoding alone. Regardless, the server MUST close the connection
143+ * after responding to such a request to avoid the potential attacks
144+ */
145+ if (*encoding == SOUP_ENCODING_CHUNKED && soup_message_headers_get_one (msg->request_headers, "Content-Length"))
146+ soup_message_headers_replace (msg->request_headers, "Connection", "close");
147+
148 /* Generate correct context for request */
149 req_host = soup_message_headers_get_one (msg->request_headers, "Host");
150 if (req_host && strchr (req_host, '/')) {
151--
1522.34.1
153
diff --git a/meta-oe/recipes-support/libsoup/libsoup-2.4/CVE-2026-1761.patch b/meta-oe/recipes-support/libsoup/libsoup-2.4/CVE-2026-1761.patch
new file mode 100644
index 0000000000..573e3e1dd0
--- /dev/null
+++ b/meta-oe/recipes-support/libsoup/libsoup-2.4/CVE-2026-1761.patch
@@ -0,0 +1,36 @@
1From 07757b7feacfc660c6c463ff2b773c13bc42d2c9 Mon Sep 17 00:00:00 2001
2From: Changqing Li <changqing.li@windriver.com>
3Date: Thu, 19 Mar 2026 17:21:32 +0800
4Subject: [PATCH 3/4] multipart: check length of bytes read
5 soup_filter_input_stream_read_until()
6
7We do make sure the read length is smaller than the buffer length when
8the boundary is not found, but we should do the same when the boundary
9is found.
10
11Spotted in #YWH-PGM9867-149
12Closes #493
13
14Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/libsoup/-/commit/cfa9d90d1a5c274233554a264c56551c13d6a6f0]
15CVE: CVE-2026-1761
16
17Signed-off-by: Changqing Li <changqing.li@windriver.com>
18---
19 libsoup/soup-filter-input-stream.c | 2 +-
20 1 file changed, 1 insertion(+), 1 deletion(-)
21
22diff --git a/libsoup/soup-filter-input-stream.c b/libsoup/soup-filter-input-stream.c
23index 2c30bf9..c34510b 100644
24--- a/libsoup/soup-filter-input-stream.c
25+++ b/libsoup/soup-filter-input-stream.c
26@@ -272,6 +272,6 @@ soup_filter_input_stream_read_until (SoupFilterInputStream *fstream,
27 if (eof && !*got_boundary)
28 read_length = MIN (fstream->priv->buf->len, length);
29 else
30- read_length = p - buf;
31+ read_length = MIN ((gsize)(p - buf), length);
32 return read_from_buf (fstream, buffer, read_length);
33 }
34--
352.34.1
36
diff --git a/meta-oe/recipes-support/libsoup/libsoup-2.4/CVE-2026-1801.patch b/meta-oe/recipes-support/libsoup/libsoup-2.4/CVE-2026-1801.patch
new file mode 100644
index 0000000000..5f445f7354
--- /dev/null
+++ b/meta-oe/recipes-support/libsoup/libsoup-2.4/CVE-2026-1801.patch
@@ -0,0 +1,126 @@
1From f9c933e258e9ef2f221cca6395f8092a1c4b93dd Mon Sep 17 00:00:00 2001
2From: Changqing Li <changqing.li@windriver.com>
3Date: Thu, 19 Mar 2026 17:10:36 +0800
4Subject: [PATCH 2/4] Fix CVE-2026-1801
5
6This patch merges 3 upstream patches
7
8Chery-pick the first two patches to make the context is the same as the
9third patch that fix CVE-2026-1801
10
11Upstream-Status: Backport
12[https://gitlab.gnome.org/GNOME/libsoup/-/commit/1e32b5e123aa1689505472bdbfcbd897eac41977,
13https://gitlab.gnome.org/GNOME/libsoup/-/commit/8a2e15c88512ae4517d2c2c887d39299725b22da,
14https://gitlab.gnome.org/GNOME/libsoup/-/commit/b9a1c0663ff8ab6e79715db4b35b54f560416ddd]
15CVE: CVE-2026-1801
16
17Signed-off-by: Changqing Li <changqing.li@windriver.com>
18---
19 libsoup/soup-body-input-stream.c | 66 ++++++++++++++++++++------------
20 1 file changed, 41 insertions(+), 25 deletions(-)
21
22diff --git a/libsoup/soup-body-input-stream.c b/libsoup/soup-body-input-stream.c
23index 6b95884..25d9312 100644
24--- a/libsoup/soup-body-input-stream.c
25+++ b/libsoup/soup-body-input-stream.c
26@@ -159,15 +159,18 @@ soup_body_input_stream_read_chunked (SoupBodyInputStream *bistream,
27 again:
28 switch (bistream->priv->chunked_state) {
29 case SOUP_BODY_INPUT_STREAM_STATE_CHUNK_SIZE:
30- nread = soup_filter_input_stream_read_line (
31- fstream, metabuf, sizeof (metabuf), blocking,
32- &got_line, cancellable, error);
33- if (nread <= 0)
34+ nread = soup_filter_input_stream_read_until (
35+ fstream, metabuf, sizeof (metabuf),
36+ "\r\n", 2, blocking, TRUE,
37+ &got_line, cancellable, error);
38+ if (nread < 0)
39 return nread;
40- if (!got_line) {
41- g_set_error_literal (error, G_IO_ERROR,
42- G_IO_ERROR_PARTIAL_INPUT,
43- _("Connection terminated unexpectedly"));
44+ if (nread == 0 || !got_line) {
45+ if (error && *error == NULL) {
46+ g_set_error_literal (error, G_IO_ERROR,
47+ G_IO_ERROR_PARTIAL_INPUT,
48+ ("Connection terminated unexpectedly"));
49+ }
50 return -1;
51 }
52
53@@ -180,9 +183,9 @@ again:
54
55 case SOUP_BODY_INPUT_STREAM_STATE_CHUNK:
56 nread = soup_body_input_stream_read_raw (
57- bistream, buffer,
58- MIN (count, bistream->priv->read_length),
59- blocking, cancellable, error);
60+ bistream, buffer,
61+ MIN (count, bistream->priv->read_length),
62+ blocking, cancellable, error);
63 if (nread > 0) {
64 bistream->priv->read_length -= nread;
65 if (bistream->priv->read_length == 0)
66@@ -191,16 +194,19 @@ again:
67 return nread;
68
69 case SOUP_BODY_INPUT_STREAM_STATE_CHUNK_END:
70- nread = soup_filter_input_stream_read_line (
71- SOUP_FILTER_INPUT_STREAM (bistream->priv->base_stream),
72- metabuf, sizeof (metabuf), blocking,
73- &got_line, cancellable, error);
74- if (nread <= 0)
75+ nread = soup_filter_input_stream_read_until (
76+ SOUP_FILTER_INPUT_STREAM (bistream->priv->base_stream),
77+ metabuf, sizeof (metabuf),
78+ "\r\n", 2, blocking, TRUE,
79+ &got_line, cancellable, error);
80+ if (nread < 0)
81 return nread;
82- if (!got_line) {
83- g_set_error_literal (error, G_IO_ERROR,
84- G_IO_ERROR_PARTIAL_INPUT,
85- _("Connection terminated unexpectedly"));
86+ if (nread == 0 || !got_line) {
87+ if (error && *error == NULL) {
88+ g_set_error_literal (error, G_IO_ERROR,
89+ G_IO_ERROR_PARTIAL_INPUT,
90+ _("Connection terminated unexpectedly"));
91+ }
92 return -1;
93 }
94
95@@ -208,13 +214,23 @@ again:
96 break;
97
98 case SOUP_BODY_INPUT_STREAM_STATE_TRAILERS:
99- nread = soup_filter_input_stream_read_line (
100- fstream, buffer, count, blocking,
101- &got_line, cancellable, error);
102- if (nread <= 0)
103+ nread = soup_filter_input_stream_read_until (
104+ fstream, metabuf, sizeof (metabuf),
105+ "\r\n", 2, blocking, TRUE,
106+ &got_line, cancellable, error);
107+ if (nread < 0)
108 return nread;
109
110- if (strncmp (buffer, "\r\n", nread) || strncmp (buffer, "\n", nread)) {
111+ if (nread == 0) {
112+ if (error && *error == NULL) {
113+ g_set_error_literal (error, G_IO_ERROR,
114+ G_IO_ERROR_PARTIAL_INPUT,
115+ _("Connection terminated unexpectedly"));
116+ }
117+ return -1;
118+ }
119+
120+ if (nread == 2 && strncmp (metabuf, "\r\n", nread) == 0) {
121 bistream->priv->chunked_state = SOUP_BODY_INPUT_STREAM_STATE_DONE;
122 bistream->priv->eof = TRUE;
123 }
124--
1252.34.1
126
diff --git a/meta-oe/recipes-support/libsoup/libsoup-2.4/CVE-2026-2369.patch b/meta-oe/recipes-support/libsoup/libsoup-2.4/CVE-2026-2369.patch
new file mode 100644
index 0000000000..814672caca
--- /dev/null
+++ b/meta-oe/recipes-support/libsoup/libsoup-2.4/CVE-2026-2369.patch
@@ -0,0 +1,33 @@
1From 5c4e65fd99ff4e3ae76c7985c5e160bb07ea0f92 Mon Sep 17 00:00:00 2001
2From: Changqing Li <changqing.li@windriver.com>
3Date: Wed, 25 Mar 2026 11:24:36 +0800
4Subject: [PATCH] sniffer: Handle potential underflow
5
6Closes #498
7
8Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/libsoup/-/commit/b91bbd7d7888c85b17a8b33173caa806dff51681]
9CVE: CVE-2026-2369
10
11Signed-off-by: Changqing Li <changqing.li@windriver.com>
12---
13 libsoup/soup-content-sniffer.c | 4 ++++
14 1 file changed, 4 insertions(+)
15
16diff --git a/libsoup/soup-content-sniffer.c b/libsoup/soup-content-sniffer.c
17index 3edc568..b091bca 100644
18--- a/libsoup/soup-content-sniffer.c
19+++ b/libsoup/soup-content-sniffer.c
20@@ -504,6 +504,10 @@ sniff_unknown (SoupContentSniffer *sniffer, SoupBuffer *buffer,
21 if (!sniff_scriptable && type_row->scriptable)
22 continue;
23
24+ /* Ensure we have data to sniff - prevents underflow in resource_length - 1 */
25+ if (resource_length == 0)
26+ continue;
27+
28 if (type_row->has_ws) {
29 guint index_stream = 0;
30 guint index_pattern = 0;
31--
322.34.1
33
diff --git a/meta-oe/recipes-support/libsoup/libsoup-2.4/CVE-2026-2443.patch b/meta-oe/recipes-support/libsoup/libsoup-2.4/CVE-2026-2443.patch
new file mode 100644
index 0000000000..99d42acb1e
--- /dev/null
+++ b/meta-oe/recipes-support/libsoup/libsoup-2.4/CVE-2026-2443.patch
@@ -0,0 +1,135 @@
1From 7bb3115a296154e3f465900ea5c984a493385a7f Mon Sep 17 00:00:00 2001
2From: Philip Withnall <pwithnall@gnome.org>
3Date: Fri, 19 Dec 2025 23:49:05 +0000
4Subject: [PATCH] Fix CVE-2026-2443
5
6Upstream-Status: Backport [
7c1796442 soup-message-headers: Rework Range response statuses to match Apache
8191ef313 soup-message-headers: Fix rejection of Range headers with trailing garbage
9be677bea soup-message-headers: Fix parsing of invalid Range suffix lengths
102bbfdfe8 soup-message-headers: Reject ranges where end is before start
11739bf7cb soup-message-headers: Reject invalid Range ends longer than the content
12]
13CVE: CVE-2026-2443
14
15Signed-off-by: Changqing Li <changqing.li@windriver.com>
16---
17 libsoup/soup-message-headers.c | 62 ++++++++++++++++++++++++----------
18 1 file changed, 44 insertions(+), 18 deletions(-)
19
20diff --git a/libsoup/soup-message-headers.c b/libsoup/soup-message-headers.c
21index bb20bbb..535cf14 100644
22--- a/libsoup/soup-message-headers.c
23+++ b/libsoup/soup-message-headers.c
24@@ -943,10 +943,16 @@ sort_ranges (gconstpointer a, gconstpointer b)
25 }
26
27 /* like soup_message_headers_get_ranges(), except it returns:
28- * SOUP_STATUS_OK if there is no Range or it should be ignored.
29- * SOUP_STATUS_PARTIAL_CONTENT if there is at least one satisfiable range.
30- * SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE if @check_satisfiable
31- * is %TRUE and the request is not satisfiable given @total_length.
32+ * - SOUP_STATUS_OK if there is no Range or it should be ignored due to being
33+ * entirely invalid.
34+ * - SOUP_STATUS_PARTIAL_CONTENT if there is at least one satisfiable range.
35+ * - SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE if @check_satisfiable
36+ * is %TRUE, the Range is valid, but no part of the request is satisfiable
37+ * given @total_length.
38+ *
39+ * @ranges and @length are only set if SOUP_STATUS_PARTIAL_CONTENT is returned.
40+ *
41+ * See https://httpwg.org/specs/rfc9110.html#field.range
42 */
43 guint
44 soup_message_headers_get_ranges_internal (SoupMessageHeaders *hdrs,
45@@ -960,22 +966,28 @@ soup_message_headers_get_ranges_internal (SoupMessageHeaders *hdrs,
46 GArray *array;
47 char *spec, *end;
48 guint status = SOUP_STATUS_OK;
49+ gboolean is_all_valid = TRUE;
50
51 if (!range || strncmp (range, "bytes", 5) != 0)
52- return status;
53+ return SOUP_STATUS_OK; /* invalid header or unknown range unit */
54
55 range += 5;
56 while (g_ascii_isspace (*range))
57 range++;
58 if (*range++ != '=')
59- return status;
60+ return SOUP_STATUS_OK; /* invalid header */
61 while (g_ascii_isspace (*range))
62 range++;
63
64 range_list = soup_header_parse_list (range);
65 if (!range_list)
66- return status;
67+ return SOUP_STATUS_OK; /* invalid list */
68
69+ /* Loop through the ranges and modify the status accordingly. Default to
70+ * status 200 (OK, ignoring the ranges). Switch to status 206 (Partial
71+ * Content) if there is at least one partially valid range. Switch to
72+ * status 416 (Range Not Satisfiable) if there are no partially valid
73+ * ranges at all. */
74 array = g_array_new (FALSE, FALSE, sizeof (SoupRange));
75 for (r = range_list; r; r = r->next) {
76 SoupRange cur;
77@@ -988,30 +1000,44 @@ soup_message_headers_get_ranges_internal (SoupMessageHeaders *hdrs,
78 cur.start = g_ascii_strtoull (spec, &end, 10);
79 if (*end == '-')
80 end++;
81- if (*end) {
82+ if (*end)
83 cur.end = g_ascii_strtoull (end, &end, 10);
84- if (cur.end < cur.start) {
85- status = SOUP_STATUS_OK;
86- break;
87- }
88- } else
89+ else
90 cur.end = total_length - 1;
91 }
92+
93 if (*end) {
94- status = SOUP_STATUS_OK;
95- break;
96- } else if (check_satisfiable && cur.start >= total_length) {
97- if (status == SOUP_STATUS_OK)
98- status = SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE;
99+ /* Junk after the range */
100+ is_all_valid = FALSE;
101+ continue;
102+ }
103+
104+ if (cur.end < cur.start) {
105+ is_all_valid = FALSE;
106+ continue;
107+ }
108+
109+ g_assert (cur.start >= 0);
110+ if (cur.end >= total_length)
111+ cur.end = total_length - 1;
112+
113+ if (cur.start >= total_length) {
114+ /* Range is valid, but unsatisfiable */
115 continue;
116 }
117
118+ /* We have at least one (at least partially) satisfiable range */
119 g_array_append_val (array, cur);
120 status = SOUP_STATUS_PARTIAL_CONTENT;
121 }
122 soup_header_free_list (range_list);
123
124 if (status != SOUP_STATUS_PARTIAL_CONTENT) {
125+ g_assert (status == SOUP_STATUS_OK);
126+
127+ if (is_all_valid && check_satisfiable)
128+ status = SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE;
129+
130 g_array_free (array, TRUE);
131 return status;
132 }
133--
1342.34.1
135
diff --git a/meta-oe/recipes-support/libsoup/libsoup-2.4_2.74.3.bb b/meta-oe/recipes-support/libsoup/libsoup-2.4_2.74.3.bb
index 68ec576d9b..e588e60cd5 100644
--- a/meta-oe/recipes-support/libsoup/libsoup-2.4_2.74.3.bb
+++ b/meta-oe/recipes-support/libsoup/libsoup-2.4_2.74.3.bb
@@ -40,6 +40,16 @@ SRC_URI = "${GNOME_MIRROR}/libsoup/${SHRT_VER}/libsoup-${PV}.tar.xz \
40 file://CVE-2025-4948.patch \ 40 file://CVE-2025-4948.patch \
41 file://CVE-2025-4969.patch \ 41 file://CVE-2025-4969.patch \
42 file://CVE-2025-4945.patch \ 42 file://CVE-2025-4945.patch \
43 file://CVE-2025-14523.patch \
44 file://CVE-2025-32049-1.patch \
45 file://CVE-2025-32049-2.patch \
46 file://CVE-2026-2443.patch \
47 file://CVE-2026-1801.patch \
48 file://CVE-2026-1761.patch \
49 file://CVE-2026-1539.patch \
50 file://CVE-2026-2369.patch \
51 file://CVE-2026-1760.patch \
52 file://CVE-2026-1467.patch \
43" 53"
44SRC_URI[sha256sum] = "e4b77c41cfc4c8c5a035fcdc320c7bc6cfb75ef7c5a034153df1413fa1d92f13" 54SRC_URI[sha256sum] = "e4b77c41cfc4c8c5a035fcdc320c7bc6cfb75ef7c5a034153df1413fa1d92f13"
45 55