Skip to content

Commit 540fed1

Browse files
committed
Fix leak on div by zero compound assignment with coercion
The result == op1 check did not work properly here, because op1 was &op1_copy at this point. Move the division by zero reporting out of the _base function, so it can check the original op1.
1 parent b976bc4 commit 540fed1

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
@@ -1253,15 +1253,16 @@ ZEND_API zend_result ZEND_FASTCALL pow_function(zval *result, zval *op1, zval *o
12531253
}
12541254
/* }}} */
12551255

1256-
/* Returns SUCCESS/FAILURE/TYPES_NOT_HANDLED */
1256+
/* Returns SUCCESS/TYPES_NOT_HANDLED/DIV_BY_ZERO */
12571257
#define TYPES_NOT_HANDLED 1
1258+
#define DIV_BY_ZERO 2
12581259
static int ZEND_FASTCALL div_function_base(zval *result, zval *op1, zval *op2) /* {{{ */
12591260
{
12601261
zend_uchar type_pair = TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2));
12611262

12621263
if (EXPECTED(type_pair == TYPE_PAIR(IS_LONG, IS_LONG))) {
12631264
if (Z_LVAL_P(op2) == 0) {
1264-
goto division_by_0;
1265+
return DIV_BY_ZERO;
12651266
} else if (Z_LVAL_P(op2) == -1 && Z_LVAL_P(op1) == ZEND_LONG_MIN) {
12661267
/* Prevent overflow error/crash */
12671268
ZVAL_DOUBLE(result, (double) ZEND_LONG_MIN / -1);
@@ -1275,31 +1276,25 @@ static int ZEND_FASTCALL div_function_base(zval *result, zval *op1, zval *op2) /
12751276
return SUCCESS;
12761277
} else if (EXPECTED(type_pair == TYPE_PAIR(IS_DOUBLE, IS_DOUBLE))) {
12771278
if (Z_DVAL_P(op2) == 0) {
1278-
goto division_by_0;
1279+
return DIV_BY_ZERO;
12791280
}
12801281
ZVAL_DOUBLE(result, Z_DVAL_P(op1) / Z_DVAL_P(op2));
12811282
return SUCCESS;
12821283
} else if (EXPECTED(type_pair == TYPE_PAIR(IS_DOUBLE, IS_LONG))) {
12831284
if (Z_LVAL_P(op2) == 0) {
1284-
goto division_by_0;
1285+
return DIV_BY_ZERO;
12851286
}
12861287
ZVAL_DOUBLE(result, Z_DVAL_P(op1) / (double)Z_LVAL_P(op2));
12871288
return SUCCESS;
12881289
} else if (EXPECTED(type_pair == TYPE_PAIR(IS_LONG, IS_DOUBLE))) {
12891290
if (Z_DVAL_P(op2) == 0) {
1290-
goto division_by_0;
1291+
return DIV_BY_ZERO;
12911292
}
12921293
ZVAL_DOUBLE(result, (double)Z_LVAL_P(op1) / Z_DVAL_P(op2));
12931294
return SUCCESS;
12941295
} else {
12951296
return TYPES_NOT_HANDLED;
12961297
}
1297-
division_by_0:
1298-
if (result != op1) {
1299-
ZVAL_UNDEF(result);
1300-
}
1301-
zend_throw_error(zend_ce_division_by_zero_error, "Division by zero");
1302-
return FAILURE;
13031298
}
13041299
/* }}} */
13051300

@@ -1309,8 +1304,12 @@ ZEND_API zend_result ZEND_FASTCALL div_function(zval *result, zval *op1, zval *o
13091304
ZVAL_DEREF(op2);
13101305

13111306
int retval = div_function_base(result, op1, op2);
1312-
if (retval != TYPES_NOT_HANDLED) {
1313-
return retval;
1307+
if (EXPECTED(retval == SUCCESS)) {
1308+
return SUCCESS;
1309+
}
1310+
1311+
if (UNEXPECTED(retval == DIV_BY_ZERO)) {
1312+
goto div_by_zero;
13141313
}
13151314

13161315
ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_DIV);
@@ -1330,8 +1329,17 @@ ZEND_API zend_result ZEND_FASTCALL div_function(zval *result, zval *op1, zval *o
13301329
}
13311330

13321331
retval = div_function_base(result, &op1_copy, &op2_copy);
1333-
ZEND_ASSERT(retval != TYPES_NOT_HANDLED && "Types should be handled");
1334-
return retval;
1332+
if (retval == SUCCESS) {
1333+
return SUCCESS;
1334+
}
1335+
1336+
div_by_zero:
1337+
ZEND_ASSERT(retval == DIV_BY_ZERO && "TYPES_NOT_HANDLED should not occur here");
1338+
if (result != op1) {
1339+
ZVAL_UNDEF(result);
1340+
}
1341+
zend_throw_error(zend_ce_division_by_zero_error, "Division by zero");
1342+
return FAILURE;
13351343
}
13361344
/* }}} */
13371345

0 commit comments

Comments
 (0)