[php-src] PHP-8.5: sqlite3: Fix leak when trying to close db if blob stream is still open
ndossche <[email protected]> Mon, 3 Aug 2026 20:56:03 +0000
| Newsgroups | gmane.comp.php.cvs.general |
|---|---|
| Message-ID | <[email protected]> |
Author: ndossche (ndossche)
Date: 2026-08-03T22:55:04+02:00
Commit: https://github.com/php/php-src/commit/eaac0378e3c2e16814f9aeef55a07c2418d6d27a
Raw diff: https://github.com/php/php-src/commit/eaac0378e3c2e16814f9aeef55a07c2418d6d27a.diff
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
Closes GH-22992.
Changed paths:
A ext/sqlite3/tests/sqlite3_close_blob_stream.phpt
M NEWS
M ext/sqlite3/sqlite3.c
Diff:
diff --git a/NEWS b/NEWS
index ee333ae9f20c..6738d104f5bc 100644
--- a/NEWS
+++ b/NEWS
@@ -18,6 +18,10 @@ PHP NEWS
. Fixed bug GH-21036 (mb_ereg_search_getregs() crashes after mb_eregi()
invalidates the regex cache). (Matthias Goergens)
+- Opcache:
+ . Fixed bug GH-22857 (Function JIT emits wrong code for FETCH_OBJ_FUNC_ARG on a
+ property hook getter, losing register-held variables). (Zhao Hao)
+
- PCRE:
. Fixed bug GH-21134 (Crash with \C + UTF-8). Using \C in UTF-8 patterns is
now forbidden. (Arnaud)
@@ -29,6 +33,9 @@ PHP NEWS
- Sockets:
. Fixed various memory related issues in ext/sockets. (David Carlier)
+- SQLite:
+ . Fix leak when trying to close db if blob stream is still open. (ndossche)
+
- Streams:
. Fixed bug GH-15836 (Use-after-free when a user stream filter accesses
$this->stream during the close flush). (iliaal)
@@ -37,10 +44,6 @@ PHP NEWS
. Fixed out-of-bounds write when shm_attach() opens an existing segment with
a size larger than the segment actually is. (David Carlier)
-- Opcache:
- . Fixed bug GH-22857 (Function JIT emits wrong code for FETCH_OBJ_FUNC_ARG on a
- property hook getter, losing register-held variables). (Zhao Hao)
-
30 Jul 2026, PHP 8.4.24
- BCMath:
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--
+<?php
+
+$db = new SQLite3(':memory:');
+$db->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"