PdoSessionHandler: fix advisory lock for pgsql when session.sid_bits_per_character > 4
This commit is contained in:
parent
e4d9bfd245
commit
0f0a6e85e3
|
@ -580,11 +580,11 @@ class PdoSessionHandler implements \SessionHandlerInterface
|
||||||
return $releaseStmt;
|
return $releaseStmt;
|
||||||
case 'pgsql':
|
case 'pgsql':
|
||||||
// Obtaining an exclusive session level advisory lock requires an integer key.
|
// Obtaining an exclusive session level advisory lock requires an integer key.
|
||||||
// So we convert the HEX representation of the session id to an integer.
|
// When session.sid_bits_per_character > 4, the session id can contain non-hex-characters.
|
||||||
// Since integers are signed, we have to skip one hex char to fit in the range.
|
// So we cannot just use hexdec().
|
||||||
if (4 === PHP_INT_SIZE) {
|
if (4 === \PHP_INT_SIZE) {
|
||||||
$sessionInt1 = hexdec(substr($sessionId, 0, 7));
|
$sessionInt1 = $this->convertStringToInt($sessionId);
|
||||||
$sessionInt2 = hexdec(substr($sessionId, 7, 7));
|
$sessionInt2 = $this->convertStringToInt(substr($sessionId, 4, 4));
|
||||||
|
|
||||||
$stmt = $this->pdo->prepare('SELECT pg_advisory_lock(:key1, :key2)');
|
$stmt = $this->pdo->prepare('SELECT pg_advisory_lock(:key1, :key2)');
|
||||||
$stmt->bindValue(':key1', $sessionInt1, \PDO::PARAM_INT);
|
$stmt->bindValue(':key1', $sessionInt1, \PDO::PARAM_INT);
|
||||||
|
@ -595,7 +595,7 @@ class PdoSessionHandler implements \SessionHandlerInterface
|
||||||
$releaseStmt->bindValue(':key1', $sessionInt1, \PDO::PARAM_INT);
|
$releaseStmt->bindValue(':key1', $sessionInt1, \PDO::PARAM_INT);
|
||||||
$releaseStmt->bindValue(':key2', $sessionInt2, \PDO::PARAM_INT);
|
$releaseStmt->bindValue(':key2', $sessionInt2, \PDO::PARAM_INT);
|
||||||
} else {
|
} else {
|
||||||
$sessionBigInt = hexdec(substr($sessionId, 0, 15));
|
$sessionBigInt = $this->convertStringToInt($sessionId);
|
||||||
|
|
||||||
$stmt = $this->pdo->prepare('SELECT pg_advisory_lock(:key)');
|
$stmt = $this->pdo->prepare('SELECT pg_advisory_lock(:key)');
|
||||||
$stmt->bindValue(':key', $sessionBigInt, \PDO::PARAM_INT);
|
$stmt->bindValue(':key', $sessionBigInt, \PDO::PARAM_INT);
|
||||||
|
@ -613,6 +613,27 @@ class PdoSessionHandler implements \SessionHandlerInterface
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes the first 4 (when PHP_INT_SIZE == 4) or 8 characters of the string as an integer.
|
||||||
|
*
|
||||||
|
* Keep in mind, PHP integers are signed.
|
||||||
|
*
|
||||||
|
* @param string $string
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
private function convertStringToInt($string)
|
||||||
|
{
|
||||||
|
if (4 === \PHP_INT_SIZE) {
|
||||||
|
return (ord($string[3]) << 24) + (ord($string[2]) << 16) + (ord($string[1]) << 8) + ord($string[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$int1 = (ord($string[7]) << 24) + (ord($string[6]) << 16) + (ord($string[5]) << 8) + ord($string[4]);
|
||||||
|
$int2 = (ord($string[3]) << 24) + (ord($string[2]) << 16) + (ord($string[1]) << 8) + ord($string[0]);
|
||||||
|
|
||||||
|
return $int2 + ($int1 << 32);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a locking or nonlocking SQL query to read session information.
|
* Return a locking or nonlocking SQL query to read session information.
|
||||||
*
|
*
|
||||||
|
|
Reference in New Issue