From 98cb17f4fd19590f261c1916c0322a7aecc768b9 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 18 May 2025 14:59:27 +0200 Subject: [PATCH] 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. Closes GH-18589. --- NEWS | 1 + Zend/tests/gh418106144.phpt | 20 ++++++++++++++++++++ Zend/zend_ast.c | 3 ++- 3 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 Zend/tests/gh418106144.phpt diff --git a/NEWS b/NEWS index 4a4259867a3..f20891f344f 100644 --- a/NEWS +++ b/NEWS @@ -8,6 +8,7 @@ PHP NEWS . Partially fixed GH-18572 (nested object comparisons leading to stack overflow). (David Carlier) . Fixed OSS-Fuzz #417078295. (nielsdos) + . Fixed OSS-Fuzz #418106144. (nielsdos) - Curl: . Fixed GH-18460 (curl_easy_setopt with CURLOPT_USERPWD/CURLOPT_USERNAME/ diff --git a/Zend/tests/gh418106144.phpt b/Zend/tests/gh418106144.phpt new file mode 100644 index 00000000000..9357b0a179b --- /dev/null +++ b/Zend/tests/gh418106144.phpt @@ -0,0 +1,20 @@ +--TEST-- +OSS-Fuzz #418106144 +--FILE-- +''){ + var_dump(); +} +try { + test(); +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} + +?> +--EXPECT-- +Foo::__toString(): Return value must be of type string, none returned diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c index bf602449e5e..0fb50e2eae1 100644 --- a/Zend/zend_ast.c +++ b/Zend/zend_ast.c @@ -564,9 +564,10 @@ ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate_inner( /* op1 > op2 is the same as op2 < op1 */ binary_op_type op = ast->kind == ZEND_AST_GREATER ? is_smaller_function : is_smaller_or_equal_function; - ret = op(result, &op2, &op1); + op(result, &op2, &op1); zval_ptr_dtor_nogc(&op1); zval_ptr_dtor_nogc(&op2); + ret = EG(exception) ? FAILURE : SUCCESS; } break; case ZEND_AST_UNARY_OP: