mirror of
https://github.com/php/php-src.git
synced 2025-08-16 14:08:47 +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 "pdo/php_pdo_driver.h"
|
||||||
#include "php_pdo_mysql.h"
|
#include "php_pdo_mysql.h"
|
||||||
#include "php_pdo_mysql_int.h"
|
#include "php_pdo_mysql_int.h"
|
||||||
|
#include "zend_interfaces.h"
|
||||||
|
|
||||||
#ifdef PDO_USE_MYSQLND
|
#ifdef PDO_USE_MYSQLND
|
||||||
# define pdo_mysql_stmt_execute_prepared(stmt) pdo_mysql_stmt_execute_prepared_mysqlnd(stmt)
|
# 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:
|
case IS_DOUBLE:
|
||||||
mysqlnd_stmt_bind_one_param(S->stmt, param->paramno, parameter, MYSQL_TYPE_DOUBLE);
|
mysqlnd_stmt_bind_one_param(S->stmt, param->paramno, parameter, MYSQL_TYPE_DOUBLE);
|
||||||
break;
|
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:
|
default:
|
||||||
|
pdo_raise_impl_error(stmt->dbh, stmt, "HY105", "Expected a scalar value or null");
|
||||||
PDO_DBG_RETURN(0);
|
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);
|
b->buffer = &Z_DVAL_P(parameter);
|
||||||
PDO_DBG_RETURN(1);
|
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:
|
default:
|
||||||
|
pdo_raise_impl_error(stmt->dbh, stmt, "HY105", "Expected a scalar value or null");
|
||||||
PDO_DBG_RETURN(0);
|
PDO_DBG_RETURN(0);
|
||||||
}
|
}
|
||||||
#endif /* PDO_USE_MYSQLND */
|
#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