Following cmb's suggestion and replacing the counter with a check
against the bound_params HT, which ensures that both cannot go
out of sync.
This commit is contained in:
Nikita Popov 2020-12-11 16:35:03 +01:00
parent 7a89157f8c
commit ccb7f1c7d8
5 changed files with 69 additions and 4 deletions

2
NEWS
View file

@ -59,6 +59,8 @@ PHP NEWS
. Fixed bug #62889 (LOAD DATA INFILE broken). (Nikita)
. Fixed bug #67004 (Executing PDOStatement::fetch() more than once prevents
releasing resultset). (Nikita)
. Fixed bug #79132 (PDO re-uses parameter values from earlier calls to
execute()). (Nikita)
- Phar:
. Fixed bug #73809 (Phar Zip parse crash - mmap fail). (cmb)

View file

@ -229,7 +229,6 @@ static int mysql_handle_preparer(pdo_dbh_t *dbh, const char *sql, size_t sql_len
S->num_params = mysql_stmt_param_count(S->stmt);
if (S->num_params) {
S->params_given = 0;
#ifdef PDO_USE_MYSQLND
S->params = NULL;
#else

View file

@ -387,7 +387,6 @@ static int pdo_mysql_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_da
strcpy(stmt->error_code, "HY093");
PDO_DBG_RETURN(0);
}
S->params_given++;
#ifndef PDO_USE_MYSQLND
b = &S->params[param->paramno];
@ -399,7 +398,7 @@ static int pdo_mysql_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_da
PDO_DBG_RETURN(1);
case PDO_PARAM_EVT_EXEC_PRE:
if (S->params_given < (unsigned int) S->num_params) {
if (zend_hash_num_elements(stmt->bound_params) < (unsigned int) S->num_params) {
/* too few parameter bound */
PDO_DBG_ERR("too few parameters bound");
strcpy(stmt->error_code, "HY093");

View file

@ -141,7 +141,6 @@ typedef struct {
PDO_MYSQL_PARAM_BIND *bound_result;
my_bool *out_null;
zend_ulong *out_length;
unsigned int params_given;
unsigned max_length:1;
/* Whether all result sets have been fully consumed.
* If this flag is not set, they need to be consumed during destruction. */

View file

@ -0,0 +1,66 @@
--TEST--
Bug #79132: PDO re-uses parameter values from earlier calls to execute()
--SKIPIF--
<?php
require_once(__DIR__ . DIRECTORY_SEPARATOR . 'skipif.inc');
require_once(__DIR__ . DIRECTORY_SEPARATOR . 'mysql_pdo_test.inc');
MySQLPDOTest::skip();
?>
--FILE--
<?php
require_once(__DIR__ . DIRECTORY_SEPARATOR . 'mysql_pdo_test.inc');
$pdo = MySQLPDOTest::factory();
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
test($pdo);
echo "\n";
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
test($pdo);
function test($pdo) {
$stmt = $pdo->prepare('select ? a, ? b');
$set = [
['a', 'b'],
['x'], /* second parameter is missing */
[1 => 'y'], /* first parameter is missing */
];
foreach ($set as $params) {
try {
var_dump($stmt->execute($params), $stmt->fetchAll(PDO::FETCH_ASSOC));
} catch (PDOException $error) {
echo $error->getMessage() . "\n";
}
}
}
?>
--EXPECT--
bool(true)
array(1) {
[0]=>
array(2) {
["a"]=>
string(1) "a"
["b"]=>
string(1) "b"
}
}
SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens
SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens
bool(true)
array(1) {
[0]=>
array(2) {
["a"]=>
string(1) "a"
["b"]=>
string(1) "b"
}
}
SQLSTATE[HY093]: Invalid parameter number
SQLSTATE[HY093]: Invalid parameter number