guix-mirrors/gnu/packages/patches/libsoup-memory-leak-in-soup_form_decode.patch
Maxim Cournoyer a1fd9f821c
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
2025-09-30 20:05:05 +02:00

101 lines
3.5 KiB
Diff

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 {