MySQL connect: Parse the Unix domain socket path correctly
authorJasonCoombs <ceo@forensics.org>
Mon, 12 Aug 2019 04:38:48 +0000 (18:38 -1000)
committerJasonCoombs <ceo@forensics.org>
Thu, 15 Aug 2019 22:45:55 +0000 (12:45 -1000)
Some Unix domain socket paths contain colons, requiring MediaWiki to use a modified parsing delimiter. For example,
Google AppEngine provides a /cloudsql/ path to a Unix domain socket used for accessing a Cloud SQL database.
See https://cloud.google.com/sql/docs/mysql/connect-app-engine
The connection name takes the form of project:region:database which introduces two additional colons to the socket path.
Previously, the code presumed the existence of only one colon in a valid Unix domain socket path.

Bug: T230306
Change-Id: I2411ac1b583fd5c143563cb3155ef4e8a29a9b08

includes/libs/rdbms/database/DatabaseMysqli.php

index d32a12e..a11e936 100644 (file)
@@ -64,9 +64,14 @@ class DatabaseMysqli extends DatabaseMysqlBase {
                        );
                }
 
-               // Other than mysql_connect, mysqli_real_connect expects an explicit port
-               // and socket parameters. So we need to parse the port and socket out of
-               // $realServer
+               // Other than mysql_connect, mysqli_real_connect expects an explicit port number
+               // e.g. "localhost:1234" or "127.0.0.1:1234"
+               // or Unix domain socket path
+               // e.g. "localhost:/socket_path" or "localhost:/foo/bar:bar:bar"
+               // colons are known to be used by Google AppEngine,
+               // see <https://cloud.google.com/sql/docs/mysql/connect-app-engine>
+               //
+               // We need to parse the port or socket path out of $realServer
                $port = null;
                $socket = null;
                $hostAndPort = IP::splitHostAndPort( $realServer );
@@ -75,9 +80,9 @@ class DatabaseMysqli extends DatabaseMysqlBase {
                        if ( $hostAndPort[1] ) {
                                $port = $hostAndPort[1];
                        }
-               } elseif ( substr_count( $realServer, ':' ) == 1 ) {
-                       // If we have a colon and something that's not a port number
-                       // inside the hostname, assume it's the socket location
+               } elseif ( substr_count( $realServer, ':/' ) == 1 ) {
+                       // If we have a colon slash instead of a colon and a port number
+                       // after the ip or hostname, assume it's the Unix domain socket path
                        list( $realServer, $socket ) = explode( ':', $realServer, 2 );
                }