Skip to content

Commit 6501051

Browse files
committed
ext/mysqli: Fix stmt->query leak in mysqli_execute_query() validation errors.
When MYSQLI_REPORT_INDEX is enabled, mysqli_execute_query() duplicates the query string into stmt->query. The two input_params validation error branches freed the MY_STMT wrapper directly without releasing stmt->query, leaking the duplicated string per failing call. close phpGH-21930
1 parent 17f6752 commit 6501051

3 files changed

Lines changed: 49 additions & 0 deletions

File tree

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ PHP NEWS
2121
IntlCalendar::equals(), ::before(), ::after(), and ::isEquivalentTo().
2222
(Weilin Du)
2323

24+
- mysqli:
25+
. Fix stmt->query leak in mysqli_execute_query() validation errors.
26+
(David Carlier)
27+
2428
- Phar:
2529
. Fixed a bypass of the magic ".phar" directory protection in
2630
Phar::addEmptyDir() for paths starting with "/.phar", while allowing

ext/mysqli/mysqli_api.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -532,6 +532,10 @@ PHP_FUNCTION(mysqli_execute_query)
532532
MYSQLND_PARAM_BIND *params;
533533

534534
if (!zend_array_is_list(input_params)) {
535+
if (stmt->query) {
536+
efree(stmt->query);
537+
stmt->query = NULL;
538+
}
535539
mysqli_stmt_close(stmt->stmt, false);
536540
stmt->stmt = NULL;
537541
efree(stmt);
@@ -542,6 +546,10 @@ PHP_FUNCTION(mysqli_execute_query)
542546
hash_num_elements = zend_hash_num_elements(input_params);
543547
param_count = mysql_stmt_param_count(stmt->stmt);
544548
if (hash_num_elements != param_count) {
549+
if (stmt->query) {
550+
efree(stmt->query);
551+
stmt->query = NULL;
552+
}
545553
mysqli_stmt_close(stmt->stmt, false);
546554
stmt->stmt = NULL;
547555
efree(stmt);
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
--TEST--
2+
mysqli_execute_query() does not leak stmt->query on input_params validation errors with MYSQLI_REPORT_INDEX
3+
--EXTENSIONS--
4+
mysqli
5+
--SKIPIF--
6+
<?php
7+
require_once 'skipifconnectfailure.inc';
8+
?>
9+
--FILE--
10+
<?php
11+
12+
require 'table.inc';
13+
14+
mysqli_report(MYSQLI_REPORT_INDEX);
15+
16+
try {
17+
$link->execute_query('SELECT label, ? AS anon, ? AS num FROM test WHERE id=?', ['foo', 42]);
18+
} catch (ValueError $e) {
19+
echo '[001] '.$e->getMessage()."\n";
20+
}
21+
22+
try {
23+
$link->execute_query('SELECT label, ? AS anon, ? AS num FROM test WHERE id=?', ['foo' => 42]);
24+
} catch (ValueError $e) {
25+
echo '[002] '.$e->getMessage()."\n";
26+
}
27+
28+
print "done!";
29+
?>
30+
--CLEAN--
31+
<?php
32+
require_once 'clean_table.inc';
33+
?>
34+
--EXPECT--
35+
[001] mysqli::execute_query(): Argument #2 ($params) must consist of exactly 3 elements, 2 present
36+
[002] mysqli::execute_query(): Argument #2 ($params) must be a list array
37+
done!

0 commit comments

Comments
 (0)