gnucash maint: Bug 797481 - crash on close of unsaved tabs by pressing [X]

John Ralls jralls at code.gnucash.org
Fri Jan 3 16:18:50 EST 2020


Updated	 via  https://github.com/Gnucash/gnucash/commit/b5fdcfcb (commit)
	from  https://github.com/Gnucash/gnucash/commit/d409d009 (commit)



commit b5fdcfcb5b31a639d82cc79920ecf830c33ec450
Author: John Ralls <jralls at ceridwen.us>
Date:   Fri Jan 3 13:13:55 2020 -0800

    Bug 797481 - crash on close of unsaved tabs by pressing [X]
    
    Use g_object_weak_ref() to null GncItemEdit::sheet to prevent
    a use-after-free crash.
    
    Note that this is a band-aid fix. To fix correctly GncItemEdit and probably
    most of the rest of the register must be rewritten with modern GObject
    macros and resource management.

diff --git a/gnucash/register/register-gnome/gnucash-item-edit.c b/gnucash/register/register-gnome/gnucash-item-edit.c
index d9b79e54d..bce88ead5 100644
--- a/gnucash/register/register-gnome/gnucash-item-edit.c
+++ b/gnucash/register/register-gnome/gnucash-item-edit.c
@@ -229,6 +229,9 @@ gnc_item_edit_get_pixel_coords (GncItemEdit *item_edit,
     SheetBlock *block;
     int xd, yd;
 
+    if (sheet == NULL)
+        return;
+
     block = gnucash_sheet_get_block (sheet, item_edit->virt_loc.vcell_loc);
     if (block == NULL)
         return;
@@ -257,6 +260,8 @@ gnc_item_edit_update (GncItemEdit *item_edit)
 {
     gint x = 0, y = 0, w, h;
 
+    if (item_edit == NULL || item_edit->sheet == NULL)
+        return FALSE;
     gnc_item_edit_get_pixel_coords (item_edit, &x, &y, &w, &h);
     gtk_layout_move (GTK_LAYOUT(item_edit->sheet),
                      GTK_WIDGET(item_edit), x, y);
@@ -657,6 +662,28 @@ gnc_item_edit_get_property (GObject *object,
     }
 }
 
+/* FIXME: Idle events calling gnc_item_edit_update can fire after the
+ * GncItemEdit is finalized, but because the GncItemEdit class is
+ * defined by hand instead of with the GType macros there's no way to
+ * run gnc_item_edit_dispose or gnc_item_edit_finalize to null out the
+ * pointers. We resort instead to a weak reference to null out the
+ * sheet when it gets finalized to prevent gnc_item_edit_upate from
+ * accessing the freed sheet.
+ *
+ * https://bugs.gnucash.org/show_bug.cgi?id=797481
+ *
+ * Note that this is still not bulletproof, after all we're still
+ * using the GncItemEdit after it has been freed but without a dispose
+ * function to do this correctly we're a bit stuck.
+ */
+static void
+sheet_destroyed (gpointer data, GObject *table)
+{
+     GncItemEdit *item_edit = (GncItemEdit*)data;
+     if (item_edit)
+          item_edit->sheet = NULL;
+}
+
 static void
 gnc_item_edit_set_property (GObject *object,
                             guint param_id,
@@ -664,11 +691,18 @@ gnc_item_edit_set_property (GObject *object,
                             GParamSpec *pspec)
 {
     GncItemEdit *item_edit = GNC_ITEM_EDIT (object);
-
     switch (param_id)
     {
     case PROP_SHEET:
+         if (item_edit->sheet)
+             g_object_weak_unref(G_OBJECT(item_edit->sheet),
+                                 (GWeakNotify)sheet_destroyed,
+                                 (gpointer)item_edit);
         item_edit->sheet = GNUCASH_SHEET (g_value_get_object (value));
+        if (item_edit->sheet)
+            g_object_weak_ref(G_OBJECT(item_edit->sheet),
+                              (GWeakNotify)sheet_destroyed,
+                              (gpointer)item_edit);
         break;
     default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
@@ -731,7 +765,9 @@ gnc_item_edit_class_init (GncItemEditClass *gnc_item_edit_class)
     widget_class->get_preferred_height = gnc_item_edit_get_preferred_height;
 }
 
-
+/* FIXME: This way of initializing GObjects is obsolete. We should be
+ * using G_DECLARE_FINAL_TYPE instead of rolling _get_type by hand.
+ */
 GType
 gnc_item_edit_get_type (void)
 {



Summary of changes:
 .../register/register-gnome/gnucash-item-edit.c    | 40 ++++++++++++++++++++--
 1 file changed, 38 insertions(+), 2 deletions(-)



More information about the gnucash-changes mailing list