Blob Blame History Raw
From f41e9517ffd362505ca91c21387e6457e7c53a2d Mon Sep 17 00:00:00 2001
From: Olivier Fourdan <ofourdan@redhat.com>
Date: Mon, 19 Nov 2018 11:25:57 +0100
Subject: [PATCH 02/12] clutter: Keep a device reference with events

If a device (virtual or real) is removed while there are remaining
events queued for that device, the event loop may try to access the
event freed memory.

To avoid the issue, add a reference to the device when the event is
created or copied, and remove the reference once the device is freed.

Closes: https://gitlab.gnome.org/GNOME/mutter/issues/393
---
 clutter/clutter/clutter-event.c | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/clutter/clutter/clutter-event.c b/clutter/clutter/clutter-event.c
index 10b6c00..1b21b6a 100644
--- a/clutter/clutter/clutter-event.c
+++ b/clutter/clutter/clutter-event.c
@@ -1095,7 +1095,7 @@ clutter_event_set_device (ClutterEvent       *event,
     {
       ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
 
-      real_event->device = device;
+      g_set_object (&real_event->device, device);
     }
 
   switch (event->type)
@@ -1364,8 +1364,8 @@ clutter_event_copy (const ClutterEvent *event)
     {
       ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
 
-      new_real_event->device = real_event->device;
-      new_real_event->source_device = real_event->source_device;
+      g_set_object (&new_real_event->device, real_event->device);
+      g_set_object (&new_real_event->source_device, real_event->source_device);
       new_real_event->delta_x = real_event->delta_x;
       new_real_event->delta_y = real_event->delta_y;
       new_real_event->is_pointer_emulated = real_event->is_pointer_emulated;
@@ -1435,6 +1435,14 @@ clutter_event_free (ClutterEvent *event)
     {
       _clutter_backend_free_event_data (clutter_get_default_backend (), event);
 
+      if (is_event_allocated (event))
+        {
+          ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
+
+          g_clear_object (&real_event->device);
+          g_clear_object (&real_event->source_device);
+        }
+
       switch (event->type)
         {
         case CLUTTER_BUTTON_PRESS:
@@ -1689,7 +1697,7 @@ clutter_event_set_source_device (ClutterEvent       *event,
     return;
 
   real_event = (ClutterEventPrivate *) event;
-  real_event->source_device = device;
+  g_set_object (&real_event->source_device, device);
 }
 
 /**
-- 
2.19.2