summaryrefslogtreecommitdiffstats
path: root/php-bug20528.patch
blob: f8a790a48acd583e6b672d653e0072402cf45bd3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
From 9d71c1e0b60cd152a47528dbe514efc443fce920 Mon Sep 17 00:00:00 2001
From: Remi Collet <remi@remirepo.net>
Date: Thu, 20 Nov 2025 02:58:45 +0100
Subject: [PATCH] Fix GH-20528: Regression breaks mysql connexion using an IPv6
 address enclosed in square brackets

---
 ext/mysqli/tests/mysqli_connect_port.phpt | 31 +++++++++++++++++++++++
 ext/mysqlnd/mysqlnd_connection.c          | 17 ++++++++++---
 2 files changed, 45 insertions(+), 3 deletions(-)
 create mode 100644 ext/mysqli/tests/mysqli_connect_port.phpt

diff --git a/ext/mysqli/tests/mysqli_connect_port.phpt b/ext/mysqli/tests/mysqli_connect_port.phpt
new file mode 100644
index 0000000000000..cb7fd1d8d1628
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_connect_port.phpt
@@ -0,0 +1,31 @@
+--TEST--
+mysqli_connect() with port in host
+--EXTENSIONS--
+mysqli
+--SKIPIF--
+<?php
+require_once 'skipifconnectfailure.inc';
+?>
+--FILE--
+<?php
+    require_once 'connect.inc';
+
+	// using port / host arguments
+    if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+        printf("Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+            $host, $user, $db, $port, $socket);
+	}
+
+    mysqli_close($link);
+
+	// using port in host
+    if (!$link = mysqli_connect("$host:$port", $user, $passwd, $db, "1$port", $socket)) {
+        printf("Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+            "$host:$port", $user, $db, "1$port", $socket);
+	}
+
+    mysqli_close($link);
+?>
+Done
+--EXPECTF--
+Done
diff --git a/ext/mysqlnd/mysqlnd_connection.c b/ext/mysqlnd/mysqlnd_connection.c
index d8e7304e9665f..8268034e8b798 100644
--- a/ext/mysqlnd/mysqlnd_connection.c
+++ b/ext/mysqlnd/mysqlnd_connection.c
@@ -553,13 +553,24 @@ MYSQLND_METHOD(mysqlnd_conn_data, get_scheme)(MYSQLND_CONN_DATA * conn, MYSQLND_
 			port = 3306;
 		}
 
-		/* ipv6 addresses are in the format [address]:port */
 		if (hostname.s[0] != '[' && mysqlnd_fast_is_ipv6_address(hostname.s)) {
+			/* IPv6 without square brackets so without port */
 			transport.l = mnd_sprintf(&transport.s, 0, "tcp://[%s]:%u", hostname.s, port);
 		} else {
-			/* Not ipv6, but could already contain a port number, in which case we should not add an extra port.
+			char *p;
+
+			/* IPv6 addresses are in the format [address]:port */
+			if (hostname.s[0] == '[') { /* IPv6 */
+				p = strchr(hostname.s, ']');
+				if (p && p[1] != ':') {
+					p = NULL;
+				}
+			} else { /* IPv4 or name */
+				p = strchr(hostname.s, ':');
+			}
+			/* Could already contain a port number, in which case we should not add an extra port.
 			 * See GH-8978. In a port doubling scenario, the first port would be used so we do the same to keep BC. */
-			if (strchr(hostname.s, ':')) {
+			if (p) {
 				/* TODO: Ideally we should be able to get rid of this workaround in the future. */
 				transport.l = mnd_sprintf(&transport.s, 0, "tcp://%s", hostname.s);
 			} else {