Skip to content

Commit c97885b

Browse files
committed
Merge branch 'PHP-8.3'
* PHP-8.3: Factor out common check for short-circuited ast Fix OSS-Fuzz #69765: Yield reference to nullsafe chain
2 parents 212b283 + 015b519 commit c97885b

File tree

2 files changed

+22
-10
lines changed

2 files changed

+22
-10
lines changed

Zend/tests/oss-fuzz-69765.phpt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
--TEST--
2+
OSS-Fuzz #69765: yield reference to nullsafe chain
3+
--FILE--
4+
<?php
5+
function &test($object) {
6+
yield $object->y?->y;
7+
}
8+
?>
9+
--EXPECTF--
10+
Fatal error: Cannot take reference of a nullsafe chain in %s on line %d

Zend/zend_compile.c

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2460,6 +2460,13 @@ static bool zend_ast_is_short_circuited(const zend_ast *ast)
24602460
}
24612461
}
24622462

2463+
static void zend_assert_not_short_circuited(const zend_ast *ast)
2464+
{
2465+
if (zend_ast_is_short_circuited(ast)) {
2466+
zend_error_noreturn(E_COMPILE_ERROR, "Cannot take reference of a nullsafe chain");
2467+
}
2468+
}
2469+
24632470
/* Mark nodes that are an inner part of a short-circuiting chain.
24642471
* We should not perform a "commit" on them, as it will be performed by the outer-most node.
24652472
* We do this to avoid passing down an argument in various compile functions. */
@@ -3463,9 +3470,8 @@ static void zend_compile_assign(znode *result, zend_ast *ast) /* {{{ */
34633470
if (!zend_is_variable_or_call(expr_ast)) {
34643471
zend_error_noreturn(E_COMPILE_ERROR,
34653472
"Cannot assign reference to non referenceable value");
3466-
} else if (zend_ast_is_short_circuited(expr_ast)) {
3467-
zend_error_noreturn(E_COMPILE_ERROR,
3468-
"Cannot take reference of a nullsafe chain");
3473+
} else {
3474+
zend_assert_not_short_circuited(expr_ast);
34693475
}
34703476

34713477
zend_compile_var(&expr_node, expr_ast, BP_VAR_W, 1);
@@ -3507,9 +3513,7 @@ static void zend_compile_assign_ref(znode *result, zend_ast *ast) /* {{{ */
35073513
zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
35083514
}
35093515
zend_ensure_writable_variable(target_ast);
3510-
if (zend_ast_is_short_circuited(source_ast)) {
3511-
zend_error_noreturn(E_COMPILE_ERROR, "Cannot take reference of a nullsafe chain");
3512-
}
3516+
zend_assert_not_short_circuited(source_ast);
35133517
if (is_globals_fetch(source_ast)) {
35143518
zend_error_noreturn(E_COMPILE_ERROR, "Cannot acquire reference to $GLOBALS");
35153519
}
@@ -5543,10 +5547,7 @@ static void zend_compile_return(zend_ast *ast) /* {{{ */
55435547
expr_node.op_type = IS_CONST;
55445548
ZVAL_NULL(&expr_node.u.constant);
55455549
} else if (by_ref && zend_is_variable(expr_ast)) {
5546-
if (zend_ast_is_short_circuited(expr_ast)) {
5547-
zend_error_noreturn(E_COMPILE_ERROR, "Cannot take reference of a nullsafe chain");
5548-
}
5549-
5550+
zend_assert_not_short_circuited(expr_ast);
55505551
zend_compile_var(&expr_node, expr_ast, BP_VAR_W, 1);
55515552
} else {
55525553
zend_compile_expr(&expr_node, expr_ast);
@@ -9936,6 +9937,7 @@ static void zend_compile_yield(znode *result, zend_ast *ast) /* {{{ */
99369937

99379938
if (value_ast) {
99389939
if (returns_by_ref && zend_is_variable(value_ast)) {
9940+
zend_assert_not_short_circuited(value_ast);
99399941
zend_compile_var(&value_node, value_ast, BP_VAR_W, 1);
99409942
} else {
99419943
zend_compile_expr(&value_node, value_ast);

0 commit comments

Comments
 (0)