[gtk+] wayland: protect against unknown mimetype requests



commit 342db27278b530a99f70c96887bb153a5507f5d2
Author: Carlos Garnacho <carlosg gnome org>
Date:   Wed Jun 24 22:10:55 2015 +0200

    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

 gdk/wayland/gdkselection-wayland.c |   39 +++++++++++++++++++++++++++++++++++-
 1 files changed, 38 insertions(+), 1 deletions(-)
---
diff --git a/gdk/wayland/gdkselection-wayland.c b/gdk/wayland/gdkselection-wayland.c
index ac5d38e..d0e7e7d 100644
--- a/gdk/wayland/gdkselection-wayland.c
+++ b/gdk/wayland/gdkselection-wayland.c
@@ -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);
@@ -549,6 +552,27 @@ gdk_wayland_selection_lookup_requestor_buffer (GdkWindow *requestor)
 }
 
 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,
                                       GdkAtom              target,
@@ -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);
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]