psppire-data-sheet: Disconnect clipboard owner-change signal on dispose.
authorBen Pfaff <blp@cs.stanford.edu>
Mon, 6 May 2013 04:39:16 +0000 (21:39 -0700)
committerBen Pfaff <blp@cs.stanford.edu>
Mon, 6 May 2013 04:39:16 +0000 (21:39 -0700)
Otherwise, any clipboard change in ownership (e.g. clicking on some cells
and typing Control+C), even after a given PsppireDataSheet closes, still
calls into on_owner_change() and commits a use-after-free error.

Reported by John Darrington.

src/ui/gui/psppire-data-sheet.c
src/ui/gui/psppire-data-sheet.h

index 201fa8cd79cd9e0d3102986545b3c99a84b0b060..01afb5ed8772e50a9bd136241de385429a0d646e 100644 (file)
@@ -1203,6 +1203,13 @@ psppire_data_sheet_dispose (GObject *object)
 {
   PsppireDataSheet *data_sheet = PSPPIRE_DATA_SHEET (object);
 
+  if (data_sheet->clip != NULL && data_sheet->on_owner_change_signal != 0)
+    {
+      g_signal_handler_disconnect (data_sheet->clip,
+                                   data_sheet->on_owner_change_signal);
+      data_sheet->on_owner_change_signal = 0;
+    }
+
   if (data_sheet->dispose_has_run)
     return;
 
@@ -1221,14 +1228,19 @@ psppire_data_sheet_dispose (GObject *object)
 static void
 psppire_data_sheet_map (GtkWidget *widget)
 {
-  GtkClipboard *clip;
+  PsppireDataSheet *data_sheet = PSPPIRE_DATA_SHEET (widget);
 
   GTK_WIDGET_CLASS (psppire_data_sheet_parent_class)->map (widget);
 
-  clip = gtk_widget_get_clipboard (widget, GDK_SELECTION_CLIPBOARD);
-  g_signal_connect (clip, "owner-change", G_CALLBACK (on_owner_change),
-                    widget);
-  on_owner_change (clip, NULL, widget);
+  data_sheet->clip = gtk_widget_get_clipboard (widget,
+                                               GDK_SELECTION_CLIPBOARD);
+  if (data_sheet->on_owner_change_signal)
+    g_signal_handler_disconnect (data_sheet->clip,
+                                 data_sheet->on_owner_change_signal);
+  data_sheet->on_owner_change_signal
+    = g_signal_connect (data_sheet->clip, "owner-change",
+                        G_CALLBACK (on_owner_change), widget);
+  on_owner_change (data_sheet->clip, NULL, widget);
 }
 
 static void
@@ -1690,6 +1702,7 @@ psppire_data_sheet_init (PsppireDataSheet *obj)
 
   obj->scroll_to_bottom_signal = 0;
   obj->scroll_to_right_signal = 0;
+  obj->on_owner_change_signal = 0;
   obj->new_variable_column = NULL;
   obj->container = NULL;
 
index 5e553ec646485f7afab5769bf04cf9161b68d56e..8497e2c1155ff23a5bc5cc1e5b3bdaa76433c5c0 100644 (file)
@@ -53,6 +53,9 @@ struct _PsppireDataSheet
   guint scroll_to_bottom_signal;
   guint scroll_to_right_signal;
 
+  GtkClipboard *clip;
+  guint on_owner_change_signal;
+
   PsppSheetViewColumn *new_variable_column;
 
   GtkBuilder *builder;