summaryrefslogtreecommitdiff
path: root/gnu/packages/patches/libsoup-fix-merge-of-ranges.patch
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/packages/patches/libsoup-fix-merge-of-ranges.patch')
-rw-r--r--gnu/packages/patches/libsoup-fix-merge-of-ranges.patch192
1 files changed, 192 insertions, 0 deletions
diff --git a/gnu/packages/patches/libsoup-fix-merge-of-ranges.patch b/gnu/packages/patches/libsoup-fix-merge-of-ranges.patch
new file mode 100644
index 0000000000..5cc7325a5d
--- /dev/null
+++ b/gnu/packages/patches/libsoup-fix-merge-of-ranges.patch
@@ -0,0 +1,192 @@
+From: Milan Crha <mcrha@redhat.com>
+Date: Tue, 15 Apr 2025 12:17:39 +0200
+Subject: soup-message-headers: Correct merge of ranges
+
+It had been skipping every second range, which generated an array
+of a lot of insane ranges, causing large memory usage by the server.
+
+Origin: upstream, 3.7.0, commit:9bb92f7a685e31e10e9e8221d0342280432ce836
+Bug: https://gitlab.gnome.org/GNOME/libsoup/-/issues/428
+Bug-CVE: https://security-tracker.debian.org/tracker/CVE-2025-32907
+Bug-Debian: https://bugs.debian.org/1103264
+---
+ libsoup/soup-message-headers.c | 1 +
+ tests/meson.build | 1 +
+ tests/server-mem-limit-test.c | 144 +++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 146 insertions(+)
+ create mode 100644 tests/server-mem-limit-test.c
+
+diff --git a/libsoup/soup-message-headers.c b/libsoup/soup-message-headers.c
+index ee7a3cb..f101d4b 100644
+--- a/libsoup/soup-message-headers.c
++++ b/libsoup/soup-message-headers.c
+@@ -1244,6 +1244,7 @@ soup_message_headers_get_ranges_internal (SoupMessageHeaders *hdrs,
+ if (cur->start <= prev->end) {
+ prev->end = MAX (prev->end, cur->end);
+ g_array_remove_index (array, i);
++ i--;
+ }
+ }
+ }
+diff --git a/tests/meson.build b/tests/meson.build
+index cf4ddbd..68e6d01 100644
+--- a/tests/meson.build
++++ b/tests/meson.build
+@@ -102,6 +102,7 @@ tests = [
+ {'name': 'samesite'},
+ {'name': 'session'},
+ {'name': 'server-auth'},
++ {'name': 'server-mem-limit'},
+ {'name': 'server'},
+ {'name': 'sniffing',
+ 'depends': [test_resources],
+diff --git a/tests/server-mem-limit-test.c b/tests/server-mem-limit-test.c
+new file mode 100644
+index 0000000..98f1c40
+--- /dev/null
++++ b/tests/server-mem-limit-test.c
+@@ -0,0 +1,144 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
++/*
++ * Copyright (C) 2025 Red Hat <www.redhat.com>
++ */
++
++#include "test-utils.h"
++
++#include <sys/resource.h>
++
++/*
++ This test limits memory usage to trigger too large buffer allocation crash.
++ As restoring the limits back to what it was does not always work, it's split
++ out of the server-test.c test with copied minimal server code.
++ */
++
++typedef struct {
++ SoupServer *server;
++ GUri *base_uri, *ssl_base_uri;
++ GSList *handlers;
++} ServerData;
++
++static void
++server_setup_nohandler (ServerData *sd, gconstpointer test_data)
++{
++ sd->server = soup_test_server_new (SOUP_TEST_SERVER_IN_THREAD);
++ sd->base_uri = soup_test_server_get_uri (sd->server, "http", NULL);
++ if (tls_available)
++ sd->ssl_base_uri = soup_test_server_get_uri (sd->server, "https", NULL);
++}
++
++static void
++server_add_handler (ServerData *sd,
++ const char *path,
++ SoupServerCallback callback,
++ gpointer user_data,
++ GDestroyNotify destroy)
++{
++ soup_server_add_handler (sd->server, path, callback, user_data, destroy);
++ sd->handlers = g_slist_prepend (sd->handlers, g_strdup (path));
++}
++
++static void
++server_setup (ServerData *sd, gconstpointer test_data)
++{
++ server_setup_nohandler (sd, test_data);
++}
++
++static void
++server_teardown (ServerData *sd, gconstpointer test_data)
++{
++ GSList *iter;
++
++ for (iter = sd->handlers; iter; iter = iter->next)
++ soup_server_remove_handler (sd->server, iter->data);
++ g_slist_free_full (sd->handlers, g_free);
++
++ g_clear_pointer (&sd->server, soup_test_server_quit_unref);
++ g_clear_pointer (&sd->base_uri, g_uri_unref);
++ g_clear_pointer (&sd->ssl_base_uri, g_uri_unref);
++}
++
++static void
++server_file_callback (SoupServer *server,
++ SoupServerMessage *msg,
++ const char *path,
++ GHashTable *query,
++ gpointer data)
++{
++ void *mem;
++
++ g_assert_cmpstr (path, ==, "/file");
++ g_assert_cmpstr (soup_server_message_get_method (msg), ==, SOUP_METHOD_GET);
++
++ mem = g_malloc0 (sizeof (char) * 1024 * 1024);
++ /* fedora-scan CI claims a warning about possibly leaked `mem` variable, thus use
++ the copy and free it explicitly, to workaround the false positive; the g_steal_pointer()
++ did not help for the malloc-ed memory */
++ soup_server_message_set_response (msg, "application/octet-stream", SOUP_MEMORY_COPY, mem, sizeof (char) * 1024 *1024);
++ soup_server_message_set_status (msg, SOUP_STATUS_OK, NULL);
++ g_free (mem);
++}
++
++static void
++do_ranges_overlaps_test (ServerData *sd, gconstpointer test_data)
++{
++ SoupSession *session;
++ SoupMessage *msg;
++ GString *range;
++ GUri *uri;
++ const char *chunk = ",0,0,0,0,0,0,0,0,0,0,0";
++
++ g_test_bug ("428");
++
++ #ifdef G_OS_WIN32
++ g_test_skip ("Cannot run under windows");
++ return;
++ #endif
++
++ range = g_string_sized_new (99 * 1024);
++ g_string_append (range, "bytes=1024");
++ while (range->len < 99 * 1024)
++ g_string_append (range, chunk);
++
++ session = soup_test_session_new (NULL);
++ server_add_handler (sd, "/file", server_file_callback, NULL, NULL);
++
++ uri = g_uri_parse_relative (sd->base_uri, "/file", SOUP_HTTP_URI_FLAGS, NULL);
++
++ msg = soup_message_new_from_uri ("GET", uri);
++ soup_message_headers_append (soup_message_get_request_headers (msg), "Range", range->str);
++
++ soup_test_session_send_message (session, msg);
++
++ soup_test_assert_message_status (msg, SOUP_STATUS_PARTIAL_CONTENT);
++
++ g_object_unref (msg);
++
++ g_string_free (range, TRUE);
++ g_uri_unref (uri);
++
++ soup_test_session_abort_unref (session);
++}
++
++int
++main (int argc, char **argv)
++{
++ int ret;
++
++ test_init (argc, argv, NULL);
++
++ #ifndef G_OS_WIN32
++ struct rlimit new_rlimit = { 1024 * 1024 * 64, 1024 * 1024 * 64 };
++ /* limit memory usage, to trigger too large memory allocation abort */
++ g_assert_cmpint (setrlimit (RLIMIT_DATA, &new_rlimit), ==, 0);
++ #endif
++
++ g_test_add ("/server-mem/range-overlaps", ServerData, NULL,
++ server_setup, do_ranges_overlaps_test, server_teardown);
++
++ ret = g_test_run ();
++
++ test_cleanup ();
++ return ret;
++}