Public bug reported:

This issue happens sometimes but it's not enough to be considered a
serious issue. It's more of an annoyance when it happens but it still
should be fixed either way.

The issue is a Use-after-free bug in gtk_widget_dispose() due to in_destruction 
flag cleared too early
=============================================================================================

Affected Versions
-----------------

| Version | Status |
|---------|--------|
| GTK 4.22.2 (libgtk-4-1 4.22.2+ds-1ubuntu1) | Confirmed vulnerable (installed) 
|
| GTK 4.22.4 (4.22.4+ds-0ubuntu0.1) | Still vulnerable (latest available, 
checked source) |

The gtk-4-22 branch has no commits addressing this issue as of 4.22.4.

Environment
-----------

- Distribution: Ubuntu 26.04
- Package: nautilus 1:50.0-0ubuntu2
- Crash: SIGSEGV (signal 11) in g_type_check_instance_is_fundamentally_a()
- Trigger: Closing a Nautilus window while a signal handler re-enters the parent
  during destroy

Source Location
---------------

File: gtk/gtkwidget.c

| Function | Line (4.22.4) | Role |
|---|---|---|
| gtk_widget_dispose | 7638-7701 | Widget dispose handler |
| gtk_widget_real_destroy | 7721-7850 | Destroys template auto-children |

Root Cause
----------

In gtk_widget_dispose() at lines 7674-7679:

    if (!priv->in_destruction)
      {
        priv->in_destruction = TRUE;
        g_signal_emit (object, widget_signals[DESTROY], 0);
        priv->in_destruction = FALSE;           // BUG: cleared too early (line 
7678)
        gtk_widget_real_destroy (widget);       // children freed here (line 
7679)
      }

Then in gtk_widget_real_destroy():

- Line 7816: g_hash_table_remove(auto_child_hash, child_class->name)
  drops the last reference on template child widgets, triggering their full
  dispose() -> finalize() chain

- Line 7823: g_clear_pointer(&auto_children, g_hash_table_unref)
  crashes because children already freed via re-entrant destruction

Since in_destruction is FALSE when real_destroy runs, if a child's finalization
emits a signal that calls back into the parent widget (which is mid-destruction
but no longer protected), the parent's state can be corrupted or doubly-freed,
resulting in a SIGSEGV in g_type_check_instance_is_fundamentally_a() ->
g_object_unref().

Crash Stack (from Nautilus core dump)
--------------------------------------

    #0  g_type_check_instance_is_fundamentally_a()   invalid instance pointer
    #1  g_object_unref()
    #2  g_hash_table_unref()                          auto_children table (line 
7823)
    #3  g_hash_table_unref()
    #4  gtk_widget_real_destroy()                     line 7823
    #5  g_signal_emit() -> g_closure_invoke()          re-entrant signal
    #6  gtk_widget_dispose()                          re-entered, no protection
    #7  g_object_unref()                              child's last ref dropped
    #8  g_hash_table_remove()                         line 7816
    #9  gtk_widget_real_destroy()                     line 7679
    #10 gtk_widget_dispose()                          line 7674-7679

Fix
---

Move priv->in_destruction = FALSE to AFTER gtk_widget_real_destroy()
completes:

    if (!priv->in_destruction)
      {
        priv->in_destruction = TRUE;
        g_signal_emit (object, widget_signals[DESTROY], 0);
    -   priv->in_destruction = FALSE;
        gtk_widget_real_destroy (widget);
    +   priv->in_destruction = FALSE;
      }

This ensures the parent remains protected by in_destruction while its children
are being torn down, preventing re-entrant destruction from corrupting the
parent's internal hash tables.

** Affects: gtk4 (Ubuntu)
     Importance: Undecided
         Status: New


** Tags: crash gtk4 in-destruction nautilus sigsegv use-after-free 
widget-dispose

-- 
You received this bug notification because you are a member of Ubuntu
Desktop Bugs, which is subscribed to gtk4 in Ubuntu.
https://bugs.launchpad.net/bugs/2156580

Title:
  Use after free bug in gtkwiget.c

To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/gtk4/+bug/2156580/+subscriptions


-- 
desktop-bugs mailing list
[email protected]
https://lists.ubuntu.com/mailman/listinfo/desktop-bugs

Reply via email to