From: Timo Sirainen Date: Tue, 16 Jun 2009 01:56:22 +0000 (-0400) Subject: IMAP: Don't crash if IDLE command is pipelined after a long-running UID FETCH or... X-Git-Tag: 2.0.alpha1~571 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=5735ada0f82788ee1b5228978d5bd8dad5a04219;p=thirdparty%2Fdovecot%2Fcore.git IMAP: Don't crash if IDLE command is pipelined after a long-running UID FETCH or UID SEARCH. --HG-- branch : HEAD --- diff --git a/src/imap/imap-client.c b/src/imap/imap-client.c index 73b8c3c227..ecd6a93279 100644 --- a/src/imap/imap-client.c +++ b/src/imap/imap-client.c @@ -412,6 +412,10 @@ static bool client_command_check_ambiguity(struct client_command_context *cmd) CLIENT_COMMAND_STATE_WAIT_UNAMBIGUITY; bool broken_client = FALSE; + if ((cmd->cmd_flags & COMMAND_FLAG_REQUIRES_SYNC) != 0 && + !imap_sync_is_allowed(cmd->client)) + return TRUE; + if ((cmd->cmd_flags & COMMAND_FLAG_BREAKS_MAILBOX) == COMMAND_FLAG_BREAKS_MAILBOX) { /* there must be no other command running that uses the diff --git a/src/imap/imap-commands.c b/src/imap/imap-commands.c index 70855338b0..1fc826d5a3 100644 --- a/src/imap/imap-commands.c +++ b/src/imap/imap-commands.c @@ -44,7 +44,8 @@ static const struct command imap_ext_commands[] = { { "CANCELUPDATE", cmd_cancelupdate,0 }, { "ENABLE", cmd_enable, 0 }, { "ID", cmd_id, 0 }, - { "IDLE", cmd_idle, COMMAND_FLAG_BREAKS_SEQS }, + { "IDLE", cmd_idle, COMMAND_FLAG_BREAKS_SEQS | + COMMAND_FLAG_REQUIRES_SYNC }, { "NAMESPACE", cmd_namespace, 0 }, { "SORT", cmd_sort, COMMAND_FLAG_USES_SEQS }, { "THREAD", cmd_thread, COMMAND_FLAG_USES_SEQS }, diff --git a/src/imap/imap-commands.h b/src/imap/imap-commands.h index 5b38686d89..c385f401cf 100644 --- a/src/imap/imap-commands.h +++ b/src/imap/imap-commands.h @@ -21,7 +21,10 @@ enum command_flags { /* Command uses selected mailbox */ COMMAND_FLAG_USES_MAILBOX = COMMAND_FLAG_BREAKS_MAILBOX | - COMMAND_FLAG_USES_SEQS + COMMAND_FLAG_USES_SEQS, + + /* Command requires mailbox syncing before it can do its job. */ + COMMAND_FLAG_REQUIRES_SYNC = 0x08 }; struct command { diff --git a/src/imap/imap-sync.c b/src/imap/imap-sync.c index c9bc02843e..ce02e8a533 100644 --- a/src/imap/imap-sync.c +++ b/src/imap/imap-sync.c @@ -475,6 +475,18 @@ int imap_sync_more(struct imap_sync_context *ctx) return ret; } +bool imap_sync_is_allowed(struct client *client) +{ + if (client->syncing) + return FALSE; + + if (client->mailbox != NULL && + mailbox_transaction_get_count(client->mailbox) > 0) + return FALSE; + + return TRUE; +} + static bool cmd_finish_sync(struct client_command_context *cmd) { if (cmd->sync->callback != NULL) @@ -676,9 +688,7 @@ bool cmd_sync_delayed(struct client *client) return FALSE; } - if (client->syncing || - (client->mailbox != NULL && - mailbox_transaction_get_count(client->mailbox) > 0)) { + if (!imap_sync_is_allowed(client)) { /* wait until mailbox can be synced */ return cmd_sync_drop_fast(client); } diff --git a/src/imap/imap-sync.h b/src/imap/imap-sync.h index 66d3fe1b0b..37d0cc9a00 100644 --- a/src/imap/imap-sync.h +++ b/src/imap/imap-sync.h @@ -17,6 +17,9 @@ int imap_sync_deinit(struct imap_sync_context *ctx, struct client_command_context *sync_cmd); int imap_sync_more(struct imap_sync_context *ctx); +/* Returns TRUE if syncing would be allowed currently. */ +bool imap_sync_is_allowed(struct client *client); + bool cmd_sync(struct client_command_context *cmd, enum mailbox_sync_flags flags, enum imap_sync_flags imap_flags, const char *tagline); bool cmd_sync_callback(struct client_command_context *cmd,