diff --git a/ext/bcmath/bcmath.c b/ext/bcmath/bcmath.c index c7c5aeb700fbe..d71e38d971ea0 100644 --- a/ext/bcmath/bcmath.c +++ b/ext/bcmath/bcmath.c @@ -1141,7 +1141,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 4b8ca12326417..a78b61c8e70e2 100644 --- a/ext/bcmath/libbcmath/src/bcmath.h +++ b/ext/bcmath/libbcmath/src/bcmath.h @@ -173,7 +173,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 num1, 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..a12f9b41d47ec 100644 --- a/ext/bcmath/libbcmath/src/raise.c +++ b/ext/bcmath/libbcmath/src/raise.c @@ -43,7 +43,7 @@ void bc_square_ex(bc_num n1, bc_num *result, size_t scale_min) { /* Raise NUM1 to the NUM2 power. The result is placed in RESULT. Maximum exponent is LONG_MAX. If a NUM2 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 num1, 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. */ @@ -92,7 +92,12 @@ 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); + // TODO: After removing bcpow's bc_init_num(), remove the NULL check + 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 +105,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/gh16236.phpt b/ext/bcmath/tests/gh16236.phpt new file mode 100644 index 0000000000000..3a91a63ba1053 --- /dev/null +++ b/ext/bcmath/tests/gh16236.phpt @@ -0,0 +1,17 @@ +--TEST-- +GH-16236 Segmentation fault (access null pointer) in ext/bcmath/libbcmath/src/rmzero.c:50 +--EXTENSIONS-- +bcmath +--FILE-- + +--EXPECT-- +done! 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