@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

When "mysqli->real_connect()" fails without setting an error code, recover more gracefully

Summary: Depends on D20779. Ref T13403. Bad parameters may cause this call to fail without setting an error code; if it does, catch the issue and go down the normal connection error pathway.

Test Plan:
- With "mysql.port" set to "quack", ran `bin/storage probe`.
- Before: wild mess of warnings as the code continued below and failed when trying to interact with the connection.
- After: clean connection failure with a useful error message.

Maniphest Tasks: T13403

Differential Revision: https://secure.phabricator.com/D20780

+33 -2
+3
src/infrastructure/storage/connection/mysql/AphrontBaseMySQLDatabaseConnection.php
··· 10 10 11 11 private $nextError; 12 12 13 + const CALLERROR_QUERY = 777777; 14 + const CALLERROR_CONNECT = 777778; 15 + 13 16 abstract protected function connect(); 14 17 abstract protected function rawQuery($raw_query); 15 18 abstract protected function rawQueries(array $raw_queries);
+30 -2
src/infrastructure/storage/connection/mysql/AphrontMySQLiDatabaseConnection.php
··· 68 68 $host = 'p:'.$host; 69 69 } 70 70 71 - @$conn->real_connect( 71 + $trap = new PhutilErrorTrap(); 72 + 73 + $ok = @$conn->real_connect( 72 74 $host, 73 75 $user, 74 76 $pass, 75 77 $database, 76 78 $port); 77 79 80 + $call_error = $trap->getErrorsAsString(); 81 + $trap->destroy(); 82 + 78 83 $errno = $conn->connect_errno; 79 84 if ($errno) { 80 85 $error = $conn->connect_error; 81 86 $this->throwConnectionException($errno, $error, $user, $host); 87 + } 88 + 89 + // See T13403. If the parameters to "real_connect()" are wrong, it may 90 + // fail without setting an error code. In this case, raise a generic 91 + // exception. (One way to reproduce this is to pass a string to the 92 + // "port" parameter.) 93 + 94 + if (!$ok) { 95 + if (strlen($call_error)) { 96 + $message = pht( 97 + 'mysqli->real_connect() failed: %s', 98 + $call_error); 99 + } else { 100 + $message = pht( 101 + 'mysqli->real_connect() failed, but did not set an error code '. 102 + 'or emit a message.'); 103 + } 104 + 105 + $this->throwConnectionException( 106 + self::CALLERROR_CONNECT, 107 + $message, 108 + $user, 109 + $host); 82 110 } 83 111 84 112 // See T13238. Attempt to prevent "LOAD DATA LOCAL INFILE", which allows a ··· 152 180 'Call to "mysqli->query()" failed, but did not set an error '. 153 181 'code or emit an error message.'); 154 182 } 155 - $this->throwQueryCodeException(777777, $message); 183 + $this->throwQueryCodeException(self::CALLERROR_QUERY, $message); 156 184 } 157 185 } 158 186