summaryrefslogtreecommitdiff
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
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.
-rw-r--r--NEWS1
-rw-r--r--ext/bcmath/libbcmath/src/raisemod.c22
-rw-r--r--ext/bcmath/tests/bug75178.phpt18
3 files changed, 34 insertions, 7 deletions
diff --git a/NEWS b/NEWS
index 7fb0cb1065..795d67d860 100644
--- a/NEWS
+++ b/NEWS
@@ -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===