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) {