]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
dsync: Fixed crash when rename algorithm thinks it has gone to infinite loop.
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Fri, 22 Apr 2016 13:25:00 +0000 (16:25 +0300)
committerGitLab <gitlab@git.dovecot.net>
Fri, 22 Apr 2016 22:43:27 +0000 (01:43 +0300)
ctx->brain was NULL, so trying to access it crashed.

src/doveadm/dsync/dsync-brain-mailbox-tree.c
src/doveadm/dsync/dsync-mailbox-tree-sync.c
src/doveadm/dsync/dsync-mailbox-tree.h

index 674cb0a48686684118bf71b7e8309f340aaea09e..786efa505317df39a9480e26261c223673547bd3 100644 (file)
@@ -310,7 +310,8 @@ static void dsync_brain_mailbox_trees_sync(struct dsync_brain *brain)
                        break;
                }
        }
-       dsync_mailbox_trees_sync_deinit(&ctx);
+       if (dsync_mailbox_trees_sync_deinit(&ctx) < 0)
+               brain->failed = TRUE;
 }
 
 bool dsync_brain_recv_mailbox_tree(struct dsync_brain *brain)
index 64fa3f7adb0b4e59706aa59e0f5a015170cefae3..3ad3eec04e1aa9c9cf5a675428f715291aba2e88 100644 (file)
@@ -27,13 +27,13 @@ struct dsync_mailbox_tree_bfs_iter {
 
 struct dsync_mailbox_tree_sync_ctx {
        pool_t pool;
-       struct dsync_brain *brain;
        struct dsync_mailbox_tree *local_tree, *remote_tree;
        enum dsync_mailbox_trees_sync_type sync_type;
        enum dsync_mailbox_trees_sync_flags sync_flags;
 
        ARRAY(struct dsync_mailbox_tree_sync_change) changes;
        unsigned int change_idx;
+       bool failed;
 };
 
 static struct dsync_mailbox_tree_bfs_iter *
@@ -1075,7 +1075,7 @@ sync_rename_temp_mailboxes(struct dsync_mailbox_tree_sync_ctx *ctx,
        return FALSE;
 }
 
-static void
+static int
 dsync_mailbox_tree_handle_renames(struct dsync_mailbox_tree_sync_ctx *ctx)
 {
        unsigned int count = 0;
@@ -1095,11 +1095,12 @@ dsync_mailbox_tree_handle_renames(struct dsync_mailbox_tree_sync_ctx *ctx)
 
        if (changed) {
                i_error("BUG: Mailbox renaming algorithm got into a potentially infinite loop, aborting");
-               ctx->brain->failed = TRUE;
+               return -1;
        }
 
        while (sync_rename_temp_mailboxes(ctx, ctx->local_tree, &ctx->local_tree->root)) ;
        while (sync_rename_temp_mailboxes(ctx, ctx->remote_tree, &ctx->remote_tree->root)) ;
+       return 0;
 }
 
 static bool sync_is_wrong_mailbox(struct dsync_mailbox_node *node,
@@ -1411,8 +1412,12 @@ dsync_mailbox_trees_sync_init(struct dsync_mailbox_tree *local_tree,
 
        dsync_mailbox_tree_update_child_timestamps(&local_tree->root, 0);
        dsync_mailbox_tree_update_child_timestamps(&remote_tree->root, 0);
-       if ((sync_flags & DSYNC_MAILBOX_TREES_SYNC_FLAG_NO_RENAMES) == 0)
-               dsync_mailbox_tree_handle_renames(ctx);
+       if ((sync_flags & DSYNC_MAILBOX_TREES_SYNC_FLAG_NO_RENAMES) == 0) {
+               if (dsync_mailbox_tree_handle_renames(ctx) < 0) {
+                       ctx->failed = TRUE;
+                       return ctx;
+               }
+       }
 
        /* if we're not doing a two-way sync, delete now any mailboxes, which
           a) shouldn't exist, b) doesn't have a matching GUID/UIDVALIDITY,
@@ -1438,12 +1443,14 @@ dsync_mailbox_trees_sync_next(struct dsync_mailbox_tree_sync_ctx *ctx)
        return array_idx(&ctx->changes, ctx->change_idx++);
 }
 
-void dsync_mailbox_trees_sync_deinit(struct dsync_mailbox_tree_sync_ctx **_ctx)
+int dsync_mailbox_trees_sync_deinit(struct dsync_mailbox_tree_sync_ctx **_ctx)
 {
        struct dsync_mailbox_tree_sync_ctx *ctx = *_ctx;
+       int ret = ctx->failed ? -1 : 0;
 
        *_ctx = NULL;
 
        array_free(&ctx->changes);
        pool_unref(&ctx->pool);
+       return ret;
 }
index af6ce369b994cec2e9cae1c88baf92f9722bc453..d317aaa34f00041dc27ceac27c924cbbdb888c3f 100644 (file)
@@ -194,7 +194,7 @@ dsync_mailbox_trees_sync_init(struct dsync_mailbox_tree *local_tree,
                              enum dsync_mailbox_trees_sync_flags sync_flags);
 const struct dsync_mailbox_tree_sync_change *
 dsync_mailbox_trees_sync_next(struct dsync_mailbox_tree_sync_ctx *ctx);
-void dsync_mailbox_trees_sync_deinit(struct dsync_mailbox_tree_sync_ctx **ctx);
+int dsync_mailbox_trees_sync_deinit(struct dsync_mailbox_tree_sync_ctx **ctx);
 
 const char *dsync_mailbox_node_to_string(const struct dsync_mailbox_node *node);
 const char *