From 8b5c926ca4fbbaf608fb37ea686c1c62a22673d3 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 7 Sep 2025 21:08:10 +0200 Subject: [PATCH] Fix bug #67563: mysqli compiled with mysqlnd does not take ipv6 adress as parameter In the past, when libmysqlclient could be used, it accepted ipv6 addresses as hostname without enclosing it first in brackets. However, in mysqlnd this never worked. In the past this caused a discrepancy between the two implementations. Nowadays, mysqli only works with mysqlnd so we don't even have to cater to libmysqlclient. However, a plain ipv6 address should still work as a hostname. Also for people migrating to newer PHP versions it's nice if this keeps working. The solution is to check if we're dealing with an ipv6 address not yet enclosed in brackets. In that case we add the brackets automatically. --- ext/mysqlnd/mysqlnd_connection.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/ext/mysqlnd/mysqlnd_connection.c b/ext/mysqlnd/mysqlnd_connection.c index d46029889fad0..a97f2820a3190 100644 --- a/ext/mysqlnd/mysqlnd_connection.c +++ b/ext/mysqlnd/mysqlnd_connection.c @@ -513,6 +513,16 @@ MYSQLND_METHOD(mysqlnd_conn_data, connect_handshake)(MYSQLND_CONN_DATA * conn, } /* }}} */ +/* ipv6 addresses have at least two colons, which is how we can differentiate between domain names and addresses */ +static bool mysqlnd_fast_is_ipv6_address(const char *s) +{ + const char *first_colon = strchr(s, ':'); + if (!first_colon) { + return false; + } + return strchr(first_colon + 1, ':') != NULL; +} + /* {{{ mysqlnd_conn_data::get_scheme */ static MYSQLND_STRING MYSQLND_METHOD(mysqlnd_conn_data, get_scheme)(MYSQLND_CONN_DATA * conn, MYSQLND_CSTRING hostname, MYSQLND_CSTRING *socket_or_pipe, unsigned int port, bool * unix_socket, bool * named_pipe) @@ -542,7 +552,13 @@ MYSQLND_METHOD(mysqlnd_conn_data, get_scheme)(MYSQLND_CONN_DATA * conn, MYSQLND_ if (!port) { port = 3306; } - transport.l = mnd_sprintf(&transport.s, 0, "tcp://%s:%u", hostname.s, port); + + /* ipv6 addresses are in the format [address]:port */ + if (hostname.s[0] != '[' && mysqlnd_fast_is_ipv6_address(hostname.s)) { + transport.l = mnd_sprintf(&transport.s, 0, "tcp://[%s]:%u", hostname.s, port); + } else { + transport.l = mnd_sprintf(&transport.s, 0, "tcp://%s:%u", hostname.s, port); + } } DBG_INF_FMT("transport=%s", transport.s? transport.s:"OOM"); DBG_RETURN(transport);