[evolution-ews] Bug #699558 - Use-after-free of a cancellable during GAL update
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-ews] Bug #699558 - Use-after-free of a cancellable during GAL update
- Date: Thu, 15 Aug 2013 12:36:27 +0000 (UTC)
commit c51b994387b9116887faad95180871e935756d7a
Author: Milan Crha <mcrha redhat com>
Date: Thu Aug 15 14:36:04 2013 +0200
Bug #699558 - Use-after-free of a cancellable during GAL update
src/addressbook/e-book-backend-ews.c | 47 ++++++++++++++++++++++++---------
src/server/e-ews-connection.c | 14 +++++-----
src/server/e-ews-connection.h | 3 ++
3 files changed, 44 insertions(+), 20 deletions(-)
---
diff --git a/src/addressbook/e-book-backend-ews.c b/src/addressbook/e-book-backend-ews.c
index ecaebd4..ca54ee9 100644
--- a/src/addressbook/e-book-backend-ews.c
+++ b/src/addressbook/e-book-backend-ews.c
@@ -2386,9 +2386,6 @@ ews_gal_store_contact (EContact *contact,
data->contact_collector = NULL;
data->collected_length = 0;
}
-
- if (percent == 100)
- e_book_backend_notify_complete (E_BOOK_BACKEND (data->cbews));
}
static gint det_sort_func (gconstpointer _a, gconstpointer _b)
@@ -2436,6 +2433,11 @@ ews_replace_gal_in_db (EBookBackendEws *cbews,
data.cbews = cbews;
ret = ews_oab_decoder_decode (eod, ews_gal_store_contact, &data, cancellable, error);
+
+ /* always notify views as complete, to not left anything behind,
+ if the decode was cancelled before full completion */
+ e_book_backend_notify_complete (E_BOOK_BACKEND (cbews));
+
if (!ret)
return ret;
@@ -2464,11 +2466,14 @@ ebews_start_gal_sync (gpointer data)
guint32 old_seq = 0;
guint32 delta_size = 0;
CamelEwsSettings *ews_settings;
+ GCancellable *cancellable;
cbews = (EBookBackendEws *) data;
ews_settings = book_backend_ews_get_collection_settings (cbews);
priv = cbews->priv;
+ cancellable = g_object_ref (priv->cancellable);
+
oab_cnc = e_ews_connection_new (priv->oab_url, ews_settings);
password = e_ews_connection_dup_password (priv->cnc);
@@ -2493,7 +2498,7 @@ ebews_start_gal_sync (gpointer data)
if (!e_ews_connection_get_oal_detail_sync (
oab_cnc, priv->folder_id, NULL, old_etag, &full_l, &etag,
- priv->cancellable, &error)) {
+ cancellable, &error)) {
ret = FALSE;
goto exit;
}
@@ -2533,7 +2538,7 @@ ebews_start_gal_sync (gpointer data)
deltas = NULL;
}
- uncompressed_filename = ews_download_gal (cbews, full, deltas, old_seq, priv->cancellable, &error);
+ uncompressed_filename = ews_download_gal (cbews, full, deltas, old_seq, cancellable, &error);
if (!uncompressed_filename) {
ret = FALSE;
goto exit;
@@ -2547,7 +2552,7 @@ ebews_start_gal_sync (gpointer data)
}
d (printf ("Ewsgal: Replacing old gal with new gal contents in db \n");)
- ret = ews_replace_gal_in_db (cbews, uncompressed_filename, priv->cancellable, &error);
+ ret = ews_replace_gal_in_db (cbews, uncompressed_filename, cancellable, &error);
if (!ret)
goto exit;
@@ -2572,6 +2577,8 @@ ebews_start_gal_sync (gpointer data)
d (printf ("Ews gal: sync successful complete \n");)
exit:
+ g_clear_object (&cancellable);
+
if (error) {
g_warning ("Unable to update gal : %s \n", error->message);
g_clear_error (&error);
@@ -2970,7 +2977,7 @@ ebews_fetch_items (EBookBackendEws *ebews,
d_name = e_ews_item_get_subject (item);
e_ews_connection_expand_dl_sync (
cnc, EWS_PRIORITY_MEDIUM, mb, &members,
- &includes_last, priv->cancellable, error);
+ &includes_last, cancellable, error);
if (*error)
goto cleanup;
@@ -3026,6 +3033,7 @@ ebews_start_sync (gpointer data)
GList *list, *link;
gchar *sync_state, *status_message = NULL;
gboolean includes_last_item;
+ GCancellable *cancellable;
GError *error = NULL;
ebews = (EBookBackendEws *) data;
@@ -3037,6 +3045,8 @@ ebews_start_sync (gpointer data)
if (!priv->cnc)
return TRUE;
+ cancellable = g_object_ref (priv->cancellable);
+
status_message = g_strdup (_("Syncing contacts..."));
list = e_book_backend_list_views (E_BOOK_BACKEND (ebews));
for (link = list; link != NULL; link = g_list_next (link))
@@ -3060,7 +3070,7 @@ ebews_start_sync (gpointer data)
&sync_state,
&includes_last_item,
&items_created, &items_updated,
- &items_deleted, priv->cancellable, &error);
+ &items_deleted, cancellable, &error);
g_free (old_sync_state);
@@ -3071,7 +3081,7 @@ ebews_start_sync (gpointer data)
e_ews_connection_sync_folder_items_sync (priv->cnc, EWS_PRIORITY_MEDIUM, NULL,
priv->folder_id, "IdOnly", NULL, EWS_MAX_FETCH_COUNT,
&sync_state, &includes_last_item, &items_created, &items_updated,
&items_deleted,
- priv->cancellable, &error);
+ cancellable, &error);
}
if (error)
@@ -3081,7 +3091,7 @@ ebews_start_sync (gpointer data)
ebews_sync_deleted_items (ebews, items_deleted, &error);
if (items_created)
- ebews_fetch_items (ebews, items_created, TRUE, NULL, priv->cancellable, &error);
+ ebews_fetch_items (ebews, items_created, TRUE, NULL, cancellable, &error);
if (error) {
g_slist_free_full (items_updated, g_object_unref);
@@ -3090,7 +3100,7 @@ ebews_start_sync (gpointer data)
}
if (items_updated)
- ebews_fetch_items (ebews, items_updated, TRUE, NULL, priv->cancellable, &error);
+ ebews_fetch_items (ebews, items_updated, TRUE, NULL, cancellable, &error);
if (error)
break;
@@ -3109,6 +3119,8 @@ ebews_start_sync (gpointer data)
e_data_book_view_notify_progress (E_DATA_BOOK_VIEW (link->data), -1, NULL);
g_list_free_full (list, g_object_unref);
+ g_clear_object (&cancellable);
+
if (error) {
g_warning ("Error Syncing Contacts: Folder %s Error: %s", priv->folder_id, error->message);
g_clear_error (&error);
@@ -3125,6 +3137,10 @@ delta_thread (gpointer data)
EBookBackendEwsPrivate *priv = ebews->priv;
gint64 end_time;
+ g_mutex_lock (&priv->dlock->mutex);
+ g_object_ref (ebews);
+ g_mutex_unlock (&priv->dlock->mutex);
+
while (TRUE) {
gboolean succeeded;
@@ -3135,6 +3151,10 @@ delta_thread (gpointer data)
g_mutex_lock (&priv->dlock->mutex);
+ /* in case this is the last reference, then this cannot join
+ the itself thread in dispose */
+ e_ews_connection_utils_unref_in_thread (ebews);
+
if (!succeeded || priv->dlock->exit)
break;
@@ -3144,6 +3164,8 @@ delta_thread (gpointer data)
if (priv->dlock->exit)
break;
+ g_object_ref (ebews);
+
g_mutex_unlock (&priv->dlock->mutex);
}
@@ -3682,9 +3704,8 @@ e_book_backend_ews_dispose (GObject *object)
if (priv->dlock) {
g_mutex_lock (&priv->dlock->mutex);
priv->dlock->exit = TRUE;
- g_mutex_unlock (&priv->dlock->mutex);
-
g_cond_signal (&priv->dlock->cond);
+ g_mutex_unlock (&priv->dlock->mutex);
if (priv->dthread)
g_thread_join (priv->dthread);
diff --git a/src/server/e-ews-connection.c b/src/server/e-ews-connection.c
index 1287ee5..ad9f1e4 100644
--- a/src/server/e-ews-connection.c
+++ b/src/server/e-ews-connection.c
@@ -189,8 +189,8 @@ ews_unref_in_thread_func (gpointer data)
return NULL;
}
-static void
-ews_unref_in_thread (gpointer object)
+void
+e_ews_connection_utils_unref_in_thread (gpointer object)
{
GThread *thread;
@@ -312,7 +312,7 @@ ews_connection_scheduled_cb (gpointer user_data)
if (sd->message)
g_object_unref (sd->message);
/* in case this is the last reference */
- ews_unref_in_thread (sd->cnc);
+ e_ews_connection_utils_unref_in_thread (sd->cnc);
g_free (sd);
return FALSE;
@@ -513,7 +513,7 @@ ews_active_job_done (EEwsConnection *cnc,
/* the 'simple' holds reference on 'cnc' and this function
* is called in a dedicated thread, which 'cnc' joins on dispose,
* thus to avoid race condition, unref the object in its own thread */
- ews_unref_in_thread (ews_node->simple);
+ e_ews_connection_utils_unref_in_thread (ews_node->simple);
g_free (ews_node);
}
@@ -2220,7 +2220,7 @@ autodiscover_response_cb (SoupSession *session,
* in connection's dispose, trying to wait on the end of itself, thus it's
* safer to unref the 'simple' in a dedicated thread.
*/
- ews_unref_in_thread (simple);
+ e_ews_connection_utils_unref_in_thread (simple);
}
static void post_restarted (SoupMessage *msg, gpointer data)
@@ -2731,7 +2731,7 @@ oal_response_cb (SoupSession *soup_session,
* for cases when the complete_in_idle is finished before the unref call, when
* the cnc will be left with the last reference and thus cannot join the soup_thread
* while still in it, the unref is done in a dedicated thread. */
- ews_unref_in_thread (simple);
+ e_ews_connection_utils_unref_in_thread (simple);
}
static void
@@ -3005,7 +3005,7 @@ oal_download_response_cb (SoupSession *soup_session,
}
g_simple_async_result_complete_in_idle (simple);
- ews_unref_in_thread (simple);
+ e_ews_connection_utils_unref_in_thread (simple);
}
static void
diff --git a/src/server/e-ews-connection.h b/src/server/e-ews-connection.h
index 2e13dc7..53d3fc7 100644
--- a/src/server/e-ews-connection.h
+++ b/src/server/e-ews-connection.h
@@ -208,6 +208,9 @@ typedef struct {
void ews_oal_free (EwsOAL *oal);
void ews_oal_details_free (EwsOALDetails *details);
+void e_ews_connection_utils_unref_in_thread
+ (gpointer object);
+
GType e_ews_connection_get_type (void);
EEwsConnection *e_ews_connection_new (const gchar *uri,
CamelEwsSettings *settings);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]