mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-10 08:52:39 +01:00
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
This commit is contained in:
parent
d9badba147
commit
f8eec38c94
2 changed files with 33 additions and 2 deletions
|
@ -10,6 +10,9 @@ abstract class AphrontBaseMySQLDatabaseConnection
|
||||||
|
|
||||||
private $nextError;
|
private $nextError;
|
||||||
|
|
||||||
|
const CALLERROR_QUERY = 777777;
|
||||||
|
const CALLERROR_CONNECT = 777778;
|
||||||
|
|
||||||
abstract protected function connect();
|
abstract protected function connect();
|
||||||
abstract protected function rawQuery($raw_query);
|
abstract protected function rawQuery($raw_query);
|
||||||
abstract protected function rawQueries(array $raw_queries);
|
abstract protected function rawQueries(array $raw_queries);
|
||||||
|
|
|
@ -68,19 +68,47 @@ final class AphrontMySQLiDatabaseConnection
|
||||||
$host = 'p:'.$host;
|
$host = 'p:'.$host;
|
||||||
}
|
}
|
||||||
|
|
||||||
@$conn->real_connect(
|
$trap = new PhutilErrorTrap();
|
||||||
|
|
||||||
|
$ok = @$conn->real_connect(
|
||||||
$host,
|
$host,
|
||||||
$user,
|
$user,
|
||||||
$pass,
|
$pass,
|
||||||
$database,
|
$database,
|
||||||
$port);
|
$port);
|
||||||
|
|
||||||
|
$call_error = $trap->getErrorsAsString();
|
||||||
|
$trap->destroy();
|
||||||
|
|
||||||
$errno = $conn->connect_errno;
|
$errno = $conn->connect_errno;
|
||||||
if ($errno) {
|
if ($errno) {
|
||||||
$error = $conn->connect_error;
|
$error = $conn->connect_error;
|
||||||
$this->throwConnectionException($errno, $error, $user, $host);
|
$this->throwConnectionException($errno, $error, $user, $host);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// See T13403. If the parameters to "real_connect()" are wrong, it may
|
||||||
|
// fail without setting an error code. In this case, raise a generic
|
||||||
|
// exception. (One way to reproduce this is to pass a string to the
|
||||||
|
// "port" parameter.)
|
||||||
|
|
||||||
|
if (!$ok) {
|
||||||
|
if (strlen($call_error)) {
|
||||||
|
$message = pht(
|
||||||
|
'mysqli->real_connect() failed: %s',
|
||||||
|
$call_error);
|
||||||
|
} else {
|
||||||
|
$message = pht(
|
||||||
|
'mysqli->real_connect() failed, but did not set an error code '.
|
||||||
|
'or emit a message.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->throwConnectionException(
|
||||||
|
self::CALLERROR_CONNECT,
|
||||||
|
$message,
|
||||||
|
$user,
|
||||||
|
$host);
|
||||||
|
}
|
||||||
|
|
||||||
// See T13238. Attempt to prevent "LOAD DATA LOCAL INFILE", which allows a
|
// See T13238. Attempt to prevent "LOAD DATA LOCAL INFILE", which allows a
|
||||||
// malicious server to ask the client for any file. At time of writing,
|
// malicious server to ask the client for any file. At time of writing,
|
||||||
// this option MUST be set after "real_connect()" on all PHP versions.
|
// this option MUST be set after "real_connect()" on all PHP versions.
|
||||||
|
@ -152,7 +180,7 @@ final class AphrontMySQLiDatabaseConnection
|
||||||
'Call to "mysqli->query()" failed, but did not set an error '.
|
'Call to "mysqli->query()" failed, but did not set an error '.
|
||||||
'code or emit an error message.');
|
'code or emit an error message.');
|
||||||
}
|
}
|
||||||
$this->throwQueryCodeException(777777, $message);
|
$this->throwQueryCodeException(self::CALLERROR_QUERY, $message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue