Skip to content

Commit b0cdd8c

Browse files
committed
Merge branch 'PHP-7.3' into PHP-7.4
* PHP-7.3: Fix #79084: mysqlnd may fetch wrong column indexes with MYSQLI_BOTH
2 parents c247898 + 1752393 commit b0cdd8c

File tree

4 files changed

+153
-6
lines changed

4 files changed

+153
-6
lines changed

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ PHP NEWS
66
. Fixed bug #79078 (Hypothetical use-after-free in curl_multi_add_handle()).
77
(cmb)
88

9+
- MySQLnd:
10+
. Fixed bug #79084 (mysqlnd may fetch wrong column indexes with MYSQLI_BOTH).
11+
(cmb)
12+
913
23 Jan 2020, PHP 7.4.2
1014

1115
- Core:

ext/mysqli/tests/bug79084.phpt

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
--TEST--
2+
Bug #79084 (mysqlnd may fetch wrong column indexes with MYSQLI_BOTH)
3+
--SKIPIF--
4+
<?php
5+
require_once('skipif.inc');
6+
require_once('skipifconnectfailure.inc');
7+
?>
8+
--FILE--
9+
<?php
10+
require_once('connect.inc');
11+
$sql = "SELECT 0 as `2007`, 0 as `2008`, 0 as `2020`";
12+
13+
// unbuffered
14+
$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
15+
$link->real_query($sql);
16+
$res = $link->use_result();
17+
$row = $res->fetch_array();
18+
var_dump($row);
19+
$link->close();
20+
21+
// buffered
22+
ini_set('mysqlnd.fetch_data_copy', false);
23+
$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
24+
$res = $link->query($sql);
25+
$row = $res->fetch_array();
26+
var_dump($row);
27+
$link->close();
28+
29+
// buffered copies
30+
ini_set('mysqlnd.fetch_data_copy', true);
31+
$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
32+
$res = $link->query($sql);
33+
$row = $res->fetch_array();
34+
var_dump($row);
35+
$link->close();
36+
?>
37+
--EXPECT--
38+
array(6) {
39+
[0]=>
40+
string(1) "0"
41+
[2007]=>
42+
string(1) "0"
43+
[1]=>
44+
string(1) "0"
45+
[2008]=>
46+
string(1) "0"
47+
[2]=>
48+
string(1) "0"
49+
[2020]=>
50+
string(1) "0"
51+
}
52+
array(6) {
53+
[0]=>
54+
string(1) "0"
55+
[2007]=>
56+
string(1) "0"
57+
[1]=>
58+
string(1) "0"
59+
[2008]=>
60+
string(1) "0"
61+
[2]=>
62+
string(1) "0"
63+
[2020]=>
64+
string(1) "0"
65+
}
66+
array(6) {
67+
[0]=>
68+
string(1) "0"
69+
[2007]=>
70+
string(1) "0"
71+
[1]=>
72+
string(1) "0"
73+
[2008]=>
74+
string(1) "0"
75+
[2]=>
76+
string(1) "0"
77+
[2020]=>
78+
string(1) "0"
79+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
--TEST--
2+
Bug #79084 (mysqlnd may fetch wrong column indexes with MYSQLI_BOTH) - collision
3+
--SKIPIF--
4+
<?php
5+
require_once('skipif.inc');
6+
require_once('skipifconnectfailure.inc');
7+
?>
8+
--FILE--
9+
<?php
10+
require_once('connect.inc');
11+
$sql = "SELECT 11111 as `1`, 22222 as `2`";
12+
13+
// unbuffered
14+
$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
15+
$link->real_query($sql);
16+
$res = $link->use_result();
17+
$row = $res->fetch_array();
18+
var_dump($row);
19+
$link->close();
20+
21+
// buffered
22+
ini_set('mysqlnd.fetch_data_copy', false);
23+
$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
24+
$res = $link->query($sql);
25+
$row = $res->fetch_array();
26+
var_dump($row);
27+
$link->close();
28+
29+
// buffered copies
30+
ini_set('mysqlnd.fetch_data_copy', true);
31+
$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
32+
$res = $link->query($sql);
33+
$row = $res->fetch_array();
34+
var_dump($row);
35+
$link->close();
36+
?>
37+
--EXPECT--
38+
array(3) {
39+
[0]=>
40+
string(5) "11111"
41+
[1]=>
42+
string(5) "11111"
43+
[2]=>
44+
string(5) "22222"
45+
}
46+
array(3) {
47+
[0]=>
48+
string(5) "11111"
49+
[1]=>
50+
string(5) "11111"
51+
[2]=>
52+
string(5) "22222"
53+
}
54+
array(3) {
55+
[0]=>
56+
string(5) "11111"
57+
[1]=>
58+
string(5) "11111"
59+
[2]=>
60+
string(5) "22222"
61+
}

ext/mysqlnd/mysqlnd_result.c

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -844,8 +844,9 @@ MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row)(MYSQLND_RES * result, void
844844
const size_t len = (Z_TYPE_P(data) == IS_STRING)? Z_STRLEN_P(data) : 0;
845845

846846
if (flags & MYSQLND_FETCH_NUM) {
847-
Z_TRY_ADDREF_P(data);
848-
zend_hash_next_index_insert(row_ht, data);
847+
if (zend_hash_index_add(row_ht, i, data) != NULL) {
848+
Z_TRY_ADDREF_P(data);
849+
}
849850
}
850851
if (flags & MYSQLND_FETCH_ASSOC) {
851852
/* zend_hash_quick_update needs length + trailing zero */
@@ -1101,8 +1102,9 @@ MYSQLND_METHOD(mysqlnd_result_buffered_zval, fetch_row)(MYSQLND_RES * result, vo
11011102
set->lengths[i] = (Z_TYPE_P(data) == IS_STRING)? Z_STRLEN_P(data) : 0;
11021103

11031104
if (flags & MYSQLND_FETCH_NUM) {
1104-
Z_TRY_ADDREF_P(data);
1105-
zend_hash_next_index_insert(Z_ARRVAL_P(row), data);
1105+
if (zend_hash_index_add(Z_ARRVAL_P(row), i, data) != NULL) {
1106+
Z_TRY_ADDREF_P(data);
1107+
}
11061108
}
11071109
if (flags & MYSQLND_FETCH_ASSOC) {
11081110
/* zend_hash_quick_update needs length + trailing zero */
@@ -1197,8 +1199,9 @@ MYSQLND_METHOD(mysqlnd_result_buffered_c, fetch_row)(MYSQLND_RES * result, void
11971199
set->lengths[i] = (Z_TYPE_P(data) == IS_STRING)? Z_STRLEN_P(data) : 0;
11981200

11991201
if (flags & MYSQLND_FETCH_NUM) {
1200-
Z_TRY_ADDREF_P(data);
1201-
zend_hash_next_index_insert(Z_ARRVAL_P(row), data);
1202+
if (zend_hash_index_add(Z_ARRVAL_P(row), i, data)) {
1203+
Z_TRY_ADDREF_P(data);
1204+
}
12021205
}
12031206
if (flags & MYSQLND_FETCH_ASSOC) {
12041207
/* zend_hash_quick_update needs length + trailing zero */

0 commit comments

Comments
 (0)