ext/pdo_sqlite: PDO::sqliteCreateCollection return type strenghtening.

Is supposed to be Pdo_Sqlite::createCollation but behavior differs in
regard of return type checks.

close GH-18799
This commit is contained in:
David Carlier 2025-06-07 16:35:30 +01:00
parent eac91d0453
commit e3cfa4bcae
No known key found for this signature in database
GPG key ID: 8486F847B4B94EF1
5 changed files with 23 additions and 6 deletions

2
NEWS
View file

@ -141,6 +141,8 @@ PHP NEWS
- PDO_SQLITE: - PDO_SQLITE:
. throw on null bytes / resolve GH-13952 (divinity76). . throw on null bytes / resolve GH-13952 (divinity76).
. Implement GH-17321: Add setAuthorizer to Pdo\Sqlite. (nielsdos) . Implement GH-17321: Add setAuthorizer to Pdo\Sqlite. (nielsdos)
. PDO::sqliteCreateCollation now throws a TypeError if the callback
has a wrong return type. (David Carlier)
- PGSQL: - PGSQL:
. Added pg_close_stmt to close a prepared statement while allowing . Added pg_close_stmt to close a prepared statement while allowing

View file

@ -268,6 +268,9 @@ PHP 8.5 UPGRADE NOTES
- PDO_SQLITE: - PDO_SQLITE:
. SQLite PDO::quote() will now throw an exception or emit a warning, . SQLite PDO::quote() will now throw an exception or emit a warning,
depending on the error mode, if the string contains a null byte. depending on the error mode, if the string contains a null byte.
. PDO::sqliteCreateCollation will now throw an exception
if the callback has the wrong return type, making it more
in line with Pdo_Sqlite::createCollation behavior.
- PGSQL: - PGSQL:
. pg_copy_from also supports inputs as Iterable. . pg_copy_from also supports inputs as Iterable.

View file

@ -385,14 +385,14 @@ static int php_sqlite_collation_callback(void *context, int string1_len, const v
zend_type_error("%s(): Return value of the collation callback must be of type int, %s returned", zend_type_error("%s(): Return value of the collation callback must be of type int, %s returned",
ZSTR_VAL(func_name), zend_zval_value_name(&retval)); ZSTR_VAL(func_name), zend_zval_value_name(&retval));
zend_string_release(func_name); zend_string_release(func_name);
zval_ptr_dtor(&retval); ret = FAILURE;
return FAILURE;
} }
if (Z_LVAL(retval) > 0) { if (Z_LVAL(retval) > 0) {
ret = 1; ret = 1;
} else if (Z_LVAL(retval) < 0) { } else if (Z_LVAL(retval) < 0) {
ret = -1; ret = -1;
} }
zval_ptr_dtor(&retval);
} }
return ret; return ret;

View file

@ -483,9 +483,16 @@ static int php_sqlite3_collation_callback(void *context, int string1_len, const
zend_call_known_fcc(&collation->callback, &retval, /* argc */ 2, zargs, /* named_params */ NULL); zend_call_known_fcc(&collation->callback, &retval, /* argc */ 2, zargs, /* named_params */ NULL);
zval_ptr_dtor(&zargs[0]);
zval_ptr_dtor(&zargs[1]);
if (!Z_ISUNDEF(retval)) { if (!Z_ISUNDEF(retval)) {
if (Z_TYPE(retval) != IS_LONG) { if (Z_TYPE(retval) != IS_LONG) {
convert_to_long(&retval); zend_string *func_name = get_active_function_or_method_name();
zend_type_error("%s(): Return value of the collation callback must be of type int, %s returned",
ZSTR_VAL(func_name), zend_zval_value_name(&retval));
zend_string_release(func_name);
ret = FAILURE;
} }
if (Z_LVAL(retval) > 0) { if (Z_LVAL(retval) > 0) {
ret = 1; ret = 1;
@ -495,9 +502,6 @@ static int php_sqlite3_collation_callback(void *context, int string1_len, const
zval_ptr_dtor(&retval); zval_ptr_dtor(&retval);
} }
zval_ptr_dtor(&zargs[0]);
zval_ptr_dtor(&zargs[1]);
return ret; return ret;
} }

View file

@ -24,6 +24,13 @@ foreach ($result as $row) {
echo $row['name'] . "\n"; echo $row['name'] . "\n";
} }
$db->sqliteCreateCollation('MYCOLLATEBAD', function($a, $b) { return $a; });
try {
$db->query('SELECT name FROM test_pdo_sqlite_createcollation ORDER BY name COLLATE MYCOLLATEBAD');
} catch (\TypeError $e) {
echo $e->getMessage(), PHP_EOL;
}
?> ?>
--EXPECT-- --EXPECT--
1 1
@ -32,3 +39,4 @@ foreach ($result as $row) {
1 1
10 10
2 2
PDO::query(): Return value of the collation callback must be of type int, string returned