Skip to content

Commit ce6c57f

Browse files
committed
Fix OSS-Fuzz #418106144
The VM assumes that an exception must be handled when the AST evaluation returns FAILURE. However, the comparison functions always return SUCCESS even if an exception happened. This can be fixed in zend_ast_evaluate_inner() or we can make is_smaller_function() etc check for the exception. I chose the former to avoid impact or API breaks. Perhaps in the future the comparison functions should either return void or return whether an exception happened, as to be not misleading.
1 parent 8e5b312 commit ce6c57f

File tree

2 files changed

+22
-1
lines changed

2 files changed

+22
-1
lines changed

Zend/tests/gh418106144.phpt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
--TEST--
2+
OSS-Fuzz #418106144
3+
--FILE--
4+
<?php
5+
6+
class Foo {
7+
function __toString(){}
8+
}
9+
function test($y=new Foo>''){
10+
var_dump();
11+
}
12+
try {
13+
test();
14+
} catch (TypeError $e) {
15+
echo $e->getMessage(), "\n";
16+
}
17+
18+
?>
19+
--EXPECT--
20+
Foo::__toString(): Return value must be of type string, none returned

Zend/zend_ast.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -564,9 +564,10 @@ ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate_inner(
564564
/* op1 > op2 is the same as op2 < op1 */
565565
binary_op_type op = ast->kind == ZEND_AST_GREATER
566566
? is_smaller_function : is_smaller_or_equal_function;
567-
ret = op(result, &op2, &op1);
567+
op(result, &op2, &op1);
568568
zval_ptr_dtor_nogc(&op1);
569569
zval_ptr_dtor_nogc(&op2);
570+
ret = EG(exception) ? FAILURE : SUCCESS;
570571
}
571572
break;
572573
case ZEND_AST_UNARY_OP:

0 commit comments

Comments
 (0)