diff options
author | Christoph M. Becker <cmbecker69@gmx.de> | 2017-09-09 13:18:26 +0200 |
---|---|---|
committer | Christoph M. Becker <cmbecker69@gmx.de> | 2017-09-09 13:18:26 +0200 |
commit | 44eec946e8c6c830992572e15e4b63b4dd92abdf (patch) | |
tree | 13a519fdb1f91cbe6bb96509515e58c1124c60b2 | |
parent | 0413feb29c94b065be6a1a2f425c72add5779a67 (diff) | |
download | php-git-44eec946e8c6c830992572e15e4b63b4dd92abdf.tar.gz |
Fixed bug #75178 (bcpowmod() misbehaves for non-integer base or modulus)
Since `bcpowmod()` does not support non-integral operands, we have to
truncate these in addition to emitting a respective warning. We also
have to work with the truncated values in the following.
We recognize that the division by one to enforce the truncation is
actually overkill, but we stick with it for now, and shall tackle the
issue for PHP 7.3.
-rw-r--r-- | NEWS | 1 | ||||
-rw-r--r-- | ext/bcmath/libbcmath/src/raisemod.c | 22 | ||||
-rw-r--r-- | ext/bcmath/tests/bug75178.phpt | 18 |
3 files changed, 34 insertions, 7 deletions
@@ -8,6 +8,7 @@ PHP NEWS - BCMath: . Fixed bug #44995 (bcpowmod() fails if scale != 0). (cmb) . Fixed bug #54598 (bcpowmod() may return 1 if modulus is 1). (okano1220, cmb) + . Fixed bug #75178 (bcpowmod() misbehaves for non-integer base or modulus). (cmb) - CLI server: . Fixed bug #70470 (Built-in server truncates headers spanning over TCP diff --git a/ext/bcmath/libbcmath/src/raisemod.c b/ext/bcmath/libbcmath/src/raisemod.c index 84a7321ea7..84788b4770 100644 --- a/ext/bcmath/libbcmath/src/raisemod.c +++ b/ext/bcmath/libbcmath/src/raisemod.c @@ -45,7 +45,7 @@ int bc_raisemod (bc_num base, bc_num expo, bc_num mod, bc_num *result, int scale) { - bc_num power, exponent, parity, temp; + bc_num power, exponent, modulus, parity, temp; int rscale; /* Check for correct numbers. */ @@ -55,12 +55,16 @@ bc_raisemod (bc_num base, bc_num expo, bc_num mod, bc_num *result, int scale) /* Set initial values. */ power = bc_copy_num (base); exponent = bc_copy_num (expo); + modulus = bc_copy_num (mod); temp = bc_copy_num (BCG(_one_)); bc_init_num(&parity); /* Check the base for scale digits. */ - if (base->n_scale != 0) + if (power->n_scale != 0) + { bc_rt_warn ("non-zero scale in base"); + bc_divide (power, BCG(_one_), &power, 0); /*truncate */ + } /* Check the exponent for scale digits. */ if (exponent->n_scale != 0) @@ -70,12 +74,15 @@ bc_raisemod (bc_num base, bc_num expo, bc_num mod, bc_num *result, int scale) } /* Check the modulus for scale digits. */ - if (mod->n_scale != 0) + if (modulus->n_scale != 0) + { bc_rt_warn ("non-zero scale in modulus"); + bc_divide (modulus, BCG(_one_), &modulus, 0); /*truncate */ + } /* Do the calculation. */ - rscale = MAX(scale, base->n_scale); - if ( !bc_compare(mod, BCG(_one_)) ) + rscale = MAX(scale, power->n_scale); + if ( !bc_compare(modulus, BCG(_one_)) ) { temp = bc_new_num (1, scale); } @@ -87,17 +94,18 @@ bc_raisemod (bc_num base, bc_num expo, bc_num mod, bc_num *result, int scale) if ( !bc_is_zero(parity) ) { bc_multiply (temp, power, &temp, rscale); - (void) bc_modulo (temp, mod, &temp, scale); + (void) bc_modulo (temp, modulus, &temp, scale); } bc_multiply (power, power, &power, rscale); - (void) bc_modulo (power, mod, &power, scale); + (void) bc_modulo (power, modulus, &power, scale); } } /* Assign the value. */ bc_free_num (&power); bc_free_num (&exponent); + bc_free_num (&modulus); bc_free_num (result); bc_free_num (&parity); *result = temp; diff --git a/ext/bcmath/tests/bug75178.phpt b/ext/bcmath/tests/bug75178.phpt new file mode 100644 index 0000000000..4e25256648 --- /dev/null +++ b/ext/bcmath/tests/bug75178.phpt @@ -0,0 +1,18 @@ +--TEST-- +Bug #75178 (bcpowmod() misbehaves for non-integer base or modulus) +--SKIPIF-- +<?php +if (!extension_loaded('bcmath')) die('skip bcmath extension is not available'); +?> +--FILE-- +<?php +var_dump(bcpowmod('4.1', '4', '3', 3)); +var_dump(bcpowmod('4', '4', '3.1', 3)); +?> +===DONE=== +--EXPECT-- +bc math warning: non-zero scale in base +string(5) "1.000" +bc math warning: non-zero scale in modulus +string(5) "1.000" +===DONE=== |