com php-src: And here is the real fix for #66124: ext/mysqlnd/m ysqlnd_ps_codec.c

From: Date: Thu, 21 Nov 2013 19:29:21 +0000
Subject: com php-src: And here is the real fix for #66124: ext/mysqlnd/m ysqlnd_ps_codec.c
Groups: php.cvs 
Request: Send a blank email to php-cvs+get-74020@lists.php.net to get a copy of this message
Commit: ce098222696b505b93faea37414446740dbd9846 Author: Andrey Hristov <andrey@php.net> Thu, 21 Nov 2013 21:29:21 +0200 Parents: 4a1c9be857a6d076ae9192a923b92b56fbb372d9 Branches: PHP-5.4 PHP-5.5 master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=ce098222696b505b93faea37414446740dbd9846 Log: And here is the real fix for #66124 Bugs: https://bugs.php.net/66124 Changed paths: M ext/mysqlnd/mysqlnd_ps_codec.c Diff: diff --git a/ext/mysqlnd/mysqlnd_ps_codec.c b/ext/mysqlnd/mysqlnd_ps_codec.c index cee0be1..2beb290 100644 --- a/ext/mysqlnd/mysqlnd_ps_codec.c +++ b/ext/mysqlnd/mysqlnd_ps_codec.c @@ -636,9 +636,8 @@ mysqlnd_stmt_execute_store_params(MYSQLND_STMT * s, zend_uchar **buf, zend_uchar occur, and force resend for the next execution. */ for (i = 0; i < stmt->param_count; i++) { - if (Z_TYPE_P(stmt->param_bind[i].zv) != IS_NULL && - (stmt->param_bind[i].type == MYSQL_TYPE_LONG || stmt->param_bind[i].type == MYSQL_TYPE_LONGLONG)) - { + short current_type = stmt->param_bind[i].type; + if (Z_TYPE_P(stmt->param_bind[i].zv) != IS_NULL && (current_type == MYSQL_TYPE_LONG || current_type == MYSQL_TYPE_LONGLONG)) { /* always copy the var, because we do many conversions */ if (Z_TYPE_P(stmt->param_bind[i].zv) != IS_LONG && PASS != mysqlnd_stmt_copy_it(&copies, stmt->param_bind[i].zv, stmt->param_count, i TSRMLS_CC)) @@ -652,10 +651,31 @@ mysqlnd_stmt_execute_store_params(MYSQLND_STMT * s, zend_uchar **buf, zend_uchar */ if (Z_TYPE_P(stmt->param_bind[i].zv) != IS_LONG) { zval *tmp_data = (copies && copies[i])? copies[i]: stmt->param_bind[i].zv; - convert_to_double_ex(&tmp_data); - if (Z_DVAL_P(tmp_data) > LONG_MAX || Z_DVAL_P(tmp_data) < LONG_MIN) { + /* + Because converting to double and back to long can lead + to losing precision we need second variable. Conversion to double is to see if + value is too big for a long. As said, precision could be lost. + */ + zval *tmp_data_copy; + MAKE_STD_ZVAL(tmp_data_copy); + *tmp_data_copy = *tmp_data; + Z_SET_REFCOUNT_P(tmp_data_copy, 1); + zval_copy_ctor(tmp_data_copy); + convert_to_double_ex(&tmp_data_copy); + + /* + if it doesn't fit in a long send it as a string. + Check bug #52891 : Wrong data inserted with mysqli/mysqlnd when using bind_param, value > LONG_MAX + We do transformation here, which will be used later when sending types. The code later relies on this. + */ + if (Z_DVAL_P(tmp_data_copy) > LONG_MAX || Z_DVAL_P(tmp_data_copy) < LONG_MIN) { stmt->send_types_to_server = resend_types_next_time = 1; + convert_to_string_ex(&tmp_data); + } else { + convert_to_long_ex(&tmp_data); } + + zval_ptr_dtor(&tmp_data_copy); } } } @@ -698,10 +718,11 @@ mysqlnd_stmt_execute_store_params(MYSQLND_STMT * s, zend_uchar **buf, zend_uchar */ if (Z_TYPE_P(stmt->param_bind[i].zv) != IS_LONG) { zval *tmp_data = (copies && copies[i])? copies[i]: stmt->param_bind[i].zv; - - convert_to_double_ex(&tmp_data); - if (Z_DVAL_P(tmp_data) > LONG_MAX || Z_DVAL_P(tmp_data) < LONG_MIN) { - convert_to_string_ex(&tmp_data); + /* + In case of IS_LONG we do nothing, it is ok, in case of string, we just need to set current_type. + The actual transformation has been performed several dozens line above. + */ + if (Z_TYPE_P(tmp_data) == IS_STRING) { current_type = MYSQL_TYPE_VAR_STRING; /* don't change stmt->param_bind[i].type to MYSQL_TYPE_VAR_STRING @@ -709,8 +730,6 @@ mysqlnd_stmt_execute_store_params(MYSQLND_STMT * s, zend_uchar **buf, zend_uchar if the type is however not long, then we will do a goto in the next switch. We want to preserve the original bind type given by the user. Thus, we do these hacks. */ - } else { - convert_to_long_ex(&tmp_data); } } }

« previous php.cvs (#74020) next »