summaryrefslogtreecommitdiff
path: root/ext/bcmath/libbcmath/src/raisemod.c
diff options
context:
space:
mode:
authorChristoph M. Becker <cmbecker69@gmx.de>2017-09-09 13:18:26 +0200
committerChristoph M. Becker <cmbecker69@gmx.de>2017-09-09 13:18:26 +0200
commit44eec946e8c6c830992572e15e4b63b4dd92abdf (patch)
tree13a519fdb1f91cbe6bb96509515e58c1124c60b2 /ext/bcmath/libbcmath/src/raisemod.c
parent0413feb29c94b065be6a1a2f425c72add5779a67 (diff)
downloadphp-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.
Diffstat (limited to 'ext/bcmath/libbcmath/src/raisemod.c')
-rw-r--r--ext/bcmath/libbcmath/src/raisemod.c22
1 files changed, 15 insertions, 7 deletions
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;