WordPress.org

Make WordPress Core

Ticket #41722: 41722.3.diff

File 41722.3.diff, 5.5 KB (added by schlessera, 2 years ago)

Moved bracket logic out of parsing, added unit test for parsing and modified regexes to fit all tested host strings.

  • src/wp-includes/wp-db.php

    diff --git src/wp-includes/wp-db.php src/wp-includes/wp-db.php
    index 57ed865a35..e676523476 100644
    class wpdb { 
    14501450                if ( $this->use_mysqli ) {
    14511451                        $this->dbh = mysqli_init();
    14521452
    1453                         // mysqli_real_connect doesn't support the host param including a port or socket
    1454                         // like mysql_connect does. This duplicates how mysql_connect detects a port and/or socket file.
    1455                         $port = null;
    1456                         $socket = null;
    1457                         $host = $this->dbhost;
    1458                         $port_or_socket = strstr( $host, ':' );
    1459                         if ( ! empty( $port_or_socket ) ) {
    1460                                 $host = substr( $host, 0, strpos( $host, ':' ) );
    1461                                 $port_or_socket = substr( $port_or_socket, 1 );
    1462                                 if ( 0 !== strpos( $port_or_socket, '/' ) ) {
    1463                                         $port = intval( $port_or_socket );
    1464                                         $maybe_socket = strstr( $port_or_socket, ':' );
    1465                                         if ( ! empty( $maybe_socket ) ) {
    1466                                                 $socket = substr( $maybe_socket, 1 );
    1467                                         }
    1468                                 } else {
    1469                                         $socket = $port_or_socket;
    1470                                 }
     1453                        list( $host, $port, $socket, $is_ipv6 ) = $this->parse_db_host( $this->dbhost );
     1454
     1455                        // If using the `mysqlnd` library, the IPv6 address needs to be
     1456                        // enclosed in square brackets, whereas it doesn't while using the
     1457                        // `libmysqlclient` library.
     1458                        // @see https://bugs.php.net/bug.php?id=67563
     1459                        if ( $is_ipv6 && extension_loaded( 'mysqlnd' ) ) {
     1460                                $host = "[$host]";
    14711461                        }
    14721462
    14731463                        if ( WP_DEBUG ) {
    class wpdb { 
    15601550        }
    15611551
    15621552        /**
     1553         * Parse the DB_HOST setting to interpret it for mysqli_real_connect.
     1554         *
     1555         * mysqli_real_connect doesn't support the host param including a port or
     1556         * socket like mysql_connect does. This duplicates how mysql_connect detects
     1557         * a port and/or socket file.
     1558         *
     1559         * @since 4.9.0
     1560         *
     1561         * @param string $host The DB_HOST setting to parse.
     1562         *
     1563         * @return array Array containing the host, the port, the socket and whether
     1564         *               it is an IPv6 address, in that order.
     1565         */
     1566        public function parse_db_host( $host ) {
     1567                $port    = null;
     1568                $socket  = null;
     1569                $is_ipv6 = false;
     1570
     1571                // We need to check for an IPv6 address first.
     1572                // An IPv6 address will always contain at least two colons.
     1573                if ( substr_count( $host, ':' ) > 1 ) {
     1574                        $pattern = '#^(?:\[)?(?<host>[0-9a-fA-F:]+)(?:\]:(?<port>[\d]+))?(?:/(?<socket>.+))?#';
     1575                        $is_ipv6 = true;
     1576                } else {
     1577                        // We seem to be dealing with an IPv4 address.
     1578                        $pattern = '#^(?<host>[^:/]*)(?::(?<port>[\d]+))?(?::(?<socket>.+))?#';
     1579                }
     1580
     1581                $matches = array();
     1582                $result = preg_match( $pattern, $host, $matches );
     1583
     1584                if ( 1 !== $result ) {
     1585                        // Couldn't parse the address, just return as is to try it out.
     1586                        return array( $host, $port, $socket );
     1587                }
     1588
     1589                foreach ( array( 'host', 'port', 'socket' ) as $component ) {
     1590                        if ( array_key_exists( $component, $matches ) ) {
     1591                                $$component = $matches[$component];
     1592                        }
     1593                }
     1594
     1595                return array( $host, $port, $socket, $is_ipv6 );
     1596        }
     1597
     1598        /**
    15631599         * Checks that the connection to the database is still up. If not, try to reconnect.
    15641600         *
    15651601         * If this function is unable to reconnect, it will forcibly die, or if after the
  • tests/phpunit/tests/db.php

    diff --git tests/phpunit/tests/db.php tests/phpunit/tests/db.php
    index ab4186c794..5e801aaa4b 100644
    class Tests_DB extends WP_UnitTestCase { 
    10751075                $this->assertSame( 'utf8', $result['charset'] );
    10761076                $this->assertSame( 'utf8_general_ci', $result['collate'] );
    10771077        }
     1078
     1079        /**
     1080         * @dataProvider parse_db_host_data_provider
     1081         * @ticket 41722
     1082         */
     1083        public function test_parse_db_host( $host_string, $host, $port, $socket, $is_ipv6 ) {
     1084                global $wpdb;
     1085                list( $parsed_host, $parsed_port, $parsed_socket, $parsed_is_ipv6 ) = $wpdb->parse_db_host( $host_string );
     1086                $this->assertEquals( $host, $parsed_host );
     1087                $this->assertEquals( $port, $parsed_port );
     1088                $this->assertEquals( $socket, $parsed_socket );
     1089                $this->assertEquals( $is_ipv6, $parsed_is_ipv6 );
     1090        }
     1091
     1092        public function parse_db_host_data_provider() {
     1093                return array(
     1094                        array(
     1095                                '',
     1096                                null,
     1097                                null,
     1098                                null,
     1099                                false,
     1100                        ),
     1101                        array(
     1102                                ':3306',
     1103                                null,
     1104                                '3306',
     1105                                null,
     1106                                false,
     1107                        ),
     1108                        array(
     1109                                ':/tmp/mysql.sock',
     1110                                null,
     1111                                null,
     1112                                '/tmp/mysql.sock',
     1113                                false,
     1114                        ),
     1115                        array(
     1116                                '127.0.0.1',
     1117                                '127.0.0.1',
     1118                                null,
     1119                                null,
     1120                                false,
     1121                        ),
     1122                        array(
     1123                                '127.0.0.1:3306',
     1124                                '127.0.0.1',
     1125                                '3306',
     1126                                null,
     1127                                false,
     1128                        ),
     1129                        array(
     1130                                'example.com',
     1131                                'example.com',
     1132                                null,
     1133                                null,
     1134                                false,
     1135                        ),
     1136                        array(
     1137                                'example.com:3306',
     1138                                'example.com',
     1139                                '3306',
     1140                                null,
     1141                                false,
     1142                        ),
     1143                        array(
     1144                                'localhost',
     1145                                'localhost',
     1146                                null,
     1147                                null,
     1148                                false,
     1149                        ),
     1150                        array(
     1151                                'localhost:/tmp/mysql.sock',
     1152                                'localhost',
     1153                                null,
     1154                                '/tmp/mysql.sock',
     1155                                false,
     1156                        ),
     1157                        array(
     1158                                '0000:0000:0000:0000:0000:0000:0000:0001',
     1159                                '0000:0000:0000:0000:0000:0000:0000:0001',
     1160                                null,
     1161                                null,
     1162                                true,
     1163                        ),
     1164                        array(
     1165                                '::1',
     1166                                '::1',
     1167                                null,
     1168                                null,
     1169                                true,
     1170                        ),
     1171                        array(
     1172                                '[::1]',
     1173                                '::1',
     1174                                null,
     1175                                null,
     1176                                true,
     1177                        ),
     1178                        array(
     1179                                '[::1]:3306',
     1180                                '::1',
     1181                                '3306',
     1182                                null,
     1183                                true,
     1184                        ),
     1185                        array(
     1186                                '2001:0db8:0000:0000:0000:ff00:0042:8329',
     1187                                '2001:0db8:0000:0000:0000:ff00:0042:8329',
     1188                                null,
     1189                                null,
     1190                                true,
     1191                        ),
     1192                        array(
     1193                                '2001:db8:0:0:0:ff00:42:8329',
     1194                                '2001:db8:0:0:0:ff00:42:8329',
     1195                                null,
     1196                                null,
     1197                                true,
     1198                        ),
     1199                        array(
     1200                                '2001:db8::ff00:42:8329',
     1201                                '2001:db8::ff00:42:8329',
     1202                                null,
     1203                                null,
     1204                                true,
     1205                        ),
     1206                );
     1207        }
    10781208}