diff options
author | Nikita Popov <nikita.ppv@gmail.com> | 2019-10-04 10:38:11 +0200 |
---|---|---|
committer | Nikita Popov <nikita.ppv@gmail.com> | 2019-10-04 10:38:11 +0200 |
commit | 9659562cb5422099cc1286263e0ef883dab4d647 (patch) | |
tree | a43393131d12393e2e4fe34ac4335e18004a1887 | |
parent | f26b60a583efb064a8c082b780b9b186c43cac64 (diff) | |
download | php-git-9659562cb5422099cc1286263e0ef883dab4d647.tar.gz |
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.
-rw-r--r-- | Zend/tests/assign_coalesce_006.phpt | 12 | ||||
-rw-r--r-- | Zend/zend_compile.c | 9 |
2 files changed, 20 insertions, 1 deletions
diff --git a/Zend/tests/assign_coalesce_006.phpt b/Zend/tests/assign_coalesce_006.phpt new file mode 100644 index 0000000000..dfe43b3c29 --- /dev/null +++ b/Zend/tests/assign_coalesce_006.phpt @@ -0,0 +1,12 @@ +--TEST-- +Null coalesce assign with memoized constant operand that is later interned (OSS-Fuzz #17903) +--FILE-- +<?php +$foo[__DIR__] ??= 42; +var_dump($foo); +?> +--EXPECTF-- +array(1) { + ["%s"]=> + int(42) +} diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 8f545ce51f..9132656d41 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -2054,6 +2054,9 @@ static void zend_compile_memoized_expr(znode *result, zend_ast *expr) /* {{{ */ } else if (result->op_type == IS_TMP_VAR) { zend_emit_op_tmp(&memoized_result, ZEND_COPY_TMP, result, NULL); } else { + if (result->op_type == IS_CONST) { + Z_TRY_ADDREF(result->u.constant); + } memoized_result = *result; } @@ -7540,7 +7543,11 @@ void zend_compile_coalesce(znode *result, zend_ast *ast) /* {{{ */ /* }}} */ static void znode_dtor(zval *zv) { - efree(Z_PTR_P(zv)); + znode *node = Z_PTR_P(zv); + if (node->op_type == IS_CONST) { + zval_ptr_dtor_nogc(&node->u.constant); + } + efree(node); } void zend_compile_assign_coalesce(znode *result, zend_ast *ast) /* {{{ */ |