Skip to content

Commit cb6fac5

Browse files
committed
Merge branch 'PHP-8.2' into PHP-8.3
* PHP-8.2: Fix GH-11878: SQLite3 callback functions cause a memory leak with a callable array
2 parents 94eb3bd + 6851c7b commit cb6fac5

File tree

3 files changed

+72
-0
lines changed

3 files changed

+72
-0
lines changed

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ PHP NEWS
4040
. Fixed bug GH-12151 (str_getcsv ending with escape zero segfualt).
4141
(Jakub Zelenka)
4242

43+
- SQLite3:
44+
. Fixed bug GH-11878 (SQLite3 callback functions cause a memory leak with
45+
a callable array). (nielsdos, arnaud-lb)
46+
4347
31 Aug 2023, PHP 8.3.0RC1
4448

4549
- Core:

ext/sqlite3/sqlite3.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2245,6 +2245,42 @@ static void php_sqlite3_object_free_storage(zend_object *object) /* {{{ */
22452245
}
22462246
/* }}} */
22472247

2248+
static HashTable *php_sqlite3_get_gc(zend_object *object, zval **table, int *n)
2249+
{
2250+
php_sqlite3_db_object *intern = php_sqlite3_db_from_obj(object);
2251+
2252+
if (intern->funcs == NULL && intern->collations == NULL) {
2253+
/* Fast path without allocations */
2254+
*table = NULL;
2255+
*n = 0;
2256+
return zend_std_get_gc(object, table, n);
2257+
} else {
2258+
zend_get_gc_buffer *gc_buffer = zend_get_gc_buffer_create();
2259+
2260+
php_sqlite3_func *func = intern->funcs;
2261+
while (func != NULL) {
2262+
zend_get_gc_buffer_add_zval(gc_buffer, &func->func);
2263+
zend_get_gc_buffer_add_zval(gc_buffer, &func->step);
2264+
zend_get_gc_buffer_add_zval(gc_buffer, &func->fini);
2265+
func = func->next;
2266+
}
2267+
2268+
php_sqlite3_collation *collation = intern->collations;
2269+
while (collation != NULL) {
2270+
zend_get_gc_buffer_add_zval(gc_buffer, &collation->cmp_func);
2271+
collation = collation->next;
2272+
}
2273+
2274+
zend_get_gc_buffer_use(gc_buffer, table, n);
2275+
2276+
if (object->properties == NULL && object->ce->default_properties_count == 0) {
2277+
return NULL;
2278+
} else {
2279+
return zend_std_get_properties(object);
2280+
}
2281+
}
2282+
}
2283+
22482284
static void php_sqlite3_stmt_object_free_storage(zend_object *object) /* {{{ */
22492285
{
22502286
php_sqlite3_stmt *intern = php_sqlite3_stmt_from_obj(object);
@@ -2377,6 +2413,7 @@ PHP_MINIT_FUNCTION(sqlite3)
23772413
sqlite3_object_handlers.offset = XtOffsetOf(php_sqlite3_db_object, zo);
23782414
sqlite3_object_handlers.clone_obj = NULL;
23792415
sqlite3_object_handlers.free_obj = php_sqlite3_object_free_storage;
2416+
sqlite3_object_handlers.get_gc = php_sqlite3_get_gc;
23802417
php_sqlite3_sc_entry = register_class_SQLite3();
23812418
php_sqlite3_sc_entry->create_object = php_sqlite3_object_new;
23822419
php_sqlite3_sc_entry->default_object_handlers = &sqlite3_object_handlers;

ext/sqlite3/tests/gh11878.phpt

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
--TEST--
2+
GH-11878 (SQLite3 callback functions cause a memory leak with a callable array)
3+
--EXTENSIONS--
4+
sqlite3
5+
--FILE--
6+
<?php
7+
class Foo {
8+
public $sqlite;
9+
public function __construct(bool $normalFunctions, bool $aggregates) {
10+
$this->sqlite = new SQLite3(":memory:");
11+
if ($aggregates) {
12+
$this->sqlite->createAggregate("indexes", array($this, "SQLiteIndex"), array($this, "SQLiteFinal"), 0);
13+
}
14+
if ($normalFunctions) {
15+
$this->sqlite->createFunction("func", array($this, "SQLiteIndex"), 0);
16+
$this->sqlite->createCollation("collation", array($this, "SQLiteIndex"));
17+
}
18+
}
19+
public function SQLiteIndex() {}
20+
public function SQLiteFinal() {}
21+
}
22+
23+
// Test different combinations to check for null pointer derefs
24+
$x = new Foo(true, true);
25+
$y = new Foo(false, true);
26+
$z = new Foo(true, false);
27+
$w = new Foo(false, false);
28+
?>
29+
Done
30+
--EXPECT--
31+
Done

0 commit comments

Comments
 (0)