diff --git a/dbus/dbus-gproxy.c b/dbus/dbus-gproxy.c index 3d5a0c5..56e66d3 100644 --- a/dbus/dbus-gproxy.c +++ b/dbus/dbus-gproxy.c @@ -2215,6 +2215,9 @@ dbus_g_proxy_end_call_internal (DBusGProxy *proxy, n_retvals_processed = 0; over = 0; + /* Keep around a copy of output arguments so we can free on error. */ + G_VA_COPY(args_unwind, args); + pending = g_hash_table_lookup (priv->pending_calls, GUINT_TO_POINTER (call_id)); dbus_pending_call_block (pending); @@ -2276,7 +2279,7 @@ dbus_g_proxy_end_call_internal (DBusGProxy *proxy, goto out; /* Anything that can be demarshaled must be storable */ - if (!_dbus_gvalue_store (&gvalue, (gpointer*) return_storage)) + if (!_dbus_gvalue_store (&gvalue, return_storage)) g_assert_not_reached (); /* Ownership of the value passes to the client, don't unset */ } @@ -2319,18 +2322,33 @@ dbus_g_proxy_end_call_internal (DBusGProxy *proxy, ret = TRUE; out: - va_end (args); - if (ret == FALSE) { int i; + + valtype = first_arg_type; for (i = 0; i < n_retvals_processed; i++) { gpointer retval; retval = va_arg (args_unwind, gpointer); + if (retval != NULL) + switch (G_TYPE_FUNDAMENTAL (valtype)) + { + case G_TYPE_STRING: + g_free (*(gchar **)retval); + break; + case G_TYPE_OBJECT: + g_object_unref (*(GObject **)retval); + break; + case G_TYPE_BOXED: + g_boxed_free (valtype, *(gpointer *)retval); + break; + default: + break; + } - g_free (retval); + valtype = va_arg (args_unwind, GType); } } va_end (args_unwind);