Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed GH-16236: Fixed a bug in BcMath\Number::pow() and bcpow() when raising negative powers of 0. #16694

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer to continue using base


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');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a stub of this to https://wiki.php.net/rfc/deprecations_php_8_5 so it is not forgotten, or follow-up PR to make this emit an E_WARNING or Throwing on master.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Var_dup the result of this to see what the output is?


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