Skip to content

Commit

Permalink
lib-smtp: client: Make smtp_client_connection_commands_abort() more r…
Browse files Browse the repository at this point in the history
…eliable by copying the command lists.

Copy the current lists of queued and waiting commands and reference each command before calling smtp_client_command_abort().
Aborting one command can cause other dependent commands to be aborted (in a transaction or from submission service), which could have caused trouble in this function.
  • Loading branch information
stephanbosch committed Dec 23, 2017
1 parent bd06411 commit 2dd2083
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 17 deletions.
30 changes: 30 additions & 0 deletions src/lib-smtp/smtp-client-command.c
Expand Up @@ -313,6 +313,36 @@ void smtp_client_command_fail(struct smtp_client_command **_cmd,
smtp_client_command_fail_reply(_cmd, &reply);
}

void smtp_client_commands_list_abort(struct smtp_client_command *cmds_list,
unsigned int cmds_list_count)
{
struct smtp_client_command *cmd;
ARRAY(struct smtp_client_command *) cmds_arr;
struct smtp_client_command **cmds;
unsigned int count, i;

if (cmds_list == NULL)
return;
i_assert(cmds_list_count > 0);

/* copy the array and reference the commands to be robust against more
than one command disappearing from the list */
t_array_init(&cmds_arr, cmds_list_count);
for (cmd = cmds_list; cmd != NULL; cmd = cmd->next) {
smtp_client_command_ref(cmd);
array_append(&cmds_arr, &cmd, 1);
}

cmds = array_get_modifiable(&cmds_arr, &count);
for (i = 0; i < count; i++) {
cmd = cmds[i];
/* fail the reply */
smtp_client_command_abort(&cmds[i]);
/* drop our reference */
smtp_client_command_unref(&cmd);
}
}

void smtp_client_commands_list_fail_reply(
struct smtp_client_command *cmds_list, unsigned int cmds_list_count,
const struct smtp_reply *reply)
Expand Down
21 changes: 4 additions & 17 deletions src/lib-smtp/smtp-client-connection.c
Expand Up @@ -122,23 +122,10 @@ smtp_client_connection_error(struct smtp_client_connection *conn,
static void
smtp_client_connection_commands_abort(struct smtp_client_connection *conn)
{
struct smtp_client_command *cmd, *cmd_next = NULL;

cmd = conn->cmd_wait_list_head;
while (cmd != NULL) {
i_assert(conn->cmd_wait_list_count > 0);
cmd_next = cmd->next;
smtp_client_command_abort(&cmd);
cmd = cmd_next;
}

cmd = conn->cmd_send_queue_head;
while (cmd != NULL) {
i_assert(conn->cmd_send_queue_count > 0);
cmd_next = cmd->next;
smtp_client_command_abort(&cmd);
cmd = cmd_next;
}
smtp_client_commands_list_abort(conn->cmd_wait_list_head,
conn->cmd_wait_list_count);
smtp_client_commands_list_abort(conn->cmd_send_queue_head,
conn->cmd_send_queue_count);
}

static void
Expand Down
3 changes: 3 additions & 0 deletions src/lib-smtp/smtp-client-private.h
Expand Up @@ -194,6 +194,9 @@ void smtp_client_command_fail(struct smtp_client_command **_cmd,
unsigned int status, const char *error);
void smtp_client_command_fail_reply(struct smtp_client_command **_cmd,
const struct smtp_reply *reply);

void smtp_client_commands_list_abort(struct smtp_client_command *cmds_list,
unsigned int cmds_list_count);
void smtp_client_commands_list_fail_reply(
struct smtp_client_command *cmds_list, unsigned int cmds_list_count,
const struct smtp_reply *reply);
Expand Down

0 comments on commit 2dd2083

Please sign in to comment.