From 0d7e53535b9b0d23f7233c9d5e6562376b29926e Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+ndossche@users.noreply.github.com> Date: Sun, 14 Dec 2025 00:31:19 +0100 Subject: [PATCH] Fix NUL byte truncation in sqlite3 TEXT column handling As a bonus, this should probably also be a tad faster. Closes GH-20704. --- NEWS | 3 ++ ext/sqlite3/sqlite3.c | 2 +- ext/sqlite3/tests/text_column_NUL_bytes.phpt | 38 ++++++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 ext/sqlite3/tests/text_column_NUL_bytes.phpt diff --git a/NEWS b/NEWS index e3c32a4e164..9fa63137d88 100644 --- a/NEWS +++ b/NEWS @@ -60,6 +60,9 @@ PHP NEWS . DirectoryIterator key can now work better with filesystem supporting larger directory indexing. (David Carlier) +- Sqlite3: + . Fix NUL byte truncation in sqlite3 TEXT column handling. (ndossche) + - Standard: . Fixed bug GH-19926 (reset internal pointer earlier while splicing array while COW violation flag is still set). (alexandre-daubois) diff --git a/ext/sqlite3/sqlite3.c b/ext/sqlite3/sqlite3.c index 0ef207d76fd..da24b037861 100644 --- a/ext/sqlite3/sqlite3.c +++ b/ext/sqlite3/sqlite3.c @@ -648,7 +648,7 @@ static void sqlite_value_to_zval(sqlite3_stmt *stmt, int column, zval *data) /* break; case SQLITE3_TEXT: - ZVAL_STRING(data, (char*)sqlite3_column_text(stmt, column)); + ZVAL_STRINGL(data, (const char *) sqlite3_column_text(stmt, column), sqlite3_column_bytes(stmt, column)); break; case SQLITE_BLOB: diff --git a/ext/sqlite3/tests/text_column_NUL_bytes.phpt b/ext/sqlite3/tests/text_column_NUL_bytes.phpt new file mode 100644 index 00000000000..cf9403d9130 --- /dev/null +++ b/ext/sqlite3/tests/text_column_NUL_bytes.phpt @@ -0,0 +1,38 @@ +--TEST-- +Text column with NUL bytes +--EXTENSIONS-- +sqlite3 +--FILE-- +exec( + 'CREATE TABLE messages ( + content TEXT + )' +); + +$insert = $db->prepare( + 'INSERT INTO messages (content) VALUES (:content)' +); + +$insert->bindValue(':content', "with\0null", SQLITE3_TEXT); +$insert->execute(); +$insert->bindValue(':content', "\0", SQLITE3_TEXT); +$insert->execute(); + +$result = $db->query('SELECT * FROM messages'); +while ($row = $result->fetchArray(SQLITE3_ASSOC)) { + var_dump($row); +} + +?> +--EXPECTF-- +array(1) { + ["content"]=> + string(9) "with%0null" +} +array(1) { + ["content"]=> + string(1) "%0" +}