From 77b50ce7d2618a430a51e8b159a6b5f25a462b49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Mon, 2 Dec 2024 16:46:17 +0000 Subject: [PATCH] gdbus: Fix leak of method invocation when registering an object with closures The invocation passed in is owned by the callback. --- gio/gdbusconnection.c | 2 +- gio/tests/gdbus-export.c | 19 ++++++++++++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/gio/gdbusconnection.c b/gio/gdbusconnection.c index 3587a0928..c2107bcaf 100644 --- a/gio/gdbusconnection.c +++ b/gio/gdbusconnection.c @@ -5950,7 +5950,7 @@ register_with_closures_on_method_call (GDBusConnection *connection, g_value_set_variant (¶ms[5], parameters); g_value_init (¶ms[6], G_TYPE_DBUS_METHOD_INVOCATION); - g_value_set_object (¶ms[6], invocation); + g_value_take_object (¶ms[6], g_steal_pointer (&invocation)); g_closure_invoke (data->method_call_closure, NULL, G_N_ELEMENTS (params), params, NULL); diff --git a/gio/tests/gdbus-export.c b/gio/tests/gdbus-export.c index 599df5bb5..5be560013 100644 --- a/gio/tests/gdbus-export.c +++ b/gio/tests/gdbus-export.c @@ -161,6 +161,23 @@ foo_method_call (GDBusConnection *connection, } } +static void +foo_method_call_with_closure (GDBusConnection *connection, + const gchar *sender, + const gchar *object_path, + const gchar *interface_name, + const gchar *method_name, + GVariant *parameters, + GDBusMethodInvocation *invocation, + gpointer user_data) +{ + /* The call below takes ownership of the invocation but ownership is not + * passed into the callback so get an additional reference here */ + g_object_ref (invocation); + + foo_method_call (connection, sender, object_path, interface_name, method_name, parameters, invocation, user_data); +} + static GVariant * foo_get_property (GDBusConnection *connection, const gchar *sender, @@ -1440,7 +1457,7 @@ test_object_registration_with_closures (void) registration_id = g_dbus_connection_register_object_with_closures (c, "/foo/boss", (GDBusInterfaceInfo *) &foo_interface_info, - g_cclosure_new (G_CALLBACK (foo_method_call), NULL, NULL), + g_cclosure_new (G_CALLBACK (foo_method_call_with_closure), NULL, NULL), g_cclosure_new (G_CALLBACK (foo_get_property), NULL, NULL), g_cclosure_new (G_CALLBACK (foo_set_property), NULL, NULL), &error);