Skip to content

Commit 36f5d71

Browse files
committed
Fix leak on foreach by ref assign to property
In this case we ended up creating an ASSIGN_OBJ_REF with VAR result operand, which was not freed. Fix this by implementing assign_ref_znode the same was as assign_znode, i.e. performing an assignment with result and then freeing the result, which will result mark the result as UNUSED. This is more robust than the special handling for result == NULL that was used before. This fixes one of the issues reported in bug #81190.
1 parent 334387b commit 36f5d71

File tree

2 files changed

+16
-7
lines changed

2 files changed

+16
-7
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
--TEST--
2+
Foreach by ref assignment to property
3+
--FILE--
4+
<?php
5+
$obj = new stdClass;
6+
foreach ([0] as &$obj->prop) {
7+
var_dump($obj->prop);
8+
}
9+
?>
10+
--EXPECT--
11+
int(0)

Zend/zend_compile.c

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2888,17 +2888,13 @@ void zend_compile_assign_ref(znode *result, zend_ast *ast) /* {{{ */
28882888
opline->extended_value &= ~ZEND_FETCH_REF;
28892889
opline->extended_value |= flags;
28902890
zend_emit_op_data(&source_node);
2891-
if (result != NULL) {
2892-
*result = target_node;
2893-
}
2891+
*result = target_node;
28942892
} else if (opline && opline->opcode == ZEND_FETCH_STATIC_PROP_W) {
28952893
opline->opcode = ZEND_ASSIGN_STATIC_PROP_REF;
28962894
opline->extended_value &= ~ZEND_FETCH_REF;
28972895
opline->extended_value |= flags;
28982896
zend_emit_op_data(&source_node);
2899-
if (result != NULL) {
2900-
*result = target_node;
2901-
}
2897+
*result = target_node;
29022898
} else {
29032899
opline = zend_emit_op(result, ZEND_ASSIGN_REF, &target_node, &source_node);
29042900
opline->extended_value = flags;
@@ -2908,9 +2904,11 @@ void zend_compile_assign_ref(znode *result, zend_ast *ast) /* {{{ */
29082904

29092905
static inline void zend_emit_assign_ref_znode(zend_ast *var_ast, znode *value_node) /* {{{ */
29102906
{
2907+
znode dummy_node;
29112908
zend_ast *assign_ast = zend_ast_create(ZEND_AST_ASSIGN_REF, var_ast,
29122909
zend_ast_create_znode(value_node));
2913-
zend_compile_assign_ref(NULL, assign_ast);
2910+
zend_compile_assign_ref(&dummy_node, assign_ast);
2911+
zend_do_free(&dummy_node);
29142912
}
29152913
/* }}} */
29162914

0 commit comments

Comments
 (0)