Hi, On Thu, Feb 05, 2015 at 05:58:04PM +0300, Vlad Orlov wrote: > […] > A serious flaw in gdk_event_apply_filters function is causing weird crashes > in various software. For example, mate-display-properties crashes when > the screen resolution is changed or a new monitor is plugged in [1]. Some > other older bugs like [2] and [3] also might be caused by this one.
Cheers for the bug. Here's a debdiff. Mike (cced) said he would ask the release team for a pre-upload unblock, so I'll hold off uploading until we hear back. (Keep me in CC on that bug please). Thanks, -- Iain Lane [ i...@orangesquash.org.uk ] Debian Developer [ la...@debian.org ] Ubuntu Developer [ la...@ubuntu.com ]
diff -Nru gtk+2.0-2.24.25/debian/changelog gtk+2.0-2.24.25/debian/changelog --- gtk+2.0-2.24.25/debian/changelog 2014-10-10 18:33:16.000000000 +0100 +++ gtk+2.0-2.24.25/debian/changelog 2015-02-23 17:51:40.000000000 +0000 @@ -1,3 +1,12 @@ +gtk+2.0 (2.24.25-2) UNRELEASED; urgency=medium + + * debian/patches/0001-Make-gdk_event_apply_filters-safe-against-changes-in.patch: + Cherry-pick patch from upstream stable branch to protect + gdk_event_apply_filters_safe from changes in the filter list (Closes: + #777142) + + -- Iain Lane <la...@debian.org> Mon, 23 Feb 2015 17:46:25 +0000 + gtk+2.0 (2.24.25-1) unstable; urgency=medium * Team upload diff -Nru gtk+2.0-2.24.25/debian/control gtk+2.0-2.24.25/debian/control --- gtk+2.0-2.24.25/debian/control 2014-10-10 18:34:04.000000000 +0100 +++ gtk+2.0-2.24.25/debian/control 2015-02-23 17:51:45.000000000 +0000 @@ -2,7 +2,7 @@ Section: libs Priority: optional Maintainer: Debian GNOME Maintainers <pkg-gnome-maintain...@lists.alioth.debian.org> -Uploaders: Emilio Pozuelo Monfort <po...@debian.org>, Iain Lane <la...@debian.org>, Michael Biebl <bi...@debian.org> +Uploaders: Iain Lane <la...@debian.org>, Michael Biebl <bi...@debian.org> Build-Depends: debhelper (>= 8.1.3), gettext, gtk-doc-tools (>= 1.11), diff -Nru gtk+2.0-2.24.25/debian/patches/0001-Make-gdk_event_apply_filters-safe-against-changes-in.patch gtk+2.0-2.24.25/debian/patches/0001-Make-gdk_event_apply_filters-safe-against-changes-in.patch --- gtk+2.0-2.24.25/debian/patches/0001-Make-gdk_event_apply_filters-safe-against-changes-in.patch 1970-01-01 01:00:00.000000000 +0100 +++ gtk+2.0-2.24.25/debian/patches/0001-Make-gdk_event_apply_filters-safe-against-changes-in.patch 2015-02-23 17:45:41.000000000 +0000 @@ -0,0 +1,351 @@ +From ee95f3d7259c0859ce41189b781b4339b4cd64aa Mon Sep 17 00:00:00 2001 +From: Matthias Clasen <mcla...@redhat.com> +Date: Fri, 13 Feb 2015 13:12:39 -0500 +Subject: [PATCH] Make gdk_event_apply_filters safe against changes in filter + list + +An event filter may add or remove filters itself. This patch does +two things to address this case. The first is to take a temporary +reference to the filter while it is being used. The second is +to wait until after the filter function is run before determining +the next node in the list to process. This guards against +changes to the next node. It also does not run functions +that have been marked as removed. Though I'm not sure if this +case can arise. + +https://bugzilla.gnome.org/show_bug.cgi?id=635380 + +Backport of 323df2b2800383832ed3c2e43626f2c6821c33ec to +the gtk-2-24 branch by Wolfgang Ulbrich. + +http://bugs.debian.org/777142 +--- + gdk/gdkinternals.h | 6 +++++ + gdk/gdkwindow.c | 30 +++++++++++++++-------- + gdk/quartz/gdkevents-quartz.c | 55 ++++++++++++++++++++++++++++++------------- + gdk/win32/gdkevents-win32.c | 37 ++++++++++++++++++++++------- + gdk/x11/gdkevents-x11.c | 37 ++++++++++++++++++++++------- + 5 files changed, 122 insertions(+), 43 deletions(-) + +diff --git a/gdk/gdkinternals.h b/gdk/gdkinternals.h +index 0bd803f..97a1daa 100644 +--- a/gdk/gdkinternals.h ++++ b/gdk/gdkinternals.h +@@ -59,9 +59,15 @@ struct _GdkColorInfo + guint ref_count; + }; + ++typedef enum { ++ GDK_EVENT_FILTER_REMOVED = 1 << 0 ++} GdkEventFilterFlags; ++ + struct _GdkEventFilter { + GdkFilterFunc function; + gpointer data; ++ GdkEventFilterFlags flags; ++ guint ref_count; + }; + + struct _GdkClientFilter { +diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c +index 45fee34..29c878f 100644 +--- a/gdk/gdkwindow.c ++++ b/gdk/gdkwindow.c +@@ -2545,13 +2545,18 @@ gdk_window_add_filter (GdkWindow *window, + { + filter = (GdkEventFilter *)tmp_list->data; + if ((filter->function == function) && (filter->data == data)) +- return; ++ { ++ filter->ref_count++; ++ return; ++ } + tmp_list = tmp_list->next; + } + + filter = g_new (GdkEventFilter, 1); + filter->function = function; + filter->data = data; ++ filter->ref_count = 1; ++ filter->flags = 0; + + if (private) + private->filters = g_list_append (private->filters, filter); +@@ -2593,16 +2598,21 @@ gdk_window_remove_filter (GdkWindow *window, + tmp_list = tmp_list->next; + + if ((filter->function == function) && (filter->data == data)) +- { +- if (private) +- private->filters = g_list_remove_link (private->filters, node); +- else +- _gdk_default_filters = g_list_remove_link (_gdk_default_filters, node); +- g_list_free_1 (node); +- g_free (filter); ++ { ++ filter->flags |= GDK_EVENT_FILTER_REMOVED; ++ filter->ref_count--; ++ if (filter->ref_count != 0) ++ return; + +- return; +- } ++ if (private) ++ private->filters = g_list_remove_link (private->filters, node); ++ else ++ _gdk_default_filters = g_list_remove_link (_gdk_default_filters, node); ++ g_list_free_1 (node); ++ g_free (filter); ++ ++ return; ++ } + } + } + +diff --git a/gdk/quartz/gdkevents-quartz.c b/gdk/quartz/gdkevents-quartz.c +index 9e57edd..f199298 100644 +--- a/gdk/quartz/gdkevents-quartz.c ++++ b/gdk/quartz/gdkevents-quartz.c +@@ -253,21 +253,42 @@ append_event (GdkEvent *event, + static gint + gdk_event_apply_filters (NSEvent *nsevent, + GdkEvent *event, +- GList *filters) ++ GList **filters) + { + GList *tmp_list; + GdkFilterReturn result; + +- tmp_list = filters; ++ tmp_list = *filters; + + while (tmp_list) + { + GdkEventFilter *filter = (GdkEventFilter*) tmp_list->data; +- +- tmp_list = tmp_list->next; ++ GList *node; ++ ++ if ((filter->flags & GDK_EVENT_FILTER_REMOVED) != 0) ++ { ++ tmp_list = tmp_list->next; ++ continue; ++ } ++ ++ filter->ref_count++; + result = filter->function (nsevent, event, filter->data); +- if (result != GDK_FILTER_CONTINUE) +- return result; ++ ++ /* get the next node after running the function since the ++ function may add or remove a next node */ ++ node = tmp_list; ++ tmp_list = tmp_list->next; ++ ++ filter->ref_count--; ++ if (filter->ref_count == 0) ++ { ++ *filters = g_list_remove_link (*filters, node); ++ g_list_free_1 (node); ++ g_free (filter); ++ } ++ ++ if (result != GDK_FILTER_CONTINUE) ++ return result; + } + + return GDK_FILTER_CONTINUE; +@@ -1319,7 +1340,7 @@ gdk_event_translate (GdkEvent *event, + /* Apply global filters */ + GdkFilterReturn result; + +- result = gdk_event_apply_filters (nsevent, event, _gdk_default_filters); ++ result = gdk_event_apply_filters (nsevent, event, &_gdk_default_filters); + if (result != GDK_FILTER_CONTINUE) + { + return_val = (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE; +@@ -1390,19 +1411,19 @@ gdk_event_translate (GdkEvent *event, + GdkFilterReturn result; + + if (filter_private->filters) +- { +- g_object_ref (window); ++ { ++ g_object_ref (window); + +- result = gdk_event_apply_filters (nsevent, event, filter_private->filters); ++ result = gdk_event_apply_filters (nsevent, event, &filter_private->filters); + +- g_object_unref (window); ++ g_object_unref (window); + +- if (result != GDK_FILTER_CONTINUE) +- { +- return_val = (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE; +- goto done; +- } +- } ++ if (result != GDK_FILTER_CONTINUE) ++ { ++ return_val = (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE; ++ goto done; ++ } ++ } + } + + /* If the app is not active leave the event to AppKit so the window gets +diff --git a/gdk/win32/gdkevents-win32.c b/gdk/win32/gdkevents-win32.c +index 8b345cb..c853e1e 100644 +--- a/gdk/win32/gdkevents-win32.c ++++ b/gdk/win32/gdkevents-win32.c +@@ -1069,7 +1069,7 @@ fill_key_event_string (GdkEvent *event) + static GdkFilterReturn + apply_event_filters (GdkWindow *window, + MSG *msg, +- GList *filters) ++ GList **filters) + { + GdkFilterReturn result = GDK_FILTER_CONTINUE; + GdkEvent *event; +@@ -1087,15 +1087,36 @@ apply_event_filters (GdkWindow *window, + */ + node = _gdk_event_queue_append (_gdk_display, event); + +- tmp_list = filters; ++ tmp_list = *filters; + while (tmp_list) + { + GdkEventFilter *filter = (GdkEventFilter *) tmp_list->data; +- +- tmp_list = tmp_list->next; ++ GList *node; ++ ++ if ((filter->flags & GDK_EVENT_FILTER_REMOVED) != 0) ++ { ++ tmp_list = tmp_list->next; ++ continue; ++ } ++ ++ filter->ref_count++; + result = filter->function (msg, event, filter->data); +- if (result != GDK_FILTER_CONTINUE) +- break; ++ ++ /* get the next node after running the function since the ++ function may add or remove a next node */ ++ node = tmp_list; ++ tmp_list = tmp_list->next; ++ ++ filter->ref_count--; ++ if (filter->ref_count == 0) ++ { ++ *filters = g_list_remove_link (*filters, node); ++ g_list_free_1 (node); ++ g_free (filter); ++ } ++ ++ if (result != GDK_FILTER_CONTINUE) ++ break; + } + + if (result == GDK_FILTER_CONTINUE || result == GDK_FILTER_REMOVE) +@@ -2075,7 +2096,7 @@ gdk_event_translate (MSG *msg, + { + /* Apply global filters */ + +- GdkFilterReturn result = apply_event_filters (NULL, msg, _gdk_default_filters); ++ GdkFilterReturn result = apply_event_filters (NULL, msg, &_gdk_default_filters); + + /* If result is GDK_FILTER_CONTINUE, we continue as if nothing + * happened. If it is GDK_FILTER_REMOVE or GDK_FILTER_TRANSLATE, +@@ -2121,7 +2142,7 @@ gdk_event_translate (MSG *msg, + { + /* Apply per-window filters */ + +- GdkFilterReturn result = apply_event_filters (window, msg, ((GdkWindowObject *) window)->filters); ++ GdkFilterReturn result = apply_event_filters (window, msg, &((GdkWindowObject *) window)->filters); + + if (result == GDK_FILTER_REMOVE || result == GDK_FILTER_TRANSLATE) + { +diff --git a/gdk/x11/gdkevents-x11.c b/gdk/x11/gdkevents-x11.c +index b96e9f5..8de98c5 100644 +--- a/gdk/x11/gdkevents-x11.c ++++ b/gdk/x11/gdkevents-x11.c +@@ -96,7 +96,7 @@ struct _GdkEventTypeX11 + + static gint gdk_event_apply_filters (XEvent *xevent, + GdkEvent *event, +- GList *filters); ++ GList **filters); + static gboolean gdk_event_translate (GdkDisplay *display, + GdkEvent *event, + XEvent *xevent, +@@ -341,21 +341,42 @@ gdk_event_get_graphics_expose (GdkWindow *window) + static gint + gdk_event_apply_filters (XEvent *xevent, + GdkEvent *event, +- GList *filters) ++ GList **filters) + { + GList *tmp_list; + GdkFilterReturn result; + +- tmp_list = filters; ++ tmp_list = *filters; + + while (tmp_list) + { + GdkEventFilter *filter = (GdkEventFilter*) tmp_list->data; ++ GList *node; + +- tmp_list = tmp_list->next; ++ if ((filter->flags & GDK_EVENT_FILTER_REMOVED) != 0) ++ { ++ tmp_list = tmp_list->next; ++ continue; ++ } ++ ++ filter->ref_count++; + result = filter->function (xevent, event, filter->data); +- if (result != GDK_FILTER_CONTINUE) +- return result; ++ ++ /* get the next node after running the function since the ++ function may add or remove a next node */ ++ node = tmp_list; ++ tmp_list = tmp_list->next; ++ ++ filter->ref_count--; ++ if (filter->ref_count == 0) ++ { ++ *filters = g_list_remove_link (*filters, node); ++ g_list_free_1 (node); ++ g_free (filter); ++ } ++ ++ if (result != GDK_FILTER_CONTINUE) ++ return result; + } + + return GDK_FILTER_CONTINUE; +@@ -944,7 +965,7 @@ gdk_event_translate (GdkDisplay *display, + /* Apply global filters */ + GdkFilterReturn result; + result = gdk_event_apply_filters (xevent, event, +- _gdk_default_filters); ++ &_gdk_default_filters); + + if (result != GDK_FILTER_CONTINUE) + { +@@ -1050,7 +1071,7 @@ gdk_event_translate (GdkDisplay *display, + g_object_ref (filter_window); + + result = gdk_event_apply_filters (xevent, event, +- filter_private->filters); ++ &filter_private->filters); + + g_object_unref (filter_window); + +-- +2.1.4 + diff -Nru gtk+2.0-2.24.25/debian/patches/series gtk+2.0-2.24.25/debian/patches/series --- gtk+2.0-2.24.25/debian/patches/series 2014-08-10 13:47:58.000000000 +0100 +++ gtk+2.0-2.24.25/debian/patches/series 2015-02-23 17:45:00.000000000 +0000 @@ -1,3 +1,4 @@ +0001-Make-gdk_event_apply_filters-safe-against-changes-in.patch 001_static-linking-dont-query-immodules.patch 002_static-linking-dont-build-perf.patch 003_gdk.pc_privates.patch
signature.asc
Description: Digital signature