summaryrefslogtreecommitdiff
path: root/xfconf
diff options
context:
space:
mode:
authorStefan Berzl <stefan@localhost.localdomain>2017-08-26 01:24:40 +0200
committerAli Abdallah <ali@xfce.org>2017-08-29 16:04:24 +0200
commit2131745b35e59fa5c1c0cec7e7ea5eaecd6c6e5f (patch)
treec3fce4e6b139ef570b05dd088e8d641078d540a6 /xfconf
parenta847db8fb3b51acdee0bacea3d386a68f3283016 (diff)
downloadxfconf-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.c17
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);