summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2019-10-04 10:38:11 +0200
committerNikita Popov <nikita.ppv@gmail.com>2019-10-04 10:38:11 +0200
commit9659562cb5422099cc1286263e0ef883dab4d647 (patch)
treea43393131d12393e2e4fe34ac4335e18004a1887
parentf26b60a583efb064a8c082b780b9b186c43cac64 (diff)
downloadphp-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.phpt12
-rw-r--r--Zend/zend_compile.c9
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) /* {{{ */