mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-11-06 01:16:17 +01:00
gdbusconnection: Fix a crash on arg0 matching
If a connection has two signal subscriptions active for the same signal, one with arg0 matching and one without, a signal which doesn’t contain an arg0 value (i.e. `g_dbus_message_get_arg0()` returns `NULL`) will cause `NULL` to be passed to `strcmp()` when checking for a match against the signal subscription which *has* arg0 matching, causing a crash. Fix that by adding the obvious `NULL` check, and add a unit test. Signed-off-by: Philip Withnall <pwithnall@gnome.org> Fixes: #3342
This commit is contained in:
parent
7b07b0e675
commit
9c66880af0
@ -3929,7 +3929,7 @@ schedule_callbacks (GDBusConnection *connection,
|
|||||||
(arg0_path == NULL || !path_rule_matches (signal_data->arg0, arg0_path)))
|
(arg0_path == NULL || !path_rule_matches (signal_data->arg0, arg0_path)))
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (!g_str_equal (signal_data->arg0, arg0))
|
else if (arg0 == NULL || !g_str_equal (signal_data->arg0, arg0))
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -549,9 +549,13 @@ test_connection_signals (void)
|
|||||||
guint s1b;
|
guint s1b;
|
||||||
guint s2;
|
guint s2;
|
||||||
guint s3;
|
guint s3;
|
||||||
|
guint s4;
|
||||||
|
guint s5;
|
||||||
gint count_s1;
|
gint count_s1;
|
||||||
gint count_s1b;
|
gint count_s1b;
|
||||||
gint count_s2;
|
gint count_s2;
|
||||||
|
gint count_s4;
|
||||||
|
gint count_s5;
|
||||||
gint count_name_owner_changed;
|
gint count_name_owner_changed;
|
||||||
GError *error;
|
GError *error;
|
||||||
gboolean ret;
|
gboolean ret;
|
||||||
@ -618,6 +622,26 @@ test_connection_signals (void)
|
|||||||
test_connection_signal_handler,
|
test_connection_signal_handler,
|
||||||
&count_name_owner_changed,
|
&count_name_owner_changed,
|
||||||
NULL);
|
NULL);
|
||||||
|
s4 = g_dbus_connection_signal_subscribe (c1,
|
||||||
|
":1.2", /* sender */
|
||||||
|
"org.gtk.GDBus.ExampleInterface", /* interface */
|
||||||
|
"FooArg0", /* member */
|
||||||
|
"/org/gtk/GDBus/ExampleInterface", /* path */
|
||||||
|
"some-arg0",
|
||||||
|
G_DBUS_SIGNAL_FLAGS_NONE,
|
||||||
|
test_connection_signal_handler,
|
||||||
|
&count_s4,
|
||||||
|
NULL);
|
||||||
|
s5 = g_dbus_connection_signal_subscribe (c1,
|
||||||
|
":1.2", /* sender */
|
||||||
|
"org.gtk.GDBus.ExampleInterface", /* interface */
|
||||||
|
"FooArg0", /* member */
|
||||||
|
"/org/gtk/GDBus/ExampleInterface", /* path */
|
||||||
|
NULL,
|
||||||
|
G_DBUS_SIGNAL_FLAGS_NONE,
|
||||||
|
test_connection_signal_handler,
|
||||||
|
&count_s5,
|
||||||
|
NULL);
|
||||||
/* Note that s1b is *just like* s1 - this is to catch a bug where N
|
/* Note that s1b is *just like* s1 - this is to catch a bug where N
|
||||||
* subscriptions of the same rule causes N calls to each of the N
|
* subscriptions of the same rule causes N calls to each of the N
|
||||||
* subscriptions instead of just 1 call to each of the N subscriptions.
|
* subscriptions instead of just 1 call to each of the N subscriptions.
|
||||||
@ -636,10 +660,14 @@ test_connection_signals (void)
|
|||||||
g_assert_cmpuint (s1b, !=, 0);
|
g_assert_cmpuint (s1b, !=, 0);
|
||||||
g_assert_cmpuint (s2, !=, 0);
|
g_assert_cmpuint (s2, !=, 0);
|
||||||
g_assert_cmpuint (s3, !=, 0);
|
g_assert_cmpuint (s3, !=, 0);
|
||||||
|
g_assert_cmpuint (s4, !=, 0);
|
||||||
|
g_assert_cmpuint (s5, !=, 0);
|
||||||
|
|
||||||
count_s1 = 0;
|
count_s1 = 0;
|
||||||
count_s1b = 0;
|
count_s1b = 0;
|
||||||
count_s2 = 0;
|
count_s2 = 0;
|
||||||
|
count_s4 = 0;
|
||||||
|
count_s5 = 0;
|
||||||
count_name_owner_changed = 0;
|
count_name_owner_changed = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -712,6 +740,38 @@ test_connection_signals (void)
|
|||||||
g_assert_cmpint (count_s1, ==, 1);
|
g_assert_cmpint (count_s1, ==, 1);
|
||||||
g_assert_cmpint (count_s2, ==, 2);
|
g_assert_cmpint (count_s2, ==, 2);
|
||||||
|
|
||||||
|
/* Emit another signal on c2 with and without arg0 set, to check matching on that.
|
||||||
|
* Matching should fail on s4 when the signal is not emitted with an arg0. It
|
||||||
|
* should succeed on s5 both times, as that doesn’t require an arg0 match. */
|
||||||
|
ret = g_dbus_connection_emit_signal (c2,
|
||||||
|
NULL, /* destination bus name */
|
||||||
|
"/org/gtk/GDBus/ExampleInterface",
|
||||||
|
"org.gtk.GDBus.ExampleInterface",
|
||||||
|
"FooArg0",
|
||||||
|
NULL,
|
||||||
|
&error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert_true (ret);
|
||||||
|
|
||||||
|
while (count_s5 < 1)
|
||||||
|
g_main_loop_run (loop);
|
||||||
|
g_assert_cmpint (count_s5, ==, 1);
|
||||||
|
|
||||||
|
ret = g_dbus_connection_emit_signal (c2,
|
||||||
|
NULL, /* destination bus name */
|
||||||
|
"/org/gtk/GDBus/ExampleInterface",
|
||||||
|
"org.gtk.GDBus.ExampleInterface",
|
||||||
|
"FooArg0",
|
||||||
|
g_variant_new_parsed ("('some-arg0',)"),
|
||||||
|
&error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert_true (ret);
|
||||||
|
|
||||||
|
while (count_s4 < 1)
|
||||||
|
g_main_loop_run (loop);
|
||||||
|
g_assert_cmpint (count_s4, ==, 1);
|
||||||
|
g_assert_cmpint (count_s5, ==, 2);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Also to check the total amount of NameOwnerChanged signals - use a 5 second ceiling
|
* Also to check the total amount of NameOwnerChanged signals - use a 5 second ceiling
|
||||||
* to avoid spinning forever
|
* to avoid spinning forever
|
||||||
@ -724,11 +784,15 @@ test_connection_signals (void)
|
|||||||
g_assert_cmpint (count_s1, ==, 1);
|
g_assert_cmpint (count_s1, ==, 1);
|
||||||
g_assert_cmpint (count_s2, ==, 2);
|
g_assert_cmpint (count_s2, ==, 2);
|
||||||
g_assert_cmpint (count_name_owner_changed, ==, 2);
|
g_assert_cmpint (count_name_owner_changed, ==, 2);
|
||||||
|
g_assert_cmpint (count_s4, ==, 1);
|
||||||
|
g_assert_cmpint (count_s5, ==, 2);
|
||||||
|
|
||||||
g_dbus_connection_signal_unsubscribe (c1, s1);
|
g_dbus_connection_signal_unsubscribe (c1, s1);
|
||||||
g_dbus_connection_signal_unsubscribe (c1, s2);
|
g_dbus_connection_signal_unsubscribe (c1, s2);
|
||||||
g_dbus_connection_signal_unsubscribe (c1, s3);
|
g_dbus_connection_signal_unsubscribe (c1, s3);
|
||||||
g_dbus_connection_signal_unsubscribe (c1, s1b);
|
g_dbus_connection_signal_unsubscribe (c1, s1b);
|
||||||
|
g_dbus_connection_signal_unsubscribe (c1, s4);
|
||||||
|
g_dbus_connection_signal_unsubscribe (c1, s5);
|
||||||
|
|
||||||
g_object_unref (c1);
|
g_object_unref (c1);
|
||||||
g_object_unref (c2);
|
g_object_unref (c2);
|
||||||
|
Loading…
Reference in New Issue
Block a user