[geary] Geary.ImapDb.Database: Fix free after use when GC'ing



commit ec7a9707433900b55863a365c9e5e28269ead1d9
Author: Michael Gratton <mike vee net>
Date:   Wed Jul 1 11:38:39 2020 +1000

    Geary.ImapDb.Database: Fix free after use when GC'ing
    
    Passing arrays to async methods will cause use-after-free segfaults
    after yielding (see GNOME/vala#751), so pass services in to `run_gc()`
    via a Gee Collection.

 src/engine/imap-db/imap-db-database.vala                    | 13 +++++--------
 .../imap-engine/imap-engine-account-synchronizer.vala       | 13 ++++++++-----
 src/engine/imap-engine/imap-engine-generic-account.vala     |  6 +++++-
 src/engine/imap-engine/imap-engine-minimal-folder.vala      |  3 +--
 4 files changed, 19 insertions(+), 16 deletions(-)
---
diff --git a/src/engine/imap-db/imap-db-database.vala b/src/engine/imap-db/imap-db-database.vala
index 921189d14..e8228feb1 100644
--- a/src/engine/imap-db/imap-db-database.vala
+++ b/src/engine/imap-db/imap-db-database.vala
@@ -94,9 +94,7 @@ private class Geary.ImapDB.Database : Geary.Db.VersionedDatabase {
     public new async void open(Db.DatabaseFlags flags, Cancellable? cancellable)
         throws Error {
         yield base.open(flags, cancellable);
-
-        Geary.ClientService services_to_pause[] = {};
-        yield run_gc(NONE, services_to_pause, cancellable);
+        yield run_gc(NONE, null, cancellable);
     }
 
     /**
@@ -106,10 +104,9 @@ private class Geary.ImapDB.Database : Geary.Db.VersionedDatabase {
      * the interval based recommendation should be bypassed.
      */
     public async void run_gc(GarbageCollectionOptions options,
-                             Geary.ClientService[] services_to_pause,
+                             Gee.Collection<Geary.ClientService>? to_pause,
                              GLib.Cancellable? cancellable)
-                                 throws Error {
-
+        throws GLib.Error {
         if (this.gc != null) {
             debug("GC abandoned, possibly already running");
             return;
@@ -133,7 +130,7 @@ private class Geary.ImapDB.Database : Geary.Db.VersionedDatabase {
         if ((recommended & GC.RecommendedOperation.VACUUM) != 0) {
             if (GarbageCollectionOptions.ALLOW_VACUUM in options) {
                 this.want_background_vacuum = false;
-                foreach (ClientService service in services_to_pause) {
+                foreach (ClientService service in to_pause) {
                     yield service.stop(gc_cancellable);
                 }
 
@@ -152,7 +149,7 @@ private class Geary.ImapDB.Database : Geary.Db.VersionedDatabase {
                         vacuum_monitor.notify_finish();
                 }
 
-                foreach (ClientService service in services_to_pause) {
+                foreach (ClientService service in to_pause) {
                     yield service.start(gc_cancellable);
                 }
             } else {
diff --git a/src/engine/imap-engine/imap-engine-account-synchronizer.vala 
b/src/engine/imap-engine/imap-engine-account-synchronizer.vala
index 5b9b9c7e5..d1b86112a 100644
--- a/src/engine/imap-engine/imap-engine-account-synchronizer.vala
+++ b/src/engine/imap-engine/imap-engine-account-synchronizer.vala
@@ -447,8 +447,7 @@ private class Geary.ImapEngine.ForegroundGarbageCollection: AccountOperation {
 
         // Run basic GC
         GenericAccount generic_account = (GenericAccount) account;
-        Geary.ClientService services_to_pause[] = {};
-        yield generic_account.local.db.run_gc(NONE, services_to_pause, cancellable);
+        yield generic_account.local.db.run_gc(NONE, null, cancellable);
     }
 
     public override bool equal_to(AccountOperation op) {
@@ -482,9 +481,13 @@ private class Geary.ImapEngine.IdleGarbageCollection: AccountOperation {
             return;
 
         GenericAccount generic_account = (GenericAccount) this.account;
-        generic_account.local.db.run_gc.begin(this.options,
-                                              {generic_account.imap, generic_account.smtp},
-                                              cancellable);
+        generic_account.local.db.run_gc.begin(
+            this.options,
+            new Gee.ArrayList<ClientService>.wrap(
+                {generic_account.imap, generic_account.smtp}
+            ),
+            cancellable
+        );
     }
 
     public void messages_detached() {
diff --git a/src/engine/imap-engine/imap-engine-generic-account.vala 
b/src/engine/imap-engine/imap-engine-generic-account.vala
index 6c5f1d2d5..ad1f87a44 100644
--- a/src/engine/imap-engine/imap-engine-generic-account.vala
+++ b/src/engine/imap-engine/imap-engine-generic-account.vala
@@ -581,7 +581,11 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.Account {
             this.old_messages_background_cleanup_request(cancellable);
         } else if (local.db.want_background_vacuum) {
             // Vacuum has been flagged as needed, run it
-            local.db.run_gc.begin(ALLOW_VACUUM, {this.imap, this.smtp}, cancellable);
+            local.db.run_gc.begin(
+                ALLOW_VACUUM,
+                new Gee.ArrayList<ClientService>.wrap({this.imap, this.smtp}),
+                cancellable
+            );
         }
     }
 
diff --git a/src/engine/imap-engine/imap-engine-minimal-folder.vala 
b/src/engine/imap-engine/imap-engine-minimal-folder.vala
index 20fdc2c2b..a9905b696 100644
--- a/src/engine/imap-engine/imap-engine-minimal-folder.vala
+++ b/src/engine/imap-engine/imap-engine-minimal-folder.vala
@@ -1299,8 +1299,7 @@ private class Geary.ImapEngine.MinimalFolder : Geary.Folder, Geary.FolderSupport
         // expunge from the remote
         yield this.replay_queue.checkpoint(cancellable);
 
-        Geary.ClientService services_to_pause[] = {};
-        yield this._account.local.db.run_gc(NONE, services_to_pause, cancellable);
+        yield this._account.local.db.run_gc(NONE, null, cancellable);
     }
 
     private void check_open(string method) throws EngineError {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]