Skip to content

Commit

Permalink
Fix phpGH-16131 Pdo\Pgsql object is uninitialized when opening a pers…
Browse files Browse the repository at this point in the history
…istent connection
  • Loading branch information
kocsismate committed Oct 11, 2024
1 parent c80949e commit 787c9ce
Show file tree
Hide file tree
Showing 5 changed files with 151 additions and 7 deletions.
10 changes: 9 additions & 1 deletion ext/pdo/pdo_dbh.c
Original file line number Diff line number Diff line change
Expand Up @@ -431,8 +431,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(object);
}

/* switch over to the persistent one */
php_pdo_dbh_fetch_object(object)->inner = pdbh;
pdo_obj->inner = pdbh;
pdbh->refcount++;
dbh = pdbh;
}
Expand Down
12 changes: 8 additions & 4 deletions ext/pdo/tests/pdo_test.inc
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand All @@ -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");
Expand All @@ -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) {
Expand Down
62 changes: 62 additions & 0 deletions ext/pdo_mysql/tests/gh16314.phpt
Original file line number Diff line number Diff line change
@@ -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) {
["?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"
}
}
9 changes: 7 additions & 2 deletions ext/pdo_mysql/tests/inc/mysql_pdo_test.inc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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");
}
Expand Down
65 changes: 65 additions & 0 deletions ext/pdo_pgsql/tests/gh16314.phpt
Original file line number Diff line number Diff line change
@@ -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"
}
}

0 comments on commit 787c9ce

Please sign in to comment.