diff --git a/NEWS b/NEWS index 1ca1c94a9dc..27413c6b500 100644 --- a/NEWS +++ b/NEWS @@ -12,8 +12,10 @@ PHP NEWS error_log set to "syslog"). (Philip Prindeville) - BCMath: + . Fixed bug #66364 (BCMath bcmul ignores scale parameter). (cmb) . Implemented request #67855 (No way to get current scale in use). (Chris Wright, cmb) + . Fixed bug #75164 (split_bc_num() is pointless). (cmb) . Fixed bug #75169 (BCMath errors/warnings bypass PHP's error handling). (cmb) - Date: diff --git a/ext/bcmath/bcmath.c b/ext/bcmath/bcmath.c index 8b3e3d9514b..1186241620a 100644 --- a/ext/bcmath/bcmath.c +++ b/ext/bcmath/bcmath.c @@ -207,21 +207,6 @@ static void php_str2num(bc_num *num, char *str) } /* }}} */ -/* {{{ split_bc_num - Convert to bc_num detecting scale */ -static bc_num split_bc_num(bc_num num) { - bc_num newnum; - if (num->n_refs >= 1) { - return num; - } - newnum = _bc_new_num_ex(0, 0, 0); - *newnum = *num; - newnum->n_refs = 1; - num->n_refs--; - return newnum; -} -/* }}} */ - /* {{{ proto string bcadd(string left_operand, string right_operand [, int scale]) Returns the sum of two arbitrary precision numbers */ PHP_FUNCTION(bcadd) @@ -249,12 +234,7 @@ PHP_FUNCTION(bcadd) php_str2num(&second, ZSTR_VAL(right)); bc_add (first, second, &result, scale); - if (result->n_scale > scale) { - result = split_bc_num(result); - result->n_scale = scale; - } - - RETVAL_STR(bc_num2str(result)); + RETVAL_STR(bc_num2str_ex(result, scale)); bc_free_num(&first); bc_free_num(&second); bc_free_num(&result); @@ -289,12 +269,7 @@ PHP_FUNCTION(bcsub) php_str2num(&second, ZSTR_VAL(right)); bc_sub (first, second, &result, scale); - if (result->n_scale > scale) { - result = split_bc_num(result); - result->n_scale = scale; - } - - RETVAL_STR(bc_num2str(result)); + RETVAL_STR(bc_num2str_ex(result, scale)); bc_free_num(&first); bc_free_num(&second); bc_free_num(&result); @@ -329,12 +304,7 @@ PHP_FUNCTION(bcmul) php_str2num(&second, ZSTR_VAL(right)); bc_multiply (first, second, &result, scale); - if (result->n_scale > scale) { - result = split_bc_num(result); - result->n_scale = scale; - } - - RETVAL_STR(bc_num2str(result)); + RETVAL_STR(bc_num2str_ex(result, scale)); bc_free_num(&first); bc_free_num(&second); bc_free_num(&result); @@ -370,11 +340,7 @@ PHP_FUNCTION(bcdiv) switch (bc_divide(first, second, &result, scale)) { case 0: /* OK */ - if (result->n_scale > scale) { - result = split_bc_num(result); - result->n_scale = scale; - } - RETVAL_STR(bc_num2str(result)); + RETVAL_STR(bc_num2str_ex(result, scale)); break; case -1: /* division by zero */ php_error_docref(NULL, E_WARNING, "Division by zero"); @@ -450,11 +416,7 @@ PHP_FUNCTION(bcpowmod) scale_int = (int) ((int)scale < 0 ? 0 : scale); if (bc_raisemod(first, second, mod, &result, scale_int) != -1) { - if (result->n_scale > scale_int) { - result = split_bc_num(result); - result->n_scale = scale_int; - } - RETVAL_STR(bc_num2str(result)); + RETVAL_STR(bc_num2str_ex(result, scale_int)); } else { RETVAL_FALSE; } @@ -494,12 +456,7 @@ PHP_FUNCTION(bcpow) php_str2num(&second, ZSTR_VAL(right)); bc_raise (first, second, &result, scale); - if (result->n_scale > scale) { - result = split_bc_num(result); - result->n_scale = scale; - } - - RETVAL_STR(bc_num2str(result)); + RETVAL_STR(bc_num2str_ex(result, scale)); bc_free_num(&first); bc_free_num(&second); bc_free_num(&result); @@ -530,11 +487,7 @@ PHP_FUNCTION(bcsqrt) php_str2num(&result, ZSTR_VAL(left)); if (bc_sqrt (&result, scale) != 0) { - if (result->n_scale > scale) { - result = split_bc_num(result); - result->n_scale = scale; - } - RETVAL_STR(bc_num2str(result)); + RETVAL_STR(bc_num2str_ex(result, scale)); } else { php_error_docref(NULL, E_WARNING, "Square root of negative number"); } diff --git a/ext/bcmath/libbcmath/src/bcmath.h b/ext/bcmath/libbcmath/src/bcmath.h index f0ab49fc528..78868edcb33 100644 --- a/ext/bcmath/libbcmath/src/bcmath.h +++ b/ext/bcmath/libbcmath/src/bcmath.h @@ -110,7 +110,7 @@ _PROTOTYPE(void bc_init_num, (bc_num *num)); _PROTOTYPE(void bc_str2num, (bc_num *num, char *str, int scale)); -_PROTOTYPE(zend_string *bc_num2str, (bc_num num)); +_PROTOTYPE(zend_string *bc_num2str_ex, (bc_num num, int scale)); _PROTOTYPE(void bc_int2num, (bc_num *num, int val)); @@ -155,5 +155,6 @@ _PROTOTYPE(void bc_out_of_memory, (void)); #define bc_new_num(length, scale) _bc_new_num_ex((length), (scale), 0) #define bc_free_num(num) _bc_free_num_ex((num), 0) +#define bc_num2str(num) bc_num2str_ex((num), (num->n_scale)) #endif diff --git a/ext/bcmath/libbcmath/src/num2str.c b/ext/bcmath/libbcmath/src/num2str.c index c72a924933a..7316d32a14a 100644 --- a/ext/bcmath/libbcmath/src/num2str.c +++ b/ext/bcmath/libbcmath/src/num2str.c @@ -41,8 +41,9 @@ /* Convert a numbers to a string. Base 10 only.*/ zend_string -*bc_num2str (num) +*bc_num2str_ex (num, scale) bc_num num; + int scale; { zend_string *str; char *sptr; @@ -51,8 +52,8 @@ zend_string /* Allocate the string memory. */ signch = ( num->n_sign == PLUS ? 0 : 1 ); /* Number of sign chars. */ - if (num->n_scale > 0) - str = zend_string_alloc(num->n_len + num->n_scale + signch + 1, 0); + if (scale > 0) + str = zend_string_alloc(num->n_len + scale + signch + 1, 0); else str = zend_string_alloc(num->n_len + signch, 0); if (str == NULL) bc_out_of_memory(); @@ -67,11 +68,13 @@ zend_string *sptr++ = BCD_CHAR(*nptr++); /* Now the fraction. */ - if (num->n_scale > 0) + if (scale > 0) { *sptr++ = '.'; - for (index=0; indexn_scale; index++) + for (index=0; indexn_scale; index++) *sptr++ = BCD_CHAR(*nptr++); + for (index = num->n_scale; index --EXPECT-- 1 --32 +-32.0000 18446744073709551616 -108.88 diff --git a/ext/bcmath/tests/bcpow_error1.phpt b/ext/bcmath/tests/bcpow_error1.phpt index 1075986587f..d3189f062aa 100644 --- a/ext/bcmath/tests/bcpow_error1.phpt +++ b/ext/bcmath/tests/bcpow_error1.phpt @@ -11,5 +11,5 @@ var_dump(bcpow('1', '1.1', 2)); ===DONE=== --EXPECTF-- Warning: bcpow(): non-zero scale in exponent in %s on line %d -string(1) "1" +string(4) "1.00" ===DONE=== diff --git a/ext/bcmath/tests/bcpow_error2.phpt b/ext/bcmath/tests/bcpow_error2.phpt index c58a7370878..49fd0b88d3d 100644 --- a/ext/bcmath/tests/bcpow_error2.phpt +++ b/ext/bcmath/tests/bcpow_error2.phpt @@ -11,5 +11,5 @@ var_dump(bcpow('0', '9223372036854775808', 2)); ===DONE=== --EXPECTF-- Warning: bcpow(): exponent too large in %s on line %d -string(1) "1" +string(4) "1.00" ===DONE=== diff --git a/ext/bcmath/tests/bug.66364.phpt b/ext/bcmath/tests/bug.66364.phpt new file mode 100644 index 00000000000..564f40e6daa --- /dev/null +++ b/ext/bcmath/tests/bug.66364.phpt @@ -0,0 +1,14 @@ +--TEST-- +Bug #66364 (BCMath bcmul ignores scale parameter) +--SKIPIF-- + +--FILE-- + +===DONE=== +--EXPECT-- +string(6) "0.0600" +===DONE=== diff --git a/ext/bcmath/tests/scale.phpt b/ext/bcmath/tests/scale.phpt new file mode 100644 index 00000000000..d49e5305119 --- /dev/null +++ b/ext/bcmath/tests/scale.phpt @@ -0,0 +1,27 @@ +--TEST-- +BCMath functions return result with requested scale +--SKIPIF-- + +--FILE-- + +===DONE=== +--EXPECT-- +bcadd: 3.00000 +bcdiv: 2.00000 +bcmul: 2.00000 +bcpow: 2.00000 +bcpowmod: 2.00000 +bcsqrt: 2.00000 +bcsub: 1.00000 +===DONE=== diff --git a/ext/bcmath/tests/scale_ini.phpt b/ext/bcmath/tests/scale_ini.phpt new file mode 100644 index 00000000000..66d9d482bff --- /dev/null +++ b/ext/bcmath/tests/scale_ini.phpt @@ -0,0 +1,29 @@ +--TEST-- +BCMath functions return result with default scale +--SKIPIF-- + +--INI-- +bcmath.scale = 5 +--FILE-- + +===DONE=== +--EXPECT-- +bcadd: 3.00000 +bcdiv: 2.00000 +bcmul: 2.00000 +bcpow: 2.00000 +bcpowmod: 2.00000 +bcsqrt: 2.00000 +bcsub: 1.00000 +===DONE===