Skip to content

Commit c6835ba

Browse files
committed
ext/sqlite3: reject NUL bytes in SQLite3::escapeString()
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 0a10f6d (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.
1 parent e60d756 commit c6835ba

2 files changed

Lines changed: 40 additions & 0 deletions

File tree

ext/sqlite3/sqlite3.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,11 @@ PHP_METHOD(SQLite3, escapeString)
473473
RETURN_THROWS();
474474
}
475475

476+
if (UNEXPECTED(zend_str_has_nul_byte(sql))) {
477+
zend_argument_value_error(1, "must not contain null bytes");
478+
RETURN_THROWS();
479+
}
480+
476481
if (ZSTR_LEN(sql)) {
477482
ret = sqlite3_mprintf("%q", ZSTR_VAL(sql));
478483
if (ret) {
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
--TEST--
2+
SQLite3::escapeString() rejects strings with embedded NUL bytes
3+
--EXTENSIONS--
4+
sqlite3
5+
--FILE--
6+
<?php
7+
8+
$cases = [
9+
"\0",
10+
"a\0b",
11+
"secret\0x",
12+
"foo\0\0bar",
13+
];
14+
15+
foreach ($cases as $in) {
16+
try {
17+
SQLite3::escapeString($in);
18+
echo "FAIL: no exception for ", bin2hex($in), "\n";
19+
} catch (ValueError $e) {
20+
echo "ValueError: ", $e->getMessage(), "\n";
21+
}
22+
}
23+
24+
echo "ok: ", SQLite3::escapeString("ok"), "\n";
25+
echo "quote: ", SQLite3::escapeString("test''%"), "\n";
26+
echo "empty: ", var_export(SQLite3::escapeString(""), true), "\n";
27+
?>
28+
--EXPECT--
29+
ValueError: SQLite3::escapeString(): Argument #1 ($string) must not contain null bytes
30+
ValueError: SQLite3::escapeString(): Argument #1 ($string) must not contain null bytes
31+
ValueError: SQLite3::escapeString(): Argument #1 ($string) must not contain null bytes
32+
ValueError: SQLite3::escapeString(): Argument #1 ($string) must not contain null bytes
33+
ok: ok
34+
quote: test''''%
35+
empty: ''

0 commit comments

Comments
 (0)