summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristoph M. Becker <cmbecker69@gmx.de>2020-01-13 11:47:40 +0100
committerChristoph M. Becker <cmbecker69@gmx.de>2020-01-13 13:21:45 +0100
commit1752393bb4013ca94d45da5a4d43997a73ae9750 (patch)
treeebbccacc3ede0095f204ed70f4d0ed4b8086a1dd
parentf6dea348318d78028a45c2f072a9170a60af4300 (diff)
downloadphp-git-1752393bb4013ca94d45da5a4d43997a73ae9750.tar.gz
Fix #79084: mysqlnd may fetch wrong column indexes with MYSQLI_BOTH
Column names can be numeric strings, so we have to make sure to insert the column values with the appropriate numeric keys, instead of adding them.
-rw-r--r--NEWS4
-rw-r--r--ext/mysqli/tests/bug79084.phpt79
-rw-r--r--ext/mysqli/tests/bug79084_collision.phpt61
-rw-r--r--ext/mysqlnd/mysqlnd_result.c15
4 files changed, 153 insertions, 6 deletions
diff --git a/NEWS b/NEWS
index b91211ce27..8f20e99211 100644
--- a/NEWS
+++ b/NEWS
@@ -6,6 +6,10 @@ PHP NEWS
. Fixed bug #79078 (Hypothetical use-after-free in curl_multi_add_handle()).
(cmb)
+- MySQLnd:
+ . Fixed bug #79084 (mysqlnd may fetch wrong column indexes with MYSQLI_BOTH).
+ (cmb)
+
23 Jan 2020, PHP 7.3.14
- Core
diff --git a/ext/mysqli/tests/bug79084.phpt b/ext/mysqli/tests/bug79084.phpt
new file mode 100644
index 0000000000..b760c4abb7
--- /dev/null
+++ b/ext/mysqli/tests/bug79084.phpt
@@ -0,0 +1,79 @@
+--TEST--
+Bug #79084 (mysqlnd may fetch wrong column indexes with MYSQLI_BOTH)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+require_once('connect.inc');
+$sql = "SELECT 0 as `2007`, 0 as `2008`, 0 as `2020`";
+
+// unbuffered
+$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+$link->real_query($sql);
+$res = $link->use_result();
+$row = $res->fetch_array();
+var_dump($row);
+$link->close();
+
+// buffered
+ini_set('mysqlnd.fetch_data_copy', false);
+$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+$res = $link->query($sql);
+$row = $res->fetch_array();
+var_dump($row);
+$link->close();
+
+// buffered copies
+ini_set('mysqlnd.fetch_data_copy', true);
+$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+$res = $link->query($sql);
+$row = $res->fetch_array();
+var_dump($row);
+$link->close();
+?>
+--EXPECT--
+array(6) {
+ [0]=>
+ string(1) "0"
+ [2007]=>
+ string(1) "0"
+ [1]=>
+ string(1) "0"
+ [2008]=>
+ string(1) "0"
+ [2]=>
+ string(1) "0"
+ [2020]=>
+ string(1) "0"
+}
+array(6) {
+ [0]=>
+ string(1) "0"
+ [2007]=>
+ string(1) "0"
+ [1]=>
+ string(1) "0"
+ [2008]=>
+ string(1) "0"
+ [2]=>
+ string(1) "0"
+ [2020]=>
+ string(1) "0"
+}
+array(6) {
+ [0]=>
+ string(1) "0"
+ [2007]=>
+ string(1) "0"
+ [1]=>
+ string(1) "0"
+ [2008]=>
+ string(1) "0"
+ [2]=>
+ string(1) "0"
+ [2020]=>
+ string(1) "0"
+}
diff --git a/ext/mysqli/tests/bug79084_collision.phpt b/ext/mysqli/tests/bug79084_collision.phpt
new file mode 100644
index 0000000000..9f0c72962d
--- /dev/null
+++ b/ext/mysqli/tests/bug79084_collision.phpt
@@ -0,0 +1,61 @@
+--TEST--
+Bug #79084 (mysqlnd may fetch wrong column indexes with MYSQLI_BOTH) - collision
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+require_once('connect.inc');
+$sql = "SELECT 11111 as `1`, 22222 as `2`";
+
+// unbuffered
+$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+$link->real_query($sql);
+$res = $link->use_result();
+$row = $res->fetch_array();
+var_dump($row);
+$link->close();
+
+// buffered
+ini_set('mysqlnd.fetch_data_copy', false);
+$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+$res = $link->query($sql);
+$row = $res->fetch_array();
+var_dump($row);
+$link->close();
+
+// buffered copies
+ini_set('mysqlnd.fetch_data_copy', true);
+$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+$res = $link->query($sql);
+$row = $res->fetch_array();
+var_dump($row);
+$link->close();
+?>
+--EXPECT--
+array(3) {
+ [0]=>
+ string(5) "11111"
+ [1]=>
+ string(5) "11111"
+ [2]=>
+ string(5) "22222"
+}
+array(3) {
+ [0]=>
+ string(5) "11111"
+ [1]=>
+ string(5) "11111"
+ [2]=>
+ string(5) "22222"
+}
+array(3) {
+ [0]=>
+ string(5) "11111"
+ [1]=>
+ string(5) "11111"
+ [2]=>
+ string(5) "22222"
+}
diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c
index 783fd2cec1..10b4d09905 100644
--- a/ext/mysqlnd/mysqlnd_result.c
+++ b/ext/mysqlnd/mysqlnd_result.c
@@ -842,8 +842,9 @@ MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row)(MYSQLND_RES * result, void
const size_t len = (Z_TYPE_P(data) == IS_STRING)? Z_STRLEN_P(data) : 0;
if (flags & MYSQLND_FETCH_NUM) {
- Z_TRY_ADDREF_P(data);
- zend_hash_next_index_insert(row_ht, data);
+ if (zend_hash_index_add(row_ht, i, data) != NULL) {
+ Z_TRY_ADDREF_P(data);
+ }
}
if (flags & MYSQLND_FETCH_ASSOC) {
/* zend_hash_quick_update needs length + trailing zero */
@@ -1099,8 +1100,9 @@ MYSQLND_METHOD(mysqlnd_result_buffered_zval, fetch_row)(MYSQLND_RES * result, vo
set->lengths[i] = (Z_TYPE_P(data) == IS_STRING)? Z_STRLEN_P(data) : 0;
if (flags & MYSQLND_FETCH_NUM) {
- Z_TRY_ADDREF_P(data);
- zend_hash_next_index_insert(Z_ARRVAL_P(row), data);
+ if (zend_hash_index_add(Z_ARRVAL_P(row), i, data) != NULL) {
+ Z_TRY_ADDREF_P(data);
+ }
}
if (flags & MYSQLND_FETCH_ASSOC) {
/* zend_hash_quick_update needs length + trailing zero */
@@ -1195,8 +1197,9 @@ MYSQLND_METHOD(mysqlnd_result_buffered_c, fetch_row)(MYSQLND_RES * result, void
set->lengths[i] = (Z_TYPE_P(data) == IS_STRING)? Z_STRLEN_P(data) : 0;
if (flags & MYSQLND_FETCH_NUM) {
- Z_TRY_ADDREF_P(data);
- zend_hash_next_index_insert(Z_ARRVAL_P(row), data);
+ if (zend_hash_index_add(Z_ARRVAL_P(row), i, data)) {
+ Z_TRY_ADDREF_P(data);
+ }
}
if (flags & MYSQLND_FETCH_ASSOC) {
/* zend_hash_quick_update needs length + trailing zero */