Skip to content

Commit 9659562

Browse files
committed
Fix use-after-free with delayed interned memoized const operand
We should addref CONST operands during memoization, as they might be destroyed by later compilation, e.g. through interning.
1 parent f26b60a commit 9659562

File tree

2 files changed

+20
-1
lines changed

2 files changed

+20
-1
lines changed

Zend/tests/assign_coalesce_006.phpt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
--TEST--
2+
Null coalesce assign with memoized constant operand that is later interned (OSS-Fuzz #17903)
3+
--FILE--
4+
<?php
5+
$foo[__DIR__] ??= 42;
6+
var_dump($foo);
7+
?>
8+
--EXPECTF--
9+
array(1) {
10+
["%s"]=>
11+
int(42)
12+
}

Zend/zend_compile.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2054,6 +2054,9 @@ static void zend_compile_memoized_expr(znode *result, zend_ast *expr) /* {{{ */
20542054
} else if (result->op_type == IS_TMP_VAR) {
20552055
zend_emit_op_tmp(&memoized_result, ZEND_COPY_TMP, result, NULL);
20562056
} else {
2057+
if (result->op_type == IS_CONST) {
2058+
Z_TRY_ADDREF(result->u.constant);
2059+
}
20572060
memoized_result = *result;
20582061
}
20592062

@@ -7540,7 +7543,11 @@ void zend_compile_coalesce(znode *result, zend_ast *ast) /* {{{ */
75407543
/* }}} */
75417544

75427545
static void znode_dtor(zval *zv) {
7543-
efree(Z_PTR_P(zv));
7546+
znode *node = Z_PTR_P(zv);
7547+
if (node->op_type == IS_CONST) {
7548+
zval_ptr_dtor_nogc(&node->u.constant);
7549+
}
7550+
efree(node);
75447551
}
75457552

75467553
void zend_compile_assign_coalesce(znode *result, zend_ast *ast) /* {{{ */

0 commit comments

Comments
 (0)