]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-smtp: client: Fix assertion panic occurring when DATA dot stream cannot be finish...
authorStephan Bosch <stephan.bosch@dovecot.fi>
Fri, 18 May 2018 08:24:46 +0000 (10:24 +0200)
committerVille Savolainen <ville.savolainen@dovecot.fi>
Mon, 4 Jun 2018 09:59:33 +0000 (12:59 +0300)
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)

src/lib-smtp/smtp-client-command.c
src/lib-smtp/smtp-client-private.h

index 4d023ed5a76334abf6c09a96d4e7cdee9a3aadee..de77a85c7122e7a4a6bcb9b05127c5aca9308144 100644 (file)
@@ -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)
 {
@@ -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);
@@ -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");
index d10aa134bb87936b7d8bb9a8c9852a974195ceba..f70b2fd6848301c1319bd4d8f1a45b76a8930902 100644 (file)
@@ -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;