Commit 7522c496300 for php.net

commit 7522c496300417d7cfbbf6a3cac48651e4574f3b
Author: Ilia Alshanetsky <ilia@ilia.ws>
Date:   Fri Jul 17 07:09:41 2026 -0400

    ext/sqlite3: reject NUL bytes in SQLite3::escapeString() (#22774)

    escapeString() used sqlite3_mprintf("%q"), which stops at the first C NUL.
    PHP strings are length-aware and may embed NULs, so values such as "a\0b"
    were silently truncated to "a" when interpolated into SQL. Prepared binds
    pass an explicit length and are unaffected.

    ext/pdo_sqlite rejected the same inputs for PDO::quote in 0a10f6db268
    (GH-13952), on 8.5 and up. That check consults the connection's error mode;
    escapeString() is static and has no connection, so it throws instead.

    Closes GH-22774

diff --git a/ext/sqlite3/sqlite3.c b/ext/sqlite3/sqlite3.c
index 67ff850cadd..b81a0677a6c 100644
--- a/ext/sqlite3/sqlite3.c
+++ b/ext/sqlite3/sqlite3.c
@@ -469,7 +469,7 @@ PHP_METHOD(SQLite3, escapeString)
 	zend_string *sql;
 	char *ret;

-	if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "S", &sql)) {
+	if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "P", &sql)) {
 		RETURN_THROWS();
 	}

diff --git a/ext/sqlite3/tests/gh_sqlite3_escapestring_nul.phpt b/ext/sqlite3/tests/gh_sqlite3_escapestring_nul.phpt
new file mode 100644
index 00000000000..49d66a1accf
--- /dev/null
+++ b/ext/sqlite3/tests/gh_sqlite3_escapestring_nul.phpt
@@ -0,0 +1,35 @@
+--TEST--
+SQLite3::escapeString() rejects strings with embedded NUL bytes
+--EXTENSIONS--
+sqlite3
+--FILE--
+<?php
+
+$cases = [
+    "\0",
+    "a\0b",
+    "secret\0x",
+    "foo\0\0bar",
+];
+
+foreach ($cases as $in) {
+    try {
+        SQLite3::escapeString($in);
+        echo "FAIL: no exception for ", bin2hex($in), "\n";
+    } catch (ValueError $e) {
+        echo "ValueError: ", $e->getMessage(), "\n";
+    }
+}
+
+echo "ok: ", SQLite3::escapeString("ok"), "\n";
+echo "quote: ", SQLite3::escapeString("test''%"), "\n";
+echo "empty: ", var_export(SQLite3::escapeString(""), true), "\n";
+?>
+--EXPECT--
+ValueError: SQLite3::escapeString(): Argument #1 ($string) must not contain any null bytes
+ValueError: SQLite3::escapeString(): Argument #1 ($string) must not contain any null bytes
+ValueError: SQLite3::escapeString(): Argument #1 ($string) must not contain any null bytes
+ValueError: SQLite3::escapeString(): Argument #1 ($string) must not contain any null bytes
+ok: ok
+quote: test''''%
+empty: ''