com php-src: Fixed bug #67983: NEWS ext/mysqli/tests/bug67983.phpt ext/mysqlnd/mysqlnd_wireprotocol.c
| From: | Nikita Popov | Date: | Wed, 16 Dec 2020 09:52:27 +0000 |
| Subject: | com php-src: Fixed bug #67983: NEWS ext/mysqli/tests/bug67983.phpt ext/mysqlnd/mysqlnd_wireprotocol.c | ||
| Groups: | php.cvs | ||
| Request: | Send a blank email to php-cvs+get-114481@lists.php.net to get a copy of this message | ||
Commit: 315f3f8dc9b3ba3639c9284301933286fc99a825
Author: Nikita Popov <nikita.ppv@gmail.com> Wed, 16 Dec 2020 10:52:27 +0100
Parents: 118ff03335d67c19817ff83d89e634fcd39275ff
Branches: PHP-7.4 PHP-8.0 master
Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=315f3f8dc9b3ba3639c9284301933286fc99a825
Log:
Fixed bug #67983
We need to check the BIT case first, otherwise it will get skipped
in INT_AND_FLOAT_NATIVE mode.
Bugs:
https://bugs.php.net/67983
Changed paths:
M NEWS
A ext/mysqli/tests/bug67983.phpt
M ext/mysqlnd/mysqlnd_wireprotocol.c
Diff:
diff --git a/NEWS b/NEWS
index a62d492d0d0..8dcb2e94f2f 100644
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,10 @@ PHP NEWS
- Core:
. Fixed bug #80523 (bogus parse error on >4GB source code). (Nikita)
+- MySQLi:
+ . Fixed bug #67983 (mysqlnd with MYSQLI_OPT_INT_AND_FLOAT_NATIVE fails to
+ interpret bit columns). (Nikita)
+
07 Jan 2021, PHP 7.4.14
- Core:
diff --git a/ext/mysqli/tests/bug67983.phpt b/ext/mysqli/tests/bug67983.phpt
new file mode 100644
index 00000000000..a72501c0768
--- /dev/null
+++ b/ext/mysqli/tests/bug67983.phpt
@@ -0,0 +1,35 @@
+--TEST--
+Bug #67983: mysqlnd with MYSQLI_OPT_INT_AND_FLOAT_NATIVE fails to interpret bit columns
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+if (!$IS_MYSQLND) {
+ die("skip mysqlnd only test");
+}
+?>
+--FILE--
+<?php
+
+require_once("connect.inc");
+
+$connection = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+mysqli_options($connection, MYSQLI_OPT_INT_AND_FLOAT_NATIVE, true);
+
+mysqli_set_charset($connection, 'utf8');
+mysqli_query($connection, 'DROP TABLE IF EXISTS test');
+mysqli_query($connection, 'CREATE TABLE test (id BIT(8))');
+mysqli_query($connection, 'INSERT INTO test VALUES (0), (1), (42)');
+
+$res = mysqli_query($connection, 'SELECT * FROM test');
+
+while ($result = mysqli_fetch_assoc($res)) {
+ var_dump($result['id']);
+}
+
+?>
+--EXPECT--
+int(0)
+int(1)
+int(42)
diff --git a/ext/mysqlnd/mysqlnd_wireprotocol.c b/ext/mysqlnd/mysqlnd_wireprotocol.c
index 98de05455ef..216f4206987 100644
--- a/ext/mysqlnd/mysqlnd_wireprotocol.c
+++ b/ext/mysqlnd/mysqlnd_wireprotocol.c
@@ -1616,8 +1616,28 @@ php_mysqlnd_rowp_read_text_protocol_aux(MYSQLND_ROW_BUFFER * row_buffer, zval
*
}
MYSQLND_INC_CONN_STATISTIC_W_VALUE2(stats, statistic, 1, STAT_BYTES_RECEIVED_PURE_DATA_TEXT,
len);
}
+ if (fields_metadata[i].type == MYSQL_TYPE_BIT) {
+ /*
+ BIT fields are specially handled. As they come as bit mask, they have
+ to be converted to human-readable representation.
+ */
+ ps_fetch_from_1_to_8_bytes(current_field, &(fields_metadata[i]), 0, (const zend_uchar **)
&p, len);
+ /*
+ We have advanced in ps_fetch_from_1_to_8_bytes. We should go back because
+ later in this function there will be an advancement.
+ */
+ p -= len;
+ if (Z_TYPE_P(current_field) == IS_LONG && !as_int_or_float) {
+ /* we are using the text protocol, so convert to string */
+ char tmp[22];
+ const size_t tmp_len = sprintf((char *)&tmp, ZEND_ULONG_FMT, Z_LVAL_P(current_field));
+ ZVAL_STRINGL(current_field, tmp, tmp_len);
+ } else if (Z_TYPE_P(current_field) == IS_STRING) {
+ /* nothing to do here, as we want a string and ps_fetch_from_1_to_8_bytes() has given us one
*/
+ }
+ }
#ifdef MYSQLND_STRING_TO_INT_CONVERSION
- if (as_int_or_float && perm_bind.php_type == IS_LONG) {
+ else if (as_int_or_float && perm_bind.php_type == IS_LONG) {
zend_uchar save = *(p + len);
/* We have to make it ASCIIZ temporarily */
*(p + len) = '\0';
@@ -1661,28 +1681,9 @@ php_mysqlnd_rowp_read_text_protocol_aux(MYSQLND_ROW_BUFFER * row_buffer, zval
*
*(p + len) = '\0';
ZVAL_DOUBLE(current_field, atof((char *) p));
*(p + len) = save;
- } else
+ }
#endif /* MYSQLND_STRING_TO_INT_CONVERSION */
- if (fields_metadata[i].type == MYSQL_TYPE_BIT) {
- /*
- BIT fields are specially handled. As they come as bit mask, they have
- to be converted to human-readable representation.
- */
- ps_fetch_from_1_to_8_bytes(current_field, &(fields_metadata[i]), 0, (const zend_uchar **)
&p, len);
- /*
- We have advanced in ps_fetch_from_1_to_8_bytes. We should go back because
- later in this function there will be an advancement.
- */
- p -= len;
- if (Z_TYPE_P(current_field) == IS_LONG && !as_int_or_float) {
- /* we are using the text protocol, so convert to string */
- char tmp[22];
- const size_t tmp_len = sprintf((char *)&tmp, ZEND_ULONG_FMT, Z_LVAL_P(current_field));
- ZVAL_STRINGL(current_field, tmp, tmp_len);
- } else if (Z_TYPE_P(current_field) == IS_STRING) {
- /* nothing to do here, as we want a string and ps_fetch_from_1_to_8_bytes() has given us one
*/
- }
- } else if (len == 0) {
+ else if (len == 0) {
ZVAL_EMPTY_STRING(current_field);
} else if (len == 1) {
ZVAL_INTERNED_STR(current_field, ZSTR_CHAR((zend_uchar)*(char *)p));