From 91f2ad4a2fc5c6027d3fa72f1344aecde2230509 Mon Sep 17 00:00:00 2001 From: Kristian Rietveld Date: Sun, 1 Jan 2017 21:04:04 +0100 Subject: [PATCH] Bug 743717 - Crashes on clipboard operation, influence by clipboard ... The problem here was that NSPasteboard would release the clipboard owner if all data items were transferred. When trying to re-use this owner at a later point, GTK+ would attempt a retain call on a released object and crash. Fix this by not immediately releasing the owner after declaring types, so by keeping our own reference around. Closes https://gitlab.gnome.org/GNOME/gtk/issues/529 --- gtk/gtkclipboard-quartz.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/gtk/gtkclipboard-quartz.c b/gtk/gtkclipboard-quartz.c index cdf8db0541..c01a9cd627 100644 --- a/gtk/gtkclipboard-quartz.c +++ b/gtk/gtkclipboard-quartz.c @@ -370,7 +370,6 @@ gtk_clipboard_set_contents (GtkClipboard *clipboard, gpointer user_data, gboolean have_owner) { - GtkClipboardOwner *owner; NSSet *types; NSAutoreleasePool *pool; @@ -406,26 +405,35 @@ gtk_clipboard_set_contents (GtkClipboard *clipboard, */ if (user_data && user_data == clipboard->user_data) { - owner = [clipboard->owner retain]; - - owner->setting_same_owner = TRUE; + clipboard->owner->setting_same_owner = TRUE; clipboard->change_count = [clipboard->pasteboard declareTypes: [types allObjects] - owner: owner]; - owner->setting_same_owner = FALSE; + owner: clipboard->owner]; + clipboard->owner->setting_same_owner = FALSE; } else { - owner = [[GtkClipboardOwner alloc] initWithClipboard:clipboard]; + GtkClipboardOwner *new_owner; + /* We do not set the new owner on clipboard->owner immediately, + * because declareTypes could (but not always does -- see also the + * comment at pasteboardChangedOwner above) cause clipboard_unset + * to be called, which releases clipboard->owner. + */ + new_owner = [[GtkClipboardOwner alloc] initWithClipboard:clipboard]; clipboard->change_count = [clipboard->pasteboard declareTypes: [types allObjects] - owner: owner]; + owner: new_owner]; + + /* In case pasteboardChangedOwner was not triggered, check to see + * whether the previous owner still needs to be released. + */ + if (clipboard->owner) + [clipboard->owner release]; + clipboard->owner = new_owner; } - [owner release]; [types release]; [pool release]; - clipboard->owner = owner; clipboard->user_data = user_data; clipboard->have_owner = have_owner; if (have_owner) @@ -538,6 +546,8 @@ clipboard_unset (GtkClipboard *clipboard) g_free (clipboard->storable_targets); clipboard->storable_targets = NULL; + if (clipboard->owner) + [clipboard->owner release]; clipboard->owner = NULL; clipboard->get_func = NULL; clipboard->clear_func = NULL;