File: tests-Ensure-that-unsubscribing-with-GetNameOwner-in-flig.patch

package info (click to toggle)
glib2.0 2.74.6-2%2Bdeb12u6
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bookworm-backports
  • size: 61,308 kB
  • sloc: ansic: 489,089; xml: 17,388; python: 7,962; perl: 1,144; sh: 1,105; makefile: 225; cpp: 195
file content (114 lines) | stat: -rw-r--r-- 3,620 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
From: Simon McVittie <smcv@collabora.com>
Date: Tue, 23 Apr 2024 21:39:43 +0100
Subject: tests: Ensure that unsubscribing with GetNameOwner in-flight doesn't
 crash

This was a bug that existed during development of this branch; make sure
it doesn't come back.

This test fails with a use-after-free and crash if we comment out the
part of name_watcher_unref_watched_name() that removes the name watcher
from `map_method_serial_to_name_watcher`.

It would also fail with an assertion failure if we asserted in
name_watcher_unref_watched_name() that get_name_owner_serial == 0
(i.e. that GetNameOwner is not in-flight at destruction).

Signed-off-by: Simon McVittie <smcv@collabora.com>
Origin: upstream, https://gitlab.gnome.org/GNOME/glib/-/issues/3268
---
 gio/tests/gdbus-subscribe.c | 52 ++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 51 insertions(+), 1 deletion(-)

diff --git a/gio/tests/gdbus-subscribe.c b/gio/tests/gdbus-subscribe.c
index 5406ba7..4cba4f5 100644
--- a/gio/tests/gdbus-subscribe.c
+++ b/gio/tests/gdbus-subscribe.c
@@ -116,6 +116,7 @@ typedef struct
   const char *member;
   const char *arg0;
   GDBusSignalFlags flags;
+  gboolean unsubscribe_immediately;
 } TestSubscribe;
 
 typedef struct
@@ -141,6 +142,7 @@ typedef struct
     TestEmitSignal signal;
     TestSubscribe subscribe;
     TestOwnName own_name;
+    guint unsubscribe_undo_step;
   } u;
 } TestStep;
 
@@ -505,6 +507,43 @@ static const TestPlan plan_limit_by_well_known_name =
   },
 };
 
+static const TestPlan plan_unsubscribe_immediately =
+{
+  .description = "Unsubscribing before GetNameOwner can return doesn't result in a crash",
+  .steps = {
+    {
+      /* Service already owns one name */
+      .action = TEST_ACTION_OWN_NAME,
+      .u.own_name = {
+        .name = ALREADY_OWNED_NAME,
+        .owner = TEST_CONN_SERVICE
+      },
+    },
+    {
+      .action = TEST_ACTION_SUBSCRIBE,
+      .u.subscribe = {
+        .string_sender = ALREADY_OWNED_NAME,
+        .path = EXAMPLE_PATH,
+        .iface = EXAMPLE_INTERFACE,
+        .unsubscribe_immediately = TRUE
+      },
+    },
+    {
+      .action = TEST_ACTION_EMIT_SIGNAL,
+      .u.signal = {
+        .sender = TEST_CONN_SERVICE,
+        .path = EXAMPLE_PATH,
+        .iface = EXAMPLE_INTERFACE,
+        .member = FOO_SIGNAL,
+        .received_by_conn = 0,
+        /* The proxy can't unsubscribe, except by destroying the proxy
+         * completely, which we don't currently implement in this test */
+        .received_by_proxy = 1
+      },
+    },
+  },
+};
+
 static const TestPlan plan_limit_to_message_bus =
 {
   .description = "A subscription to the message bus only accepts messages "
@@ -855,8 +894,18 @@ fixture_subscribe (Fixture             *f,
                                                subscribe->flags,
                                                subscribed_signal_cb,
                                                f, NULL);
+
       g_assert_cmpuint (id, !=, 0);
-      f->subscriptions[step_number] = id;
+
+      if (subscribe->unsubscribe_immediately)
+        {
+          g_test_message ("\tImmediately unsubscribing");
+          g_dbus_connection_signal_unsubscribe (subscriber, id);
+        }
+      else
+        {
+          f->subscriptions[step_number] = id;
+        }
     }
 
   if (f->mode != SUBSCRIPTION_MODE_CONN)
@@ -1287,6 +1336,7 @@ main (int   argc,
   ADD_SUBSCRIBE_TEST (nonexistent_unique_name);
   ADD_SUBSCRIBE_TEST (limit_by_well_known_name);
   ADD_SUBSCRIBE_TEST (limit_to_message_bus);
+  ADD_SUBSCRIBE_TEST (unsubscribe_immediately);
 
   return g_test_run();
 }