diff --git a/sql/net_serv.cc b/sql/net_serv.cc index d3388bb2f62fe..5940318c6629c 100644 --- a/sql/net_serv.cc +++ b/sql/net_serv.cc @@ -986,6 +986,7 @@ my_real_read(NET *net, size_t *complen, size_t length; uint i,retry_count=0; ulong len=packet_error; + bool proxy_parsed= false; my_bool expect_error_packet __attribute__((unused))= 0; thr_alarm_t alarmed; #ifndef NO_ALARM @@ -1253,16 +1254,21 @@ my_real_read(NET *net, size_t *complen, packets_out_of_order: { - switch (handle_proxy_header(net)) { - case ABORT: + if (!proxy_parsed) + { + switch (handle_proxy_header(net)) + { + case ABORT: /* error happened, message is already written. */ len= packet_error; - goto end; - case RETRY: + goto end; + case RETRY: + proxy_parsed= true; goto retry; - case IGNORE: + case IGNORE: break; - } + } + } DBUG_PRINT("error", ("Packets out of order (Found: %d, expected %u)", diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index ef8f9c3d34a86..e0d818300ca59 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -20786,6 +20786,23 @@ static void test_proxy_header_limits() mysql_close(m); } +/* Test that connection fails with multiple proxy headers (MDEV-40878) */ +static void test_proxy_header_multiple() +{ + MYSQL *m; + const char header[]= "PROXY TCP4 192.0.2.1 127.0.0.1 12345 3306\r\n" + "PROXY TCP4 192.0.2.2 127.0.0.1 12346 3306\r\n"; + myheader("test_proxy_header_multiple"); + + m = mysql_client_init(NULL); + DIE_UNLESS(m); + mysql_optionsv(m, MARIADB_OPT_PROXY_HEADER, header, sizeof(header)-1); + + /* Connection should fail, second proxy header is interpreted as packet error */ + DIE_UNLESS(mysql_real_connect(m, opt_host, "root", "", NULL, opt_port, opt_unix_socket, 0) == NULL); + mysql_close(m); +} + /* MDEV-37556 memory leak in proxy protocol for non-loopback @@ -21095,6 +21112,7 @@ static void test_proxy_header() test_proxy_header_localhost(); test_proxy_header_ignore(); test_proxy_header_limits(); + test_proxy_header_multiple(); test_proxy_header_dbug_remote_connection(); test_proxy_header_connect_errors_reset(); test_proxy_header_proxy_host_connect_errors_reset();