diff --git a/ext/bcmath/bcmath.c b/ext/bcmath/bcmath.c index c7c5aeb700fbe..1b4dd331c9b95 100644 --- a/ext/bcmath/bcmath.c +++ b/ext/bcmath/bcmath.c @@ -615,7 +615,10 @@ PHP_FUNCTION(bcpow) goto cleanup; } - bc_raise(first, exponent, &result, scale); + if (!bc_raise(first, exponent, &result, scale)) { + zend_throw_exception_ex(zend_ce_division_by_zero_error, 0, "Negative power of zero"); + goto cleanup; + } RETVAL_NEW_STR(bc_num2str_ex(result, scale)); @@ -1141,7 +1144,10 @@ static zend_result bcmath_number_pow_internal( } return FAILURE; } - bc_raise(n1, exponent, ret, *scale); + if (!bc_raise(n1, exponent, ret, *scale)) { + zend_throw_exception_ex(zend_ce_division_by_zero_error, 0, "Negative power of zero"); + return FAILURE; + } bc_rm_trailing_zeros(*ret); if (scale_expand) { size_t diff = *scale - (*ret)->n_scale; diff --git a/ext/bcmath/libbcmath/src/bcmath.h b/ext/bcmath/libbcmath/src/bcmath.h index f346624b09ed5..bb6eb5ca82497 100644 --- a/ext/bcmath/libbcmath/src/bcmath.h +++ b/ext/bcmath/libbcmath/src/bcmath.h @@ -168,7 +168,7 @@ typedef enum { raise_mod_status bc_raisemod(bc_num base, bc_num exponent, bc_num mod, bc_num *result, size_t scale); -void bc_raise(bc_num base, long exponent, bc_num *resul, size_t scale); +bool bc_raise(bc_num base, long exponent, bc_num *result, size_t scale); void bc_raise_bc_exponent(bc_num base, bc_num exponent, bc_num *resul, size_t scale); diff --git a/ext/bcmath/libbcmath/src/raise.c b/ext/bcmath/libbcmath/src/raise.c index 162f84a830538..1e283864694b6 100644 --- a/ext/bcmath/libbcmath/src/raise.c +++ b/ext/bcmath/libbcmath/src/raise.c @@ -40,10 +40,10 @@ void bc_square_ex(bc_num n1, bc_num *result, size_t scale_min) { *(result) = square_ex; } -/* Raise NUM1 to the NUM2 power. The result is placed in RESULT. - Maximum exponent is LONG_MAX. If a NUM2 is not an integer, +/* Raise "base" to the "exponent" power. The result is placed in RESULT. + Maximum exponent is LONG_MAX. If a "exponent" is not an integer, only the integer part is used. */ -void bc_raise(bc_num num1, long exponent, bc_num *result, size_t scale) { +bool bc_raise(bc_num base, long exponent, bc_num *result, size_t scale) { bc_num temp, power; size_t rscale; size_t pwrscale; @@ -54,7 +54,7 @@ void bc_raise(bc_num num1, long exponent, bc_num *result, size_t scale) { if (exponent == 0) { bc_free_num (result); *result = bc_copy_num(BCG(_one_)); - return; + return true; } /* Other initializations. */ @@ -64,12 +64,12 @@ void bc_raise(bc_num num1, long exponent, bc_num *result, size_t scale) { rscale = scale; } else { is_neg = false; - rscale = MIN (num1->n_scale * exponent, MAX(scale, num1->n_scale)); + rscale = MIN (base->n_scale * exponent, MAX(scale, base->n_scale)); } /* Set initial value of temp. */ - power = bc_copy_num(num1); - pwrscale = num1->n_scale; + power = bc_copy_num(base); + pwrscale = base->n_scale; while ((exponent & 1) == 0) { pwrscale = 2 * pwrscale; bc_square_ex(power, &power, pwrscale); @@ -92,7 +92,11 @@ void bc_raise(bc_num num1, long exponent, bc_num *result, size_t scale) { /* Assign the value. */ if (is_neg) { - bc_divide(BCG(_one_), temp, result, rscale); + if (bc_divide(BCG(_one_), temp, result, rscale) == false) { + bc_free_num (&temp); + bc_free_num (&power); + return false; + } bc_free_num (&temp); } else { bc_free_num (result); @@ -100,6 +104,7 @@ void bc_raise(bc_num num1, long exponent, bc_num *result, size_t scale) { (*result)->n_scale = MIN(scale, (*result)->n_scale); } bc_free_num (&power); + return true; } /* This is used internally by BCMath */ diff --git a/ext/bcmath/tests/bcpow.phpt b/ext/bcmath/tests/bcpow.phpt index 799cbbd090bc2..9a46152f99632 100644 --- a/ext/bcmath/tests/bcpow.phpt +++ b/ext/bcmath/tests/bcpow.phpt @@ -60,17 +60,17 @@ Number "-9" (scale 0) Number "0" (scale 0) 0 ** 15 = 0 -0 ** -15 = 0 +0 ** -15 = Negative power of zero 0 ** 1 = 0 -0 ** -9 = 0 +0 ** -9 = Negative power of zero 0 ** 0 = 1 0 ** -0 = 1 Number "-0" (scale 0) -0 ** 15 = 0 --0 ** -15 = 0 +-0 ** -15 = Negative power of zero -0 ** 1 = 0 --0 ** -9 = 0 +-0 ** -9 = Negative power of zero -0 ** 0 = 1 -0 ** -0 = 1 @@ -188,17 +188,17 @@ Number "-9" (scale 10) Number "0" (scale 10) 0 ** 15 = 0.0000000000 -0 ** -15 = 0.0000000000 +0 ** -15 = Negative power of zero 0 ** 1 = 0.0000000000 -0 ** -9 = 0.0000000000 +0 ** -9 = Negative power of zero 0 ** 0 = 1.0000000000 0 ** -0 = 1.0000000000 Number "-0" (scale 10) -0 ** 15 = 0.0000000000 --0 ** -15 = 0.0000000000 +-0 ** -15 = Negative power of zero -0 ** 1 = 0.0000000000 --0 ** -9 = 0.0000000000 +-0 ** -9 = Negative power of zero -0 ** 0 = 1.0000000000 -0 ** -0 = 1.0000000000 diff --git a/ext/bcmath/tests/bcpow_div_by_zero.phpt b/ext/bcmath/tests/bcpow_div_by_zero.phpt new file mode 100644 index 0000000000000..ac1e8187450cc --- /dev/null +++ b/ext/bcmath/tests/bcpow_div_by_zero.phpt @@ -0,0 +1,29 @@ +--TEST-- +bcpow() negative power of zero +--EXTENSIONS-- +bcmath +--INI-- +bcmath.scale=0 +--FILE-- +getMessage(), "\n"; + } + } +} + +?> +--EXPECT-- +Negative power of zero +Negative power of zero +Negative power of zero +Negative power of zero +Negative power of zero +Negative power of zero diff --git a/ext/bcmath/tests/number/methods/pow_div_by_zero.phpt b/ext/bcmath/tests/number/methods/pow_div_by_zero.phpt new file mode 100644 index 0000000000000..6a7099b1c30ee --- /dev/null +++ b/ext/bcmath/tests/number/methods/pow_div_by_zero.phpt @@ -0,0 +1,41 @@ +--TEST-- +BcMath\Number pow(): negative power of zero +--EXTENSIONS-- +bcmath +--FILE-- +pow($exponent); + } catch (Error $e) { + echo $e->getMessage() . "\n"; + } + } +} +?> +--EXPECT-- +0 ** -3: int +Negative power of zero +0 ** -2: string +Negative power of zero +0 ** -2: object +Negative power of zero +0 ** -3: int +Negative power of zero +0 ** -2: string +Negative power of zero +0 ** -2: object +Negative power of zero diff --git a/ext/bcmath/tests/number/operators/pow_div_by_zero.phpt b/ext/bcmath/tests/number/operators/pow_div_by_zero.phpt new file mode 100644 index 0000000000000..ff03626fca600 --- /dev/null +++ b/ext/bcmath/tests/number/operators/pow_div_by_zero.phpt @@ -0,0 +1,41 @@ +--TEST-- +BcMath\Number pow: negative power of zero by operator +--EXTENSIONS-- +bcmath +--FILE-- +getMessage() . "\n"; + } + } +} +?> +--EXPECT-- +0 ** -3: int +Negative power of zero +0 ** -2: string +Negative power of zero +0 ** -2: object +Negative power of zero +0 ** -3: int +Negative power of zero +0 ** -2: string +Negative power of zero +0 ** -2: object +Negative power of zero diff --git a/ext/bcmath/tests/run_bcmath_tests_function.inc b/ext/bcmath/tests/run_bcmath_tests_function.inc index 5bdafb2575db3..5cca15ac51575 100644 --- a/ext/bcmath/tests/run_bcmath_tests_function.inc +++ b/ext/bcmath/tests/run_bcmath_tests_function.inc @@ -13,11 +13,16 @@ function run_bcmath_tests( foreach ($firstTerms as $firstTerm) { echo "Number \"$firstTerm\" (scale $scale)\n"; foreach ($secondTerms as $secondTerm) { + try { + $ret = $bcmath_function($firstTerm, $secondTerm, $scale); + } catch (Throwable $e) { + $ret = $e->getMessage(); + } echo $firstTerm, " $symbol ", str_pad($secondTerm, STRING_PADDING), " = ", - $bcmath_function($firstTerm, $secondTerm, $scale), + $ret, "\n"; } echo "\n";