wayland: protect against unknown mimetype requests
This oddly can be reproduced with weston+weston-dnd, when dragging anything from GTK+ into weston-dnd, it will insist on picking its custom application/x-wayland-dnd-flower mimetype, and this request forwarded by the compositor, even if GTK+ didn't announce it on its wl_data_source mimetype list. (What should probably happen here is that the request is silenced, and/or weston-dnd picks (null)) This should be harmless, we are leaking though the fd in that case, because the emission of GdkEventSelection on an unhandled mimetype results in NOP. In order to avoid this, we should check whether the mimetype is supported at all on the backend code and possibly close the fd, this involves storing these in the first place. https://bugzilla.gnome.org/show_bug.cgi?id=751414
This commit is contained in:
@ -89,6 +89,7 @@ struct _GdkWaylandSelection
|
||||
|
||||
/* Source-side data */
|
||||
StoredSelection stored_selection;
|
||||
GArray *source_targets;
|
||||
|
||||
struct wl_data_source *clipboard_source;
|
||||
GdkWindow *clipboard_owner;
|
||||
@ -273,6 +274,7 @@ gdk_wayland_selection_new (void)
|
||||
g_hash_table_new_full (NULL, NULL, NULL,
|
||||
(GDestroyNotify) selection_buffer_cancel_and_unref);
|
||||
selection->stored_selection.fd = -1;
|
||||
selection->source_targets = g_array_new (FALSE, FALSE, sizeof (GdkAtom));
|
||||
return selection;
|
||||
}
|
||||
|
||||
@ -280,6 +282,7 @@ void
|
||||
gdk_wayland_selection_free (GdkWaylandSelection *selection)
|
||||
{
|
||||
g_hash_table_destroy (selection->selection_buffers);
|
||||
g_array_unref (selection->source_targets);
|
||||
|
||||
if (selection->targets)
|
||||
g_list_free (selection->targets);
|
||||
@ -548,6 +551,27 @@ gdk_wayland_selection_lookup_requestor_buffer (GdkWindow *requestor)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_wayland_selection_source_handles_target (GdkWaylandSelection *wayland_selection,
|
||||
GdkAtom target)
|
||||
{
|
||||
GdkAtom atom;
|
||||
guint i;
|
||||
|
||||
if (target == GDK_NONE)
|
||||
return FALSE;
|
||||
|
||||
for (i = 0; i < wayland_selection->source_targets->len; i++)
|
||||
{
|
||||
atom = g_array_index (wayland_selection->source_targets, GdkAtom, i);
|
||||
|
||||
if (atom == target)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_wayland_selection_request_target (GdkWaylandSelection *wayland_selection,
|
||||
GdkWindow *window,
|
||||
@ -578,11 +602,17 @@ gdk_wayland_selection_request_target (GdkWaylandSelection *wayland_selection,
|
||||
|
||||
wayland_selection->source_requested_target = target;
|
||||
|
||||
if (window && target != GDK_NONE)
|
||||
if (window &&
|
||||
gdk_wayland_selection_source_handles_target (wayland_selection, target))
|
||||
{
|
||||
gdk_wayland_selection_emit_request (window, selection, target);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
close (fd);
|
||||
wayland_selection->stored_selection.fd = -1;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
@ -1027,6 +1057,8 @@ gdk_wayland_selection_add_targets (GdkWindow *window,
|
||||
guint ntargets,
|
||||
GdkAtom *targets)
|
||||
{
|
||||
GdkDisplay *display = gdk_window_get_display (window);
|
||||
GdkWaylandSelection *wayland_selection = gdk_wayland_display_get_selection (display);
|
||||
struct wl_data_source *data_source;
|
||||
guint i;
|
||||
|
||||
@ -1037,6 +1069,8 @@ gdk_wayland_selection_add_targets (GdkWindow *window,
|
||||
if (!data_source)
|
||||
return;
|
||||
|
||||
g_array_append_vals (wayland_selection->source_targets, targets, ntargets);
|
||||
|
||||
for (i = 0; i < ntargets; i++)
|
||||
wl_data_source_offer (data_source, gdk_atom_name (targets[i]));
|
||||
|
||||
@ -1057,5 +1091,8 @@ void
|
||||
gdk_wayland_selection_clear_targets (GdkDisplay *display,
|
||||
GdkAtom selection)
|
||||
{
|
||||
GdkWaylandSelection *wayland_selection = gdk_wayland_display_get_selection (display);
|
||||
|
||||
g_array_set_size (wayland_selection->source_targets, 0);
|
||||
gdk_wayland_selection_unset_data_source (display, selection);
|
||||
}
|
||||
|
Reference in New Issue
Block a user