From 58424290b757703ad1912e30c90938b463f3bbfb Mon Sep 17 00:00:00 2001 From: ndossche <7771979+ndossche@users.noreply.github.com> Date: Sat, 1 Aug 2026 23:12:12 +0200 Subject: [PATCH] sqlite3: Fix leak when trying to close db if blob stream is still open Discovered coincidentally with ESSS [1], even though I was actually using it for something else. [1] https://github.com/csl-ugent/ESSS --- ext/sqlite3/sqlite3.c | 4 +++- .../tests/sqlite3_close_blob_stream.phpt | 22 +++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 ext/sqlite3/tests/sqlite3_close_blob_stream.phpt diff --git a/ext/sqlite3/sqlite3.c b/ext/sqlite3/sqlite3.c index 1bb93e0e2675..20714c38aada 100644 --- a/ext/sqlite3/sqlite3.c +++ b/ext/sqlite3/sqlite3.c @@ -2255,7 +2255,9 @@ static void php_sqlite3_object_free_storage(zend_object *object) /* {{{ */ } if (intern->initialised && intern->db) { - sqlite3_close(intern->db); + /* Use sqlite3_close_v2() because the object may be destroyed while resources depending on the connection are still alive, + * e.g. a blob stream created by SQLite3::openBlob(). */ + sqlite3_close_v2(intern->db); intern->initialised = 0; } diff --git a/ext/sqlite3/tests/sqlite3_close_blob_stream.phpt b/ext/sqlite3/tests/sqlite3_close_blob_stream.phpt new file mode 100644 index 000000000000..d2426445a7cd --- /dev/null +++ b/ext/sqlite3/tests/sqlite3_close_blob_stream.phpt @@ -0,0 +1,22 @@ +--TEST-- +Destroying the SQLite3 object while a blob stream is still open must not leak the connection +--EXTENSIONS-- +sqlite3 +--FILE-- +exec('CREATE TABLE test (data BLOB)'); +$db->exec("INSERT INTO test (data) VALUES (x'34323432')"); + +$stream = $db->openBlob('test', 'data', 1); +var_dump($db->close()); +unset($db); +var_dump(fread($stream, 4)); +fclose($stream); + +?> +--EXPECTF-- +Warning: SQLite3::close(): Unable to close database: %s in %s on line %d +bool(false) +string(4) "4242"