Skip to content

Commit 2611223

Browse files
committed
Add a hard exception if more values provided than parameters
1 parent 5fcf80b commit 2611223

File tree

2 files changed

+35
-26
lines changed

2 files changed

+35
-26
lines changed

ext/mysqli/mysqli_api.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -828,6 +828,11 @@ PHP_FUNCTION(mysqli_stmt_execute)
828828
unsigned int index;
829829
MYSQLND_PARAM_BIND *params;
830830

831+
if(zend_hash_num_elements(Z_ARRVAL_P(input_params)) > mysql_stmt_param_count(stmt->stmt)) {
832+
zend_argument_count_error("The number of values must match the number of parameters in the prepared statement");
833+
RETURN_THROWS();
834+
}
835+
831836
params = mysqlnd_stmt_alloc_param_bind(stmt->stmt);
832837
if (!params) {
833838
// can we safely return here?

ext/mysqli/tests/mysqli_stmt_execute_bind.phpt

Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -43,57 +43,66 @@ if (mysqli_get_server_version($link) <= 40100) {
4343
}
4444
$stmt = null;
4545

46-
// 3. param number has to match - missing all parameters
46+
// 3. Too many parameters
47+
$stmt = $link->prepare('SELECT label, ? AS anon, ? AS num FROM test WHERE id=?');
48+
try {
49+
$stmt->execute([&$abc, null, $id, 24]);
50+
} catch (ArgumentCountError $e) {
51+
echo '[002] '.$e->getMessage()."\n";
52+
}
53+
$stmt = null;
54+
55+
// 4. param number has to match - missing all parameters
4756
$stmt = $link->prepare('SELECT label, ? AS anon, ? AS num FROM test WHERE id=?');
4857
try {
4958
$stmt->execute([]);
5059
} catch (mysqli_sql_exception $e) {
51-
echo '[002] '.$e->getMessage()."\n";
60+
echo '[003] '.$e->getMessage()."\n";
5261
}
5362
$stmt = null;
5463

55-
// 4. param number has to match - missing argument to execute()
64+
// 5. param number has to match - missing argument to execute()
5665
$stmt = $link->prepare('SELECT label, ? AS anon, ? AS num FROM test WHERE id=?');
5766
try {
5867
$stmt->execute();
5968
} catch (mysqli_sql_exception $e) {
60-
echo '[003] '.$e->getMessage()."\n";
69+
echo '[004] '.$e->getMessage()."\n";
6170
}
6271
$stmt = null;
6372

64-
// 5. wrong argument to execute()
73+
// 6. wrong argument to execute()
6574
$stmt = $link->prepare('SELECT label, ? AS anon, ? AS num FROM test WHERE id=?');
6675
try {
6776
$stmt->execute(42);
6877
} catch (TypeError $e) {
69-
echo '[004] '.$e->getMessage()."\n";
78+
echo '[005] '.$e->getMessage()."\n";
7079
}
7180
$stmt = null;
7281

73-
// 6. objects are not arrays and are not accepted
82+
// 7. objects are not arrays and are not accepted
7483
$stmt = $link->prepare('SELECT label, ? AS anon, ? AS num FROM test WHERE id=?');
7584
try {
7685
$stmt->execute((object)[&$abc, 42, $id]);
7786
} catch (TypeError $e) {
78-
echo '[005] '.$e->getMessage()."\n";
87+
echo '[006] '.$e->getMessage()."\n";
7988
}
8089
$stmt = null;
8190

82-
// 7. arrays by reference work too
91+
// 8. arrays by reference work too
8392
$stmt = $link->prepare('SELECT label, ? AS anon, ? AS num FROM test WHERE id=?');
8493
$arr = [&$abc, 42, $id];
8594
$arr2 = &$arr;
8695
$stmt->execute($arr2);
8796
assert($stmt->get_result()->fetch_assoc() === ['label'=>'a', 'anon'=>'abc', 'num' => '42']);
8897
$stmt = null;
8998

90-
// 8. no placeholders in statement. params are ignored
99+
// 9. no placeholders in statement. nothing to bind in an empty array
91100
$stmt = $link->prepare('SELECT label FROM test WHERE id=1');
92-
$stmt->execute(['I am ignored']);
101+
$stmt->execute([]);
93102
assert($stmt->get_result()->fetch_assoc() === ['label'=>'a']);
94103
$stmt = null;
95104

96-
// 9. once bound the values are persisted. Just like in PDO
105+
// 10. once bound the values are persisted. Just like in PDO
97106
$stmt = $link->prepare('SELECT label, ? AS anon, ? AS num FROM test WHERE id=?');
98107
$stmt->execute(['abc', 42, $id]);
99108
assert($stmt->get_result()->fetch_assoc() === ['label'=>'a', 'anon'=>'abc', 'num' => '42']);
@@ -102,29 +111,23 @@ if (mysqli_get_server_version($link) <= 40100) {
102111
try {
103112
$stmt->execute([]); // no params here. PDO doesn't throw an error, but mysqli does
104113
} catch (mysqli_sql_exception $e) {
105-
echo '[006] '.$e->getMessage()."\n";
114+
echo '[007] '.$e->getMessage()."\n";
106115
}
107116
$stmt = null;
108117

109-
// 10. mixing binding styles not possible. Also, NULL should stay NULL when bound as string
118+
// 11. mixing binding styles not possible. Also, NULL should stay NULL when bound as string
110119
$stmt = $link->prepare('SELECT label, ? AS anon, ? AS num FROM test WHERE id=?');
111120
$stmt->bind_param('sss', ...['abc', 42, null]);
112121
$stmt->execute([null, null, $id]);
113122
assert($stmt->get_result()->fetch_assoc() === ['label'=>'a', 'anon'=>null, 'num' => null]);
114123
$stmt = null;
115124

116-
// 11. array keys are ignored. Even numerical indices are not considered (PDO does a weird thing with the numerical indices)
125+
// 12. array keys are ignored. Even numerical indices are not considered (PDO does a weird thing with the numerical indices)
117126
$stmt = $link->prepare('SELECT label, ? AS anon, ? AS num FROM test WHERE id=?');
118127
$stmt->execute(['A'=>'abc', 2=>42, null=>$id]);
119128
assert($stmt->get_result()->fetch_assoc() === ['label'=>'a', 'anon'=>'abc', 'num' => '42']);
120129
$stmt = null;
121130

122-
// 12. Too many parameters is not a problem. The redundant ones just get ignored
123-
$stmt = $link->prepare('SELECT label, ? AS anon, ? AS num FROM test WHERE id=?');
124-
$stmt->execute(['abc', null, $id, 42]);
125-
assert($stmt->get_result()->fetch_assoc() === ['label'=>'a', 'anon'=>'abc', 'num' => null]);
126-
$stmt = null;
127-
128131

129132
mysqli_close($link);
130133
print "done!";
@@ -135,9 +138,10 @@ if (mysqli_get_server_version($link) <= 40100) {
135138
?>
136139
--EXPECT--
137140
[001] No data supplied for 1 parameter in prepared statement
138-
[002] No data supplied for 3 parameters in prepared statement
139-
[003] No data supplied for parameters in prepared statement
140-
[004] mysqli_stmt::execute(): Argument #1 ($params) must be of type ?array, int given
141-
[005] mysqli_stmt::execute(): Argument #1 ($params) must be of type ?array, stdClass given
142-
[006] No data supplied for 3 parameters in prepared statement
141+
[002] The number of values must match the number of parameters in the prepared statement
142+
[003] No data supplied for 3 parameters in prepared statement
143+
[004] No data supplied for parameters in prepared statement
144+
[005] mysqli_stmt::execute(): Argument #1 ($params) must be of type ?array, int given
145+
[006] mysqli_stmt::execute(): Argument #1 ($params) must be of type ?array, stdClass given
146+
[007] No data supplied for 3 parameters in prepared statement
143147
done!

0 commit comments

Comments
 (0)