Skip to content

Commit 307e476

Browse files
committed
Fixed bug #81216 (Nullsafe operator leaks dynamic property name)
Fixes oss-fuzz #38542
1 parent 929d847 commit 307e476

File tree

3 files changed

+27
-9
lines changed

3 files changed

+27
-9
lines changed

NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ PHP NEWS
22
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
33
?? ??? ????, PHP 8.1.2
44

5+
- Core:
6+
. Fixed bug #81216 (Nullsafe operator leaks dynamic property name). (Dmitry)
7+
58
- MBString:
69
. Fixed bug #81693 (mb_check_encoding(7bit) segfaults). (cmb)
710

Zend/tests/bug81216.phpt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
--TEST--
2+
Bug #81216: Nullsafe operator leaks dynamic property name
3+
--FILE--
4+
<?php
5+
$str = "foo";
6+
null?->{$str . "bar"};
7+
?>
8+
DONE
9+
--EXPECT--
10+
DONE

Zend/zend_compile.c

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2258,11 +2258,9 @@ static zend_op *zend_delayed_compile_end(uint32_t offset) /* {{{ */
22582258

22592259
ZEND_ASSERT(count >= offset);
22602260
for (i = offset; i < count; ++i) {
2261-
opline = get_next_op();
2262-
memcpy(opline, &oplines[i], sizeof(zend_op));
2263-
if (opline->opcode == ZEND_JMP_NULL) {
2264-
uint32_t opnum = get_next_op_number() - 1;
2265-
zend_stack_push(&CG(short_circuiting_opnums), &opnum);
2261+
if (oplines[i].opcode != ZEND_NOP) {
2262+
opline = get_next_op();
2263+
memcpy(opline, &oplines[i], sizeof(zend_op));
22662264
}
22672265
}
22682266

@@ -2890,11 +2888,18 @@ static zend_op *zend_delayed_compile_prop(znode *result, zend_ast *ast, uint32_t
28902888
opline = zend_delayed_compile_var(&obj_node, obj_ast, type, 0);
28912889
zend_separate_if_call_and_write(&obj_node, obj_ast, type);
28922890
if (nullsafe) {
2893-
/* We will push to the short_circuiting_opnums stack in zend_delayed_compile_end(). */
2894-
opline = zend_delayed_emit_op(NULL, ZEND_JMP_NULL, &obj_node, NULL);
2895-
if (opline->op1_type == IS_CONST) {
2896-
Z_TRY_ADDREF_P(CT_CONSTANT(opline->op1));
2891+
/* Flush delayed oplines */
2892+
zend_op *opline = NULL, *oplines = zend_stack_base(&CG(delayed_oplines_stack));
2893+
uint32_t i, count = zend_stack_count(&CG(delayed_oplines_stack));
2894+
2895+
for (i = 0; i < count; ++i) {
2896+
if (oplines[i].opcode != ZEND_NOP) {
2897+
opline = get_next_op();
2898+
memcpy(opline, &oplines[i], sizeof(zend_op));
2899+
oplines[i].opcode = ZEND_NOP;
2900+
}
28972901
}
2902+
zend_emit_jmp_null(&obj_node);
28982903
}
28992904
}
29002905

0 commit comments

Comments
 (0)