[php-src] PHP-8.5: Merge branch 'PHP-8.4' into PHP-8.5

From: Date: Wed, 30 Sep 2026 17:51:09 +0000
Subject: [php-src] PHP-8.5: Merge branch 'PHP-8.4' into PHP-8.5
Groups: php.cvs 
Request: Send a blank email to php-cvs+get-141812@lists.php.net to get a copy of this message
Author: Ilia Alshanetsky (iliaal) Date: 2026-09-30T13:27:53-04:00 Commit: https://github.com/php/php-src/commit/f2469f6684f4f3c429daaadbfb62b3fe7c188117 Raw diff: https://github.com/php/php-src/commit/f2469f6684f4f3c429daaadbfb62b3fe7c188117.diff Merge branch 'PHP-8.4' into PHP-8.5 * PHP-8.4: ext/pdo: Report bound params and columns to GC Changed paths: A ext/pdo/tests/get_gc_bound_params.phpt M NEWS M ext/pdo/pdo_stmt.c Diff: diff --git a/NEWS b/NEWS index 8e820bc166b7..2077be6ee3db 100644 --- a/NEWS +++ b/NEWS @@ -132,6 +132,8 @@ PHP NEWS "array given" regardless of the value passed. (Ilia Alshanetsky) . Fixed PDOStatement::bindParam() and bindColumn() leaking the driver options value. (Ilia Alshanetsky) + . Fixed PDOStatement not reporting its bound parameters and columns to the + cycle collector. (Ilia Alshanetsky) - PDO_DBLIB: . Fixed bug GH-23741 (segfault after a failed query inside a PDO diff --git a/ext/pdo/pdo_stmt.c b/ext/pdo/pdo_stmt.c index 1077823d7ee3..d0bb89ea6a22 100644 --- a/ext/pdo/pdo_stmt.c +++ b/ext/pdo/pdo_stmt.c @@ -2061,6 +2061,22 @@ static HashTable *dbstmt_get_gc(zend_object *object, zval **gc_data, int *gc_cou } else if (default_fetch_mode == PDO_FETCH_CLASS && stmt->fetch.cls.ctor_args != NULL) { zend_get_gc_buffer_add_ht(gc_buffer, stmt->fetch.cls.ctor_args); } + if (stmt->bound_params) { + zval *val; + ZEND_HASH_FOREACH_VAL(stmt->bound_params, val) { + struct pdo_bound_param_data *param = Z_PTR_P(val); + zend_get_gc_buffer_add_zval(gc_buffer, &param->parameter); + zend_get_gc_buffer_add_zval(gc_buffer, &param->driver_params); + } ZEND_HASH_FOREACH_END(); + } + if (stmt->bound_columns) { + zval *val; + ZEND_HASH_FOREACH_VAL(stmt->bound_columns, val) { + struct pdo_bound_param_data *param = Z_PTR_P(val); + zend_get_gc_buffer_add_zval(gc_buffer, &param->parameter); + zend_get_gc_buffer_add_zval(gc_buffer, &param->driver_params); + } ZEND_HASH_FOREACH_END(); + } zend_get_gc_buffer_use(gc_buffer, gc_data, gc_count); /** diff --git a/ext/pdo/tests/get_gc_bound_params.phpt b/ext/pdo/tests/get_gc_bound_params.phpt new file mode 100644 index 000000000000..01c824a477c0 --- /dev/null +++ b/ext/pdo/tests/get_gc_bound_params.phpt @@ -0,0 +1,66 @@ +--TEST-- +PDO Common: PDOStatement::get_gc() must report bound params and columns for cycle collection +--EXTENSIONS-- +pdo +--SKIPIF-- +<?php +$dir = getenv('REDIR_TEST_DIR'); +if (false == $dir) die('skip no driver'); +require_once $dir . 'pdo_test.inc'; +PDOTest::skip(); +?> +--FILE-- +<?php +if (getenv('REDIR_TEST_DIR') === false) putenv('REDIR_TEST_DIR='.__DIR__ . '/../../pdo/tests/'); +require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc'; + +class Tracked { + public static array $collected = []; + + public function __construct(public string $name, public PDOStatement $stmt) {} + + public function __destruct() { + self::$collected[] = $this->name; + } +} + +$db = PDOTest::factory(); +$db->exec('CREATE TABLE get_gc_bound_params (a INT, b INT)'); + +$insert = $db->prepare('INSERT INTO get_gc_bound_params VALUES (?, ?)'); +$param = new Tracked('param', $insert); +$insert->bindParam(1, $param, PDO::PARAM_INT); +$paramOption = null; +$insert->bindParam(2, $paramOption, PDO::PARAM_INT, 0, new Tracked('param driver option', $insert)); + +$select = $db->query('SELECT a, b FROM get_gc_bound_params'); +$column = new Tracked('column', $select); +$select->bindColumn(1, $column, PDO::PARAM_INT); +$columnOption = null; +$select->bindColumn(2, $columnOption, PDO::PARAM_INT, 0, new Tracked('column driver option', $select)); + +unset($param, $paramOption, $column, $columnOption, $insert, $select, $db); +var_dump(Tracked::$collected); +gc_collect_cycles(); +sort(Tracked::$collected); +var_dump(Tracked::$collected); +?> +--CLEAN-- +<?php +require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc'; +$db = PDOTest::factory(); +PDOTest::dropTableIfExists($db, 'get_gc_bound_params'); +?> +--EXPECT-- +array(0) { +} +array(4) { + [0]=> + string(6) "column" + [1]=> + string(20) "column driver option" + [2]=> + string(5) "param" + [3]=> + string(19) "param driver option" +}

« previous php.cvs (#141812) next »