mirror of
https://codeberg.org/guix/guix.git
synced 2026-01-25 12:05:19 -06:00
gnu: libsoup: Apply patches fixing deadlocks and CVE-2025-4476.
The patches are a subset taken from Debian (see: <https://sources.debian.org/patches/libsoup3/3.6.5-3/>). * gnu/packages/patches/libsoup-auth-digest-fix-crash.patch * gnu/packages/patches/libsoup-deadlock-in-add_listener_in_thread.patch * gnu/packages/patches/libsoup-fix-merge-of-ranges.patch * gnu/packages/patches/libsoup-memory-leak-in-soup_form_decode.patch * gnu/packages/patches/libsoup-multipart-bounds-check.patch * gnu/packages/patches/libsoup-use-libdl-instead-of-gmodule.patch: New files. * gnu/local.mk (dist_patch_DATA): Register them. * gnu/packages/gnome.scm (libsoup-minimal): Apply them. Change-Id: I7e4968c1d87e28860fc68616f6107d018e0d93dd
This commit is contained in:
parent
5a9f1de9af
commit
111d7e518e
8 changed files with 561 additions and 5 deletions
|
|
@ -1799,6 +1799,12 @@ dist_patch_DATA = \
|
|||
%D%/packages/patches/libsecret-fix-test-paths.patch \
|
||||
%D%/packages/patches/libsepol-versioned-docbook.patch \
|
||||
%D%/packages/patches/libskk-fix-invalid-escape.patch \
|
||||
%D%/packages/patches/libsoup-auth-digest-fix-crash.patch \
|
||||
%D%/packages/patches/libsoup-deadlock-in-add_listener_in_thread.patch \
|
||||
%D%/packages/patches/libsoup-fix-merge-of-ranges.patch \
|
||||
%D%/packages/patches/libsoup-memory-leak-in-soup_form_decode.patch \
|
||||
%D%/packages/patches/libsoup-multipart-bounds-check.patch \
|
||||
%D%/packages/patches/libsoup-use-libdl-instead-of-gmodule.patch \
|
||||
%D%/packages/patches/libspatialite-libxml2-2.14.patch \
|
||||
%D%/packages/patches/libtar-CVE-2013-4420.patch \
|
||||
%D%/packages/patches/libtar-CVE-2021-33643-CVE-2021-33644.patch \
|
||||
|
|
|
|||
|
|
@ -5104,7 +5104,15 @@ as OpenStreetMap, OpenCycleMap, OpenAerialMap and Maps.")
|
|||
"libsoup-" version ".tar.xz"))
|
||||
(sha256
|
||||
(base32
|
||||
"0d52mnvvsvwpc3scjva5fbvns8f8ijyswgjwjhbr151ymid7d4b8"))))
|
||||
"0d52mnvvsvwpc3scjva5fbvns8f8ijyswgjwjhbr151ymid7d4b8"))
|
||||
(patches
|
||||
(search-patches
|
||||
"libsoup-auth-digest-fix-crash.patch"
|
||||
"libsoup-deadlock-in-add_listener_in_thread.patch"
|
||||
"libsoup-fix-merge-of-ranges.patch"
|
||||
"libsoup-memory-leak-in-soup_form_decode.patch"
|
||||
"libsoup-multipart-bounds-check.patch"
|
||||
"libsoup-use-libdl-instead-of-gmodule.patch"))))
|
||||
(build-system meson-build-system)
|
||||
(arguments
|
||||
(list
|
||||
|
|
@ -5128,21 +5136,21 @@ as OpenStreetMap, OpenCycleMap, OpenAerialMap and Maps.")
|
|||
(substitute* "tests/hsts-db-test.c"
|
||||
((".*/hsts-db/subdomains.*") "")))))))
|
||||
(native-inputs
|
||||
(list `(,glib "bin") ;for glib-mkenums
|
||||
(list `(,glib "bin") ;for glib-mkenums
|
||||
gobject-introspection
|
||||
pkg-config
|
||||
python-wrapper
|
||||
vala
|
||||
curl
|
||||
gnutls ;for 'certtool'
|
||||
gnutls ;for 'certtool'
|
||||
httpd/pinned))
|
||||
(propagated-inputs
|
||||
;; libsoup-3.0.pc refers to all of these (except where otherwise noted)
|
||||
(list brotli
|
||||
glib
|
||||
glib-networking ; for GIO runtime modules
|
||||
glib-networking ; for GIO runtime modules
|
||||
libpsl
|
||||
nghttp2 ;for pkg-config
|
||||
nghttp2 ;for pkg-config
|
||||
`(,nghttp2 "lib")
|
||||
libxml2
|
||||
mit-krb5
|
||||
|
|
|
|||
31
gnu/packages/patches/libsoup-auth-digest-fix-crash.patch
Normal file
31
gnu/packages/patches/libsoup-auth-digest-fix-crash.patch
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
From: Michael Catanzaro <mcatanzaro@redhat.com>
|
||||
Date: Thu, 8 May 2025 09:27:01 -0500
|
||||
Subject: auth-digest: fix crash in soup_auth_digest_get_protection_space()
|
||||
|
||||
We need to validate the Domain parameter in the WWW-Authenticate header.
|
||||
|
||||
Unfortunately this crash only occurs when listening on default ports 80
|
||||
and 443, so there's no good way to test for this. The test would require
|
||||
running as root.
|
||||
|
||||
Origin: upstream, 3.7.0, commit:e64c221f9c7d09b48b610c5626b3b8c400f0907c
|
||||
Bug: https://gitlab.gnome.org/GNOME/libsoup/-/issues/440
|
||||
Bug-CVE: https://security-tracker.debian.org/tracker/CVE-2025-4476
|
||||
Bug-Debian: https://bugs.debian.org/1105887
|
||||
---
|
||||
libsoup/auth/soup-auth-digest.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/libsoup/auth/soup-auth-digest.c b/libsoup/auth/soup-auth-digest.c
|
||||
index d8bb291..292f204 100644
|
||||
--- a/libsoup/auth/soup-auth-digest.c
|
||||
+++ b/libsoup/auth/soup-auth-digest.c
|
||||
@@ -220,7 +220,7 @@ soup_auth_digest_get_protection_space (SoupAuth *auth, GUri *source_uri)
|
||||
if (uri &&
|
||||
g_strcmp0 (g_uri_get_scheme (uri), g_uri_get_scheme (source_uri)) == 0 &&
|
||||
g_uri_get_port (uri) == g_uri_get_port (source_uri) &&
|
||||
- !strcmp (g_uri_get_host (uri), g_uri_get_host (source_uri)))
|
||||
+ !g_strcmp0 (g_uri_get_host (uri), g_uri_get_host (source_uri)))
|
||||
dir = g_strdup (g_uri_get_path (uri));
|
||||
else
|
||||
dir = NULL;
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
From: Michael Catanzaro <mcatanzaro@redhat.com>
|
||||
Date: Wed, 30 Apr 2025 14:13:41 -0500
|
||||
Subject: test-utils: fix deadlock in add_listener_in_thread()
|
||||
|
||||
The mutex is locked in the wrong place here.
|
||||
|
||||
Hopefully fixes #379
|
||||
|
||||
Origin: upstream, 3.7.0, commit:3c0cee2cfddb9ba31b30421f2b3cdd3c5a255e99
|
||||
Bug: https://gitlab.gnome.org/GNOME/libsoup/-/issues/379
|
||||
---
|
||||
tests/test-utils.c | 6 ++++--
|
||||
1 file changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/tests/test-utils.c b/tests/test-utils.c
|
||||
index 62f0b83..6fb09b6 100644
|
||||
--- a/tests/test-utils.c
|
||||
+++ b/tests/test-utils.c
|
||||
@@ -627,9 +627,11 @@ static gboolean
|
||||
add_listener_in_thread (gpointer user_data)
|
||||
{
|
||||
AddListenerData *data = user_data;
|
||||
+ GUri *uri;
|
||||
|
||||
- data->uri = add_listener (data->server, data->scheme, data->host);
|
||||
+ uri = add_listener (data->server, data->scheme, data->host);
|
||||
g_mutex_lock (&data->mutex);
|
||||
+ data->uri = uri;
|
||||
g_cond_signal (&data->cond);
|
||||
g_mutex_unlock (&data->mutex);
|
||||
|
||||
@@ -661,9 +663,9 @@ soup_test_server_get_uri (SoupServer *server,
|
||||
data.host = host;
|
||||
data.uri = NULL;
|
||||
|
||||
- g_mutex_lock (&data.mutex);
|
||||
soup_add_completion (context, add_listener_in_thread, &data);
|
||||
|
||||
+ g_mutex_lock (&data.mutex);
|
||||
while (!data.uri)
|
||||
g_cond_wait (&data.cond, &data.mutex);
|
||||
|
||||
192
gnu/packages/patches/libsoup-fix-merge-of-ranges.patch
Normal file
192
gnu/packages/patches/libsoup-fix-merge-of-ranges.patch
Normal file
|
|
@ -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;
|
||||
+}
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
From: Milan Crha <mcrha@redhat.com>
|
||||
Date: Tue, 13 May 2025 10:38:49 +0200
|
||||
Subject: soup-form: Fix a possible memory leak in
|
||||
soup_form_decode_multipart()
|
||||
|
||||
The output variables can be set multiple times, when there are multiparts
|
||||
with the same name, thus first clear any previously value and only then
|
||||
assign a new value.
|
||||
|
||||
Origin: upstream, 3.7.0, commit:66b5c5be947062df9caf7025b56ee1de32aee3ac
|
||||
Bug: https://gitlab.gnome.org/GNOME/libsoup/-/issues/446
|
||||
---
|
||||
libsoup/soup-form.c | 12 +++++++++---
|
||||
tests/forms-test.c | 41 +++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 50 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/libsoup/soup-form.c b/libsoup/soup-form.c
|
||||
index 2eb5d57..98130c8 100644
|
||||
--- a/libsoup/soup-form.c
|
||||
+++ b/libsoup/soup-form.c
|
||||
@@ -168,12 +168,18 @@ soup_form_decode_multipart (SoupMultipart *multipart,
|
||||
}
|
||||
|
||||
if (file_control_name && !strcmp (name, file_control_name)) {
|
||||
- if (filename)
|
||||
+ if (filename) {
|
||||
+ g_free (*filename);
|
||||
*filename = g_strdup (g_hash_table_lookup (params, "filename"));
|
||||
- if (content_type)
|
||||
+ }
|
||||
+ if (content_type) {
|
||||
+ g_free (*content_type);
|
||||
*content_type = g_strdup (soup_message_headers_get_content_type (part_headers, NULL));
|
||||
- if (file)
|
||||
+ }
|
||||
+ if (file) {
|
||||
+ g_clear_pointer (file, g_bytes_unref);
|
||||
*file = g_bytes_ref (part_body);
|
||||
+ }
|
||||
} else {
|
||||
g_hash_table_insert (form_data_set,
|
||||
g_strdup (name),
|
||||
diff --git a/tests/forms-test.c b/tests/forms-test.c
|
||||
index 1002374..183900f 100644
|
||||
--- a/tests/forms-test.c
|
||||
+++ b/tests/forms-test.c
|
||||
@@ -485,6 +485,46 @@ md5_callback (SoupServer *server,
|
||||
soup_server_message_set_status (msg, SOUP_STATUS_METHOD_NOT_ALLOWED, NULL);
|
||||
}
|
||||
|
||||
+static void
|
||||
+do_form_decode_multipart_test (void)
|
||||
+{
|
||||
+ SoupMultipart *multipart = soup_multipart_new ("multipart/form-data");
|
||||
+ const char *file_control_name = "uploaded_file";
|
||||
+ char *content_type = NULL;
|
||||
+ char *filename = NULL;
|
||||
+ GBytes *file = NULL;
|
||||
+ GHashTable *result;
|
||||
+ int part;
|
||||
+
|
||||
+ for (part = 0; part < 2; part++) {
|
||||
+ SoupMessageHeaders *headers = soup_message_headers_new (SOUP_MESSAGE_HEADERS_MULTIPART);
|
||||
+ GHashTable *params = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
|
||||
+ GBytes *body = g_bytes_new (NULL, 0);
|
||||
+
|
||||
+ g_hash_table_insert (params, g_strdup ("name"), g_strdup (file_control_name));
|
||||
+ g_hash_table_insert (params, g_strdup ("filename"), g_strdup (file_control_name));
|
||||
+ soup_message_headers_set_content_disposition (headers, "form-data", params);
|
||||
+ soup_message_headers_set_content_type (headers, "text/x-form", NULL);
|
||||
+ soup_multipart_append_part (multipart, headers, body);
|
||||
+
|
||||
+ soup_message_headers_unref (headers);
|
||||
+ g_hash_table_destroy (params);
|
||||
+ g_bytes_unref (body);
|
||||
+ }
|
||||
+
|
||||
+ /* this would leak memory of the output variables, due to two parts having the same 'file_control_name' */
|
||||
+ result = soup_form_decode_multipart (multipart, file_control_name, &filename, &content_type, &file);
|
||||
+ g_assert_nonnull (result);
|
||||
+ g_assert_cmpstr (content_type, ==, "text/x-form");
|
||||
+ g_assert_cmpstr (filename, ==, file_control_name);
|
||||
+ g_assert_nonnull (file);
|
||||
+
|
||||
+ g_hash_table_destroy (result);
|
||||
+ g_free (content_type);
|
||||
+ g_free (filename);
|
||||
+ g_bytes_unref (file);
|
||||
+}
|
||||
+
|
||||
static gboolean run_tests = TRUE;
|
||||
|
||||
static GOptionEntry no_test_entry[] = {
|
||||
@@ -525,6 +565,7 @@ main (int argc, char **argv)
|
||||
g_uri_unref (uri);
|
||||
|
||||
g_test_add_func ("/forms/decode", do_form_decode_test);
|
||||
+ g_test_add_func ("/forms/decodemultipart", do_form_decode_multipart_test);
|
||||
|
||||
ret = g_test_run ();
|
||||
} else {
|
||||
106
gnu/packages/patches/libsoup-multipart-bounds-check.patch
Normal file
106
gnu/packages/patches/libsoup-multipart-bounds-check.patch
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
From: Milan Crha <mcrha@redhat.com>
|
||||
Date: Tue, 15 Apr 2025 09:03:00 +0200
|
||||
Subject: multipart: Fix read out of buffer bounds under
|
||||
soup_multipart_new_from_message()
|
||||
|
||||
This is CVE-2025-32914, special crafted input can cause read out of buffer bounds
|
||||
of the body argument.
|
||||
|
||||
Origin: upstream, 3.7.0, commit:5bfcf8157597f2d327050114fb37ff600004dbcf
|
||||
Bug: https://gitlab.gnome.org/GNOME/libsoup/-/issues/436
|
||||
Bug-CVE: https://security-tracker.debian.org/tracker/CVE-2025-32914
|
||||
Bug-Debian: https://bugs.debian.org/1103267
|
||||
---
|
||||
libsoup/soup-multipart.c | 2 +-
|
||||
tests/multipart-test.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 59 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/libsoup/soup-multipart.c b/libsoup/soup-multipart.c
|
||||
index 2421c91..102ce37 100644
|
||||
--- a/libsoup/soup-multipart.c
|
||||
+++ b/libsoup/soup-multipart.c
|
||||
@@ -173,7 +173,7 @@ soup_multipart_new_from_message (SoupMessageHeaders *headers,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
- split = strstr (start, "\r\n\r\n");
|
||||
+ split = g_strstr_len (start, body_end - start, "\r\n\r\n");
|
||||
if (!split || split > end) {
|
||||
soup_multipart_free (multipart);
|
||||
return NULL;
|
||||
diff --git a/tests/multipart-test.c b/tests/multipart-test.c
|
||||
index 2c0e7e9..f5b9868 100644
|
||||
--- a/tests/multipart-test.c
|
||||
+++ b/tests/multipart-test.c
|
||||
@@ -471,6 +471,62 @@ test_multipart (gconstpointer data)
|
||||
loop = NULL;
|
||||
}
|
||||
|
||||
+static void
|
||||
+test_multipart_bounds_good (void)
|
||||
+{
|
||||
+ #define TEXT "line1\r\nline2"
|
||||
+ SoupMultipart *multipart;
|
||||
+ SoupMessageHeaders *headers, *set_headers = NULL;
|
||||
+ GBytes *bytes, *set_bytes = NULL;
|
||||
+ const char *raw_data = "--123\r\nContent-Type: text/plain;\r\n\r\n" TEXT "\r\n--123--\r\n";
|
||||
+ gboolean success;
|
||||
+
|
||||
+ headers = soup_message_headers_new (SOUP_MESSAGE_HEADERS_MULTIPART);
|
||||
+ soup_message_headers_append (headers, "Content-Type", "multipart/mixed; boundary=\"123\"");
|
||||
+
|
||||
+ bytes = g_bytes_new (raw_data, strlen (raw_data));
|
||||
+
|
||||
+ multipart = soup_multipart_new_from_message (headers, bytes);
|
||||
+
|
||||
+ g_assert_nonnull (multipart);
|
||||
+ g_assert_cmpint (soup_multipart_get_length (multipart), ==, 1);
|
||||
+ success = soup_multipart_get_part (multipart, 0, &set_headers, &set_bytes);
|
||||
+ g_assert_true (success);
|
||||
+ g_assert_nonnull (set_headers);
|
||||
+ g_assert_nonnull (set_bytes);
|
||||
+ g_assert_cmpint (strlen (TEXT), ==, g_bytes_get_size (set_bytes));
|
||||
+ g_assert_cmpstr ("text/plain", ==, soup_message_headers_get_content_type (set_headers, NULL));
|
||||
+ g_assert_cmpmem (TEXT, strlen (TEXT), g_bytes_get_data (set_bytes, NULL), g_bytes_get_size (set_bytes));
|
||||
+
|
||||
+ soup_message_headers_unref (headers);
|
||||
+ g_bytes_unref (bytes);
|
||||
+
|
||||
+ soup_multipart_free (multipart);
|
||||
+
|
||||
+ #undef TEXT
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+test_multipart_bounds_bad (void)
|
||||
+{
|
||||
+ SoupMultipart *multipart;
|
||||
+ SoupMessageHeaders *headers;
|
||||
+ GBytes *bytes;
|
||||
+ const char *raw_data = "--123\r\nContent-Type: text/plain;\r\nline1\r\nline2\r\n--123--\r\n";
|
||||
+
|
||||
+ headers = soup_message_headers_new (SOUP_MESSAGE_HEADERS_MULTIPART);
|
||||
+ soup_message_headers_append (headers, "Content-Type", "multipart/mixed; boundary=\"123\"");
|
||||
+
|
||||
+ bytes = g_bytes_new (raw_data, strlen (raw_data));
|
||||
+
|
||||
+ /* it did read out of raw_data/bytes bounds */
|
||||
+ multipart = soup_multipart_new_from_message (headers, bytes);
|
||||
+ g_assert_null (multipart);
|
||||
+
|
||||
+ soup_message_headers_unref (headers);
|
||||
+ g_bytes_unref (bytes);
|
||||
+}
|
||||
+
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
@@ -498,6 +554,8 @@ main (int argc, char **argv)
|
||||
g_test_add_data_func ("/multipart/sync", GINT_TO_POINTER (SYNC_MULTIPART), test_multipart);
|
||||
g_test_add_data_func ("/multipart/async", GINT_TO_POINTER (ASYNC_MULTIPART), test_multipart);
|
||||
g_test_add_data_func ("/multipart/async-small-reads", GINT_TO_POINTER (ASYNC_MULTIPART_SMALL_READS), test_multipart);
|
||||
+ g_test_add_func ("/multipart/bounds-good", test_multipart_bounds_good);
|
||||
+ g_test_add_func ("/multipart/bounds-bad", test_multipart_bounds_bad);
|
||||
|
||||
ret = g_test_run ();
|
||||
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
From: Fabio Manganiello <fabio@manganiello.tech>
|
||||
Date: Tue, 15 Jul 2025 15:41:47 +0200
|
||||
Subject: soup-init: Use libdl instead of gmodule in `soup2_is_loaded` check
|
||||
|
||||
Calling `g_module_open` in the library constructor can cause deadlocks
|
||||
when libsoup is used with other libraries that also contend for GLib
|
||||
mutexes. `dlopen` should be used instead.
|
||||
|
||||
Co-authored-by: Nirbheek Chauhan <nirbheek@centricular.com>
|
||||
Bug: https://gitlab.gnome.org/GNOME/libsoup/-/issues/463
|
||||
Bug: https://gitlab.gnome.org/GNOME/glib/-/issues/1443
|
||||
Bug-Debian: https://bugs.debian.org/1109685
|
||||
Origin: https://gitlab.gnome.org/GNOME/libsoup/-/merge_requests/475
|
||||
Applied-upstream: 3.7.0, commit:1296cbf983f036f20262c453926dff77e1d6a852
|
||||
Applied-upstream: 3.6.6, commit:2316e56a5502ac4c41ef4ff56a3266e680aca129
|
||||
---
|
||||
libsoup/soup-init.c | 28 +++++++++++++++++-----------
|
||||
1 file changed, 17 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/libsoup/soup-init.c b/libsoup/soup-init.c
|
||||
index 8a33c77..3392e8e 100644
|
||||
--- a/libsoup/soup-init.c
|
||||
+++ b/libsoup/soup-init.c
|
||||
@@ -10,7 +10,6 @@
|
||||
#endif
|
||||
|
||||
#include <glib/gi18n-lib.h>
|
||||
-#include <gmodule.h>
|
||||
#include "gconstructor.h"
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
@@ -18,21 +17,28 @@
|
||||
#include <windows.h>
|
||||
|
||||
HMODULE soup_dll;
|
||||
+#else
|
||||
+#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
static gboolean
|
||||
soup2_is_loaded (void)
|
||||
{
|
||||
- GModule *module = g_module_open (NULL, 0);
|
||||
- gpointer func;
|
||||
- gboolean result = FALSE;
|
||||
-
|
||||
- if (g_module_symbol (module, "soup_uri_new", &func))
|
||||
- result = TRUE;
|
||||
-
|
||||
- g_module_close (module);
|
||||
-
|
||||
- return result;
|
||||
+ gboolean result = FALSE;
|
||||
+
|
||||
+ /* Skip on PE/COFF, as it doesn't have a flat symbol namespace */
|
||||
+#ifndef G_OS_WIN32
|
||||
+ gpointer handle;
|
||||
+ gpointer func;
|
||||
+
|
||||
+ handle = dlopen (NULL, RTLD_LAZY | RTLD_GLOBAL);
|
||||
+ if (handle != NULL) {
|
||||
+ func = dlsym (handle, "soup_uri_new");
|
||||
+ result = (func != NULL);
|
||||
+ dlclose (handle);
|
||||
+ }
|
||||
+#endif
|
||||
+ return result;
|
||||
}
|
||||
|
||||
static void
|
||||
Loading…
Add table
Reference in a new issue