Mercurial > dovecot > core-2.2
diff src/director/login-connection.c @ 20693:fa67f1a329da
Fix control flow and T_BEGIN/T_END hygiene
You mustn't goto, break, continue, or return from out of a
T_BEGIN {...} T_END block, as that will lose a t_pop().
This has been seen in the wild: Panic: Leaked t_pop() call
Signed-off-by: Phil Carmody <phil@dovecot.fi>
author | Phil Carmody <phil@dovecot.fi> |
---|---|
date | Wed, 31 Aug 2016 20:14:41 +0300 |
parents | 0f22db71df7a |
children | 59437f8764c6 |
line wrap: on
line diff
--- a/src/director/login-connection.c Wed Aug 31 09:20:49 2016 +0300 +++ b/src/director/login-connection.c Wed Aug 31 20:14:41 2016 +0300 @@ -73,21 +73,27 @@ static void login_connection_authreply_input(struct login_connection *conn) { + bool bail = FALSE; const char *line; - while ((line = i_stream_read_next_line(conn->input)) != NULL) T_BEGIN { + while (!bail && (line = i_stream_read_next_line(conn->input)) != NULL) T_BEGIN { if (!conn->handshaked) { if (!version_string_verify(line, "director-authreply-client", AUTHREPLY_PROTOCOL_MAJOR_VERSION)) { i_error("authreply client sent invalid handshake: %s", line); login_connection_deinit(&conn); - return; + bail = TRUE; /* don't return from within a T_BEGIN {...} T_END */ + } else { + conn->handshaked = TRUE; } - conn->handshaked = TRUE; } else { auth_input_line(line, conn); } } T_END; + + if (bail) + return; + if (conn->input->eof) { if (conn->input->stream_errno != 0 && conn->input->stream_errno != ECONNRESET) {