From 72cf32f09a6c41b6717d1cb74bf5b19656c84d5d Mon Sep 17 00:00:00 2001 From: Saki Takamachi Date: Tue, 5 Nov 2024 21:12:24 +0900 Subject: [PATCH 1/3] Added gc_handler to properly handle circular references. --- ext/pdo/pdo_stmt.c | 18 ++++++++++++++++ ext/pdo/tests/gh16703.phpt | 43 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 ext/pdo/tests/gh16703.phpt diff --git a/ext/pdo/pdo_stmt.c b/ext/pdo/pdo_stmt.c index 239b8d6a99bef..13180e29ee865 100644 --- a/ext/pdo/pdo_stmt.c +++ b/ext/pdo/pdo_stmt.c @@ -2077,6 +2077,23 @@ static zend_function *dbstmt_method_get(zend_object **object_pp, zend_string *me return fbc; } +static HashTable *dbstmt_get_gc(zend_object *object, zval **gc_data, int *gc_count) +{ + pdo_stmt_t *stmt = php_pdo_stmt_fetch_object(object); + *gc_data = &stmt->fetch.into; + *gc_count = 1; + + /** + * If there are no dynamic properties and the default property is 1 (that is, there is only one property + * of string that does not participate in GC), there is no need to call zend_std_get_properties(). + */ + if (object->properties == NULL && object->ce->default_properties_count <= 1) { + return NULL; + } else { + return zend_std_get_properties(object); + } +} + zend_object_handlers pdo_dbstmt_object_handlers; zend_object_handlers pdo_row_object_handlers; @@ -2495,6 +2512,7 @@ void pdo_stmt_init(void) pdo_dbstmt_object_handlers.get_method = dbstmt_method_get; pdo_dbstmt_object_handlers.compare = zend_objects_not_comparable; pdo_dbstmt_object_handlers.clone_obj = NULL; + pdo_dbstmt_object_handlers.get_gc = dbstmt_get_gc; pdo_row_ce = register_class_PDORow(); pdo_row_ce->create_object = pdo_row_new; diff --git a/ext/pdo/tests/gh16703.phpt b/ext/pdo/tests/gh16703.phpt new file mode 100644 index 0000000000000..fba785c660f6b --- /dev/null +++ b/ext/pdo/tests/gh16703.phpt @@ -0,0 +1,43 @@ +--TEST-- +GH-16703: Memory leak of setFetchMode() +--EXTENSIONS-- +pdo +--SKIPIF-- + +--FILE-- + [TestStmt::class]], +); + +$db->exec('CREATE TABLE gh16703 (name varchar(255))'); +$db->exec("INSERT INTO gh16703 (name) VALUES ('test_name')"); + +$stmt = $db->query('SELECT name FROM gh16703'); +$t = $stmt; +$stmt->setFetchMode(PDO::FETCH_INTO, $stmt); +$stmt->fetch(); +echo "done!\n"; +?> +--CLEAN-- +exec('DROP TABLE gh16703'); +?> +--EXPECT-- +done! From 6ab32fe7d177b8e945ce8f8edc35b182d428c9c6 Mon Sep 17 00:00:00 2001 From: Saki Takamachi <34942839+SakiTakamachi@users.noreply.github.com> Date: Tue, 5 Nov 2024 21:24:47 +0900 Subject: [PATCH 2/3] Added putenv into test Co-authored-by: Christoph M. Becker --- ext/pdo/tests/gh16703.phpt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/pdo/tests/gh16703.phpt b/ext/pdo/tests/gh16703.phpt index fba785c660f6b..fc6fba0da6d7a 100644 --- a/ext/pdo/tests/gh16703.phpt +++ b/ext/pdo/tests/gh16703.phpt @@ -11,7 +11,7 @@ PDOTest::skip(); ?> --FILE-- Date: Tue, 5 Nov 2024 22:52:39 +0900 Subject: [PATCH 3/3] Fixed a test --- ext/pdo/tests/gh16703.phpt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ext/pdo/tests/gh16703.phpt b/ext/pdo/tests/gh16703.phpt index fc6fba0da6d7a..e5b4b8640389e 100644 --- a/ext/pdo/tests/gh16703.phpt +++ b/ext/pdo/tests/gh16703.phpt @@ -21,7 +21,10 @@ $db = new PDO( getenv('PDOTEST_DSN'), getenv('PDOTEST_USER') ?: null, getenv('PDOTEST_PASS') ?: null, - [PDO::ATTR_STATEMENT_CLASS => [TestStmt::class]], + [ + PDO::ATTR_CASE => PDO::CASE_LOWER, + PDO::ATTR_STATEMENT_CLASS => [TestStmt::class], + ], ); $db->exec('CREATE TABLE gh16703 (name varchar(255))'); @@ -35,6 +38,8 @@ echo "done!\n"; ?> --CLEAN-- exec('DROP TABLE gh16703');