Skip to content

Commit

Permalink
Fix use after free on compound division by zero
Browse files Browse the repository at this point in the history
We can't destroy the result operand early, because the division
might fail, in which case we need to preserve the original value.
Place the division result in a temporary zval, and only copy it
on success.

Fixes oss-fuzz #35876.
  • Loading branch information
nikic committed Jul 7, 2021
1 parent 52a00fe commit 62ecf54
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 6 deletions.
16 changes: 16 additions & 0 deletions Zend/tests/div_by_zero_compound_refcounted.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
--TEST--
Division by zero in compound assignment with refcounted operand
--FILE--
<?php
$h = "1";
$h .= "2";
try {
$h /= 0;
} catch (DivisionByZeroError $e) {
echo $e->getMessage(), "\n";
}
var_dump($h);
?>
--EXPECT--
Division by zero
string(2) "12"
12 changes: 6 additions & 6 deletions Zend/zend_operators.c
Original file line number Diff line number Diff line change
Expand Up @@ -1314,7 +1314,7 @@ ZEND_API zend_result ZEND_FASTCALL div_function(zval *result, zval *op1, zval *o

ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_DIV);

zval op1_copy, op2_copy;
zval result_copy, op1_copy, op2_copy;
if (UNEXPECTED(zendi_try_convert_scalar_to_number(op1, &op1_copy) == FAILURE)
|| UNEXPECTED(zendi_try_convert_scalar_to_number(op2, &op2_copy) == FAILURE)) {
zend_binop_error("/", op1, op2);
Expand All @@ -1324,12 +1324,12 @@ ZEND_API zend_result ZEND_FASTCALL div_function(zval *result, zval *op1, zval *o
return FAILURE;
}

if (result == op1) {
zval_ptr_dtor(result);
}

retval = div_function_base(result, &op1_copy, &op2_copy);
retval = div_function_base(&result_copy, &op1_copy, &op2_copy);
if (retval == SUCCESS) {
if (result == op1) {
zval_ptr_dtor(result);
}
ZVAL_COPY_VALUE(result, &result_copy);
return SUCCESS;
}

Expand Down

0 comments on commit 62ecf54

Please sign in to comment.