[gtkmm/gtkmm-2-16] Correct misuse of container handle (bgo #586626)



commit 9171bfc30d06e81c8bc8daef0636a783af8cf8d3
Author: Daniel Elstner <danielk openismus com>
Date:   Tue Sep 15 16:49:51 2009 +0200

    Correct misuse of container handle (bgo #586626)
    
    * gtk/src/clipboard.{ccg,hg} (Clipboard::wait_for_targets): Create
    an intermediate array of allocated C strings and transfer ownership
    on return, instead of trying to returned a handle to a container
    with local scope.  (Based on patch by Peter Clifton.)
    (SignalProxy_TargetsReceived_gtk_callback): Correct another misuse
    of the container handles similar to the above, except for the crash.
    (SignalProxy_RichTextReceived_gtk_callback): Simplify the code and
    plug a memory leak in the event of an exception.

 ChangeLog             |   13 ++++++
 gtk/src/clipboard.ccg |  109 +++++++++++++++++++-----------------------------
 2 files changed, 56 insertions(+), 66 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 54b4889..268f232 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2009-09-15  Daniel Elstner  <danielk openismus com>
+
+	Correct misuse of container handle (bgo #586626)
+
+	* gtk/src/clipboard.{ccg,hg} (Clipboard::wait_for_targets): Create
+	an intermediate array of allocated C strings and transfer ownership
+	on return, instead of trying to returned a handle to a container
+	with local scope.  (Based on patch by Peter Clifton.)
+	(SignalProxy_TargetsReceived_gtk_callback): Correct another misuse
+	of the container handles similar to the above, except for the crash.
+	(SignalProxy_RichTextReceived_gtk_callback): Simplify the code and
+	plug a memory leak in the event of an exception.
+
 2009-09-07  Murray Cumming  <murrayc murrayc com>
 
 	* gtk/src/enums.hg: Include gtkmmconfig.h because we use 
diff --git a/gtk/src/clipboard.ccg b/gtk/src/clipboard.ccg
index eff18bf..04ac5a9 100644
--- a/gtk/src/clipboard.ccg
+++ b/gtk/src/clipboard.ccg
@@ -1,6 +1,3 @@
-// -*- c++ -*-
-/* $Id: clipboard.ccg,v 1.11 2006/06/13 17:16:26 murrayc Exp $ */
-
 /* 
  *
  * Copyright 2002 The gtkmm Development Team
@@ -118,47 +115,33 @@ static void SignalProxy_Received_gtk_callback(GtkClipboard*, GtkSelectionData* s
   delete the_slot;
 }
 
-//This is not public API:
-typedef std::list<Glib::ustring> listStrings;
-static listStrings util_convert_atoms_to_strings(GdkAtom* targets, int n_targets)
+static void SignalProxy_TargetsReceived_gtk_callback(GtkClipboard*, GdkAtom* atoms,
+                                                     gint n_atoms, gpointer data)
 {
-  listStrings listTargets;
+  Gtk::Clipboard::SlotTargetsReceived *const
+    slot = static_cast<Gtk::Clipboard::SlotTargetsReceived*>(data);
 
-  //Add the targets to the C++ container:
-  for(int i = 0; i < n_targets; i++)
+#ifdef GLIBMM_EXCEPTIONS_ENABLED
+  try
+#endif
   {
-    //Convert the atom to a string:
-    char* atom_name = gdk_atom_name(targets[i]);
-    if(atom_name)
-    {
-      listTargets.push_back( Glib::ustring(atom_name) );
-      g_free(atom_name);
-    }
-  }
+    // TODO: This conversion should normally be performed in a custom
+    // Traits implementation.  Alternatively, a real container could
+    // have been used as the argument instead of handle.
+    const unsigned int n_names = (n_atoms > 0) ? n_atoms : 0;
+    char** names = g_new(char*, n_names);
 
-  return listTargets;
-}
+    std::transform(&atoms[0], &atoms[n_names], &names[0], &gdk_atom_name);
 
-static void SignalProxy_TargetsReceived_gtk_callback(GtkClipboard*, GdkAtom* atoms, gint n_atoms, gpointer data)
-{
-  Gtk::Clipboard::SlotTargetsReceived* the_slot = static_cast<Gtk::Clipboard::SlotTargetsReceived*>(data);
-
-  #ifdef GLIBMM_EXCEPTIONS_ENABLED
-  try
-  {
-  #endif //GLIBMM_EXCEPTIONS_ENABLED
-    listStrings listTargets = util_convert_atoms_to_strings(atoms, n_atoms);
-    (*the_slot)(listTargets);
-    //I guess that GTK+ does a g_free of the GdkAtoms* array itself, so we do not need to. murrayc.
-  #ifdef GLIBMM_EXCEPTIONS_ENABLED
+    (*slot)(Glib::StringArrayHandle(names, n_names, Glib::OWNERSHIP_DEEP));
   }
-  catch(...)
+#ifdef GLIBMM_EXCEPTIONS_ENABLED
+  catch (...)
   {
     Glib::exception_handlers_invoke();
   }
-  #endif //GLIBMM_EXCEPTIONS_ENABLED
-
-  delete the_slot; // the callback is only used once
+#endif
+  delete slot; // the callback is only used once
 }
 
 
@@ -182,26 +165,26 @@ static void SignalProxy_TextReceived_gtk_callback(GtkClipboard*, const char* tex
   delete the_slot; // the callback is only used once
 }
 
-static void SignalProxy_RichTextReceived_gtk_callback(GtkClipboard*, GdkAtom format, const guint8* text, gsize             length, void* data)
+static void SignalProxy_RichTextReceived_gtk_callback(GtkClipboard*, GdkAtom format,
+                                                      const guint8* text, gsize length, void* data)
 {
-  Gtk::Clipboard::SlotRichTextReceived* the_slot = static_cast<Gtk::Clipboard::SlotRichTextReceived*>(data);
+  Gtk::Clipboard::SlotRichTextReceived *const
+    slot = static_cast<Gtk::Clipboard::SlotRichTextReceived*>(data);
 
-  #ifdef GLIBMM_EXCEPTIONS_ENABLED
+#ifdef GLIBMM_EXCEPTIONS_ENABLED
   try
+#endif
   {
-  #endif //GLIBMM_EXCEPTIONS_ENABLED
-    gchar* format_atom_name = gdk_atom_name(format);
-    (*the_slot)( (format_atom_name ? Glib::ustring(format_atom_name) : Glib::ustring()), (text ? std::string((char*)text, length) : std::string()) );
-    g_free(format_atom_name);
-  #ifdef GLIBMM_EXCEPTIONS_ENABLED
+    (*slot)(Glib::convert_return_gchar_ptr_to_ustring(gdk_atom_name(format)),
+            (text) ? std::string(reinterpret_cast<const char*>(text), length) : std::string());
   }
+#ifdef GLIBMM_EXCEPTIONS_ENABLED
   catch(...)
   {
     Glib::exception_handlers_invoke();
   }
-  #endif //GLIBMM_EXCEPTIONS_ENABLED
-
-  delete the_slot; // the callback is only used once
+#endif
+  delete slot; // the callback is only used once
 }
 
 static void SignalProxy_UrisReceived_gtk_callback(GtkClipboard*, gchar** uris, void* data)
@@ -329,29 +312,23 @@ SelectionData Clipboard::wait_for_contents(const Glib::ustring& target) const
 
 Glib::StringArrayHandle Clipboard::wait_for_targets() const
 {
-  std::list<Glib::ustring> listTargets;
-
-  //Get a newly-allocated array of atoms:
-  GdkAtom* targets = 0;
-  gint n_targets = 0;
-  gboolean test = gtk_clipboard_wait_for_targets( const_cast<GtkClipboard*>(gobj()), &targets, &n_targets );
-  if(!test)
-    n_targets = 0; //otherwise it will be -1.
-
-  //Add the targets to the C++ container:
-  for(int i = 0; i < n_targets; i++)
+  char**   names = 0;
+  GdkAtom* atoms = 0;
+  int  n_targets = 0;
+
+  // TODO: This works, but is not the intended way to use the array handles.
+  // Normally one would define custom Traits for the conversion, but that is
+  // not possible here because it would break binary compatibility.
+  if (gtk_clipboard_wait_for_targets(const_cast<GtkClipboard*>(gobj()), &atoms, &n_targets))
   {
-    //Convert the atom to a string:
-    gchar* const atom_name = gdk_atom_name(targets[i]);
-
-    Glib::ustring target;
-    if(atom_name)
-      target = Glib::ScopedPtr<char>(atom_name).get(); //This frees the gchar*.
-
-    listTargets.push_back(target);
+    names = g_new(char*, n_targets);
+    std::transform(&atoms[0], &atoms[n_targets], &names[0], &gdk_atom_name);
+    g_free(atoms);
   }
+  else
+    n_targets = 0;
 
-  return listTargets;
+  return Glib::StringArrayHandle(names, n_targets, Glib::OWNERSHIP_DEEP);
 }
 
 void Clipboard::set_can_store(const ArrayHandle_TargetEntry& targets)



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