diff options
author | Stefan Berzl <stefan@localhost.localdomain> | 2017-08-26 01:24:40 +0200 |
---|---|---|
committer | Ali Abdallah <ali@xfce.org> | 2017-08-29 16:04:24 +0200 |
commit | 2131745b35e59fa5c1c0cec7e7ea5eaecd6c6e5f (patch) | |
tree | c3fce4e6b139ef570b05dd088e8d641078d540a6 /xfconf | |
parent | a847db8fb3b51acdee0bacea3d386a68f3283016 (diff) | |
download | xfconf-2131745b35e59fa5c1c0cec7e7ea5eaecd6c6e5f.tar.gz |
When multiple calls are made for the same property, it's possible that xfconf_cache_set may be called twice before xfconf_cache_set_property_reply_handler, in which case old_item gets freed and the second handler call might cause undefined behavior or a segfault.
Added a counter to prevent that.
Signed-off-by: Ali Abdallah <ali@xfce.org>
Diffstat (limited to 'xfconf')
-rw-r--r-- | xfconf/xfconf-cache.c | 17 |
1 files changed, 14 insertions, 3 deletions
diff --git a/xfconf/xfconf-cache.c b/xfconf/xfconf-cache.c index 48c820d..f3bbe43 100644 --- a/xfconf/xfconf-cache.c +++ b/xfconf/xfconf-cache.c @@ -152,6 +152,8 @@ typedef struct GCancellable *cancellable; + gint pending_calls_count; + /** * Variant to be send on the wire * Used in xfconf_cache_old_item_end_call @@ -177,6 +179,7 @@ xfconf_cache_old_item_new(XfconfCache *cache, const gchar *property) old_item->cancellable = g_cancellable_new (); old_item->cache = cache; old_item->variant = NULL; + old_item->pending_calls_count = 0; return old_item; } @@ -330,7 +333,8 @@ xfconf_cache_class_init(XfconfCacheClass *klass) signals[SIG_PROPERTY_CHANGED] = g_signal_new(I_("property-changed"), XFCONF_TYPE_CACHE, - G_SIGNAL_RUN_LAST, + G_SIGNAL_RUN_LAST + | G_SIGNAL_DETAILED, G_STRUCT_OFFSET(XfconfCacheClass, property_changed), NULL, @@ -596,7 +600,9 @@ xfconf_cache_set_property_reply_handler(GDBusProxy *proxy, gboolean result; old_item = (XfconfCacheOldItem *) user_data; cache = old_item->cache; - if(!cache->pending_calls) + + old_item->pending_calls_count--; + if(old_item->pending_calls_count > 0) return; xfconf_cache_mutex_lock(cache); @@ -879,6 +885,11 @@ xfconf_cache_set(XfconfCache *cache, g_object_unref (old_item->cancellable); old_item->cancellable = g_cancellable_new(); } + + if(old_item->variant){ + g_variant_unref(old_item->variant); + old_item->variant = NULL; + } } else { old_item = xfconf_cache_old_item_new(cache, property); if(item) @@ -898,8 +909,8 @@ xfconf_cache_set(XfconfCache *cache, (GAsyncReadyCallback) xfconf_cache_set_property_reply_handler, old_item); - /* Val will be freed asynchronously */ old_item->variant = val; + old_item->pending_calls_count++; g_hash_table_insert(cache->pending_calls, old_item->cancellable, old_item); |