After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 709967 - Double free in gtkicontheme.c
Double free in gtkicontheme.c
Status: RESOLVED FIXED
Product: gtk+
Classification: Platform
Component: .General
3.10.x
Other Linux
: Normal critical
: ---
Assigned To: gtk-bugs
gtk-bugs
Depends on:
Blocks:
 
 
Reported: 2013-10-12 06:38 UTC by Sebastián E. Peyrott
Modified: 2013-10-16 01:30 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Fixes double-free. (974 bytes, patch)
2013-10-12 06:38 UTC, Sebastián E. Peyrott
none Details | Review
New fix with jjacky recommendation (712 bytes, patch)
2013-10-13 23:45 UTC, Sebastián E. Peyrott
needs-work Details | Review
New patch. Properly formatted. (1.04 KB, patch)
2013-10-15 22:39 UTC, Sebastián E. Peyrott
none Details | Review

Description Sebastián E. Peyrott 2013-10-12 06:38:24 UTC
Created attachment 257086 [details] [review]
Fixes double-free.

Since GTK version 3.10.1 Gnome Shell has been crashing on my system when showing the activities view. Reverting to GTK version 3.10.0 fixes the problem. 

I traced the crash to commit 8938f3c47da6a09ea79dca910e06089c8a32c217 which is related to bug 709264.

The double free is caused by 'g_clear_error (&icon_info->load_error);' in the finalize function. load_error is first freed by this call: '        g_propagate_error (error, icon_info->load_error);' in 'gtk_icon_info_load_icon' when 'error' is NULL (g_propagate_error frees the second parameter if the first is NULL, personally I find that behavior prone to cause errors).

I have attached a patch that fixes the crash I was experiencing.

Here's a backtrace that seems to confirm what was described above:

Program received signal SIGABRT, Aborted.
0x00000034b74353d9 in raise () from /usr/lib/libc.so.6
  • #0 raise
    from /usr/lib/libc.so.6
  • #1 abort
    from /usr/lib/libc.so.6
  • #2 g_slice_free1
    from /usr/lib/libglib-2.0.so.0
  • #3 g_clear_error
    from /usr/lib/libglib-2.0.so.0
  • #4 gtk_icon_info_finalize
    from /usr/lib/libgtk-3.so.0
  • #5 g_object_unref
    from /usr/lib/libgobject-2.0.so.0
  • #6 ??
    from /usr/lib/libgio-2.0.so.0
  • #7 g_object_unref
    from /usr/lib/libgobject-2.0.so.0
  • #8 ??
    from /usr/lib/libglib-2.0.so.0
  • #9 ??
    from /usr/lib/libglib-2.0.so.0
  • #10 g_main_context_dispatch
    from /usr/lib/libglib-2.0.so.0
  • #11 ??
    from /usr/lib/libglib-2.0.so.0
  • #12 g_main_loop_run
    from /usr/lib/libglib-2.0.so.0
  • #13 meta_run
    from /usr/lib/libmutter.so.0
  • #14 ??
  • #15 __libc_start_main
    from /usr/lib/libc.so.6
  • #16 ??

The process is Gnome Shell. This trace can easily be triggered by setting G_SLICE=debug-blocks. Otherwise the crash is triggered later in other calls to g_slice_free.
Comment 1 Alfonso 2013-10-13 16:30:46 UTC
I'm experiencing this bug too. With the upgrade to gtk 3.10.1 the system has become unusable, crashing every time that you try to show the activities view. Downgrading to 3.10.0 fixes the problem. I'm using the default theme for gtk and gnome-shell, in case it makes any difference.
Comment 2 Olivier Brunel (jjacky) 2013-10-13 23:12:21 UTC
Review of attachment 257086 [details] [review]:

::: gtk/gtkicontheme.c
@@ +3882,3 @@
+             be possible for the caller to request the error later. */ 
+          if (error)
+            g_propagate_error (error, icon_info->load_error);

This looks wrong to me, because if error isn't NULL you'll get the same double-free crash. Instead of propagate you should do *error = g_error_copy (icon_info->load_error);
Comment 3 Sebastián E. Peyrott 2013-10-13 23:19:35 UTC
You are probably correct. I assumed this line in the docs:

"If dest is NULL, free src; otherwise, moves src into *dest. The error variable dest points to must be NULL."

...meant that g_propagate_error would take care of everything (now I notice g_propagate_error cannot possibly set src to NULL). It is probably meant to be used as one of the last lines in a function (similar to throw in exceptions perhaps?).

Anyway, your suggestion is correct, I'll make a new patch.
Comment 4 Sebastián E. Peyrott 2013-10-13 23:45:25 UTC
Created attachment 257199 [details] [review]
New fix with jjacky recommendation

