Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package libsoup for openSUSE:Factory checked in at 2026-02-16 13:23:11 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/libsoup (Old) and /work/SRC/openSUSE:Factory/.libsoup.new.1977 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "libsoup" Mon Feb 16 13:23:11 2026 rev:164 rq:1333050 version:3.6.5 Changes: -------- --- /work/SRC/openSUSE:Factory/libsoup/libsoup.changes 2026-02-03 21:26:46.856743383 +0100 +++ /work/SRC/openSUSE:Factory/.libsoup.new.1977/libsoup.changes 2026-02-16 13:23:35.333718847 +0100 @@ -1,0 +2,11 @@ +Sat Feb 14 09:45:23 UTC 2026 - Michael Gorse <[email protected]> + +- Add more CVE fixes: + + libsoup-CVE-2025-32049.patch (bsc#1240751 CVE-2025-32049 + glgo#GNOME/libsoup#390) + + libsoup-CVE-2026-2443.patch (bsc#1258170 CVE-2026-2443 + glgo#GNOME/libsoup#487) + + libsoup-CVE-2026-2369.patch (bsc#1258120 CVE-2026-2369 + glgo#GNOME/libsoup!508) + +------------------------------------------------------------------- New: ---- libsoup-CVE-2025-32049.patch libsoup-CVE-2026-2369.patch libsoup-CVE-2026-2443.patch ----------(New B)---------- New:- Add more CVE fixes: + libsoup-CVE-2025-32049.patch (bsc#1240751 CVE-2025-32049 glgo#GNOME/libsoup#390) New: glgo#GNOME/libsoup#487) + libsoup-CVE-2026-2369.patch (bsc#1258120 CVE-2026-2369 glgo#GNOME/libsoup!508) New: glgo#GNOME/libsoup#390) + libsoup-CVE-2026-2443.patch (bsc#1258170 CVE-2026-2443 glgo#GNOME/libsoup#487) ----------(New E)---------- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ libsoup.spec ++++++ --- /var/tmp/diff_new_pack.EJPL1t/_old 2026-02-16 13:23:36.237756455 +0100 +++ /var/tmp/diff_new_pack.EJPL1t/_new 2026-02-16 13:23:36.237756455 +0100 @@ -54,6 +54,12 @@ Patch12: libsoup-CVE-2026-1536.patch # PATCH-FIX-UPSTREAM libsoup-CVE-2026-1761.patch bsc#1257598, CVE-2026-1761, glgo#GNOME/libsoup!496 [email protected] -- multipart: check length of bytes read soup_filter_input_stream_read_until() Patch13: libsoup-CVE-2026-1761.patch +# PATCH-FIX-OPENSUSE libsoup-CVE-2025-32049.patch bsc#1240751 [email protected] -- add size limit for total message size. +Patch14: libsoup-CVE-2025-32049.patch +# PATCH-FIX-UPSTREAM libsoup-CVE-2026-2443.patch bsc#1243170 [email protected] -- fix out-of-bounds read when processing range headers. +Patch15: libsoup-CVE-2026-2443.patch +# PATCH-FIX-UPSTREAM libsoup-CVE-2026-2369.patch bsc#1258120 [email protected] -- handle potential underflow in the content sniffer. +Patch16: libsoup-CVE-2026-2369.patch BuildRequires: glib-networking BuildRequires: meson >= 0.53 ++++++ libsoup-CVE-2025-32049.patch ++++++ diff --git a/libsoup/websocket/soup-websocket-connection.c b/libsoup/websocket/soup-websocket-connection.c index a1448134..48b08b60 100644 --- a/libsoup/websocket/soup-websocket-connection.c +++ b/libsoup/websocket/soup-websocket-connection.c @@ -971,6 +971,11 @@ process_contents (SoupWebsocketConnection *self, switch (priv->message_opcode) { case 0x01: case 0x02: + /* Safety valve */ + if (priv->message_data->len + payload_len > priv->max_incoming_payload_size) { + too_big_error_and_close (self, (priv->message_data->len + payload_len)); + return; + } g_byte_array_append (priv->message_data, payload, payload_len); break; default: ++++++ libsoup-CVE-2026-2369.patch ++++++ >From b91bbd7d7888c85b17a8b33173caa806dff51681 Mon Sep 17 00:00:00 2001 From: Samuel Dainard <> Date: Wed, 11 Feb 2026 10:19:04 -0600 Subject: [PATCH] sniffer: Handle potential underflow Closes #498 --- libsoup/content-sniffer/soup-content-sniffer.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libsoup/content-sniffer/soup-content-sniffer.c b/libsoup/content-sniffer/soup-content-sniffer.c index 26757a6a..16961cca 100644 --- a/libsoup/content-sniffer/soup-content-sniffer.c +++ b/libsoup/content-sniffer/soup-content-sniffer.c @@ -524,6 +524,10 @@ sniff_unknown (SoupContentSniffer *sniffer, GBytes *buffer, if (!sniff_scriptable && type_row->scriptable) continue; + /* Ensure we have data to sniff - prevents underflow in resource_length - 1 */ + if (resource_length == 0) + continue; + if (type_row->has_ws) { guint index_stream = 0; guint index_pattern = 0; -- 2.53.0 ++++++ libsoup-CVE-2026-2443.patch ++++++ diff -urp libsoup-3.6.5.orig/libsoup/soup-message-headers.c libsoup-3.6.5/libsoup/soup-message-headers.c --- libsoup-3.6.5.orig/libsoup/soup-message-headers.c 2026-02-14 04:14:09.575357979 -0600 +++ libsoup-3.6.5/libsoup/soup-message-headers.c 2026-02-14 04:17:20.278921604 -0600 @@ -1176,10 +1176,16 @@ sort_ranges (gconstpointer a, gconstpoin } /* like soup_message_headers_get_ranges(), except it returns: - * SOUP_STATUS_OK if there is no Range or it should be ignored. - * SOUP_STATUS_PARTIAL_CONTENT if there is at least one satisfiable range. - * SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE if @check_satisfiable - * is %TRUE and the request is not satisfiable given @total_length. + * - SOUP_STATUS_OK if there is no Range or it should be ignored due to being + * entirely invalid. + * - SOUP_STATUS_PARTIAL_CONTENT if there is at least one satisfiable range. + * - SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE if @check_satisfiable + * is %TRUE, the Range is valid, but no part of the request is satisfiable + * given @total_length. + * + * @ranges and @length are only set if SOUP_STATUS_PARTIAL_CONTENT is returned. + * + * See https://httpwg.org/specs/rfc9110.html#field.range */ guint soup_message_headers_get_ranges_internal (SoupMessageHeaders *hdrs, @@ -1193,22 +1199,28 @@ soup_message_headers_get_ranges_internal GArray *array; char *spec, *end; guint status = SOUP_STATUS_OK; + gboolean is_all_valid = TRUE; if (!range || strncmp (range, "bytes", 5) != 0) - return status; + return SOUP_STATUS_OK; /* invalid header or unknown range unit */ range += 5; while (g_ascii_isspace (*range)) range++; if (*range++ != '=') - return status; + return SOUP_STATUS_OK; /* invalid header */ while (g_ascii_isspace (*range)) range++; range_list = soup_header_parse_list (range); if (!range_list) - return status; + return SOUP_STATUS_OK; /* invalid list */ + /* Loop through the ranges and modify the status accordingly. Default to + * status 200 (OK, ignoring the ranges). Switch to status 206 (Partial + * Content) if there is at least one partially valid range. Switch to + * status 416 (Range Not Satisfiable) if there are no partially valid + * ranges at all. */ array = g_array_new (FALSE, FALSE, sizeof (SoupRange)); for (r = range_list; r; r = r->next) { SoupRange cur; @@ -1221,30 +1233,44 @@ soup_message_headers_get_ranges_internal cur.start = g_ascii_strtoull (spec, &end, 10); if (*end == '-') end++; - if (*end) { + if (*end) cur.end = g_ascii_strtoull (end, &end, 10); - if (cur.end < cur.start) { - status = SOUP_STATUS_OK; - break; - } - } else + else cur.end = total_length - 1; } + if (*end) { - status = SOUP_STATUS_OK; - break; - } else if (check_satisfiable && cur.start >= total_length) { - if (status == SOUP_STATUS_OK) - status = SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE; + /* Junk after the range */ + is_all_valid = FALSE; + continue; + } + + if (cur.end < cur.start) { + is_all_valid = FALSE; continue; } + g_assert (cur.start >= 0); + if (cur.end >= total_length) + cur.end = total_length - 1; + + if (cur.start >= total_length) { + /* Range is valid, but unsatisfiable */ + continue; + } + + /* We have at least one (at least partially) satisfiable range */ g_array_append_val (array, cur); status = SOUP_STATUS_PARTIAL_CONTENT; } soup_header_free_list (range_list); if (status != SOUP_STATUS_PARTIAL_CONTENT) { + g_assert (status == SOUP_STATUS_OK); + + if (is_all_valid && check_satisfiable) + status = SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE; + g_array_free (array, TRUE); return status; } diff -urp libsoup-3.6.5.orig/tests/range-test.c libsoup-3.6.5/tests/range-test.c --- libsoup-3.6.5.orig/tests/range-test.c 2026-02-14 03:51:18.021654823 -0600 +++ libsoup-3.6.5/tests/range-test.c 2026-02-14 04:17:20.279517774 -0600 @@ -61,7 +61,8 @@ check_part (SoupMessageHeaders *headers, static void do_single_range (SoupSession *session, SoupMessage *msg, - int start, int end, gboolean succeed) + int start, int end, SoupStatus expected_status, + int expected_start, int expected_end) { const char *content_type; GBytes *body; @@ -71,7 +72,7 @@ do_single_range (SoupSession *session, S body = soup_test_session_async_send (session, msg, NULL, NULL); - if (!succeed) { + if (expected_status == SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE) { soup_test_assert_message_status (msg, SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE); if (soup_message_get_status (msg) != SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE) { const char *content_range; @@ -81,31 +82,81 @@ do_single_range (SoupSession *session, S if (content_range) debug_printf (1, " Content-Range: %s\n", content_range); } + } else if (expected_status == SOUP_STATUS_OK) { + soup_test_assert_message_status (msg, SOUP_STATUS_OK); - g_object_unref (msg); - return; - } - - soup_test_assert_message_status (msg, SOUP_STATUS_PARTIAL_CONTENT); + content_type = soup_message_headers_get_content_type ( + soup_message_get_response_headers (msg), NULL); + g_assert_cmpstr (content_type, !=, "multipart/byteranges"); + + g_assert_false (soup_message_headers_get_content_range ( + soup_message_get_response_headers (msg), NULL, NULL, NULL)); + g_assert_cmpint (soup_message_headers_get_content_length ( + soup_message_get_response_headers (msg)), ==, g_bytes_get_size (full_response)); + } else { + soup_test_assert_message_status (msg, SOUP_STATUS_PARTIAL_CONTENT); + + content_type = soup_message_headers_get_content_type ( + soup_message_get_response_headers (msg), NULL); + g_assert_cmpstr (content_type, !=, "multipart/byteranges"); - content_type = soup_message_headers_get_content_type ( - soup_message_get_response_headers (msg), NULL); - g_assert_cmpstr (content_type, !=, "multipart/byteranges"); + check_part (soup_message_get_response_headers (msg), body, TRUE, expected_start, expected_end); + } - check_part (soup_message_get_response_headers (msg), body, TRUE, start, end); - g_bytes_unref (body); + g_clear_pointer (&body, g_bytes_unref); g_object_unref (msg); } static void request_single_range (SoupSession *session, const char *uri, - int start, int end, gboolean succeed) + int start, int end, SoupStatus expected_status, + int expected_start, int expected_end) { SoupMessage *msg; msg = soup_message_new ("GET", uri); soup_message_headers_set_range (soup_message_get_request_headers (msg), start, end); - do_single_range (session, msg, start, end, succeed); + do_single_range (session, msg, start, end, expected_status, expected_start, expected_end); +} + +/* This always asserts failure (either 406 or 200 with no Content-Range); it’s + * intended to be used for passing invalid + * Range header formats which can’t be built by calling + * soup_message_headers_set_range(). */ +static void +request_single_range_by_string (SoupSession *session, const char *uri, + const char *range, SoupStatus expected_status) +{ + SoupMessage *msg; + GBytes *body; + + msg = soup_message_new ("GET", uri); + soup_message_headers_replace (soup_message_get_request_headers (msg), "Range", range); + + debug_printf (1, " Range: %s\n", + soup_message_headers_get_one (soup_message_get_request_headers (msg), "Range")); + + body = soup_test_session_async_send (session, msg, NULL, NULL); + + if (expected_status == SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE) { + soup_test_assert_message_status (msg, SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE); + } else { + const char *content_type; + + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + + content_type = soup_message_headers_get_content_type ( + soup_message_get_response_headers (msg), NULL); + g_assert_cmpstr (content_type, !=, "multipart/byteranges"); + + g_assert_false (soup_message_headers_get_content_range ( + soup_message_get_response_headers (msg), NULL, NULL, NULL)); + g_assert_cmpint (soup_message_headers_get_content_length ( + soup_message_get_response_headers (msg)), ==, g_bytes_get_size (full_response)); + } + + g_clear_pointer (&body, g_bytes_unref); + g_object_unref (msg); } static void @@ -172,7 +223,9 @@ request_double_range (SoupSession *sessi do_single_range (session, msg, MIN (first_start, second_start), MAX (first_end, second_end), - TRUE); + SOUP_STATUS_PARTIAL_CONTENT, + MIN (first_start, second_start), + MAX (first_end, second_end)); } else do_multi_range (session, msg, expected_return_ranges); } @@ -200,7 +253,9 @@ request_triple_range (SoupSession *sessi do_single_range (session, msg, MIN (first_start, MIN (second_start, third_start)), MAX (first_end, MAX (second_end, third_end)), - TRUE); + SOUP_STATUS_PARTIAL_CONTENT, + MIN (first_start, MIN (second_start, third_start)), + MAX (first_end, MAX (second_end, third_end))); } else do_multi_range (session, msg, expected_return_ranges); } @@ -256,7 +311,8 @@ do_range_test (SoupSession *session, con debug_printf (1, "Requesting %d-%d\n", 0 * twelfths, 1 * twelfths); request_single_range (session, uri, 0 * twelfths, 1 * twelfths, - TRUE); + SOUP_STATUS_PARTIAL_CONTENT, + 0 * twelfths, 1 * twelfths); /* B: 11, end-relative request. These two are mostly redundant * in terms of data coverage, but they may still catch @@ -265,11 +321,13 @@ do_range_test (SoupSession *session, con debug_printf (1, "Requesting %d-\n", 11 * twelfths); request_single_range (session, uri, 11 * twelfths, -1, - TRUE); + SOUP_STATUS_PARTIAL_CONTENT, + 11 * twelfths, -1); debug_printf (1, "Requesting -%d\n", 1 * twelfths); request_single_range (session, uri, -1 * twelfths, -1, - TRUE); + SOUP_STATUS_PARTIAL_CONTENT, + -1 * twelfths, -1); /* C: 2 and 5 */ debug_printf (1, "Requesting %d-%d,%d-%d\n", @@ -322,7 +380,8 @@ do_range_test (SoupSession *session, con (int) full_response_length + 100); request_single_range (session, uri, full_response_length + 1, full_response_length + 100, - FALSE); + SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE, + 0, 0); debug_printf (1, "Requesting (semi-invalid) 1-10,%d-%d,20-30\n", (int) full_response_length + 1, @@ -331,6 +390,57 @@ do_range_test (SoupSession *session, con 1, 10, full_response_length + 1, full_response_length + 100, 20, 30); + + debug_printf (1, "Requesting (invalid end) %d-%d\n", + 1, + (int) full_response_length + 1000); + request_single_range (session, uri, + 1, full_response_length + 1000, + SOUP_STATUS_PARTIAL_CONTENT, + 1, full_response_length - 1); + + debug_printf (1, "Requesting (end before start) %d-%d\n", + 10, + 1); + request_single_range (session, uri, + 10, 1, + SOUP_STATUS_OK, + 1, full_response_length); + + debug_printf (1, "Requesting (malformed suffix length) -0\n"); + request_single_range_by_string (session, uri, + "bytes=-0", + SOUP_STATUS_OK); + + debug_printf (1, "Requesting (extra content after valid header value) 0-10\n"); + request_single_range_by_string (session, uri, + "bytes=0-10 but with weird trailing content", + SOUP_STATUS_OK); + + debug_printf (1, "Requesting (invalid range dash) 0a10\n"); + request_single_range_by_string (session, uri, + "bytes=0a10", + SOUP_STATUS_OK); + + debug_printf (1, "Requesting (invalid range unit) 0-10\n"); + request_single_range_by_string (session, uri, + "horses=0-10", + SOUP_STATUS_OK); + + debug_printf (1, "Requesting (missing equals) 0-10\n"); + request_single_range_by_string (session, uri, + "bytes 0-10", + SOUP_STATUS_OK); + + debug_printf (1, "Requesting (end before start but with whitespace) 10-1\n"); + request_single_range_by_string (session, uri, + "bytes \t = \t 10-1", + SOUP_STATUS_OK); + + debug_printf (1, "Requesting (delimiters but no ranges)\n"); + request_single_range_by_string (session, uri, + "bytes=, ,,\t, ", + SOUP_STATUS_OK); } static void
