GNOME Bugzilla – Bug 733232
rhythmbox crashes while using jamendo due to double free in libgrilo
Last modified: 2014-07-21 20:47:18 UTC
Steps to reproduce: 1. Go to jamendo tab in latest rhythmbox 2. Start clicking the "artist" / "album" / "feeds" at random. 3. Rhythmbox crashes with few seconds. System information: debian sid amd64 Package information: ii gir1.2-grilo-0.2 0.2.10-1 amd64 Framework for discovering and browsing media - GObject introspection data ii grilo-plugins-0.2:amd64 0.2.12-4 amd64 Framework for discovering and browsing media - Plugins ii grilo-plugins-0.2-dbg:amd64 0.2.12-4 amd64 Framework for discovering and browsing media - Plugin debugging symbols ii libgrilo-0.2-1:amd64 0.2.10-1 amd64 Framework for discovering and browsing media - Shared libraries ii libgrilo-0.2-1-dbg:amd64 0.2.10-1 amd64 Framework for discovering and browsing media - debugging symbols ii libgrilo-0.2-dev 0.2.10-1 amd64 Framework for discovering and browsing media - Development files
Backtrace: Breakpoint 6, g_free (mem=0x1ce2d50) at /tmp/buildd/glib2.0-2.40.0/./glib/gmem.c:189 189 if (G_LIKELY (mem))
+ Trace 233824
I spent some time looking into it. The below patch fixes the problem. diff -r 2e134f2db3a7 libgrilo-0.2-1/grilo-0.2.10/libs/net/grl-net-wc.c --- a/libgrilo-0.2-1/grilo-0.2.10/libs/net/grl-net-wc.c Tue Jul 15 23:25:55 2014 +0530 +++ b/libgrilo-0.2-1/grilo-0.2.10/libs/net/grl-net-wc.c Wed Jul 16 06:15:22 2014 +0530 @@ -1128,10 +1128,9 @@ struct request_clos *c; while ((c = g_queue_pop_head (priv->pending))) { + if(c->cancellable) + g_object_unref (c->cancellable); g_source_remove (c->source_id); - g_object_unref (c->cancellable); - g_free (c->url); - g_free (c); } g_get_current_time (&priv->last_request); Explanation of the fix: 1. The first call to g_free is called when g_source_remove is invoked, which calls the request_clos_destroy() callback, as part of the source destruction. This applies to both g_free cases in the code. Hence, both g_free() calls are removed. 2. GCancellable from the application could be NULL, and should be checked. 3. request_clos object 'c' is freed ( g_free(c) ) in request_close_destroy(), so g_object_unref(..) has to be called prior to g_source_remove() I've manually tested this to work fine with rhythmbox.
Cool. Could you upload a patch with the changes? If you can't I can do it on your behalf.
Created attachment 280779 [details] [review] Patch that fixes the crash
Created attachment 280785 [details] [review] net: Fix invalid free https://bugzilla.gnome.org/show_bug.cgi?id=733232 Signed-off-by: Juan A. Suarez Romero <jasuarez@igalia.com>
Review of attachment 280785 [details] [review]: This looks incorrect. ::: libs/net/grl-net-wc.c @@ -1131,3 @@ g_source_remove (c->source_id); - g_object_unref (c->cancellable); - g_free (c->url); You'd be leaking the URL, and the struct itself. Use g_clear_object() and g_clear_pointer() instead?
Review of attachment 280785 [details] [review]: ::: libs/net/grl-net-wc.c @@ +1130,2 @@ while ((c = g_queue_pop_head (priv->pending))) { + g_clear_object (&c->cancellable); In fact, the cancellable shouldn't be unref'ed. We don't own a single reference to it: 775 c->cancellable = cancellable;• This code should probably cancel the cancellable though.
(In reply to comment #6) > Review of attachment 280785 [details] [review]: > > This looks incorrect. > > ::: libs/net/grl-net-wc.c > @@ -1131,3 @@ > g_source_remove (c->source_id); > - g_object_unref (c->cancellable); > - g_free (c->url); > > You'd be leaking the URL, and the struct itself. > Not sure, see comment #2. For each request_clos we create a g_idle function, with request_close_destroy() destructor that frees the url and the struct itself. The id of the g_idle function is stored in c->source_id. So I assume that g_source_remove() will trigger the destructor. Am I correct?
(In reply to comment #7) > In fact, the cancellable shouldn't be unref'ed. We don't own a single reference > to it: > 775 c->cancellable = cancellable;• > > This code should probably cancel the cancellable though. Right.
Created attachment 280851 [details] [review] net: Fix double-free using the Jamendo plugin The item in the queue is already freed when the source is removed, through a destroy notify, so no need to do it twice. Ensure we cancel the cancellable though, but do not unref it as we do not own it.