mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00
Fixed GH-13167 Fixed the behavior of bindValue
and bindParam
. (#13384)
Fixed to generate an error when a non-scalar value is passed in `PDO_PARAM_EVT_EXEC_PRE` of `pdo_mysql_stmt_param_hook` unless it is a `Stringable` object.
This commit is contained in:
parent
10957e498c
commit
68f10504de
2 changed files with 101 additions and 0 deletions
|
@ -27,6 +27,7 @@
|
|||
#include "pdo/php_pdo_driver.h"
|
||||
#include "php_pdo_mysql.h"
|
||||
#include "php_pdo_mysql_int.h"
|
||||
#include "zend_interfaces.h"
|
||||
|
||||
#ifdef PDO_USE_MYSQLND
|
||||
# define pdo_mysql_stmt_execute_prepared(stmt) pdo_mysql_stmt_execute_prepared_mysqlnd(stmt)
|
||||
|
@ -490,7 +491,14 @@ static int pdo_mysql_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_da
|
|||
case IS_DOUBLE:
|
||||
mysqlnd_stmt_bind_one_param(S->stmt, param->paramno, parameter, MYSQL_TYPE_DOUBLE);
|
||||
break;
|
||||
case IS_OBJECT:
|
||||
if(zend_class_implements_interface(Z_OBJCE_P(parameter), zend_ce_stringable)) {
|
||||
mysqlnd_stmt_bind_one_param(S->stmt, param->paramno, parameter, MYSQL_TYPE_VAR_STRING);
|
||||
break;
|
||||
}
|
||||
ZEND_FALLTHROUGH;
|
||||
default:
|
||||
pdo_raise_impl_error(stmt->dbh, stmt, "HY105", "Expected a scalar value or null");
|
||||
PDO_DBG_RETURN(0);
|
||||
}
|
||||
|
||||
|
@ -530,7 +538,19 @@ static int pdo_mysql_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_da
|
|||
b->buffer = &Z_DVAL_P(parameter);
|
||||
PDO_DBG_RETURN(1);
|
||||
|
||||
case IS_OBJECT:
|
||||
if(zend_class_implements_interface(Z_OBJCE_P(parameter), zend_ce_stringable)) {
|
||||
convert_to_string(parameter);
|
||||
b->buffer_type = MYSQL_TYPE_STRING;
|
||||
b->buffer = Z_STRVAL_P(parameter);
|
||||
b->buffer_length = Z_STRLEN_P(parameter);
|
||||
*b->length = Z_STRLEN_P(parameter);
|
||||
PDO_DBG_RETURN(1);
|
||||
}
|
||||
ZEND_FALLTHROUGH;
|
||||
|
||||
default:
|
||||
pdo_raise_impl_error(stmt->dbh, stmt, "HY105", "Expected a scalar value or null");
|
||||
PDO_DBG_RETURN(0);
|
||||
}
|
||||
#endif /* PDO_USE_MYSQLND */
|
||||
|
|
81
ext/pdo_mysql/tests/gh13384.phpt
Normal file
81
ext/pdo_mysql/tests/gh13384.phpt
Normal file
|
@ -0,0 +1,81 @@
|
|||
--TEST--
|
||||
GH-13384 Fixed GH-13167 Fixed the behavior when an inappropriate value was passed to `bindValue` and `bindParam`.
|
||||
--EXTENSIONS--
|
||||
pdo_mysql
|
||||
--SKIPIF--
|
||||
<?php
|
||||
require_once __DIR__ . '/inc/mysql_pdo_test.inc';
|
||||
MySQLPDOTest::skip();
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once __DIR__ . '/inc/mysql_pdo_test.inc';
|
||||
$db = MySQLPDOTest::factory();
|
||||
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
|
||||
|
||||
$stringableObject = new class () implements Stringable {
|
||||
public function __toString(): string
|
||||
{
|
||||
return '555';
|
||||
}
|
||||
};
|
||||
|
||||
echo "Stringable object, value set after bindParam:\n";
|
||||
try {
|
||||
$stmt = $db->prepare('SELECT ?');
|
||||
$param = 'foo';
|
||||
$stmt->bindParam(1, $param, PDO::PARAM_STR);
|
||||
$param = $stringableObject;
|
||||
$stmt->execute();
|
||||
var_dump(is_object($param), $param === $stringableObject);
|
||||
echo "\n";
|
||||
} catch (Throwable $e) {
|
||||
echo $e->getMessage()."\n\n";
|
||||
}
|
||||
|
||||
echo "Stringable object, bindValue:\n";
|
||||
$stmt = $db->prepare('SELECT (?)');
|
||||
$stmt->bindValue(1, $stringableObject, PDO::PARAM_INT);
|
||||
$stmt->execute();
|
||||
var_dump($stmt->fetchAll(PDO::FETCH_ASSOC));
|
||||
echo "\n";
|
||||
|
||||
echo "Normal object, bindValue:\n";
|
||||
try {
|
||||
$stmt = $db->prepare('SELECT (?)');
|
||||
$stmt->bindValue(1, new stdClass(), PDO::PARAM_INT);
|
||||
$stmt->execute();
|
||||
} catch (Throwable $e) {
|
||||
echo $e->getMessage()."\n\n";
|
||||
}
|
||||
|
||||
echo "Array, bindParam:\n";
|
||||
try {
|
||||
$stmt = $db->prepare('SELECT (?)');
|
||||
$param = ['aaa'];
|
||||
$stmt->bindParam(1, $param, PDO::PARAM_INT);
|
||||
$stmt->execute();
|
||||
} catch (Throwable $e) {
|
||||
echo $e->getMessage();
|
||||
}
|
||||
?>
|
||||
--EXPECT--
|
||||
Stringable object, value set after bindParam:
|
||||
bool(true)
|
||||
bool(true)
|
||||
|
||||
Stringable object, bindValue:
|
||||
array(1) {
|
||||
[0]=>
|
||||
array(1) {
|
||||
["?"]=>
|
||||
string(3) "555"
|
||||
}
|
||||
}
|
||||
|
||||
Normal object, bindValue:
|
||||
SQLSTATE[HY105]: Invalid parameter type: Expected a scalar value or null
|
||||
|
||||
Array, bindParam:
|
||||
SQLSTATE[HY105]: Invalid parameter type: Expected a scalar value or null
|
Loading…
Add table
Add a link
Reference in a new issue