Mercurial > dovecot > core-2.2
changeset 20610:faa75dd3298b
doveadm-server: Fixed potential hang when reading replies to multiple commands
author | Timo Sirainen <timo.sirainen@dovecot.fi> |
---|---|
date | Mon, 08 Aug 2016 19:16:57 +0300 |
parents | 241194ca9c82 |
children | be966bc4b758 |
files | src/doveadm/server-connection.c |
diffstat | 1 files changed, 19 insertions(+), 9 deletions(-) [+] |
line wrap: on
line diff
--- a/src/doveadm/server-connection.c Mon Aug 08 19:11:16 2016 +0300 +++ b/src/doveadm/server-connection.c Mon Aug 08 19:16:57 2016 +0300 @@ -59,6 +59,7 @@ static struct server_connection *printing_conn = NULL; static void server_connection_input(struct server_connection *conn); +static bool server_connection_input_one(struct server_connection *conn); static void print_connection_released(void) { @@ -264,10 +265,7 @@ static void server_connection_input(struct server_connection *conn) { - const unsigned char *data; - size_t size; const char *line; - int exit_code; if (!conn->handshaked) { if ((line = i_stream_read_next_line(conn->input)) == NULL) { @@ -314,24 +312,34 @@ } } + while (server_connection_input_one(conn)) ; +} + +static bool server_connection_input_one(struct server_connection *conn) +{ + const unsigned char *data; + size_t size; + const char *line; + int exit_code; + data = i_stream_get_data(conn->input, &size); if (size == 0) - return; + return FALSE; switch (conn->state) { case SERVER_REPLY_STATE_DONE: i_error("doveadm server sent unexpected input"); server_connection_destroy(&conn); - return; + return FALSE; case SERVER_REPLY_STATE_PRINT: server_handle_input(conn, data, size); if (conn->state != SERVER_REPLY_STATE_RET) - break; + return FALSE; /* fall through */ case SERVER_REPLY_STATE_RET: line = i_stream_next_line(conn->input); if (line == NULL) - return; + return FALSE; if (line[0] == '+') server_connection_callback(conn, 0, ""); else if (line[0] == '-') { @@ -347,14 +355,16 @@ i_error("doveadm server sent broken input " "(expected cmd reply): %s", line); server_connection_destroy(&conn); - break; + return FALSE; } if (conn->callback == NULL) { /* we're finished, close the connection */ server_connection_destroy(&conn); + return FALSE; } - break; + return TRUE; } + i_unreached(); } static int server_connection_read_settings(struct server_connection *conn)