Skip to content

Commit

Permalink
lib-smtp: client: Fix assertion panic occurring when DATA dot stream …
Browse files Browse the repository at this point in the history
…cannot be finished immediately.

If o_stream_finish() returns 0, o_stream_send_istream() would be called again
later which causes the panic. Instead, it should only call o_stream_finish() or
o_stream_flush() again to finish the last bit of the output.

Panic was:

Panic: file ostream.c: line 394 (o_stream_send_istream): assertion failed: (!_outstream->finished)
  • Loading branch information
stephanbosch authored and villesavolainen committed Jun 4, 2018
1 parent 07660d3 commit e3dc647
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 10 deletions.
43 changes: 33 additions & 10 deletions src/lib-smtp/smtp-client-command.c
Expand Up @@ -419,6 +419,27 @@ smtp_client_command_sent(struct smtp_client_command *cmd)
}
}

static int
smtp_client_command_finish_dot_stream(struct smtp_client_command *cmd)
{
struct smtp_client_connection *conn = cmd->conn;
int ret;

i_assert(cmd->stream_dot);
i_assert(conn->dot_output != NULL);

/* this concludes the dot stream with CRLF.CRLF */
if ((ret=o_stream_finish(conn->dot_output)) < 0) {
o_stream_unref(&conn->dot_output);
smtp_client_connection_handle_output_error(conn);
return -1;
}
if (ret == 0)
return 0;
o_stream_unref(&conn->dot_output);
return 1;
}

static int
smtp_client_command_send_stream(struct smtp_client_command *cmd)
{
Expand All @@ -428,6 +449,14 @@ smtp_client_command_send_stream(struct smtp_client_command *cmd)
enum ostream_send_istream_result res;
int ret;

if (cmd->stream_finished) {
if ((ret=smtp_client_command_finish_dot_stream(cmd)) <= 0)
return ret;
/* done sending payload */
smtp_client_command_debug(cmd, "Finished sending payload");
i_stream_unref(&cmd->stream);
return 1;
}
if (cmd->stream_dot) {
if (conn->dot_output == NULL)
conn->dot_output = o_stream_create_dot(output, FALSE);
Expand All @@ -446,16 +475,10 @@ smtp_client_command_send_stream(struct smtp_client_command *cmd)
/* finished with the stream */
smtp_client_command_debug(cmd,
"Finished reading payload stream");
if (conn->dot_output != NULL) {
/* this concludes the dot stream with CRLF.CRLF */
if ((ret=o_stream_finish(conn->dot_output)) < 0) {
o_stream_unref(&conn->dot_output);
smtp_client_connection_handle_output_error(conn);
return -1;
}
if (ret == 0)
return 0;
o_stream_unref(&conn->dot_output);
cmd->stream_finished = TRUE;
if (cmd->stream_dot) {
if ((ret=smtp_client_command_finish_dot_stream(cmd)) <= 0)
return ret;
}
/* done sending payload */
smtp_client_command_debug(cmd, "Finished sending payload");
Expand Down
1 change: 1 addition & 0 deletions src/lib-smtp/smtp-client-private.h
Expand Up @@ -43,6 +43,7 @@ struct smtp_client_command {

bool has_stream:1;
bool stream_dot:1;
bool stream_finished:1;
bool ehlo:1;
bool locked:1;
bool plug:1;
Expand Down

0 comments on commit e3dc647

Please sign in to comment.