Skip to content

Commit d3deb82

Browse files
committed
Merge branch 'PHP-8.0'
* PHP-8.0: Fix leak on div by zero compound assignment with coercion
2 parents adfa585 + 540fed1 commit d3deb82

File tree

2 files changed

+37
-15
lines changed

2 files changed

+37
-15
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
--TEST--
2+
Division by zero in compound operator with type coercion
3+
--FILE--
4+
<?php
5+
$x = 42;
6+
try {
7+
$$x /= 0;
8+
} catch (DivisionByZeroError $e) {
9+
echo $e->getMessage(), "\n";
10+
}
11+
?>
12+
--EXPECTF--
13+
Warning: Undefined variable $42 in %s on line %d
14+
Division by zero

Zend/zend_operators.c

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1297,15 +1297,16 @@ ZEND_API zend_result ZEND_FASTCALL pow_function(zval *result, zval *op1, zval *o
12971297
}
12981298
/* }}} */
12991299

1300-
/* Returns SUCCESS/FAILURE/TYPES_NOT_HANDLED */
1300+
/* Returns SUCCESS/TYPES_NOT_HANDLED/DIV_BY_ZERO */
13011301
#define TYPES_NOT_HANDLED 1
1302+
#define DIV_BY_ZERO 2
13021303
static int ZEND_FASTCALL div_function_base(zval *result, zval *op1, zval *op2) /* {{{ */
13031304
{
13041305
zend_uchar type_pair = TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2));
13051306

13061307
if (EXPECTED(type_pair == TYPE_PAIR(IS_LONG, IS_LONG))) {
13071308
if (Z_LVAL_P(op2) == 0) {
1308-
goto division_by_0;
1309+
return DIV_BY_ZERO;
13091310
} else if (Z_LVAL_P(op2) == -1 && Z_LVAL_P(op1) == ZEND_LONG_MIN) {
13101311
/* Prevent overflow error/crash */
13111312
ZVAL_DOUBLE(result, (double) ZEND_LONG_MIN / -1);
@@ -1319,31 +1320,25 @@ static int ZEND_FASTCALL div_function_base(zval *result, zval *op1, zval *op2) /
13191320
return SUCCESS;
13201321
} else if (EXPECTED(type_pair == TYPE_PAIR(IS_DOUBLE, IS_DOUBLE))) {
13211322
if (Z_DVAL_P(op2) == 0) {
1322-
goto division_by_0;
1323+
return DIV_BY_ZERO;
13231324
}
13241325
ZVAL_DOUBLE(result, Z_DVAL_P(op1) / Z_DVAL_P(op2));
13251326
return SUCCESS;
13261327
} else if (EXPECTED(type_pair == TYPE_PAIR(IS_DOUBLE, IS_LONG))) {
13271328
if (Z_LVAL_P(op2) == 0) {
1328-
goto division_by_0;
1329+
return DIV_BY_ZERO;
13291330
}
13301331
ZVAL_DOUBLE(result, Z_DVAL_P(op1) / (double)Z_LVAL_P(op2));
13311332
return SUCCESS;
13321333
} else if (EXPECTED(type_pair == TYPE_PAIR(IS_LONG, IS_DOUBLE))) {
13331334
if (Z_DVAL_P(op2) == 0) {
1334-
goto division_by_0;
1335+
return DIV_BY_ZERO;
13351336
}
13361337
ZVAL_DOUBLE(result, (double)Z_LVAL_P(op1) / Z_DVAL_P(op2));
13371338
return SUCCESS;
13381339
} else {
13391340
return TYPES_NOT_HANDLED;
13401341
}
1341-
division_by_0:
1342-
if (result != op1) {
1343-
ZVAL_UNDEF(result);
1344-
}
1345-
zend_throw_error(zend_ce_division_by_zero_error, "Division by zero");
1346-
return FAILURE;
13471342
}
13481343
/* }}} */
13491344

@@ -1353,8 +1348,12 @@ ZEND_API zend_result ZEND_FASTCALL div_function(zval *result, zval *op1, zval *o
13531348
ZVAL_DEREF(op2);
13541349

13551350
int retval = div_function_base(result, op1, op2);
1356-
if (retval != TYPES_NOT_HANDLED) {
1357-
return retval;
1351+
if (EXPECTED(retval == SUCCESS)) {
1352+
return SUCCESS;
1353+
}
1354+
1355+
if (UNEXPECTED(retval == DIV_BY_ZERO)) {
1356+
goto div_by_zero;
13581357
}
13591358

13601359
ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_DIV);
@@ -1374,8 +1373,17 @@ ZEND_API zend_result ZEND_FASTCALL div_function(zval *result, zval *op1, zval *o
13741373
}
13751374

13761375
retval = div_function_base(result, &op1_copy, &op2_copy);
1377-
ZEND_ASSERT(retval != TYPES_NOT_HANDLED && "Types should be handled");
1378-
return retval;
1376+
if (retval == SUCCESS) {
1377+
return SUCCESS;
1378+
}
1379+
1380+
div_by_zero:
1381+
ZEND_ASSERT(retval == DIV_BY_ZERO && "TYPES_NOT_HANDLED should not occur here");
1382+
if (result != op1) {
1383+
ZVAL_UNDEF(result);
1384+
}
1385+
zend_throw_error(zend_ce_division_by_zero_error, "Division by zero");
1386+
return FAILURE;
13791387
}
13801388
/* }}} */
13811389

0 commit comments

Comments
 (0)