Commit 407c45debce for php.net
commit 407c45debce31f5544cbd3c62983646d39523436
Author: ndossche <7771979+ndossche@users.noreply.github.com>
Date: Fri May 15 12:55:39 2026 +0200
sqlite: fix error checks for column retrieval
These can return NULL on OOM.
And for blobs, it can return NULL for empty blobs (so *no* failure,
just an edge case). Passing NULL to memcpy is UB, so we have to
check for a NULL pointer there to avoid UB.
Closes GH-22045.
diff --git a/NEWS b/NEWS
index 7aa9ec33744..faeb27fdf6d 100644
--- a/NEWS
+++ b/NEWS
@@ -36,6 +36,9 @@ PHP NEWS
Phar::addEmptyDir() for paths starting with "/.phar", while allowing
non-magic directory names that merely share the ".phar" prefix. (Weilin Du)
+- Sqlite:
+ . Fix error checks for column retrieval. (ndossche)
+
- Zlib:
. Fixed memory leak if deflate initialization fails and there is a dict.
(ndossche)
diff --git a/ext/sqlite3/sqlite3.c b/ext/sqlite3/sqlite3.c
index 100cf32680e..1bb93e0e267 100644
--- a/ext/sqlite3/sqlite3.c
+++ b/ext/sqlite3/sqlite3.c
@@ -627,7 +627,7 @@ PHP_METHOD(SQLite3, query)
}
/* }}} */
-static void sqlite_value_to_zval(sqlite3_stmt *stmt, int column, zval *data) /* {{{ */
+static void sqlite_value_to_zval(php_sqlite3_db_object *db_obj, sqlite3_stmt *stmt, int column, zval *data) /* {{{ */
{
sqlite3_int64 val;
@@ -636,7 +636,13 @@ static void sqlite_value_to_zval(sqlite3_stmt *stmt, int column, zval *data) /*
val = sqlite3_column_int64(stmt, column);
#if LONG_MAX <= 2147483647
if (val > ZEND_LONG_MAX || val < ZEND_LONG_MIN) {
- ZVAL_STRINGL(data, (char *)sqlite3_column_text(stmt, column), sqlite3_column_bytes(stmt, column));
+ const char *text = (const char *) sqlite3_column_text(stmt, column);
+ if (UNEXPECTED(text == NULL)) {
+ php_sqlite3_error(db_obj, SQLITE_NOMEM, "Failed to retrieve column value due to out of memory");
+ ZVAL_NULL(data);
+ } else {
+ ZVAL_STRINGL(data, text, sqlite3_column_bytes(stmt, column));
+ }
} else {
#endif
ZVAL_LONG(data, (zend_long) val);
@@ -653,13 +659,33 @@ static void sqlite_value_to_zval(sqlite3_stmt *stmt, int column, zval *data) /*
ZVAL_NULL(data);
break;
- case SQLITE3_TEXT:
- ZVAL_STRING(data, (char*)sqlite3_column_text(stmt, column));
+ case SQLITE3_TEXT: {
+ const char *text = (const char *) sqlite3_column_text(stmt, column);
+ if (UNEXPECTED(text == NULL)) {
+ php_sqlite3_error(db_obj, SQLITE_NOMEM, "Failed to retrieve column value due to out of memory");
+ ZVAL_NULL(data);
+ } else {
+ ZVAL_STRING(data, text);
+ }
break;
+ }
case SQLITE_BLOB:
- default:
- ZVAL_STRINGL(data, (char*)sqlite3_column_blob(stmt, column), sqlite3_column_bytes(stmt, column));
+ default: {
+ const char *blob = (const char *) sqlite3_column_blob(stmt, column);
+ if (UNEXPECTED(blob == NULL)) {
+ if (sqlite3_errcode(sqlite3_db_handle(stmt)) == SQLITE_NOMEM) {
+ php_sqlite3_error(db_obj, SQLITE_NOMEM, "Failed to retrieve column value due to out of memory");
+ ZVAL_NULL(data);
+ } else {
+ /* Zero-length BLOB */
+ ZVAL_EMPTY_STRING(data);
+ }
+ } else {
+ ZVAL_STRINGL(data, blob, sqlite3_column_bytes(stmt, column));
+ }
+ break;
+ }
}
}
/* }}} */
@@ -709,13 +735,13 @@ PHP_METHOD(SQLite3, querySingle)
case SQLITE_ROW: /* Valid Row */
{
if (!entire_row) {
- sqlite_value_to_zval(stmt, 0, return_value);
+ sqlite_value_to_zval(db_obj, stmt, 0, return_value);
} else {
int i = 0;
array_init(return_value);
for (i = 0; i < sqlite3_data_count(stmt); i++) {
zval data;
- sqlite_value_to_zval(stmt, i, &data);
+ sqlite_value_to_zval(db_obj, stmt, i, &data);
add_assoc_zval(return_value, (char*)sqlite3_column_name(stmt, i), &data);
}
}
@@ -1973,7 +1999,7 @@ PHP_METHOD(SQLite3Result, fetchArray)
for (i = 0; i < n_cols; i++) {
zval data;
- sqlite_value_to_zval(result_obj->stmt_obj->stmt, i, &data);
+ sqlite_value_to_zval(result_obj->db_obj, result_obj->stmt_obj->stmt, i, &data);
if (mode & PHP_SQLITE3_NUM) {
add_index_zval(return_value, i, &data);