Skip to content

Division by zero for pow() with zero base and negative exponent #11

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

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
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
711 changes: 710 additions & 1 deletion Zend/tests/runtime_compile_time_binary_operands.phpt

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions Zend/zend_compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -8902,6 +8902,10 @@ ZEND_API bool zend_binary_op_produces_error(uint32_t opcode, const zval *op1, co
/* Division by zero throws an error. */
return 1;
}
if ((opcode == ZEND_POW) && zval_get_long(op1) == 0 && zval_get_long(op2) < 0) {
/* 0 ** (<=0) throws a division by zero error. */
zend_error(E_DEPRECATED, "Power of base 0 and negative exponent is deprecated");
}
if ((opcode == ZEND_SL || opcode == ZEND_SR) && zval_get_long(op2) < 0) {
/* Shift by negative number throws an error. */
return 1;
Expand Down
41 changes: 34 additions & 7 deletions Zend/zend_operators.c
Original file line number Diff line number Diff line change
Expand Up @@ -1287,6 +1287,21 @@ ZEND_API zend_result ZEND_FASTCALL mul_function(zval *result, zval *op1, zval *o
}
/* }}} */

static void ZEND_COLD zend_power_base_0_exponent_lt_eq_0_error(void)
{
zend_error(E_DEPRECATED, "Power of base 0 and negative exponent is deprecated");
}

static zend_result safe_pow(double *result, double base, double exponent)
{
if (base == 0.0 && exponent < 0.0) {
zend_power_base_0_exponent_lt_eq_0_error();
}

*result = pow(base, exponent);
return SUCCESS;
}

static zend_result ZEND_FASTCALL pow_function_base(zval *result, zval *op1, zval *op2) /* {{{ */
{
uint8_t type_pair = TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2));
Expand All @@ -1311,32 +1326,44 @@ static zend_result ZEND_FASTCALL pow_function_base(zval *result, zval *op1, zval
--i;
ZEND_SIGNED_MULTIPLY_LONG(l1, l2, l1, dval, overflow);
if (overflow) {
ZVAL_DOUBLE(result, dval * pow(l2, i));
double pow_result;
safe_pow(&pow_result, l2, i);
ZVAL_DOUBLE(result, dval * pow_result);
return SUCCESS;
}
} else {
i /= 2;
ZEND_SIGNED_MULTIPLY_LONG(l2, l2, l2, dval, overflow);
if (overflow) {
ZVAL_DOUBLE(result, (double)l1 * pow(dval, i));
double pow_result;
safe_pow(&pow_result, dval, i);
ZVAL_DOUBLE(result, (double)l1 * pow_result);
return SUCCESS;
}
}
}
/* i == 0 */
ZVAL_LONG(result, l1);
} else {
ZVAL_DOUBLE(result, pow((double)Z_LVAL_P(op1), (double)Z_LVAL_P(op2)));
double pow_result;
safe_pow(&pow_result, (double)Z_LVAL_P(op1), (double)Z_LVAL_P(op2));
ZVAL_DOUBLE(result, pow_result);
}
return SUCCESS;
} else if (EXPECTED(type_pair == TYPE_PAIR(IS_DOUBLE, IS_DOUBLE))) {
ZVAL_DOUBLE(result, pow(Z_DVAL_P(op1), Z_DVAL_P(op2)));
double pow_result;
safe_pow(&pow_result, Z_DVAL_P(op1), Z_DVAL_P(op2));
ZVAL_DOUBLE(result, pow_result);
return SUCCESS;
} else if (EXPECTED(type_pair == TYPE_PAIR(IS_LONG, IS_DOUBLE))) {
ZVAL_DOUBLE(result, pow((double)Z_LVAL_P(op1), Z_DVAL_P(op2)));
double pow_result;
safe_pow(&pow_result, (double)Z_LVAL_P(op1), Z_DVAL_P(op2));
ZVAL_DOUBLE(result, pow_result);
return SUCCESS;
} else if (EXPECTED(type_pair == TYPE_PAIR(IS_DOUBLE, IS_LONG))) {
ZVAL_DOUBLE(result, pow(Z_DVAL_P(op1), (double)Z_LVAL_P(op2)));
double pow_result;
safe_pow(&pow_result, Z_DVAL_P(op1), (double)Z_LVAL_P(op2));
ZVAL_DOUBLE(result, pow_result);
return SUCCESS;
} else {
return FAILURE;
Expand Down Expand Up @@ -1372,7 +1399,7 @@ ZEND_API zend_result ZEND_FASTCALL pow_function(zval *result, zval *op1, zval *o
return SUCCESS;
}

ZEND_ASSERT(0 && "Operation must succeed");
ZVAL_UNDEF(result);
return FAILURE;
}
/* }}} */
Expand Down
4 changes: 3 additions & 1 deletion ext/standard/tests/math/bug45712.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ var_dump($inf==='abc');
var_dump($inf===$inf);

?>
--EXPECT--
--EXPECTF--
float(NAN)
bool(true)
bool(false)
Expand All @@ -57,6 +57,8 @@ bool(false)
bool(false)
bool(false)
bool(false)

