From d165eb90a18fca1376af2b45c517d0c800b2573f Mon Sep 17 00:00:00 2001 From: Olivier Fourdan Date: Mon, 19 Nov 2018 11:25:57 +0100 Subject: [PATCH] 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 10b6c0082..1b21b6a97 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); } /**