From ce098222696b505b93faea37414446740dbd9846 Mon Sep 17 00:00:00 2001 From: Andrey Hristov Date: Thu, 21 Nov 2013 21:29:21 +0200 Subject: And here is the real fix for #66124 --- ext/mysqlnd/mysqlnd_ps_codec.c | 41 ++++++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 11 deletions(-) (limited to 'ext/mysqlnd/mysqlnd_ps_codec.c') diff --git a/ext/mysqlnd/mysqlnd_ps_codec.c b/ext/mysqlnd/mysqlnd_ps_codec.c index cee0be181e..2beb290312 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); } } } -- cgit v1.2.1 From c0d060f5c02db168f1de895b41afffbc6e3cacfb Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Fri, 3 Jan 2014 11:04:26 +0800 Subject: Bump year --- ext/mysqlnd/mysqlnd_ps_codec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ext/mysqlnd/mysqlnd_ps_codec.c') diff --git a/ext/mysqlnd/mysqlnd_ps_codec.c b/ext/mysqlnd/mysqlnd_ps_codec.c index 2beb290312..e2640c775b 100644 --- a/ext/mysqlnd/mysqlnd_ps_codec.c +++ b/ext/mysqlnd/mysqlnd_ps_codec.c @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ - | Copyright (c) 2006-2013 The PHP Group | + | Copyright (c) 2006-2014 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | -- cgit v1.2.1 From 47c902777297ce895aa915c13efdb00881af3669 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Fri, 3 Jan 2014 11:06:16 +0800 Subject: Bump year --- ext/mysqlnd/mysqlnd_ps_codec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ext/mysqlnd/mysqlnd_ps_codec.c') diff --git a/ext/mysqlnd/mysqlnd_ps_codec.c b/ext/mysqlnd/mysqlnd_ps_codec.c index a3a973e811..d0e44fa275 100644 --- a/ext/mysqlnd/mysqlnd_ps_codec.c +++ b/ext/mysqlnd/mysqlnd_ps_codec.c @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ - | Copyright (c) 2006-2013 The PHP Group | + | Copyright (c) 2006-2014 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | -- cgit v1.2.1 From c081ce628f0d76d44784d7bb8e06428b06142ac0 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Fri, 3 Jan 2014 11:08:10 +0800 Subject: Bump year --- ext/mysqlnd/mysqlnd_ps_codec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ext/mysqlnd/mysqlnd_ps_codec.c') diff --git a/ext/mysqlnd/mysqlnd_ps_codec.c b/ext/mysqlnd/mysqlnd_ps_codec.c index a3a973e811..d0e44fa275 100644 --- a/ext/mysqlnd/mysqlnd_ps_codec.c +++ b/ext/mysqlnd/mysqlnd_ps_codec.c @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ - | Copyright (c) 2006-2013 The PHP Group | + | Copyright (c) 2006-2014 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | -- cgit v1.2.1 From 0c90c207a71b90cc840d449a1952f16edd64cb4b Mon Sep 17 00:00:00 2001 From: Andrey Hristov Date: Fri, 24 Jan 2014 11:39:24 +0200 Subject: Backport refactoring from php-src --- ext/mysqlnd/mysqlnd_ps_codec.c | 340 +++++++++++++++++++++++------------------ 1 file changed, 192 insertions(+), 148 deletions(-) (limited to 'ext/mysqlnd/mysqlnd_ps_codec.c') diff --git a/ext/mysqlnd/mysqlnd_ps_codec.c b/ext/mysqlnd/mysqlnd_ps_codec.c index d0e44fa275..724feea07f 100644 --- a/ext/mysqlnd/mysqlnd_ps_codec.c +++ b/ext/mysqlnd/mysqlnd_ps_codec.c @@ -516,68 +516,70 @@ mysqlnd_stmt_copy_it(zval *** copies, zval * original, unsigned int param_count, /* }}} */ -/* {{{ mysqlnd_stmt_execute_store_params */ -static enum_func_status -mysqlnd_stmt_execute_store_params(MYSQLND_STMT * s, zend_uchar **buf, zend_uchar **p, size_t *buf_len TSRMLS_DC) +/* {{{ mysqlnd_stmt_free_copies */ +static void +mysqlnd_stmt_free_copies(MYSQLND_STMT_DATA * stmt, zval ** copies TSRMLS_DC) { - MYSQLND_STMT_DATA * stmt = s->data; - unsigned int i = 0; - zend_uchar * provided_buffer = *buf; - size_t left = (*buf_len - (*p - *buf)); - size_t data_size = 0; - zval **copies = NULL;/* if there are different types */ - enum_func_status ret = FAIL; - int resend_types_next_time = 0; - size_t null_byte_offset; + if (copies) { + unsigned int i; + for (i = 0; i < stmt->param_count; i++) { + if (copies[i]) { + zval_ptr_dtor(&copies[i]); + } + } + mnd_efree(copies); + } +} +/* }}} */ - DBG_ENTER("mysqlnd_stmt_execute_store_params"); - { - unsigned int null_count = (stmt->param_count + 7) / 8; - /* give it some reserved space - 20 bytes */ - if (left < (null_count + 20)) { - unsigned int offset = *p - *buf; - zend_uchar *tmp_buf; - *buf_len = offset + null_count + 20; - tmp_buf = mnd_emalloc(*buf_len); - if (!tmp_buf) { - SET_OOM_ERROR(*stmt->error_info); - goto end; - } - memcpy(tmp_buf, *buf, offset); - if (*buf != provided_buffer) { - mnd_efree(*buf); - } - *buf = tmp_buf; +/* {{{ mysqlnd_stmt_execute_check_n_enlarge_buffer */ +static enum_func_status +mysqlnd_stmt_execute_check_n_enlarge_buffer(zend_uchar **buf, zend_uchar **p, size_t * buf_len, zend_uchar * const provided_buffer, size_t needed_bytes TSRMLS_DC) +{ + const size_t overalloc = 5; + size_t left = (*buf_len - (*p - *buf)); - /* Update our pos pointer */ - *p = *buf + offset; + if (left < (needed_bytes + overalloc)) { + size_t offset = *p - *buf; + zend_uchar *tmp_buf; + *buf_len = offset + needed_bytes + overalloc; + tmp_buf = mnd_emalloc(*buf_len); + if (!tmp_buf) { + return FAIL; } - /* put `null` bytes */ - null_byte_offset = *p - *buf; - memset(*p, 0, null_count); - *p += null_count; + memcpy(tmp_buf, *buf, offset); + if (*buf != provided_buffer) { + mnd_efree(*buf); + } + *buf = tmp_buf; + /* Update our pos pointer */ + *p = *buf + offset; } + return PASS; +} +/* }}} */ - left = (*buf_len - (*p - *buf)); -/* 1. Store type information */ - /* - check if need to send the types even if stmt->send_types_to_server is 0. This is because - if we send "i" (42) then the type will be int and the server will expect int. However, if next - time we try to send > LONG_MAX, the conversion to string will send a string and the server - won't expect it and interpret the value as 0. Thus we need to resend the types, if any such values - occur, and force resend for the next execution. - */ + +/* {{{ mysqlnd_stmt_execute_prepare_param_types */ +static enum_func_status +mysqlnd_stmt_execute_prepare_param_types(MYSQLND_STMT_DATA * stmt, zval *** copies_param, int * resend_types_next_time TSRMLS_DC) +{ + unsigned int i; + DBG_ENTER("mysqlnd_stmt_execute_prepare_param_types"); for (i = 0; i < stmt->param_count; i++) { 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)) { + zval ** copies; /* 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)) + PASS != mysqlnd_stmt_copy_it(copies_param, stmt->param_bind[i].zv, stmt->param_count, i TSRMLS_CC)) { SET_OOM_ERROR(*stmt->error_info); goto end; } + copies = *copies_param; /* 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 @@ -602,7 +604,7 @@ mysqlnd_stmt_execute_store_params(MYSQLND_STMT * s, zend_uchar **buf, zend_uchar 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; + stmt->send_types_to_server = *resend_types_next_time = 1; convert_to_string_ex(&tmp_data); } else { convert_to_long_ex(&tmp_data); @@ -612,68 +614,61 @@ mysqlnd_stmt_execute_store_params(MYSQLND_STMT * s, zend_uchar **buf, zend_uchar } } } + DBG_RETURN(PASS); +end: + DBG_RETURN(FAIL); +} +/* }}} */ - int1store(*p, stmt->send_types_to_server); - (*p)++; - - if (stmt->send_types_to_server) { - /* 2 bytes per type, and leave 20 bytes for future use */ - if (left < ((stmt->param_count * 2) + 20)) { - unsigned int offset = *p - *buf; - zend_uchar *tmp_buf; - *buf_len = offset + stmt->param_count * 2 + 20; - tmp_buf = mnd_emalloc(*buf_len); - if (!tmp_buf) { - SET_OOM_ERROR(*stmt->error_info); - goto end; - } - memcpy(tmp_buf, *buf, offset); - if (*buf != provided_buffer) { - mnd_efree(*buf); - } - *buf = tmp_buf; - /* Update our pos pointer */ - *p = *buf + offset; - } - for (i = 0; i < stmt->param_count; i++) { - short current_type = stmt->param_bind[i].type; - /* our types are not unsigned */ +/* {{{ mysqlnd_stmt_execute_store_types */ +static void +mysqlnd_stmt_execute_store_types(MYSQLND_STMT_DATA * stmt, zval ** copies, zend_uchar ** p) +{ + unsigned int i; + for (i = 0; i < stmt->param_count; i++) { + short current_type = stmt->param_bind[i].type; + /* our types are not unsigned */ #if SIZEOF_LONG==8 - if (current_type == MYSQL_TYPE_LONG) { - current_type = MYSQL_TYPE_LONGLONG; - } + if (current_type == MYSQL_TYPE_LONG) { + current_type = MYSQL_TYPE_LONGLONG; + } #endif - if (Z_TYPE_P(stmt->param_bind[i].zv) != IS_NULL && (current_type == MYSQL_TYPE_LONG || current_type == MYSQL_TYPE_LONGLONG)) { + if (Z_TYPE_P(stmt->param_bind[i].zv) != IS_NULL && (current_type == MYSQL_TYPE_LONG || current_type == MYSQL_TYPE_LONGLONG)) { + /* + 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 + */ + if (Z_TYPE_P(stmt->param_bind[i].zv) != IS_LONG) { + const zval *tmp_data = (copies && copies[i])? copies[i]: stmt->param_bind[i].zv; /* - 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 + 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(stmt->param_bind[i].zv) != IS_LONG) { - zval *tmp_data = (copies && copies[i])? copies[i]: stmt->param_bind[i].zv; + if (Z_TYPE_P(tmp_data) == IS_STRING) { + current_type = MYSQL_TYPE_VAR_STRING; /* - 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. + don't change stmt->param_bind[i].type to MYSQL_TYPE_VAR_STRING + we force convert_to_long_ex in all cases, thus the type will be right in the next switch. + 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. */ - 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 - we force convert_to_long_ex in all cases, thus the type will be right in the next switch. - 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. - */ - } } } - int2store(*p, current_type); - *p+= 2; } + int2store(*p, current_type); + *p+= 2; } - stmt->send_types_to_server = resend_types_next_time; +} +/* }}} */ -/* 2. Store data */ - /* 2.1 Calculate how much space we need */ + +/* {{{ mysqlnd_stmt_execute_calculate_param_values_size */ +static enum_func_status +mysqlnd_stmt_execute_calculate_param_values_size(MYSQLND_STMT_DATA * stmt, zval *** copies_param, size_t * data_size TSRMLS_DC) +{ + unsigned int i; + DBG_ENTER("mysqlnd_stmt_execute_calculate_param_values_size"); for (i = 0; i < stmt->param_count; i++) { unsigned int j; zval *the_var = stmt->param_bind[i].zv; @@ -684,8 +679,8 @@ mysqlnd_stmt_execute_store_params(MYSQLND_STMT * s, zend_uchar **buf, zend_uchar for (j = i + 1; j < stmt->param_count; j++) { if (stmt->param_bind[j].zv == the_var) { /* Double binding of the same zval, make a copy */ - if (!copies || !copies[i]) { - if (PASS != mysqlnd_stmt_copy_it(&copies, the_var, stmt->param_count, i TSRMLS_CC)) { + if (!*copies_param || !(*copies_param)[i]) { + if (PASS != mysqlnd_stmt_copy_it(copies_param, the_var, stmt->param_count, i TSRMLS_CC)) { SET_OOM_ERROR(*stmt->error_info); goto end; } @@ -696,10 +691,10 @@ mysqlnd_stmt_execute_store_params(MYSQLND_STMT * s, zend_uchar **buf, zend_uchar switch (stmt->param_bind[i].type) { case MYSQL_TYPE_DOUBLE: - data_size += 8; + *data_size += 8; if (Z_TYPE_P(the_var) != IS_DOUBLE) { - if (!copies || !copies[i]) { - if (PASS != mysqlnd_stmt_copy_it(&copies, the_var, stmt->param_count, i TSRMLS_CC)) { + if (!*copies_param || !(*copies_param)[i]) { + if (PASS != mysqlnd_stmt_copy_it(copies_param, the_var, stmt->param_count, i TSRMLS_CC)) { SET_OOM_ERROR(*stmt->error_info); goto end; } @@ -708,23 +703,23 @@ mysqlnd_stmt_execute_store_params(MYSQLND_STMT * s, zend_uchar **buf, zend_uchar break; case MYSQL_TYPE_LONGLONG: { - zval *tmp_data = (copies && copies[i])? copies[i]: stmt->param_bind[i].zv; + zval *tmp_data = (*copies_param && (*copies_param)[i])? (*copies_param)[i]: stmt->param_bind[i].zv; if (Z_TYPE_P(tmp_data) == IS_STRING) { goto use_string; } convert_to_long_ex(&tmp_data); } - data_size += 8; + *data_size += 8; break; case MYSQL_TYPE_LONG: { - zval *tmp_data = (copies && copies[i])? copies[i]: stmt->param_bind[i].zv; + zval *tmp_data = (*copies_param && (*copies_param)[i])? (*copies_param)[i]: stmt->param_bind[i].zv; if (Z_TYPE_P(tmp_data) == IS_STRING) { goto use_string; } convert_to_long_ex(&tmp_data); } - data_size += 4; + *data_size += 4; break; case MYSQL_TYPE_LONG_BLOB: if (!(stmt->param_bind[i].flags & MYSQLND_PARAM_BIND_BLOB_USED)) { @@ -733,58 +728,43 @@ mysqlnd_stmt_execute_store_params(MYSQLND_STMT * s, zend_uchar **buf, zend_uchar Empty string has length of 0, encoded in 1 byte. No real data will follows after it. */ - data_size++; + (*data_size)++; } break; case MYSQL_TYPE_VAR_STRING: use_string: - data_size += 8; /* max 8 bytes for size */ + *data_size += 8; /* max 8 bytes for size */ if (Z_TYPE_P(the_var) != IS_STRING) { - if (!copies || !copies[i]) { - if (PASS != mysqlnd_stmt_copy_it(&copies, the_var, stmt->param_count, i TSRMLS_CC)) { + if (!*copies_param || !(*copies_param)[i]) { + if (PASS != mysqlnd_stmt_copy_it(copies_param, the_var, stmt->param_count, i TSRMLS_CC)) { SET_OOM_ERROR(*stmt->error_info); goto end; } } - the_var = copies[i]; + the_var = (*copies_param)[i]; } convert_to_string_ex(&the_var); - data_size += Z_STRLEN_P(the_var); + *data_size += Z_STRLEN_P(the_var); break; } } + DBG_RETURN(PASS); +end: + DBG_RETURN(FAIL); +} +/* }}} */ - /* 2.2 Enlarge the buffer, if needed */ - left = (*buf_len - (*p - *buf)); - if (left < data_size) { - unsigned int offset = *p - *buf; - zend_uchar *tmp_buf; - *buf_len = offset + data_size + 10; /* Allocate + 10 for safety */ - tmp_buf = mnd_emalloc(*buf_len); - if (!tmp_buf) { - SET_OOM_ERROR(*stmt->error_info); - goto end; - } - memcpy(tmp_buf, *buf, offset); - /* - When too many columns the buffer provided to the function might not be sufficient. - In this case new buffer has been allocated above. When we allocate a buffer and then - allocate a bigger one here, we should free the first one. - */ - if (*buf != provided_buffer) { - mnd_efree(*buf); - } - *buf = tmp_buf; - /* Update our pos pointer */ - *p = *buf + offset; - } - /* 2.3 Store the actual data */ +/* {{{ mysqlnd_stmt_execute_store_param_values */ +static void +mysqlnd_stmt_execute_store_param_values(MYSQLND_STMT_DATA * stmt, zval ** copies, zend_uchar * buf, zend_uchar ** p, size_t null_byte_offset) +{ + unsigned int i; for (i = 0; i < stmt->param_count; i++) { - zval *data = (copies && copies[i])? copies[i]: stmt->param_bind[i].zv; + zval * data = (copies && copies[i])? copies[i]: stmt->param_bind[i].zv; /* Handle long data */ if (stmt->param_bind[i].zv && Z_TYPE_P(data) == IS_NULL) { - (*buf + null_byte_offset)[i/8] |= (zend_uchar) (1 << (i & 7)); + (buf + null_byte_offset)[i/8] |= (zend_uchar) (1 << (i & 7)); } else { switch (stmt->param_bind[i].type) { case MYSQL_TYPE_DOUBLE: @@ -819,7 +799,7 @@ use_string: case MYSQL_TYPE_VAR_STRING: send_string: { - unsigned int len = Z_STRLEN_P(data); + size_t len = Z_STRLEN_P(data); /* to is after p. The latter hasn't been moved */ *p = php_mysqlnd_net_store_length(*p, len); memcpy(*p, Z_STRVAL_P(data), len); @@ -828,22 +808,86 @@ send_string: break; default: /* Won't happen, but set to NULL */ - (*buf + null_byte_offset)[i/8] |= (zend_uchar) (1 << (i & 7)); + (buf + null_byte_offset)[i/8] |= (zend_uchar) (1 << (i & 7)); break; } } } - ret = PASS; -end: - if (copies) { - for (i = 0; i < stmt->param_count; i++) { - if (copies[i]) { - zval_ptr_dtor(&copies[i]); - } +} +/* }}} */ + + +/* {{{ mysqlnd_stmt_execute_store_params */ +static enum_func_status +mysqlnd_stmt_execute_store_params(MYSQLND_STMT * s, zend_uchar **buf, zend_uchar **p, size_t *buf_len TSRMLS_DC) +{ + MYSQLND_STMT_DATA * stmt = s->data; + unsigned int i = 0; + zend_uchar * provided_buffer = *buf; + size_t data_size = 0; + zval **copies = NULL;/* if there are different types */ + enum_func_status ret = FAIL; + int resend_types_next_time = 0; + size_t null_byte_offset; + + DBG_ENTER("mysqlnd_stmt_execute_store_params"); + + { + unsigned int null_count = (stmt->param_count + 7) / 8; + if (FAIL == mysqlnd_stmt_execute_check_n_enlarge_buffer(buf, p, buf_len, provided_buffer, null_count TSRMLS_CC)) { + SET_OOM_ERROR(*stmt->error_info); + goto end; } - mnd_efree(copies); + /* put `null` bytes */ + null_byte_offset = *p - *buf; + memset(*p, 0, null_count); + *p += null_count; + } + +/* 1. Store type information */ + /* + check if need to send the types even if stmt->send_types_to_server is 0. This is because + if we send "i" (42) then the type will be int and the server will expect int. However, if next + time we try to send > LONG_MAX, the conversion to string will send a string and the server + won't expect it and interpret the value as 0. Thus we need to resend the types, if any such values + occur, and force resend for the next execution. + */ + if (FAIL == mysqlnd_stmt_execute_prepare_param_types(stmt, &copies, &resend_types_next_time TSRMLS_CC)) { + goto end; + } + + int1store(*p, stmt->send_types_to_server); + (*p)++; + + if (stmt->send_types_to_server) { + if (FAIL == mysqlnd_stmt_execute_check_n_enlarge_buffer(buf, p, buf_len, provided_buffer, stmt->param_count * 2 TSRMLS_CC)) { + SET_OOM_ERROR(*stmt->error_info); + goto end; + } + mysqlnd_stmt_execute_store_types(stmt, copies, p); } + stmt->send_types_to_server = resend_types_next_time; + +/* 2. Store data */ + /* 2.1 Calculate how much space we need */ + if (FAIL == mysqlnd_stmt_execute_calculate_param_values_size(stmt, &copies, &data_size TSRMLS_CC)) { + goto end; + } + + /* 2.2 Enlarge the buffer, if needed */ + if (FAIL == mysqlnd_stmt_execute_check_n_enlarge_buffer(buf, p, buf_len, provided_buffer, data_size TSRMLS_CC)) { + SET_OOM_ERROR(*stmt->error_info); + goto end; + } + + /* 2.3 Store the actual data */ + mysqlnd_stmt_execute_store_param_values(stmt, copies, *buf, p, null_byte_offset); + + ret = PASS; +end: + mysqlnd_stmt_free_copies(stmt, copies TSRMLS_CC); + DBG_INF_FMT("ret=%s", ret == PASS? "PASS":"FAIL"); DBG_RETURN(ret); } -- cgit v1.2.1 From cd2cc7b8f95aee903e13c8aefc5f78d2e57a53ba Mon Sep 17 00:00:00 2001 From: Andrey Hristov Date: Fri, 24 Jan 2014 11:52:35 +0200 Subject: Reduce code duplication a bit --- ext/mysqlnd/mysqlnd_ps_codec.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) (limited to 'ext/mysqlnd/mysqlnd_ps_codec.c') diff --git a/ext/mysqlnd/mysqlnd_ps_codec.c b/ext/mysqlnd/mysqlnd_ps_codec.c index 724feea07f..e890c2b473 100644 --- a/ext/mysqlnd/mysqlnd_ps_codec.c +++ b/ext/mysqlnd/mysqlnd_ps_codec.c @@ -670,6 +670,7 @@ mysqlnd_stmt_execute_calculate_param_values_size(MYSQLND_STMT_DATA * stmt, zval unsigned int i; DBG_ENTER("mysqlnd_stmt_execute_calculate_param_values_size"); for (i = 0; i < stmt->param_count; i++) { + unsigned short is_longlong = 0; unsigned int j; zval *the_var = stmt->param_bind[i].zv; @@ -702,15 +703,8 @@ mysqlnd_stmt_execute_calculate_param_values_size(MYSQLND_STMT_DATA * stmt, zval } break; case MYSQL_TYPE_LONGLONG: - { - zval *tmp_data = (*copies_param && (*copies_param)[i])? (*copies_param)[i]: stmt->param_bind[i].zv; - if (Z_TYPE_P(tmp_data) == IS_STRING) { - goto use_string; - } - convert_to_long_ex(&tmp_data); - } - *data_size += 8; - break; + is_longlong = 4; + /* fall-through */ case MYSQL_TYPE_LONG: { zval *tmp_data = (*copies_param && (*copies_param)[i])? (*copies_param)[i]: stmt->param_bind[i].zv; @@ -719,7 +713,7 @@ mysqlnd_stmt_execute_calculate_param_values_size(MYSQLND_STMT_DATA * stmt, zval } convert_to_long_ex(&tmp_data); } - *data_size += 4; + *data_size += 4 + is_longlong; break; case MYSQL_TYPE_LONG_BLOB: if (!(stmt->param_bind[i].flags & MYSQLND_PARAM_BIND_BLOB_USED)) { -- cgit v1.2.1 From 350b5dddacb03f4f8e0c1f9094dbaa40a180ef92 Mon Sep 17 00:00:00 2001 From: Andrey Hristov Date: Fri, 24 Jan 2014 12:31:19 +0200 Subject: WS --- ext/mysqlnd/mysqlnd_ps_codec.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'ext/mysqlnd/mysqlnd_ps_codec.c') diff --git a/ext/mysqlnd/mysqlnd_ps_codec.c b/ext/mysqlnd/mysqlnd_ps_codec.c index e890c2b473..d96a57721c 100644 --- a/ext/mysqlnd/mysqlnd_ps_codec.c +++ b/ext/mysqlnd/mysqlnd_ps_codec.c @@ -686,7 +686,7 @@ mysqlnd_stmt_execute_calculate_param_values_size(MYSQLND_STMT_DATA * stmt, zval goto end; } } - break; + break; } } @@ -830,7 +830,7 @@ mysqlnd_stmt_execute_store_params(MYSQLND_STMT * s, zend_uchar **buf, zend_uchar unsigned int null_count = (stmt->param_count + 7) / 8; if (FAIL == mysqlnd_stmt_execute_check_n_enlarge_buffer(buf, p, buf_len, provided_buffer, null_count TSRMLS_CC)) { SET_OOM_ERROR(*stmt->error_info); - goto end; + goto end; } /* put `null` bytes */ null_byte_offset = *p - *buf; @@ -850,13 +850,13 @@ mysqlnd_stmt_execute_store_params(MYSQLND_STMT * s, zend_uchar **buf, zend_uchar goto end; } - int1store(*p, stmt->send_types_to_server); + int1store(*p, stmt->send_types_to_server); (*p)++; if (stmt->send_types_to_server) { if (FAIL == mysqlnd_stmt_execute_check_n_enlarge_buffer(buf, p, buf_len, provided_buffer, stmt->param_count * 2 TSRMLS_CC)) { SET_OOM_ERROR(*stmt->error_info); - goto end; + goto end; } mysqlnd_stmt_execute_store_types(stmt, copies, p); } @@ -872,7 +872,7 @@ mysqlnd_stmt_execute_store_params(MYSQLND_STMT * s, zend_uchar **buf, zend_uchar /* 2.2 Enlarge the buffer, if needed */ if (FAIL == mysqlnd_stmt_execute_check_n_enlarge_buffer(buf, p, buf_len, provided_buffer, data_size TSRMLS_CC)) { SET_OOM_ERROR(*stmt->error_info); - goto end; + goto end; } /* 2.3 Store the actual data */ -- cgit v1.2.1 From 6288bb8ffefe9cf9648b8d2190729c087b5c2586 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Tue, 17 Jun 2014 17:50:54 +0800 Subject: Refactoring mysqlnd (incompleted, only mysqlnd ext compilable) --- ext/mysqlnd/mysqlnd_ps_codec.c | 93 +++++++++++++++++++----------------------- 1 file changed, 42 insertions(+), 51 deletions(-) (limited to 'ext/mysqlnd/mysqlnd_ps_codec.c') diff --git a/ext/mysqlnd/mysqlnd_ps_codec.c b/ext/mysqlnd/mysqlnd_ps_codec.c index d96a57721c..13b44d10a9 100644 --- a/ext/mysqlnd/mysqlnd_ps_codec.c +++ b/ext/mysqlnd/mysqlnd_ps_codec.c @@ -117,7 +117,7 @@ ps_fetch_from_1_to_8_bytes(zval * zv, const MYSQLND_FIELD * const field, unsigne } if (tmp_len) { - ZVAL_STRINGL(zv, tmp, tmp_len, 1); + ZVAL_STRINGL(zv, tmp, tmp_len); } (*row)+= byte_count; DBG_VOID_RETURN; @@ -236,7 +236,7 @@ ps_fetch_time(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_le length = mnd_sprintf(&value, 0, "%s%02u:%02u:%02u", (t.neg ? "-" : ""), t.hour, t.minute, t.second); DBG_INF_FMT("%s", value); - ZVAL_STRINGL(zv, value, length, 1); + ZVAL_STRINGL(zv, value, length); mnd_sprintf_free(value); DBG_VOID_RETURN; } @@ -273,7 +273,7 @@ ps_fetch_date(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_le length = mnd_sprintf(&value, 0, "%04u-%02u-%02u", t.year, t.month, t.day); DBG_INF_FMT("%s", value); - ZVAL_STRINGL(zv, value, length, 1); + ZVAL_STRINGL(zv, value, length); mnd_sprintf_free(value); DBG_VOID_RETURN; } @@ -317,7 +317,7 @@ ps_fetch_datetime(zval * zv, const MYSQLND_FIELD * const field, unsigned int pac length = mnd_sprintf(&value, 0, "%04u-%02u-%02u %02u:%02u:%02u", t.year, t.month, t.day, t.hour, t.minute, t.second); DBG_INF_FMT("%s", value); - ZVAL_STRINGL(zv, value, length, 1); + ZVAL_STRINGL(zv, value, length); mnd_sprintf_free(value); DBG_VOID_RETURN; } @@ -336,7 +336,7 @@ ps_fetch_string(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_ DBG_ENTER("ps_fetch_string"); DBG_INF_FMT("len = %lu", length); DBG_INF("copying from the row buffer"); - ZVAL_STRINGL(zv, (char *)*row, length, 1); + ZVAL_STRINGL(zv, (char *)*row, length); (*row) += length; DBG_VOID_RETURN; @@ -499,16 +499,15 @@ void _mysqlnd_init_ps_fetch_subsystem() /* {{{ mysqlnd_stmt_copy_it */ static enum_func_status -mysqlnd_stmt_copy_it(zval *** copies, zval * original, unsigned int param_count, unsigned int current TSRMLS_DC) +mysqlnd_stmt_copy_it(zval ** copies, zval * original, unsigned int param_count, unsigned int current TSRMLS_DC) { if (!*copies) { - *copies = mnd_ecalloc(param_count, sizeof(zval *)); + *copies = mnd_ecalloc(param_count, sizeof(zval)); } if (*copies) { - MAKE_STD_ZVAL((*copies)[current]); - *(*copies)[current] = *original; - Z_SET_REFCOUNT_P((*copies)[current], 1); - zval_copy_ctor((*copies)[current]); + ZVAL_COPY(&(*copies)[current], original); + //????Z_SET_REFCOUNT_P((*copies)[current], 1); + //zval_copy_ctor((*copies)[current]); return PASS; } return FAIL; @@ -518,14 +517,12 @@ mysqlnd_stmt_copy_it(zval *** copies, zval * original, unsigned int param_count, /* {{{ mysqlnd_stmt_free_copies */ static void -mysqlnd_stmt_free_copies(MYSQLND_STMT_DATA * stmt, zval ** copies TSRMLS_DC) +mysqlnd_stmt_free_copies(MYSQLND_STMT_DATA * stmt, zval *copies TSRMLS_DC) { if (copies) { unsigned int i; for (i = 0; i < stmt->param_count; i++) { - if (copies[i]) { - zval_ptr_dtor(&copies[i]); - } + zval_ptr_dtor(&copies[i]); } mnd_efree(copies); } @@ -563,39 +560,34 @@ mysqlnd_stmt_execute_check_n_enlarge_buffer(zend_uchar **buf, zend_uchar **p, si /* {{{ mysqlnd_stmt_execute_prepare_param_types */ static enum_func_status -mysqlnd_stmt_execute_prepare_param_types(MYSQLND_STMT_DATA * stmt, zval *** copies_param, int * resend_types_next_time TSRMLS_DC) +mysqlnd_stmt_execute_prepare_param_types(MYSQLND_STMT_DATA * stmt, zval ** copies_param, int * resend_types_next_time TSRMLS_DC) { unsigned int i; DBG_ENTER("mysqlnd_stmt_execute_prepare_param_types"); for (i = 0; i < stmt->param_count; i++) { 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)) { - zval ** copies; + if (Z_TYPE(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_param, stmt->param_bind[i].zv, stmt->param_count, i TSRMLS_CC)) + if (Z_TYPE(stmt->param_bind[i].zv) != IS_LONG && + PASS != mysqlnd_stmt_copy_it(copies_param, &stmt->param_bind[i].zv, stmt->param_count, i TSRMLS_CC)) { SET_OOM_ERROR(*stmt->error_info); goto end; } - copies = *copies_param; /* 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 */ - if (Z_TYPE_P(stmt->param_bind[i].zv) != IS_LONG) { - zval *tmp_data = (copies && copies[i])? copies[i]: stmt->param_bind[i].zv; + if (Z_TYPE(stmt->param_bind[i].zv) != IS_LONG) { + zval *tmp_data = (*copies_param && !Z_ISUNDEF((*copies_param)[i]))? &(*copies_param)[i]: &stmt->param_bind[i].zv; /* 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); + zval tmp_data_copy; + ZVAL_COPY(&tmp_data_copy, tmp_data); convert_to_double_ex(&tmp_data_copy); /* @@ -603,11 +595,11 @@ mysqlnd_stmt_execute_prepare_param_types(MYSQLND_STMT_DATA * stmt, zval *** copi 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) { + if (Z_DVAL(tmp_data_copy) > LONG_MAX || Z_DVAL(tmp_data_copy) < LONG_MIN) { stmt->send_types_to_server = *resend_types_next_time = 1; - convert_to_string_ex(&tmp_data); + convert_to_string_ex(tmp_data); } else { - convert_to_long_ex(&tmp_data); + convert_to_long_ex(tmp_data); } zval_ptr_dtor(&tmp_data_copy); @@ -623,7 +615,7 @@ end: /* {{{ mysqlnd_stmt_execute_store_types */ static void -mysqlnd_stmt_execute_store_types(MYSQLND_STMT_DATA * stmt, zval ** copies, zend_uchar ** p) +mysqlnd_stmt_execute_store_types(MYSQLND_STMT_DATA * stmt, zval * copies, zend_uchar ** p) { unsigned int i; for (i = 0; i < stmt->param_count; i++) { @@ -634,13 +626,13 @@ mysqlnd_stmt_execute_store_types(MYSQLND_STMT_DATA * stmt, zval ** copies, zend_ current_type = MYSQL_TYPE_LONGLONG; } #endif - if (Z_TYPE_P(stmt->param_bind[i].zv) != IS_NULL && (current_type == MYSQL_TYPE_LONG || current_type == MYSQL_TYPE_LONGLONG)) { + if (!Z_ISNULL(stmt->param_bind[i].zv) && (current_type == MYSQL_TYPE_LONG || current_type == MYSQL_TYPE_LONGLONG)) { /* 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 */ - if (Z_TYPE_P(stmt->param_bind[i].zv) != IS_LONG) { - const zval *tmp_data = (copies && copies[i])? copies[i]: stmt->param_bind[i].zv; + if (Z_TYPE(stmt->param_bind[i].zv) != IS_LONG) { + const zval *tmp_data = (copies && !Z_ISUNDEF(copies[i]))? &copies[i]: &stmt->param_bind[i].zv; /* 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. @@ -665,22 +657,22 @@ mysqlnd_stmt_execute_store_types(MYSQLND_STMT_DATA * stmt, zval ** copies, zend_ /* {{{ mysqlnd_stmt_execute_calculate_param_values_size */ static enum_func_status -mysqlnd_stmt_execute_calculate_param_values_size(MYSQLND_STMT_DATA * stmt, zval *** copies_param, size_t * data_size TSRMLS_DC) +mysqlnd_stmt_execute_calculate_param_values_size(MYSQLND_STMT_DATA * stmt, zval ** copies_param, size_t * data_size TSRMLS_DC) { unsigned int i; DBG_ENTER("mysqlnd_stmt_execute_calculate_param_values_size"); for (i = 0; i < stmt->param_count; i++) { unsigned short is_longlong = 0; unsigned int j; - zval *the_var = stmt->param_bind[i].zv; + zval *the_var = &stmt->param_bind[i].zv; if (!the_var || (stmt->param_bind[i].type != MYSQL_TYPE_LONG_BLOB && Z_TYPE_P(the_var) == IS_NULL)) { continue; } for (j = i + 1; j < stmt->param_count; j++) { - if (stmt->param_bind[j].zv == the_var) { + if (&stmt->param_bind[j].zv == the_var) { /* Double binding of the same zval, make a copy */ - if (!*copies_param || !(*copies_param)[i]) { + if (!*copies_param || Z_ISUNDEF((*copies_param)[i])) { if (PASS != mysqlnd_stmt_copy_it(copies_param, the_var, stmt->param_count, i TSRMLS_CC)) { SET_OOM_ERROR(*stmt->error_info); goto end; @@ -694,7 +686,7 @@ mysqlnd_stmt_execute_calculate_param_values_size(MYSQLND_STMT_DATA * stmt, zval case MYSQL_TYPE_DOUBLE: *data_size += 8; if (Z_TYPE_P(the_var) != IS_DOUBLE) { - if (!*copies_param || !(*copies_param)[i]) { + if (!*copies_param || Z_ISUNDEF((*copies_param)[i])) { if (PASS != mysqlnd_stmt_copy_it(copies_param, the_var, stmt->param_count, i TSRMLS_CC)) { SET_OOM_ERROR(*stmt->error_info); goto end; @@ -707,11 +699,11 @@ mysqlnd_stmt_execute_calculate_param_values_size(MYSQLND_STMT_DATA * stmt, zval /* fall-through */ case MYSQL_TYPE_LONG: { - zval *tmp_data = (*copies_param && (*copies_param)[i])? (*copies_param)[i]: stmt->param_bind[i].zv; + zval *tmp_data = (*copies_param && !Z_ISUNDEF((*copies_param)[i]))? &(*copies_param)[i]: &stmt->param_bind[i].zv; if (Z_TYPE_P(tmp_data) == IS_STRING) { goto use_string; } - convert_to_long_ex(&tmp_data); + convert_to_long_ex(tmp_data); } *data_size += 4 + is_longlong; break; @@ -729,15 +721,15 @@ mysqlnd_stmt_execute_calculate_param_values_size(MYSQLND_STMT_DATA * stmt, zval use_string: *data_size += 8; /* max 8 bytes for size */ if (Z_TYPE_P(the_var) != IS_STRING) { - if (!*copies_param || !(*copies_param)[i]) { + if (!*copies_param || Z_ISUNDEF((*copies_param)[i])) { if (PASS != mysqlnd_stmt_copy_it(copies_param, the_var, stmt->param_count, i TSRMLS_CC)) { SET_OOM_ERROR(*stmt->error_info); goto end; } } - the_var = (*copies_param)[i]; + the_var = &((*copies_param)[i]); } - convert_to_string_ex(&the_var); + convert_to_string_ex(the_var); *data_size += Z_STRLEN_P(the_var); break; } @@ -751,18 +743,18 @@ end: /* {{{ mysqlnd_stmt_execute_store_param_values */ static void -mysqlnd_stmt_execute_store_param_values(MYSQLND_STMT_DATA * stmt, zval ** copies, zend_uchar * buf, zend_uchar ** p, size_t null_byte_offset) +mysqlnd_stmt_execute_store_param_values(MYSQLND_STMT_DATA * stmt, zval * copies, zend_uchar * buf, zend_uchar ** p, size_t null_byte_offset) { unsigned int i; for (i = 0; i < stmt->param_count; i++) { - zval * data = (copies && copies[i])? copies[i]: stmt->param_bind[i].zv; + zval * data = (copies && !Z_ISUNDEF(copies[i]))? &copies[i]: &stmt->param_bind[i].zv; /* Handle long data */ - if (stmt->param_bind[i].zv && Z_TYPE_P(data) == IS_NULL) { + if (!Z_ISUNDEF(stmt->param_bind[i].zv) && Z_TYPE_P(data) == IS_NULL) { (buf + null_byte_offset)[i/8] |= (zend_uchar) (1 << (i & 7)); } else { switch (stmt->param_bind[i].type) { case MYSQL_TYPE_DOUBLE: - convert_to_double_ex(&data); + convert_to_double_ex(data); float8store(*p, Z_DVAL_P(data)); (*p) += 8; break; @@ -816,10 +808,9 @@ static enum_func_status mysqlnd_stmt_execute_store_params(MYSQLND_STMT * s, zend_uchar **buf, zend_uchar **p, size_t *buf_len TSRMLS_DC) { MYSQLND_STMT_DATA * stmt = s->data; - unsigned int i = 0; zend_uchar * provided_buffer = *buf; size_t data_size = 0; - zval **copies = NULL;/* if there are different types */ + zval *copies = NULL;/* if there are different types */ enum_func_status ret = FAIL; int resend_types_next_time = 0; size_t null_byte_offset; -- cgit v1.2.1 From 049e52f19b5854d6b9bce8ada3c3cb1a1bd01d56 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Thu, 19 Jun 2014 14:24:49 +0800 Subject: Fixed various bugs --- ext/mysqlnd/mysqlnd_ps_codec.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'ext/mysqlnd/mysqlnd_ps_codec.c') diff --git a/ext/mysqlnd/mysqlnd_ps_codec.c b/ext/mysqlnd/mysqlnd_ps_codec.c index 13b44d10a9..234cec4fb7 100644 --- a/ext/mysqlnd/mysqlnd_ps_codec.c +++ b/ext/mysqlnd/mysqlnd_ps_codec.c @@ -505,6 +505,7 @@ mysqlnd_stmt_copy_it(zval ** copies, zval * original, unsigned int param_count, *copies = mnd_ecalloc(param_count, sizeof(zval)); } if (*copies) { + ZVAL_DEREF(original); ZVAL_COPY(&(*copies)[current], original); //????Z_SET_REFCOUNT_P((*copies)[current], 1); //zval_copy_ctor((*copies)[current]); @@ -587,6 +588,7 @@ mysqlnd_stmt_execute_prepare_param_types(MYSQLND_STMT_DATA * stmt, zval ** copie value is too big for a long. As said, precision could be lost. */ zval tmp_data_copy; + ZVAL_DEREF(tmp_data); ZVAL_COPY(&tmp_data_copy, tmp_data); convert_to_double_ex(&tmp_data_copy); -- cgit v1.2.1 From d8a4b1affb00298036cbadbaadc2067330488b41 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Thu, 19 Jun 2014 22:28:43 +0800 Subject: Fixed paramters binding --- ext/mysqlnd/mysqlnd_ps_codec.c | 56 +++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 23 deletions(-) (limited to 'ext/mysqlnd/mysqlnd_ps_codec.c') diff --git a/ext/mysqlnd/mysqlnd_ps_codec.c b/ext/mysqlnd/mysqlnd_ps_codec.c index 234cec4fb7..5d860f254d 100644 --- a/ext/mysqlnd/mysqlnd_ps_codec.c +++ b/ext/mysqlnd/mysqlnd_ps_codec.c @@ -505,7 +505,6 @@ mysqlnd_stmt_copy_it(zval ** copies, zval * original, unsigned int param_count, *copies = mnd_ecalloc(param_count, sizeof(zval)); } if (*copies) { - ZVAL_DEREF(original); ZVAL_COPY(&(*copies)[current], original); //????Z_SET_REFCOUNT_P((*copies)[current], 1); //zval_copy_ctor((*copies)[current]); @@ -567,11 +566,13 @@ mysqlnd_stmt_execute_prepare_param_types(MYSQLND_STMT_DATA * stmt, zval ** copie DBG_ENTER("mysqlnd_stmt_execute_prepare_param_types"); for (i = 0; i < stmt->param_count; i++) { short current_type = stmt->param_bind[i].type; + zval *parameter = &stmt->param_bind[i].zv; - if (Z_TYPE(stmt->param_bind[i].zv) != IS_NULL && (current_type == MYSQL_TYPE_LONG || current_type == MYSQL_TYPE_LONGLONG)) { + ZVAL_DEREF(parameter); + if (!Z_ISNULL_P(parameter) && (current_type == MYSQL_TYPE_LONG || current_type == MYSQL_TYPE_LONGLONG)) { /* always copy the var, because we do many conversions */ - if (Z_TYPE(stmt->param_bind[i].zv) != IS_LONG && - PASS != mysqlnd_stmt_copy_it(copies_param, &stmt->param_bind[i].zv, stmt->param_count, i TSRMLS_CC)) + if (Z_TYPE_P(parameter) != IS_LONG && + PASS != mysqlnd_stmt_copy_it(copies_param, parameter, stmt->param_count, i TSRMLS_CC)) { SET_OOM_ERROR(*stmt->error_info); goto end; @@ -580,15 +581,14 @@ mysqlnd_stmt_execute_prepare_param_types(MYSQLND_STMT_DATA * stmt, zval ** copie 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 */ - if (Z_TYPE(stmt->param_bind[i].zv) != IS_LONG) { - zval *tmp_data = (*copies_param && !Z_ISUNDEF((*copies_param)[i]))? &(*copies_param)[i]: &stmt->param_bind[i].zv; + if (Z_TYPE_P(parameter) != IS_LONG) { + zval *tmp_data = (*copies_param && !Z_ISUNDEF((*copies_param)[i]))? &(*copies_param)[i]: parameter; /* 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; - ZVAL_DEREF(tmp_data); ZVAL_COPY(&tmp_data_copy, tmp_data); convert_to_double_ex(&tmp_data_copy); @@ -622,19 +622,21 @@ mysqlnd_stmt_execute_store_types(MYSQLND_STMT_DATA * stmt, zval * copies, zend_u unsigned int i; for (i = 0; i < stmt->param_count; i++) { short current_type = stmt->param_bind[i].type; + zval *parameter = &stmt->param_bind[i].zv; /* our types are not unsigned */ #if SIZEOF_LONG==8 if (current_type == MYSQL_TYPE_LONG) { current_type = MYSQL_TYPE_LONGLONG; } #endif - if (!Z_ISNULL(stmt->param_bind[i].zv) && (current_type == MYSQL_TYPE_LONG || current_type == MYSQL_TYPE_LONGLONG)) { + ZVAL_DEREF(parameter); + if (!Z_ISNULL_P(parameter) && (current_type == MYSQL_TYPE_LONG || current_type == MYSQL_TYPE_LONGLONG)) { /* 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 */ - if (Z_TYPE(stmt->param_bind[i].zv) != IS_LONG) { - const zval *tmp_data = (copies && !Z_ISUNDEF(copies[i]))? &copies[i]: &stmt->param_bind[i].zv; + if (Z_TYPE_P(parameter) != IS_LONG) { + const zval *tmp_data = (copies && !Z_ISUNDEF(copies[i]))? &copies[i] : parameter; /* 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. @@ -666,21 +668,26 @@ mysqlnd_stmt_execute_calculate_param_values_size(MYSQLND_STMT_DATA * stmt, zval for (i = 0; i < stmt->param_count; i++) { unsigned short is_longlong = 0; unsigned int j; - zval *the_var = &stmt->param_bind[i].zv; + zval *bind_var, *the_var = &stmt->param_bind[i].zv; - if (!the_var || (stmt->param_bind[i].type != MYSQL_TYPE_LONG_BLOB && Z_TYPE_P(the_var) == IS_NULL)) { + bind_var = the_var; + ZVAL_DEREF(the_var); + if ((stmt->param_bind[i].type != MYSQL_TYPE_LONG_BLOB && Z_TYPE_P(the_var) == IS_NULL)) { continue; } - for (j = i + 1; j < stmt->param_count; j++) { - if (&stmt->param_bind[j].zv == the_var) { - /* Double binding of the same zval, make a copy */ - if (!*copies_param || Z_ISUNDEF((*copies_param)[i])) { - if (PASS != mysqlnd_stmt_copy_it(copies_param, the_var, stmt->param_count, i TSRMLS_CC)) { - SET_OOM_ERROR(*stmt->error_info); - goto end; + + if (Z_ISREF_P(bind_var)) { + for (j = i + 1; j < stmt->param_count; j++) { + if (Z_ISREF(stmt->param_bind[j].zv) && Z_REFVAL(stmt->param_bind[j].zv) == the_var) { + /* Double binding of the same zval, make a copy */ + if (!*copies_param || Z_ISUNDEF((*copies_param)[i])) { + if (PASS != mysqlnd_stmt_copy_it(copies_param, the_var, stmt->param_count, i TSRMLS_CC)) { + SET_OOM_ERROR(*stmt->error_info); + goto end; + } } + break; } - break; } } @@ -701,7 +708,7 @@ mysqlnd_stmt_execute_calculate_param_values_size(MYSQLND_STMT_DATA * stmt, zval /* fall-through */ case MYSQL_TYPE_LONG: { - zval *tmp_data = (*copies_param && !Z_ISUNDEF((*copies_param)[i]))? &(*copies_param)[i]: &stmt->param_bind[i].zv; + zval *tmp_data = (*copies_param && !Z_ISUNDEF((*copies_param)[i]))? &(*copies_param)[i]: the_var; if (Z_TYPE_P(tmp_data) == IS_STRING) { goto use_string; } @@ -749,9 +756,12 @@ mysqlnd_stmt_execute_store_param_values(MYSQLND_STMT_DATA * stmt, zval * copies, { unsigned int i; for (i = 0; i < stmt->param_count; i++) { - zval * data = (copies && !Z_ISUNDEF(copies[i]))? &copies[i]: &stmt->param_bind[i].zv; + zval *data, *parameter = &stmt->param_bind[i].zv; + + ZVAL_DEREF(parameter); + data = (copies && !Z_ISUNDEF(copies[i]))? &copies[i]: parameter; /* Handle long data */ - if (!Z_ISUNDEF(stmt->param_bind[i].zv) && Z_TYPE_P(data) == IS_NULL) { + if (!Z_ISUNDEF_P(parameter) && Z_TYPE_P(data) == IS_NULL) { (buf + null_byte_offset)[i/8] |= (zend_uchar) (1 << (i & 7)); } else { switch (stmt->param_bind[i].type) { -- cgit v1.2.1 From 587923ccc837fc22901f3114631bcc3b1b384fcd Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Mon, 23 Jun 2014 23:01:35 +0800 Subject: Cleanup (refactoring is finish) --- ext/mysqlnd/mysqlnd_ps_codec.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'ext/mysqlnd/mysqlnd_ps_codec.c') diff --git a/ext/mysqlnd/mysqlnd_ps_codec.c b/ext/mysqlnd/mysqlnd_ps_codec.c index 5d860f254d..e80aa5565e 100644 --- a/ext/mysqlnd/mysqlnd_ps_codec.c +++ b/ext/mysqlnd/mysqlnd_ps_codec.c @@ -506,8 +506,6 @@ mysqlnd_stmt_copy_it(zval ** copies, zval * original, unsigned int param_count, } if (*copies) { ZVAL_COPY(&(*copies)[current], original); - //????Z_SET_REFCOUNT_P((*copies)[current], 1); - //zval_copy_ctor((*copies)[current]); return PASS; } return FAIL; -- cgit v1.2.1 From c044164a96553668cc6c4ae1eb32f18219308851 Mon Sep 17 00:00:00 2001 From: Keyur Govande Date: Thu, 14 Aug 2014 18:19:56 +0000 Subject: Patch for bug #67839 (mysqli does not handle 4-byte floats correctly) Before the patch, a value of 9.99 in a FLOAT column came out of mysqli as 9.9998998641968. This is because it would naively cast a 4-byte float into PHP's internal 8-byte double. To fix this, with GCC we use the built-in decimal support to "up-convert" the 4-byte float to a 8-byte double. When that is not available, we fall back to converting the float to a string and then converting the string to a double. This mimics what MySQL does. --- ext/mysqlnd/mysqlnd_ps_codec.c | 49 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 45 insertions(+), 4 deletions(-) (limited to 'ext/mysqlnd/mysqlnd_ps_codec.c') diff --git a/ext/mysqlnd/mysqlnd_ps_codec.c b/ext/mysqlnd/mysqlnd_ps_codec.c index e2640c775b..3f7d31002f 100644 --- a/ext/mysqlnd/mysqlnd_ps_codec.c +++ b/ext/mysqlnd/mysqlnd_ps_codec.c @@ -195,12 +195,53 @@ void ps_fetch_float(zval *zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar **row, zend_bool as_unicode TSRMLS_DC) { - float value; + float fval; + double dval; DBG_ENTER("ps_fetch_float"); - float4get(value, *row); - ZVAL_DOUBLE(zv, value); + float4get(fval, *row); (*row)+= 4; - DBG_INF_FMT("value=%f", value); + DBG_INF_FMT("value=%f", fval); + + /* + * The following is needed to correctly support 4-byte floats. + * Otherwise, a value of 9.99 in a FLOAT column comes out of mysqli + * as 9.9998998641968. + * + * For GCC, we use the built-in decimal support to "up-convert" a + * 4-byte float to a 8-byte double. + * When that is not available, we fall back to converting the float + * to a string and then converting the string to a double. This mimics + * what MySQL does. + */ +#ifdef HAVE_DECIMAL_FP_SUPPORT + { + typedef float dec32 __attribute__((mode(SD))); + dec32 d32val = fval; + + /* The following cast is guaranteed to do the right thing */ + dval = (double) d32val; + } +#else + { + char num_buf[2048]; /* Over allocated */ + char *s; + + /* Convert to string. Ignoring localization, etc. + * Following MySQL's rules. If precision is undefined (NOT_FIXED_DEC i.e. 31) + * or larger than 31, the value is limited to 6 (FLT_DIG). + */ + s = php_gcvt(fval, + field->decimals >= 31 ? 6 : field->decimals, + '.', + 'e', + num_buf); + + /* And now convert back to double */ + dval = zend_strtod(s, NULL); + } +#endif + + ZVAL_DOUBLE(zv, dval); DBG_VOID_RETURN; } /* }}} */ -- cgit v1.2.1 From 63d3f0b844b3a5f1c94be3c97bca29235dc2b3fc Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Tue, 19 Aug 2014 08:07:31 +0200 Subject: basic macro replacements, all at once --- ext/mysqlnd/mysqlnd_ps_codec.c | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) (limited to 'ext/mysqlnd/mysqlnd_ps_codec.c') diff --git a/ext/mysqlnd/mysqlnd_ps_codec.c b/ext/mysqlnd/mysqlnd_ps_codec.c index 746cf01a26..6f160d2223 100644 --- a/ext/mysqlnd/mysqlnd_ps_codec.c +++ b/ext/mysqlnd/mysqlnd_ps_codec.c @@ -84,7 +84,7 @@ ps_fetch_from_1_to_8_bytes(zval * zv, const MYSQLND_FIELD * const field, unsigne #endif /* #if SIZEOF_LONG==4 */ { if (byte_count < 8 || uval <= L64(9223372036854775807)) { - ZVAL_LONG(zv, (long) uval); /* the cast is safe, we are in the range */ + ZVAL_INT(zv, (long) uval); /* the cast is safe, we are in the range */ } else { DBG_INF("stringify"); tmp_len = sprintf((char *)&tmp, MYSQLND_LLU_SPEC, uval); @@ -112,7 +112,7 @@ ps_fetch_from_1_to_8_bytes(zval * zv, const MYSQLND_FIELD * const field, unsigne } else #endif /* SIZEOF */ { - ZVAL_LONG(zv, (long) lval); /* the cast is safe, we are in the range */ + ZVAL_INT(zv, (long) lval); /* the cast is safe, we are in the range */ } } @@ -406,32 +406,32 @@ void _mysqlnd_init_ps_fetch_subsystem() mysqlnd_ps_fetch_functions[MYSQL_TYPE_TINY].func = ps_fetch_int8; mysqlnd_ps_fetch_functions[MYSQL_TYPE_TINY].pack_len = 1; - mysqlnd_ps_fetch_functions[MYSQL_TYPE_TINY].php_type = IS_LONG; + mysqlnd_ps_fetch_functions[MYSQL_TYPE_TINY].php_type = IS_INT; mysqlnd_ps_fetch_functions[MYSQL_TYPE_TINY].can_ret_as_str_in_uni = TRUE; mysqlnd_ps_fetch_functions[MYSQL_TYPE_SHORT].func = ps_fetch_int16; mysqlnd_ps_fetch_functions[MYSQL_TYPE_SHORT].pack_len = 2; - mysqlnd_ps_fetch_functions[MYSQL_TYPE_SHORT].php_type = IS_LONG; + mysqlnd_ps_fetch_functions[MYSQL_TYPE_SHORT].php_type = IS_INT; mysqlnd_ps_fetch_functions[MYSQL_TYPE_SHORT].can_ret_as_str_in_uni = TRUE; mysqlnd_ps_fetch_functions[MYSQL_TYPE_YEAR].func = ps_fetch_int16; mysqlnd_ps_fetch_functions[MYSQL_TYPE_YEAR].pack_len = 2; - mysqlnd_ps_fetch_functions[MYSQL_TYPE_YEAR].php_type = IS_LONG; + mysqlnd_ps_fetch_functions[MYSQL_TYPE_YEAR].php_type = IS_INT; mysqlnd_ps_fetch_functions[MYSQL_TYPE_YEAR].can_ret_as_str_in_uni = TRUE; mysqlnd_ps_fetch_functions[MYSQL_TYPE_INT24].func = ps_fetch_int32; mysqlnd_ps_fetch_functions[MYSQL_TYPE_INT24].pack_len = 4; - mysqlnd_ps_fetch_functions[MYSQL_TYPE_INT24].php_type = IS_LONG; + mysqlnd_ps_fetch_functions[MYSQL_TYPE_INT24].php_type = IS_INT; mysqlnd_ps_fetch_functions[MYSQL_TYPE_INT24].can_ret_as_str_in_uni = TRUE; mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONG].func = ps_fetch_int32; mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONG].pack_len = 4; - mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONG].php_type = IS_LONG; + mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONG].php_type = IS_INT; mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONG].can_ret_as_str_in_uni = TRUE; mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONGLONG].func = ps_fetch_int64; mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONGLONG].pack_len= 8; - mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONGLONG].php_type= IS_LONG; + mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONGLONG].php_type= IS_INT; mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONGLONG].can_ret_as_str_in_uni = TRUE; mysqlnd_ps_fetch_functions[MYSQL_TYPE_FLOAT].func = ps_fetch_float; @@ -495,7 +495,7 @@ void _mysqlnd_init_ps_fetch_subsystem() mysqlnd_ps_fetch_functions[MYSQL_TYPE_BIT].func = ps_fetch_bit; mysqlnd_ps_fetch_functions[MYSQL_TYPE_BIT].pack_len = 8; - mysqlnd_ps_fetch_functions[MYSQL_TYPE_BIT].php_type = IS_LONG; + mysqlnd_ps_fetch_functions[MYSQL_TYPE_BIT].php_type = IS_INT; mysqlnd_ps_fetch_functions[MYSQL_TYPE_BIT].can_ret_as_str_in_uni = TRUE; mysqlnd_ps_fetch_functions[MYSQL_TYPE_VAR_STRING].func = ps_fetch_string; @@ -610,7 +610,7 @@ mysqlnd_stmt_execute_prepare_param_types(MYSQLND_STMT_DATA * stmt, zval ** copie ZVAL_DEREF(parameter); if (!Z_ISNULL_P(parameter) && (current_type == MYSQL_TYPE_LONG || current_type == MYSQL_TYPE_LONGLONG)) { /* always copy the var, because we do many conversions */ - if (Z_TYPE_P(parameter) != IS_LONG && + if (Z_TYPE_P(parameter) != IS_INT && PASS != mysqlnd_stmt_copy_it(copies_param, parameter, stmt->param_count, i TSRMLS_CC)) { SET_OOM_ERROR(*stmt->error_info); @@ -620,7 +620,7 @@ mysqlnd_stmt_execute_prepare_param_types(MYSQLND_STMT_DATA * stmt, zval ** copie 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 */ - if (Z_TYPE_P(parameter) != IS_LONG) { + if (Z_TYPE_P(parameter) != IS_INT) { zval *tmp_data = (*copies_param && !Z_ISUNDEF((*copies_param)[i]))? &(*copies_param)[i]: parameter; /* Because converting to double and back to long can lead @@ -640,7 +640,7 @@ mysqlnd_stmt_execute_prepare_param_types(MYSQLND_STMT_DATA * stmt, zval ** copie stmt->send_types_to_server = *resend_types_next_time = 1; convert_to_string_ex(tmp_data); } else { - convert_to_long_ex(tmp_data); + convert_to_int_ex(tmp_data); } zval_ptr_dtor(&tmp_data_copy); @@ -674,17 +674,17 @@ mysqlnd_stmt_execute_store_types(MYSQLND_STMT_DATA * stmt, zval * copies, zend_u 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 */ - if (Z_TYPE_P(parameter) != IS_LONG) { + if (Z_TYPE_P(parameter) != IS_INT) { const zval *tmp_data = (copies && !Z_ISUNDEF(copies[i]))? &copies[i] : parameter; /* - In case of IS_LONG we do nothing, it is ok, in case of string, we just need to set current_type. + In case of IS_INT 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 - we force convert_to_long_ex in all cases, thus the type will be right in the next switch. + we force convert_to_int_ex in all cases, thus the type will be right in the next switch. 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. */ @@ -751,7 +751,7 @@ mysqlnd_stmt_execute_calculate_param_values_size(MYSQLND_STMT_DATA * stmt, zval if (Z_TYPE_P(tmp_data) == IS_STRING) { goto use_string; } - convert_to_long_ex(tmp_data); + convert_to_int_ex(tmp_data); } *data_size += 4 + is_longlong; break; @@ -778,7 +778,7 @@ use_string: the_var = &((*copies_param)[i]); } convert_to_string_ex(the_var); - *data_size += Z_STRLEN_P(the_var); + *data_size += Z_STRSIZE_P(the_var); break; } } @@ -814,7 +814,7 @@ mysqlnd_stmt_execute_store_param_values(MYSQLND_STMT_DATA * stmt, zval * copies, goto send_string; } /* data has alreade been converted to long */ - int8store(*p, Z_LVAL_P(data)); + int8store(*p, Z_IVAL_P(data)); (*p) += 8; break; case MYSQL_TYPE_LONG: @@ -822,7 +822,7 @@ mysqlnd_stmt_execute_store_param_values(MYSQLND_STMT_DATA * stmt, zval * copies, goto send_string; } /* data has alreade been converted to long */ - int4store(*p, Z_LVAL_P(data)); + int4store(*p, Z_IVAL_P(data)); (*p) += 4; break; case MYSQL_TYPE_LONG_BLOB: @@ -836,7 +836,7 @@ mysqlnd_stmt_execute_store_param_values(MYSQLND_STMT_DATA * stmt, zval * copies, case MYSQL_TYPE_VAR_STRING: send_string: { - size_t len = Z_STRLEN_P(data); + size_t len = Z_STRSIZE_P(data); /* to is after p. The latter hasn't been moved */ *p = php_mysqlnd_net_store_length(*p, len); memcpy(*p, Z_STRVAL_P(data), len); -- cgit v1.2.1 From bdbf47df181bdafc1b2bc2df1d23815f01510b88 Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Tue, 19 Aug 2014 16:51:06 +0200 Subject: ported mysql and mysqlnd --- ext/mysqlnd/mysqlnd_ps_codec.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'ext/mysqlnd/mysqlnd_ps_codec.c') diff --git a/ext/mysqlnd/mysqlnd_ps_codec.c b/ext/mysqlnd/mysqlnd_ps_codec.c index 6f160d2223..8b59d918ba 100644 --- a/ext/mysqlnd/mysqlnd_ps_codec.c +++ b/ext/mysqlnd/mysqlnd_ps_codec.c @@ -41,7 +41,7 @@ enum mysqlnd_timestamp_type struct st_mysqlnd_time { unsigned int year, month, day, hour, minute, second; - unsigned long second_part; + php_uint_t second_part; zend_bool neg; enum mysqlnd_timestamp_type time_type; }; @@ -76,7 +76,7 @@ ps_fetch_from_1_to_8_bytes(zval * zv, const MYSQLND_FIELD * const field, unsigne case 1:uval = (uint64_t) uint1korr(*row);break; } -#if SIZEOF_LONG==4 +#if SIZEOF_ZEND_INT==4 if (uval > INT_MAX) { DBG_INF("stringify"); tmp_len = sprintf((char *)&tmp, MYSQLND_LLU_SPEC, uval); @@ -84,7 +84,7 @@ ps_fetch_from_1_to_8_bytes(zval * zv, const MYSQLND_FIELD * const field, unsigne #endif /* #if SIZEOF_LONG==4 */ { if (byte_count < 8 || uval <= L64(9223372036854775807)) { - ZVAL_INT(zv, (long) uval); /* the cast is safe, we are in the range */ + ZVAL_INT(zv, (php_int_t) uval); /* the cast is safe, we are in the range */ } else { DBG_INF("stringify"); tmp_len = sprintf((char *)&tmp, MYSQLND_LLU_SPEC, uval); @@ -105,14 +105,14 @@ ps_fetch_from_1_to_8_bytes(zval * zv, const MYSQLND_FIELD * const field, unsigne case 1:lval = (int64_t) *(int8_t*)*row;break; } -#if SIZEOF_LONG==4 +#if SIZEOF_ZEND_INT==4 if ((L64(2147483647) < (int64_t) lval) || (L64(-2147483648) > (int64_t) lval)) { DBG_INF("stringify"); tmp_len = sprintf((char *)&tmp, MYSQLND_LL_SPEC, lval); } else #endif /* SIZEOF */ { - ZVAL_INT(zv, (long) lval); /* the cast is safe, we are in the range */ + ZVAL_INT(zv, (php_int_t) lval); /* the cast is safe, we are in the range */ } } @@ -246,7 +246,7 @@ static void ps_fetch_time(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row TSRMLS_DC) { struct st_mysqlnd_time t; - unsigned long length; /* First byte encodes the length*/ + php_uint_t length; /* First byte encodes the length*/ char * value; DBG_ENTER("ps_fetch_time"); @@ -256,11 +256,11 @@ ps_fetch_time(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_le t.time_type = MYSQLND_TIMESTAMP_TIME; t.neg = (zend_bool) to[0]; - t.day = (unsigned long) sint4korr(to+1); + t.day = (php_uint_t) sint4korr(to+1); t.hour = (unsigned int) to[5]; t.minute = (unsigned int) to[6]; t.second = (unsigned int) to[7]; - t.second_part = (length > 8) ? (unsigned long) sint4korr(to+8) : 0; + t.second_part = (length > 8) ? (php_uint_t) sint4korr(to+8) : 0; t.year = t.month= 0; if (t.day) { /* Convert days to hours at once */ @@ -289,7 +289,7 @@ static void ps_fetch_date(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row TSRMLS_DC) { struct st_mysqlnd_time t = {0}; - unsigned long length; /* First byte encodes the length*/ + php_uint_t length; /* First byte encodes the length*/ char * value; DBG_ENTER("ps_fetch_date"); @@ -326,7 +326,7 @@ static void ps_fetch_datetime(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row TSRMLS_DC) { struct st_mysqlnd_time t; - unsigned long length; /* First byte encodes the length*/ + php_uint_t length; /* First byte encodes the length*/ char * value; DBG_ENTER("ps_fetch_datetime"); @@ -347,7 +347,7 @@ ps_fetch_datetime(zval * zv, const MYSQLND_FIELD * const field, unsigned int pac } else { t.hour = t.minute = t.second= 0; } - t.second_part = (length > 7) ? (unsigned long) sint4korr(to+7) : 0; + t.second_part = (length > 7) ? (php_uint_t) sint4korr(to+7) : 0; (*row)+= length; } else { @@ -373,7 +373,7 @@ ps_fetch_string(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_ For now just copy, before we make it possible to write \0 to the row buffer */ - const unsigned long length = php_mysqlnd_net_field_length(row); + const php_uint_t length = php_mysqlnd_net_field_length(row); DBG_ENTER("ps_fetch_string"); DBG_INF_FMT("len = %lu", length); DBG_INF("copying from the row buffer"); @@ -389,7 +389,7 @@ ps_fetch_string(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_ static void ps_fetch_bit(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row TSRMLS_DC) { - unsigned long length = php_mysqlnd_net_field_length(row); + php_uint_t length = php_mysqlnd_net_field_length(row); ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, length TSRMLS_CC); } /* }}} */ @@ -636,7 +636,7 @@ mysqlnd_stmt_execute_prepare_param_types(MYSQLND_STMT_DATA * stmt, zval ** copie 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(tmp_data_copy) > LONG_MAX || Z_DVAL(tmp_data_copy) < LONG_MIN) { + if (Z_DVAL(tmp_data_copy) > PHP_INT_MAX || Z_DVAL(tmp_data_copy) < PHP_INT_MIN) { stmt->send_types_to_server = *resend_types_next_time = 1; convert_to_string_ex(tmp_data); } else { @@ -663,7 +663,7 @@ mysqlnd_stmt_execute_store_types(MYSQLND_STMT_DATA * stmt, zval * copies, zend_u short current_type = stmt->param_bind[i].type; zval *parameter = &stmt->param_bind[i].zv; /* our types are not unsigned */ -#if SIZEOF_LONG==8 +#if SIZEOF_ZEND_INT==8 if (current_type == MYSQL_TYPE_LONG) { current_type = MYSQL_TYPE_LONGLONG; } -- cgit v1.2.1 From c3e3c98ec666812daaaca896cf5ef758a8a6df14 Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Mon, 25 Aug 2014 19:24:55 +0200 Subject: master renames phase 1 --- ext/mysqlnd/mysqlnd_ps_codec.c | 52 +++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 26 deletions(-) (limited to 'ext/mysqlnd/mysqlnd_ps_codec.c') diff --git a/ext/mysqlnd/mysqlnd_ps_codec.c b/ext/mysqlnd/mysqlnd_ps_codec.c index 8b59d918ba..c669706917 100644 --- a/ext/mysqlnd/mysqlnd_ps_codec.c +++ b/ext/mysqlnd/mysqlnd_ps_codec.c @@ -41,7 +41,7 @@ enum mysqlnd_timestamp_type struct st_mysqlnd_time { unsigned int year, month, day, hour, minute, second; - php_uint_t second_part; + zend_ulong second_part; zend_bool neg; enum mysqlnd_timestamp_type time_type; }; @@ -84,7 +84,7 @@ ps_fetch_from_1_to_8_bytes(zval * zv, const MYSQLND_FIELD * const field, unsigne #endif /* #if SIZEOF_LONG==4 */ { if (byte_count < 8 || uval <= L64(9223372036854775807)) { - ZVAL_INT(zv, (php_int_t) uval); /* the cast is safe, we are in the range */ + ZVAL_LONG(zv, (zend_long) uval); /* the cast is safe, we are in the range */ } else { DBG_INF("stringify"); tmp_len = sprintf((char *)&tmp, MYSQLND_LLU_SPEC, uval); @@ -112,7 +112,7 @@ ps_fetch_from_1_to_8_bytes(zval * zv, const MYSQLND_FIELD * const field, unsigne } else #endif /* SIZEOF */ { - ZVAL_INT(zv, (php_int_t) lval); /* the cast is safe, we are in the range */ + ZVAL_LONG(zv, (zend_long) lval); /* the cast is safe, we are in the range */ } } @@ -246,7 +246,7 @@ static void ps_fetch_time(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row TSRMLS_DC) { struct st_mysqlnd_time t; - php_uint_t length; /* First byte encodes the length*/ + zend_ulong length; /* First byte encodes the length*/ char * value; DBG_ENTER("ps_fetch_time"); @@ -256,11 +256,11 @@ ps_fetch_time(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_le t.time_type = MYSQLND_TIMESTAMP_TIME; t.neg = (zend_bool) to[0]; - t.day = (php_uint_t) sint4korr(to+1); + t.day = (zend_ulong) sint4korr(to+1); t.hour = (unsigned int) to[5]; t.minute = (unsigned int) to[6]; t.second = (unsigned int) to[7]; - t.second_part = (length > 8) ? (php_uint_t) sint4korr(to+8) : 0; + t.second_part = (length > 8) ? (zend_ulong) sint4korr(to+8) : 0; t.year = t.month= 0; if (t.day) { /* Convert days to hours at once */ @@ -289,7 +289,7 @@ static void ps_fetch_date(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row TSRMLS_DC) { struct st_mysqlnd_time t = {0}; - php_uint_t length; /* First byte encodes the length*/ + zend_ulong length; /* First byte encodes the length*/ char * value; DBG_ENTER("ps_fetch_date"); @@ -326,7 +326,7 @@ static void ps_fetch_datetime(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row TSRMLS_DC) { struct st_mysqlnd_time t; - php_uint_t length; /* First byte encodes the length*/ + zend_ulong length; /* First byte encodes the length*/ char * value; DBG_ENTER("ps_fetch_datetime"); @@ -347,7 +347,7 @@ ps_fetch_datetime(zval * zv, const MYSQLND_FIELD * const field, unsigned int pac } else { t.hour = t.minute = t.second= 0; } - t.second_part = (length > 7) ? (php_uint_t) sint4korr(to+7) : 0; + t.second_part = (length > 7) ? (zend_ulong) sint4korr(to+7) : 0; (*row)+= length; } else { @@ -373,7 +373,7 @@ ps_fetch_string(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_ For now just copy, before we make it possible to write \0 to the row buffer */ - const php_uint_t length = php_mysqlnd_net_field_length(row); + const zend_ulong length = php_mysqlnd_net_field_length(row); DBG_ENTER("ps_fetch_string"); DBG_INF_FMT("len = %lu", length); DBG_INF("copying from the row buffer"); @@ -389,7 +389,7 @@ ps_fetch_string(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_ static void ps_fetch_bit(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row TSRMLS_DC) { - php_uint_t length = php_mysqlnd_net_field_length(row); + zend_ulong length = php_mysqlnd_net_field_length(row); ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, length TSRMLS_CC); } /* }}} */ @@ -406,32 +406,32 @@ void _mysqlnd_init_ps_fetch_subsystem() mysqlnd_ps_fetch_functions[MYSQL_TYPE_TINY].func = ps_fetch_int8; mysqlnd_ps_fetch_functions[MYSQL_TYPE_TINY].pack_len = 1; - mysqlnd_ps_fetch_functions[MYSQL_TYPE_TINY].php_type = IS_INT; + mysqlnd_ps_fetch_functions[MYSQL_TYPE_TINY].php_type = IS_LONG; mysqlnd_ps_fetch_functions[MYSQL_TYPE_TINY].can_ret_as_str_in_uni = TRUE; mysqlnd_ps_fetch_functions[MYSQL_TYPE_SHORT].func = ps_fetch_int16; mysqlnd_ps_fetch_functions[MYSQL_TYPE_SHORT].pack_len = 2; - mysqlnd_ps_fetch_functions[MYSQL_TYPE_SHORT].php_type = IS_INT; + mysqlnd_ps_fetch_functions[MYSQL_TYPE_SHORT].php_type = IS_LONG; mysqlnd_ps_fetch_functions[MYSQL_TYPE_SHORT].can_ret_as_str_in_uni = TRUE; mysqlnd_ps_fetch_functions[MYSQL_TYPE_YEAR].func = ps_fetch_int16; mysqlnd_ps_fetch_functions[MYSQL_TYPE_YEAR].pack_len = 2; - mysqlnd_ps_fetch_functions[MYSQL_TYPE_YEAR].php_type = IS_INT; + mysqlnd_ps_fetch_functions[MYSQL_TYPE_YEAR].php_type = IS_LONG; mysqlnd_ps_fetch_functions[MYSQL_TYPE_YEAR].can_ret_as_str_in_uni = TRUE; mysqlnd_ps_fetch_functions[MYSQL_TYPE_INT24].func = ps_fetch_int32; mysqlnd_ps_fetch_functions[MYSQL_TYPE_INT24].pack_len = 4; - mysqlnd_ps_fetch_functions[MYSQL_TYPE_INT24].php_type = IS_INT; + mysqlnd_ps_fetch_functions[MYSQL_TYPE_INT24].php_type = IS_LONG; mysqlnd_ps_fetch_functions[MYSQL_TYPE_INT24].can_ret_as_str_in_uni = TRUE; mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONG].func = ps_fetch_int32; mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONG].pack_len = 4; - mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONG].php_type = IS_INT; + mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONG].php_type = IS_LONG; mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONG].can_ret_as_str_in_uni = TRUE; mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONGLONG].func = ps_fetch_int64; mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONGLONG].pack_len= 8; - mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONGLONG].php_type= IS_INT; + mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONGLONG].php_type= IS_LONG; mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONGLONG].can_ret_as_str_in_uni = TRUE; mysqlnd_ps_fetch_functions[MYSQL_TYPE_FLOAT].func = ps_fetch_float; @@ -495,7 +495,7 @@ void _mysqlnd_init_ps_fetch_subsystem() mysqlnd_ps_fetch_functions[MYSQL_TYPE_BIT].func = ps_fetch_bit; mysqlnd_ps_fetch_functions[MYSQL_TYPE_BIT].pack_len = 8; - mysqlnd_ps_fetch_functions[MYSQL_TYPE_BIT].php_type = IS_INT; + mysqlnd_ps_fetch_functions[MYSQL_TYPE_BIT].php_type = IS_LONG; mysqlnd_ps_fetch_functions[MYSQL_TYPE_BIT].can_ret_as_str_in_uni = TRUE; mysqlnd_ps_fetch_functions[MYSQL_TYPE_VAR_STRING].func = ps_fetch_string; @@ -610,7 +610,7 @@ mysqlnd_stmt_execute_prepare_param_types(MYSQLND_STMT_DATA * stmt, zval ** copie ZVAL_DEREF(parameter); if (!Z_ISNULL_P(parameter) && (current_type == MYSQL_TYPE_LONG || current_type == MYSQL_TYPE_LONGLONG)) { /* always copy the var, because we do many conversions */ - if (Z_TYPE_P(parameter) != IS_INT && + if (Z_TYPE_P(parameter) != IS_LONG && PASS != mysqlnd_stmt_copy_it(copies_param, parameter, stmt->param_count, i TSRMLS_CC)) { SET_OOM_ERROR(*stmt->error_info); @@ -620,7 +620,7 @@ mysqlnd_stmt_execute_prepare_param_types(MYSQLND_STMT_DATA * stmt, zval ** copie 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 */ - if (Z_TYPE_P(parameter) != IS_INT) { + if (Z_TYPE_P(parameter) != IS_LONG) { zval *tmp_data = (*copies_param && !Z_ISUNDEF((*copies_param)[i]))? &(*copies_param)[i]: parameter; /* Because converting to double and back to long can lead @@ -674,10 +674,10 @@ mysqlnd_stmt_execute_store_types(MYSQLND_STMT_DATA * stmt, zval * copies, zend_u 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 */ - if (Z_TYPE_P(parameter) != IS_INT) { + if (Z_TYPE_P(parameter) != IS_LONG) { const zval *tmp_data = (copies && !Z_ISUNDEF(copies[i]))? &copies[i] : parameter; /* - In case of IS_INT we do nothing, it is ok, in case of string, we just need to set current_type. + 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) { @@ -778,7 +778,7 @@ use_string: the_var = &((*copies_param)[i]); } convert_to_string_ex(the_var); - *data_size += Z_STRSIZE_P(the_var); + *data_size += Z_STRLEN_P(the_var); break; } } @@ -814,7 +814,7 @@ mysqlnd_stmt_execute_store_param_values(MYSQLND_STMT_DATA * stmt, zval * copies, goto send_string; } /* data has alreade been converted to long */ - int8store(*p, Z_IVAL_P(data)); + int8store(*p, Z_LVAL_P(data)); (*p) += 8; break; case MYSQL_TYPE_LONG: @@ -822,7 +822,7 @@ mysqlnd_stmt_execute_store_param_values(MYSQLND_STMT_DATA * stmt, zval * copies, goto send_string; } /* data has alreade been converted to long */ - int4store(*p, Z_IVAL_P(data)); + int4store(*p, Z_LVAL_P(data)); (*p) += 4; break; case MYSQL_TYPE_LONG_BLOB: @@ -836,7 +836,7 @@ mysqlnd_stmt_execute_store_param_values(MYSQLND_STMT_DATA * stmt, zval * copies, case MYSQL_TYPE_VAR_STRING: send_string: { - size_t len = Z_STRSIZE_P(data); + size_t len = Z_STRLEN_P(data); /* to is after p. The latter hasn't been moved */ *p = php_mysqlnd_net_store_length(*p, len); memcpy(*p, Z_STRVAL_P(data), len); -- cgit v1.2.1 From 4d997f63d98c663b2d9acccd3655572652f61c7d Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Mon, 25 Aug 2014 20:22:49 +0200 Subject: master renames phase 3 --- ext/mysqlnd/mysqlnd_ps_codec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ext/mysqlnd/mysqlnd_ps_codec.c') diff --git a/ext/mysqlnd/mysqlnd_ps_codec.c b/ext/mysqlnd/mysqlnd_ps_codec.c index c669706917..cfe6f26280 100644 --- a/ext/mysqlnd/mysqlnd_ps_codec.c +++ b/ext/mysqlnd/mysqlnd_ps_codec.c @@ -636,7 +636,7 @@ mysqlnd_stmt_execute_prepare_param_types(MYSQLND_STMT_DATA * stmt, zval ** copie 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(tmp_data_copy) > PHP_INT_MAX || Z_DVAL(tmp_data_copy) < PHP_INT_MIN) { + if (Z_DVAL(tmp_data_copy) > ZEND_LONG_MAX || Z_DVAL(tmp_data_copy) < ZEND_LONG_MIN) { stmt->send_types_to_server = *resend_types_next_time = 1; convert_to_string_ex(tmp_data); } else { -- cgit v1.2.1 From 28b7a033185478839c511551ce2344e459e7f880 Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Mon, 25 Aug 2014 21:20:44 +0200 Subject: master renamings phase 5 --- ext/mysqlnd/mysqlnd_ps_codec.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'ext/mysqlnd/mysqlnd_ps_codec.c') diff --git a/ext/mysqlnd/mysqlnd_ps_codec.c b/ext/mysqlnd/mysqlnd_ps_codec.c index cfe6f26280..2e414cacef 100644 --- a/ext/mysqlnd/mysqlnd_ps_codec.c +++ b/ext/mysqlnd/mysqlnd_ps_codec.c @@ -76,7 +76,7 @@ ps_fetch_from_1_to_8_bytes(zval * zv, const MYSQLND_FIELD * const field, unsigne case 1:uval = (uint64_t) uint1korr(*row);break; } -#if SIZEOF_ZEND_INT==4 +#if SIZEOF_ZEND_LONG==4 if (uval > INT_MAX) { DBG_INF("stringify"); tmp_len = sprintf((char *)&tmp, MYSQLND_LLU_SPEC, uval); @@ -105,7 +105,7 @@ ps_fetch_from_1_to_8_bytes(zval * zv, const MYSQLND_FIELD * const field, unsigne case 1:lval = (int64_t) *(int8_t*)*row;break; } -#if SIZEOF_ZEND_INT==4 +#if SIZEOF_ZEND_LONG==4 if ((L64(2147483647) < (int64_t) lval) || (L64(-2147483648) > (int64_t) lval)) { DBG_INF("stringify"); tmp_len = sprintf((char *)&tmp, MYSQLND_LL_SPEC, lval); @@ -663,7 +663,7 @@ mysqlnd_stmt_execute_store_types(MYSQLND_STMT_DATA * stmt, zval * copies, zend_u short current_type = stmt->param_bind[i].type; zval *parameter = &stmt->param_bind[i].zv; /* our types are not unsigned */ -#if SIZEOF_ZEND_INT==8 +#if SIZEOF_ZEND_LONG==8 if (current_type == MYSQL_TYPE_LONG) { current_type = MYSQL_TYPE_LONGLONG; } -- cgit v1.2.1 From af59e92b24c8f624672720d47ef65bd8457728b9 Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Mon, 25 Aug 2014 21:51:49 +0200 Subject: master renames phase 7 --- ext/mysqlnd/mysqlnd_ps_codec.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'ext/mysqlnd/mysqlnd_ps_codec.c') diff --git a/ext/mysqlnd/mysqlnd_ps_codec.c b/ext/mysqlnd/mysqlnd_ps_codec.c index 2e414cacef..7cb462960b 100644 --- a/ext/mysqlnd/mysqlnd_ps_codec.c +++ b/ext/mysqlnd/mysqlnd_ps_codec.c @@ -640,7 +640,7 @@ mysqlnd_stmt_execute_prepare_param_types(MYSQLND_STMT_DATA * stmt, zval ** copie stmt->send_types_to_server = *resend_types_next_time = 1; convert_to_string_ex(tmp_data); } else { - convert_to_int_ex(tmp_data); + convert_to_long_ex(tmp_data); } zval_ptr_dtor(&tmp_data_copy); @@ -684,7 +684,7 @@ mysqlnd_stmt_execute_store_types(MYSQLND_STMT_DATA * stmt, zval * copies, zend_u current_type = MYSQL_TYPE_VAR_STRING; /* don't change stmt->param_bind[i].type to MYSQL_TYPE_VAR_STRING - we force convert_to_int_ex in all cases, thus the type will be right in the next switch. + we force convert_to_long_ex in all cases, thus the type will be right in the next switch. 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. */ @@ -751,7 +751,7 @@ mysqlnd_stmt_execute_calculate_param_values_size(MYSQLND_STMT_DATA * stmt, zval if (Z_TYPE_P(tmp_data) == IS_STRING) { goto use_string; } - convert_to_int_ex(tmp_data); + convert_to_long_ex(tmp_data); } *data_size += 4 + is_longlong; break; -- cgit v1.2.1 From dff820cea3d51d3bfb925bd1a09cbb2ee741e2b3 Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Wed, 10 Sep 2014 19:29:11 +0200 Subject: fix precision when fetching float through mysqlnd fixes failing ext/mysqli/tests/010.phpt --- ext/mysqlnd/mysqlnd_ps_codec.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'ext/mysqlnd/mysqlnd_ps_codec.c') diff --git a/ext/mysqlnd/mysqlnd_ps_codec.c b/ext/mysqlnd/mysqlnd_ps_codec.c index fa4ed9da6f..d96091210b 100644 --- a/ext/mysqlnd/mysqlnd_ps_codec.c +++ b/ext/mysqlnd/mysqlnd_ps_codec.c @@ -200,17 +200,27 @@ ps_fetch_float(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_l /* The following cast is guaranteed to do the right thing */ dval = (double) d32val; } +#elif defined(PHP_WIN32) + { + /* float datatype on Winows is already 4 byte but has a precision of 7 digits */ + char num_buf[2048]; + (void)_gcvt_s(num_buf, 2048, fval, field->decimals >= 31 ? 7 : field->decimals); + dval = zend_strtod(num_buf, NULL); + } #else { char num_buf[2048]; /* Over allocated */ char *s; +#ifndef FLT_DIG +# define FLT_DIG 6 +#endif /* Convert to string. Ignoring localization, etc. * Following MySQL's rules. If precision is undefined (NOT_FIXED_DEC i.e. 31) * or larger than 31, the value is limited to 6 (FLT_DIG). */ s = php_gcvt(fval, - field->decimals >= 31 ? 6 : field->decimals, + field->decimals >= 31 ? FLT_DIG : field->decimals, '.', 'e', num_buf); -- cgit v1.2.1 From d0cb715373c3fbe9dc095378ec5ed8c71f799f67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20Schl=C3=BCter?= Date: Fri, 19 Sep 2014 18:33:14 +0200 Subject: s/PHP 5/PHP 7/ --- ext/mysqlnd/mysqlnd_ps_codec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ext/mysqlnd/mysqlnd_ps_codec.c') diff --git a/ext/mysqlnd/mysqlnd_ps_codec.c b/ext/mysqlnd/mysqlnd_ps_codec.c index 8f83a9e2af..e98d1c3a52 100644 --- a/ext/mysqlnd/mysqlnd_ps_codec.c +++ b/ext/mysqlnd/mysqlnd_ps_codec.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 2006-2014 The PHP Group | +----------------------------------------------------------------------+ -- cgit v1.2.1