Files
php-src/ext/sqlite3/tests/sqlite3_close_from_callback_aggregate.phpt
Ilia Alshanetsky 7300fa520d ext/sqlite3: reject close() from inside a callback
SQLite3::close() called from within a userland function, aggregate,
collation or authorizer callback freed the registered statements and
functions while sqlite3 was still executing, corrupting the active
statement and crashing the request. Track callback re-entry with a
per-database counter shared by all four callback kinds and throw an
Error from close() while it is non-zero; the database stays usable and
can be closed after the query completes.

Closes GH-23650
2026-09-16 09:02:46 -04:00

42 lines
981 B
PHP

--TEST--
SQLite3::close() from within a createAggregate() callback must not corrupt active statement
--EXTENSIONS--
sqlite3
--FILE--
<?php
$db = new SQLite3(':memory:');
$db->exec('CREATE TABLE t (a INTEGER)');
$db->exec('INSERT INTO t VALUES (1)');
$db->exec('INSERT INTO t VALUES (2)');
$reported = false;
$db->createAggregate('agg', function ($context, $rows, $a) use (&$db, &$reported) {
if (!$reported) {
$reported = true;
try {
var_dump($db->close());
} catch (Throwable $e) {
echo $e::class, ": ", $e->getMessage(), "\n";
}
}
return (int) $context + $a;
}, function ($context, $rows) {
return $context;
}, 1);
$stmt = $db->prepare('SELECT agg(a) FROM t');
$res = $stmt->execute();
var_dump($res->fetchArray(SQLITE3_NUM));
$res->finalize();
var_dump($db->close());
echo "done\n";
?>
--EXPECT--
Error: Cannot close SQLite3 database while inside a callback
array(1) {
[0]=>
int(3)
}
bool(true)
done