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
This commit is contained in:
Olivier Fourdan 2018-11-19 11:25:57 +01:00 committed by Ray Strode
parent 53a5c6a14a
commit d165eb90a1

View File

@ -1095,7 +1095,7 @@ clutter_event_set_device (ClutterEvent *event,
{ {
ClutterEventPrivate *real_event = (ClutterEventPrivate *) event; ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
real_event->device = device; g_set_object (&real_event->device, device);
} }
switch (event->type) switch (event->type)
@ -1364,8 +1364,8 @@ clutter_event_copy (const ClutterEvent *event)
{ {
ClutterEventPrivate *real_event = (ClutterEventPrivate *) event; ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
new_real_event->device = real_event->device; g_set_object (&new_real_event->device, real_event->device);
new_real_event->source_device = real_event->source_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_x = real_event->delta_x;
new_real_event->delta_y = real_event->delta_y; new_real_event->delta_y = real_event->delta_y;
new_real_event->is_pointer_emulated = real_event->is_pointer_emulated; 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); _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) switch (event->type)
{ {
case CLUTTER_BUTTON_PRESS: case CLUTTER_BUTTON_PRESS:
@ -1689,7 +1697,7 @@ clutter_event_set_source_device (ClutterEvent *event,
return; return;
real_event = (ClutterEventPrivate *) event; real_event = (ClutterEventPrivate *) event;
real_event->source_device = device; g_set_object (&real_event->source_device, device);
} }
/** /**