Merge branch 'PHP-8.4'

* PHP-8.4:
  Fix GH-16314 "Pdo\Mysql object is uninitialized" when opening a persistent connection (#16369)
This commit is contained in:
Máté Kocsis 2024-11-05 08:33:11 +01:00
commit a47d823405
No known key found for this signature in database
GPG Key ID: FD055E41728BF310
5 changed files with 151 additions and 7 deletions

View File

@ -436,8 +436,16 @@ PDO_API void php_pdo_internal_construct_driver(INTERNAL_FUNCTION_PARAMETERS, zen
if (pdbh) {
efree(dbh);
pdo_dbh_object_t *pdo_obj;
if (new_zval_object) {
pdo_obj = Z_PDO_OBJECT_P(new_zval_object);
} else {
pdo_obj = php_pdo_dbh_fetch_object(current_object);
}
/* switch over to the persistent one */
php_pdo_dbh_fetch_object(current_object)->inner = pdbh;
pdo_obj->inner = pdbh;
pdbh->refcount++;
dbh = pdbh;
}

View File

@ -18,7 +18,7 @@ if (getenv('PDOTEST_DSN') === false) {
class PDOTest {
// create an instance of the PDO driver, based on
// the current environment
static function factory($classname = PDO::class) {
static function factory($classname = PDO::class, bool $useConnectMethod = false) {
$dsn = getenv('PDOTEST_DSN');
$user = getenv('PDOTEST_USER');
$pass = getenv('PDOTEST_PASS');
@ -32,7 +32,11 @@ class PDOTest {
if ($user === false) $user = NULL;
if ($pass === false) $pass = NULL;
$db = new $classname($dsn, $user, $pass, $attr);
if ($useConnectMethod) {
$db = $classname::connect($dsn, $user, $pass, $attr);
} else {
$db = new $classname($dsn, $user, $pass, $attr);
}
if (!$db) {
die("Could not create PDO object (DSN=$dsn, user=$user)\n");
@ -54,12 +58,12 @@ class PDOTest {
}
}
static function test_factory($file, $classname = PDO::class) {
static function test_factory($file, $classname = PDO::class, bool $useConnectMethod = false) {
$config = self::get_config($file);
foreach ($config['ENV'] as $k => $v) {
putenv("$k=$v");
}
return self::factory($classname);
return self::factory($classname, $useConnectMethod);
}
static function get_config($file) {

View File

@ -0,0 +1,62 @@
--TEST--
GH-16314 "Pdo\Mysql object is uninitialized" when opening a persistent connection
--EXTENSIONS--
pdo_mysql
--SKIPIF--
<?php
require_once __DIR__ . '/inc/mysql_pdo_test.inc';
MySQLPDOTest::skip();
?>
--FILE--
<?php
require_once __DIR__ . '/inc/mysql_pdo_test.inc';
$pdo = MySQLPDOTest::factory(Pdo\Mysql::class, null, [PDO::ATTR_PERSISTENT => true], false);
var_dump($pdo->query('SELECT 1;')->fetchAll());
$pdo = MySQLPDOTest::factory(Pdo\Mysql::class, null, [PDO::ATTR_PERSISTENT => true], true);
var_dump($pdo->query('SELECT 1;')->fetchAll());
$pdo = MySQLPDOTest::factory(Pdo::class, null, [PDO::ATTR_PERSISTENT => true], false);
var_dump($pdo->query('SELECT 1;')->fetchAll());
$pdo = MySQLPDOTest::factory(Pdo::class, null, [PDO::ATTR_PERSISTENT => true], true);
var_dump($pdo->query('SELECT 1;')->fetchAll());
?>
--EXPECT--
array(1) {
[0]=>
array(2) {
[1]=>
int(1)
[0]=>
int(1)
}
}
array(1) {
[0]=>
array(2) {
[1]=>
int(1)
[0]=>
int(1)
}
}
array(1) {
[0]=>
array(2) {
[1]=>
int(1)
[0]=>
int(1)
}
}
array(1) {
[0]=>
array(2) {
[1]=>
int(1)
[0]=>
int(1)
}
}

View File

@ -8,7 +8,7 @@ foreach ($env as $k => $v) {
class MySQLPDOTest extends PDOTest {
static function factory($classname = PDO::class, $mydsn = null, $myAttr = null) {
static function factory($classname = PDO::class, $mydsn = null, $myAttr = null, bool $useConnectMethod = false) {
$dsn = self::getDSN($mydsn);
$user = PDO_MYSQL_TEST_USER;
$pass = PDO_MYSQL_TEST_PASS;
@ -20,7 +20,12 @@ class MySQLPDOTest extends PDOTest {
$attr = is_string($attr) && strlen($attr) ? unserialize($attr) : null;
}
$db = new $classname($dsn, $user, $pass, $attr);
if ($useConnectMethod) {
$db = $classname::connect($dsn, $user, $pass, $attr);
} else {
$db = new $classname($dsn, $user, $pass, $attr);
}
if (!$db) {
die("Could not create PDO object (DSN=$dsn, user=$user)\n");
}

View File

@ -0,0 +1,65 @@
--TEST--
GH-16314 "Pdo\Pgsql object is uninitialized" when opening a persistent connection
--EXTENSIONS--
pdo_pgsql
--SKIPIF--
<?php
require __DIR__ . '/config.inc';
require __DIR__ . '/../../../ext/pdo/tests/pdo_test.inc';
PDOTest::skip();
?>
--FILE--
<?php
putenv('PDOTEST_ATTR='.serialize([PDO::ATTR_PERSISTENT => true]));
require __DIR__ . '/../../../ext/pdo/tests/pdo_test.inc';
$pdo = PDOTest::test_factory(__DIR__ . '/common.phpt', Pdo\Pgsql::class, false);
var_dump($pdo->query('SELECT 1;')->fetchAll());
$pdo = PDOTest::test_factory(__DIR__ . '/common.phpt', Pdo\Pgsql::class, true);
var_dump($pdo->query('SELECT 1;')->fetchAll());
$pdo = PDOTest::test_factory(__DIR__ . '/common.phpt', Pdo::class, false);
var_dump($pdo->query('SELECT 1;')->fetchAll());
$pdo = PDOTest::test_factory(__DIR__ . '/common.phpt', Pdo::class, true);
var_dump($pdo->query('SELECT 1;')->fetchAll());
?>
--EXPECT--
array(1) {
[0]=>
array(2) {
["?column?"]=>
string(1) "1"
[0]=>
string(1) "1"
}
}
array(1) {
[0]=>
array(2) {
["?column?"]=>
string(1) "1"
[0]=>
string(1) "1"
}
}
array(1) {
[0]=>
array(2) {
["?column?"]=>
string(1) "1"
[0]=>
string(1) "1"
}
}
array(1) {
[0]=>
array(2) {
["?column?"]=>
string(1) "1"
[0]=>
string(1) "1"
}
}