From 34b0579f1542471947564bf56cfcf51946f57313 Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Fri, 22 Apr 2016 16:25:00 +0300 Subject: [PATCH] dsync: Fixed crash when rename algorithm thinks it has gone to infinite loop. ctx->brain was NULL, so trying to access it crashed. --- src/doveadm/dsync/dsync-brain-mailbox-tree.c | 3 ++- src/doveadm/dsync/dsync-mailbox-tree-sync.c | 19 +++++++++++++------ src/doveadm/dsync/dsync-mailbox-tree.h | 2 +- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/doveadm/dsync/dsync-brain-mailbox-tree.c b/src/doveadm/dsync/dsync-brain-mailbox-tree.c index 674cb0a486..786efa5053 100644 --- a/src/doveadm/dsync/dsync-brain-mailbox-tree.c +++ b/src/doveadm/dsync/dsync-brain-mailbox-tree.c @@ -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) diff --git a/src/doveadm/dsync/dsync-mailbox-tree-sync.c b/src/doveadm/dsync/dsync-mailbox-tree-sync.c index 64fa3f7adb..3ad3eec04e 100644 --- a/src/doveadm/dsync/dsync-mailbox-tree-sync.c +++ b/src/doveadm/dsync/dsync-mailbox-tree-sync.c @@ -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; } diff --git a/src/doveadm/dsync/dsync-mailbox-tree.h b/src/doveadm/dsync/dsync-mailbox-tree.h index af6ce369b9..d317aaa34f 100644 --- a/src/doveadm/dsync/dsync-mailbox-tree.h +++ b/src/doveadm/dsync/dsync-mailbox-tree.h @@ -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 * -- 2.47.3