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
This commit is contained in:
Kristian Rietveld
2017-01-01 21:04:04 +01:00
committed by John Ralls
parent 93bf85e92f
commit 91f2ad4a2f

View File

@ -370,7 +370,6 @@ gtk_clipboard_set_contents (GtkClipboard *clipboard,
gpointer user_data, gpointer user_data,
gboolean have_owner) gboolean have_owner)
{ {
GtkClipboardOwner *owner;
NSSet *types; NSSet *types;
NSAutoreleasePool *pool; NSAutoreleasePool *pool;
@ -406,26 +405,35 @@ gtk_clipboard_set_contents (GtkClipboard *clipboard,
*/ */
if (user_data && user_data == clipboard->user_data) if (user_data && user_data == clipboard->user_data)
{ {
owner = [clipboard->owner retain]; clipboard->owner->setting_same_owner = TRUE;
owner->setting_same_owner = TRUE;
clipboard->change_count = [clipboard->pasteboard declareTypes: [types allObjects] clipboard->change_count = [clipboard->pasteboard declareTypes: [types allObjects]
owner: owner]; owner: clipboard->owner];
owner->setting_same_owner = FALSE; clipboard->owner->setting_same_owner = FALSE;
} }
else 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] 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]; [types release];
[pool release]; [pool release];
clipboard->owner = owner;
clipboard->user_data = user_data; clipboard->user_data = user_data;
clipboard->have_owner = have_owner; clipboard->have_owner = have_owner;
if (have_owner) if (have_owner)
@ -538,6 +546,8 @@ clipboard_unset (GtkClipboard *clipboard)
g_free (clipboard->storable_targets); g_free (clipboard->storable_targets);
clipboard->storable_targets = NULL; clipboard->storable_targets = NULL;
if (clipboard->owner)
[clipboard->owner release];
clipboard->owner = NULL; clipboard->owner = NULL;
clipboard->get_func = NULL; clipboard->get_func = NULL;
clipboard->clear_func = NULL; clipboard->clear_func = NULL;