Andrew Geissler | 82c905d | 2020-04-13 13:39:40 -0500 | [diff] [blame] | 1 | From ef2be42998e3fc10299055a5a01f7c791538174c Mon Sep 17 00:00:00 2001 |
| 2 | From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= <sebastian@centricular.com> |
| 3 | Date: Mon, 3 Feb 2020 15:38:28 +0200 |
| 4 | Subject: [PATCH] GMainContext - Fix GSource iterator if iteration can modify |
| 5 | the list |
| 6 | |
| 7 | We first have to ref the next source and then unref the previous one. |
| 8 | This might be the last reference to the previous source, and freeing the |
| 9 | previous source might unref and free the next one which would then leave |
| 10 | use with a dangling pointer here. |
| 11 | |
| 12 | Fixes https://gitlab.gnome.org/GNOME/glib/issues/2031 |
| 13 | |
| 14 | Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/glib/-/commit/b06c48de7554607ff3fb58d6c0510cfa5088e909] |
| 15 | |
| 16 | --- |
| 17 | glib/gmain.c | 8 ++++++-- |
| 18 | 1 file changed, 6 insertions(+), 2 deletions(-) |
| 19 | |
| 20 | diff --git a/glib/gmain.c b/glib/gmain.c |
| 21 | index af979c8..a9a287d 100644 |
| 22 | --- a/glib/gmain.c |
| 23 | +++ b/glib/gmain.c |
| 24 | @@ -969,13 +969,17 @@ g_source_iter_next (GSourceIter *iter, GSource **source) |
| 25 | * GSourceList to be removed from source_lists (if iter->source is |
| 26 | * the only source in its list, and it is destroyed), so we have to |
| 27 | * keep it reffed until after we advance iter->current_list, above. |
| 28 | + * |
| 29 | + * Also we first have to ref the next source before unreffing the |
| 30 | + * previous one as unreffing the previous source can potentially |
| 31 | + * free the next one. |
| 32 | */ |
| 33 | + if (next_source && iter->may_modify) |
| 34 | + g_source_ref (next_source); |
| 35 | |
| 36 | if (iter->source && iter->may_modify) |
| 37 | g_source_unref_internal (iter->source, iter->context, TRUE); |
| 38 | iter->source = next_source; |
| 39 | - if (iter->source && iter->may_modify) |
| 40 | - g_source_ref (iter->source); |
| 41 | |
| 42 | *source = iter->source; |
| 43 | return *source != NULL; |