Skip to content

Commit

Permalink
Fixed a bug in BcMath\Number::pow() when raising negative powers of 0.
Browse files Browse the repository at this point in the history
  • Loading branch information
SakiTakamachi committed Nov 4, 2024
1 parent 5c7c5d9 commit c048993
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 5 deletions.
5 changes: 4 additions & 1 deletion ext/bcmath/bcmath.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion ext/bcmath/libbcmath/src/bcmath.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
11 changes: 8 additions & 3 deletions ext/bcmath/libbcmath/src/raise.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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. */
Expand Down Expand Up @@ -92,14 +92,19 @@ 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);
*result = temp;
(*result)->n_scale = MIN(scale, (*result)->n_scale);
}
bc_free_num (&power);
return true;
}

/* This is used internally by BCMath */
Expand Down
17 changes: 17 additions & 0 deletions ext/bcmath/tests/gh16236.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
--TEST--
GH-16236 Segmentation fault (access null pointer) in ext/bcmath/libbcmath/src/rmzero.c:50
--EXTENSIONS--
bcmath
--FILE--
<?php
/**
* The existing bcpow() specification returns 0 for negative powers.
* This is mathematically incorrect and will need to be changed to raise an error at some point.
* This test is to ensure the existing specifications until the specifications are changed.
*/
bcpow('0', '-2');

echo 'done!';
?>
--EXPECT--
done!
41 changes: 41 additions & 0 deletions ext/bcmath/tests/number/methods/pow_div_by_zero.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
--TEST--
BcMath\Number pow(): negative power of zero
--EXTENSIONS--
bcmath
--FILE--
<?php

$values = [0, '0'];

$exponents = [
[-3, 'int'],
['-2', 'string'],
[new BcMath\Number('-2'), 'object'],
];

foreach ($values as $value) {
$num = new BcMath\Number($value);

foreach ($exponents as [$exponent, $type]) {
echo "{$value} ** {$exponent}: {$type}\n";
try {
$num->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
41 changes: 41 additions & 0 deletions ext/bcmath/tests/number/operators/pow_div_by_zero.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
--TEST--
BcMath\Number pow: negative power of zero by operator
--EXTENSIONS--
bcmath
--FILE--
<?php

$values = [0, '0'];

$exponents = [
[-3, 'int'],
['-2', 'string'],
[new BcMath\Number('-2'), 'object'],
];

foreach ($values as $value) {
$num = new BcMath\Number($value);

foreach ($exponents as [$exponent, $type]) {
echo "{$value} ** {$exponent}: {$type}\n";
try {
$num ** $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

0 comments on commit c048993

Please sign in to comment.