Deprecated: Power of base 0 and negative exponent is deprecated in %s on line %d
float(INF)
bool(true)
bool(false)
Expand Down
33 changes: 18 additions & 15 deletions ext/standard/tests/math/is_finite_basic.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,29 @@
Test is_finite() - basic function test is_finite()
--FILE--
<?php
$values = array(234,
-234,
23.45e1,
-23.45e1,
0xEA,
0352,
"234",
"234.5",
"23.45e1",
true,
false,
pow(0, -2),
acos(1.01));
;
$values = [
234,
-234,
23.45e1,
-23.45e1,
0xea,
0352,
"234",
"234.5",
"23.45e1",
true,
false,
pow(0, -2),
acos(1.01),
];
for ($i = 0; $i < count($values); $i++) {
$res = is_finite($values[$i]);
var_dump($res);
}
?>
--EXPECT--
--EXPECTF--

Deprecated: Power of base 0 and negative exponent is deprecated in %s on line %d
bool(true)
bool(true)
bool(true)
Expand Down
3 changes: 2 additions & 1 deletion ext/standard/tests/math/is_infinite_basic.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ for ($i = 0; $i < count($values); $i++) {
var_dump($res);
}
?>
--EXPECT--
--EXPECTF--
Deprecated: Power of base 0 and negative exponent is deprecated in %s on line %d
bool(false)
bool(false)
bool(false)
Expand Down
32 changes: 17 additions & 15 deletions ext/standard/tests/math/is_nan_basic.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,30 @@
Test is_nan() - basic function test is_nan()
--FILE--
<?php
$values = array(234,
-234,
23.45e1,
-23.45e1,
0xEA,
0352,
"234",
"234.5",
"23.45e1",
true,
false,
pow(0, -2),
acos(1.01));

$values = [
234,
-234,
23.45e1,
-23.45e1,
0xea,
0352,
"234",
"234.5",
"23.45e1",
true,
false,
pow(0, -2),
acos(1.01),
];

for ($i = 0; $i < count($values); $i++) {
$res = is_nan($values[$i]);
var_dump($res);
}

?>
--EXPECT--
--EXPECTF--
Deprecated: Power of base 0 and negative exponent is deprecated in %s on line %d
bool(false)
bool(false)
bool(false)
Expand Down
18 changes: 17 additions & 1 deletion ext/standard/tests/math/pow.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ var_dump(epsilon_equal( LONG_MAX*LONG_MAX , pow(LONG_MAX,2.0) ));
var_dump(epsilon_equal( LONG_MIN*LONG_MIN , pow(LONG_MIN,2.0) ));

?>
--EXPECT--
--EXPECTF--
1,1,0,0
bool(true)
bool(true)
Expand All @@ -155,7 +155,11 @@ bool(true)
bool(true)
bool(true)
bool(true)

Deprecated: Power of base 0 and negative exponent is deprecated in %s on line %d
bool(true)

Deprecated: Power of base 0 and negative exponent is deprecated in %s on line %d
bool(true)
bool(true)
bool(true)
Expand All @@ -180,7 +184,11 @@ bool(true)
bool(true)
bool(true)
bool(true)

Deprecated: Power of base 0 and negative exponent is deprecated in %s on line %d
bool(true)

Deprecated: Power of base 0 and negative exponent is deprecated in %s on line %d
bool(true)
bool(true)
bool(true)
Expand Down Expand Up @@ -212,7 +220,11 @@ bool(true)
bool(true)
bool(true)
bool(true)

Deprecated: Power of base 0 and negative exponent is deprecated in %s on line %d
bool(true)

Deprecated: Power of base 0 and negative exponent is deprecated in %s on line %d
bool(true)
bool(true)
bool(true)
Expand All @@ -237,7 +249,11 @@ bool(true)
bool(true)
bool(true)
bool(true)

Deprecated: Power of base 0 and negative exponent is deprecated in %s on line %d
bool(true)

Deprecated: Power of base 0 and negative exponent is deprecated in %s on line %d
bool(true)
bool(true)
bool(true)
Expand Down
40 changes: 40 additions & 0 deletions ext/standard/tests/math/pow_divisionbyzero.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
--TEST--
pow() division by zero error
--FILE--
<?php

var_dump(pow(0, -0));
var_dump(pow(0.0, -0));
var_dump(pow(0, -0.0));
var_dump(pow(0.0, -0.0));
var_dump(pow(0, -0.01));
var_dump(pow(0.0, -0.01));
var_dump(pow(0, -1));
var_dump(pow(0.0, -1));
var_dump(pow(0, -1.1));
var_dump(pow(0.0, -1.1));

?>
--EXPECTF--
int(1)
float(1)
float(1)
float(1)

Deprecated: Power of base 0 and negative exponent is deprecated in %s on line %d
float(INF)

Deprecated: Power of base 0 and negative exponent is deprecated in %s on line %d
float(INF)

Deprecated: Power of base 0 and negative exponent is deprecated in %s on line %d
float(INF)

Deprecated: Power of base 0 and negative exponent is deprecated in %s on line %d
float(INF)

Deprecated: Power of base 0 and negative exponent is deprecated in %s on line %d
float(INF)

Deprecated: Power of base 0 and negative exponent is deprecated in %s on line %d
float(INF)