Mercurial > dovecot > core-2.2
changeset 12751:3053befe6a64
imap: Fixed infinite loop / memory eating with SEARCHRES + pipelining $.
If SEARCH RETURN (SAVE) command was running long enough so that Dovecot
started executing the next command, and if that command used $ in
messageset, Dovecot went into infinite function recursion.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Tue, 22 Feb 2011 11:59:57 +0200 |
parents | 324f9ca60539 |
children | be78b9fd88e7 |
files | src/imap/imap-client.c src/imap/imap-client.h |
diffstat | 2 files changed, 17 insertions(+), 4 deletions(-) [+] |
line wrap: on
line diff
--- a/src/imap/imap-client.c Tue Feb 22 11:14:31 2011 +0200 +++ b/src/imap/imap-client.c Tue Feb 22 11:59:57 2011 +0200 @@ -432,7 +432,7 @@ return NULL; } -static bool client_command_check_ambiguity(struct client_command_context *cmd) +static bool client_command_is_ambiguous(struct client_command_context *cmd) { enum command_flags flags; enum client_command_state max_state = @@ -443,6 +443,17 @@ !imap_sync_is_allowed(cmd->client)) return TRUE; + if (cmd->search_save_result_used) { + /* if there are pending commands that update the search + save result, wait */ + struct client_command_context *old_cmd = cmd->next; + + for (; old_cmd != NULL; old_cmd = old_cmd->next) { + if (old_cmd->search_save_result) + return TRUE; + } + } + if ((cmd->cmd_flags & COMMAND_FLAG_BREAKS_MAILBOX) == COMMAND_FLAG_BREAKS_MAILBOX) { /* there must be no other command running that uses the @@ -578,11 +589,11 @@ /* the command is waiting for existing ambiguity causing commands to finish. */ - if (client_command_check_ambiguity(cmd)) { + if (client_command_is_ambiguous(cmd)) { /* we could be waiting for existing sync to finish */ if (!cmd_sync_delayed(client)) return; - if (client_command_check_ambiguity(cmd)) + if (client_command_is_ambiguous(cmd)) return; } cmd->state = CLIENT_COMMAND_STATE_WAIT_INPUT; @@ -690,7 +701,7 @@ } else if ((command = command_find(cmd->name)) != NULL) { cmd->func = command->func; cmd->cmd_flags = command->flags; - if (client_command_check_ambiguity(cmd)) { + if (client_command_is_ambiguous(cmd)) { /* do nothing until existing commands are finished */ i_assert(cmd->state == CLIENT_COMMAND_STATE_WAIT_INPUT); cmd->state = CLIENT_COMMAND_STATE_WAIT_UNAMBIGUITY; @@ -907,6 +918,7 @@ i_assert(cmd->state == CLIENT_COMMAND_STATE_WAIT_INPUT); cmd->client->input_lock = cmd; cmd->state = CLIENT_COMMAND_STATE_WAIT_UNAMBIGUITY; + cmd->search_save_result_used = TRUE; io_remove(&cmd->client->io); return TRUE; }
--- a/src/imap/imap-client.h Tue Feb 22 11:14:31 2011 +0200 +++ b/src/imap/imap-client.h Tue Feb 22 11:59:57 2011 +0200 @@ -82,6 +82,7 @@ unsigned int cancel:1; /* command is wanted to be cancelled */ unsigned int param_error:1; unsigned int search_save_result:1; /* search result is being updated */ + unsigned int search_save_result_used:1; /* command uses search save */ unsigned int temp_executed:1; /* temporary execution state tracking */ };