Patch with jjacky's recommendation. Compiled and tested agains master/HEAD. No crashes in Gnome Shell.
Comment 5 Philipe Reis 2013-10-14 16:17:56 UTC
I'm affected too. Gnome-shell with crashing activities is unusable. Reverting to gtk 3.10.0 fixed. Strangely I'm not affected in another computer.
Comment 6 Emmanuele Bassi (:ebassi) 2013-10-15 10:46:49 UTC
GtkIconView has nothing to do with GtkIconTheme; re-assigning to the right component.
Comment 7 Emmanuele Bassi (:ebassi) 2013-10-15 10:52:51 UTC
Review of attachment 257199 [details] [review]:

thanks for the patch. it would be great if you could attach a patch formatted using `git format-patch`, or using `git bz`, as it makes it easier for us to review and apply (while also crediting the author).

::: gtk/gtkicontheme.c
@@ +3876,3 @@
+        {
+          /* g_propagate_error would be wrong here as
+             icon_info->load_error gets freed in the

g_propagate_error() clears the original error, but does not set it to NULL. g_clear_error() is NULL safe, so this should really be:

  if (icon_info->load_error != NULL)
    {
      g_propagate_error (error, icon_info->load_error);
      icon_info->load_error = NULL;
    }

@@ +3877,3 @@
+          /* g_propagate_error would be wrong here as
+             icon_info->load_error gets freed in the
+             finalizer. */

coding style: multi-line comments should be in the form:

  /* line 1
   * line 2
   */

@@ +3879,3 @@
+             finalizer. */
+          if (error)
+            *error = g_error_copy(icon_info->load_error);

coding style: missing space between function name and parenthesis.
Comment 8 Olivier Brunel (jjacky) 2013-10-15 11:42:33 UTC
> g_propagate_error() clears the original error, but does not set it to NULL.
> g_clear_error() is NULL safe, so this should really be:
> 
>   if (icon_info->load_error != NULL)
>     {
>       g_propagate_error (error, icon_info->load_error);
>       icon_info->load_error = NULL;
>     }

Are you sure? It seemed to me that the expected behavior was that icon_info->load_error should remain set, to indicate a load attempt was done & failed; Hence my suggestion of copying the error.
Comment 9 Emmanuele Bassi (:ebassi) 2013-10-15 11:52:36 UTC
(In reply to comment #8)
> > g_propagate_error() clears the original error, but does not set it to NULL.
> > g_clear_error() is NULL safe, so this should really be:
> > 
> >   if (icon_info->load_error != NULL)
> >     {
> >       g_propagate_error (error, icon_info->load_error);
> >       icon_info->load_error = NULL;
> >     }
> 
> Are you sure? It seemed to me that the expected behavior was that
> icon_info->load_error should remain set, to indicate a load attempt was done &
> failed; Hence my suggestion of copying the error.

the intent seems to be that one, yes. as far as I can see it, the only case where load_icon() can be called multiple times after an error is that somebody is mixing the synchronous and asynchronous API in the same process, using the same GtkIconInfo. the whole design seems to be a bit messy to me, with far too much caching going on.

anyway, g_error_copy() seems to be what gtk_icon_info_load_icon_finish() uses, so we can use it in load_icon() as well.

could you please amend your patch so that it follows the GTK coding style, and use git format-patch? that would be most helpful.
Comment 10 Sebastián E. Peyrott 2013-10-15 14:14:56 UTC
I see this was fixed in d967266b772f3050dffae98aa449128f63055fc4 in master, so there's no need to resubmit the patch I guess. Thanks for reviewing the patch, I'll make sure to follow the guidelines in the future.
Comment 11 Sebastián E. Peyrott 2013-10-15 14:20:32 UTC
Whoa, is this line right in the commit?

if (*error)

I though error was a pointer to a pointer, so you could pass NULL as a parameter in case you did not want to receive the error. If so, this would crash? I'm at work right now, so I cannot take a deeper look right now.
Comment 12 Olivier Brunel (jjacky) 2013-10-15 14:56:32 UTC
Yeah, that commit will cause a segfault if error is NULL, needs to be fixed.
Comment 13 Sebastián E. Peyrott 2013-10-15 22:38:38 UTC
Reopening (see previous comments).
Comment 14 Sebastián E. Peyrott 2013-10-15 22:39:23 UTC
Created attachment 257393 [details] [review]
New patch. Properly formatted.

Attached properly formatted patch. If you want a fix against master HEAD, let me know.
Comment 15 Matthias Clasen 2013-10-16 01:30:51 UTC
Thanks, fixed