Skip to content

Commit

Permalink
make sure quote() returns datatype string
Browse files Browse the repository at this point in the history
  • Loading branch information
divinity76 committed Apr 15, 2024
1 parent 565fe3a commit 3e573cf
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 15 deletions.
13 changes: 7 additions & 6 deletions ext/pdo_sqlite/sqlite_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -227,20 +227,21 @@ static zend_string* sqlite_handle_quoter(pdo_dbh_t *dbh, const zend_string *unqu
return NULL;
}
if(ZSTR_LEN(unquoted) != 0 && memchr(ZSTR_VAL(unquoted), '\0', ZSTR_LEN(unquoted))) {
// x'hex'
zend_string *quoted = zend_string_safe_alloc(3 + (2 * ZSTR_LEN(unquoted)), 1, 0, 0);
// (''||x'hex')
// the odd (''||) thing is to make sure quote produce a sqlite datatype "string" rather than "blob" ...
// https://github.com/php/php-src/pull/13962/files#r1565485792
zend_string *quoted = zend_string_safe_alloc(9 + (2 * ZSTR_LEN(unquoted)), 1, 0, 0);
char *outptr = ZSTR_VAL(quoted);
const char *inptr = ZSTR_VAL(unquoted);
const char *const inendptr = inptr + ZSTR_LEN(unquoted);
*outptr++ = 'x';
*outptr++ = '\'';
memcpy(outptr, "(''||x'", 7);
outptr += 7;
while(inptr != inendptr) {
const unsigned char c = *inptr++;
*outptr++ = "0123456789ABCDEF"[c >> 4];
*outptr++ = "0123456789ABCDEF"[c & 0x0F];
}
*outptr++ = '\'';
*outptr = '\0'; // todo: does zend_string_safe_alloc do this for us? i don't know
memcpy(outptr, "')", 3); // todo: does zend_string_safe_alloc write the null terminator? if it does, reduce this to 2
return quoted;
}
quoted = safe_emalloc(2, ZSTR_LEN(unquoted), 3);
Expand Down
24 changes: 15 additions & 9 deletions ext/pdo_sqlite/tests/gh13952.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ $test_cases = [
"\x00foo\x00\x00\x00bar\x00",
"\x00\x00\x00foo",
"foo\x00\x00\x00",
"\x80", // << invalid UTF8
"\x00\x80\x00", // << invalid UTF8
];

foreach($test_cases as $test){
Expand All @@ -38,7 +40,7 @@ $db->exec('CREATE TABLE test (name TEXT)');

foreach ($test_cases as $test_case) {
$quoted = $db->quote($test_case);
echo trim(json_encode($test_case), '"'), " -> $quoted\n";
echo trim(json_encode($test_case, JSON_PARTIAL_OUTPUT_ON_ERROR), '"'), " -> $quoted\n";
$db->exec("INSERT INTO test (name) VALUES (" . $quoted . ")");
}

Expand All @@ -51,17 +53,19 @@ foreach ($stmt->fetchAll() as $result) {
--EXPECTF--
-> ''
x -> 'x'
\u0000 -> x'00'
a\u0000b -> x'610062'
\u0000\u0000\u0000 -> x'000000'
\u0000 -> (''||x'00')
a\u0000b -> (''||x'610062')
\u0000\u0000\u0000 -> (''||x'000000')
foobar -> 'foobar'
foo'''bar -> 'foo''''''bar'
'foo'''bar' -> '''foo''''''bar'''
'foo'\u0000'bar' -> x'27666F6F27002762617227'
foo\u0000\u0000\u0000bar -> x'666F6F000000626172'
\u0000foo\u0000\u0000\u0000bar\u0000 -> x'00666F6F00000062617200'
\u0000\u0000\u0000foo -> x'000000666F6F'
foo\u0000\u0000\u0000 -> x'666F6F000000'
'foo'\u0000'bar' -> (''||x'27666F6F27002762617227')
foo\u0000\u0000\u0000bar -> (''||x'666F6F000000626172')
\u0000foo\u0000\u0000\u0000bar\u0000 -> (''||x'00666F6F00000062617200')
\u0000\u0000\u0000foo -> (''||x'000000666F6F')
foo\u0000\u0000\u0000 -> (''||x'666F6F000000')
null -> '€'
null -> (''||x'008000')
string(0) ""
string(1) "x"
string(1) "%0"
Expand All @@ -75,3 +79,5 @@ string(9) "foo%0%0%0bar"
string(11) "%0foo%0%0%0bar%0"
string(6) "%0%0%0foo"
string(6) "foo%0%0%0"
string(1) "€"
string(3) "%0€%0"

0 comments on commit 3e573cf

Please sign in to comment.