Commit 7744eab9336 for php.net

commit 7744eab93367e0af560fcfa1b8a82cf9fdc90916
Author: David Carlier <devnexen@gmail.com>
Date:   Sat Mar 21 07:46:13 2026 +0000

    ext/sqlite3: fix wrong pointer types passed to the free list comparator.

    SQLite3Stmt::close() and SQLite3Result::finalize() passed
    php_sqlite3_stmt pointer types instead of sqlite3_stmt pointers
    to zend_llist_del_element, causing the comparator to never match
    and both methods to silently become no-ops.

    Regression introduced in 5eae6d14052 ("Don't store the object
    zval directly").

    close GH-21483

diff --git a/NEWS b/NEWS
index 77a509ba262..338e14bee08 100644
--- a/NEWS
+++ b/NEWS
@@ -39,6 +39,9 @@ PHP                                                                        NEWS
   . Fix concurrent iteration and deletion issues in SplObjectStorage.
     (ndossche)

+- Sqlite3:
+  . Fixed wrong free list comparator pointer type. (David Carlier)
+
 - Streams:
   . Fixed bug GH-21468 (Segfault in file_get_contents w/ a https URL
     and a proxy set). (ndossche)
diff --git a/ext/sqlite3/sqlite3.c b/ext/sqlite3/sqlite3.c
index cea3ca0e3fb..7aef25bf73b 100644
--- a/ext/sqlite3/sqlite3.c
+++ b/ext/sqlite3/sqlite3.c
@@ -38,7 +38,7 @@ ZEND_DECLARE_MODULE_GLOBALS(sqlite3)
 static PHP_GINIT_FUNCTION(sqlite3);
 static int php_sqlite3_authorizer(void *autharg, int action, const char *arg1, const char *arg2, const char *arg3, const char *arg4);
 static void sqlite3_param_dtor(zval *data);
-static int php_sqlite3_compare_stmt_free(php_sqlite3_stmt **stmt_obj_ptr, sqlite3_stmt *statement);
+static int php_sqlite3_compare_stmt_free(php_sqlite3_stmt **stmt_obj_ptr, php_sqlite3_stmt *statement);
 static zend_always_inline void php_sqlite3_fetch_one(int n_cols, php_sqlite3_result *result_obj, zend_long mode, zval *result);

 #define SQLITE3_CHECK_INITIALIZED(db_obj, member, class_name) \
@@ -2145,7 +2145,7 @@ PHP_METHOD(SQLite3Result, finalize)

 	/* We need to finalize an internal statement */
 	if (!result_obj->is_prepared_statement) {
-		zend_llist_del_element(&(result_obj->db_obj->free_list), &result_obj->stmt_obj,
+		zend_llist_del_element(&(result_obj->db_obj->free_list), result_obj->stmt_obj,
 			(int (*)(void *, void *)) php_sqlite3_compare_stmt_free);
 	} else {
 		sqlite3_reset(result_obj->stmt_obj->stmt);
@@ -2260,9 +2260,9 @@ static void php_sqlite3_free_list_dtor(void **item)
 }
 /* }}} */

-static int php_sqlite3_compare_stmt_free(php_sqlite3_stmt **stmt_obj_ptr, sqlite3_stmt *statement ) /* {{{ */
+static int php_sqlite3_compare_stmt_free(php_sqlite3_stmt **stmt_obj_ptr, php_sqlite3_stmt *statement ) /* {{{ */
 {
-	return ((*stmt_obj_ptr)->initialised && statement == (*stmt_obj_ptr)->stmt);
+	return ((*stmt_obj_ptr)->initialised && statement == *stmt_obj_ptr);
 }
 /* }}} */

@@ -2376,7 +2376,7 @@ static void php_sqlite3_stmt_object_free_storage(zend_object *object) /* {{{ */
 	}

 	if (intern->initialised) {
-		zend_llist_del_element(&(intern->db_obj->free_list), intern->stmt,
+		zend_llist_del_element(&(intern->db_obj->free_list), intern,
 			(int (*)(void *, void *)) php_sqlite3_compare_stmt_free);
 	}