1
0
mirror of https://github.com/php/php-src.git synced 2026-04-23 07:58:20 +02:00

Fix use-after-free in assign-ref compilation

zend_emit_op_data may reallocate the op_array, so the assignment
of the RETURNS_FUNCTION flag may happen on an outdated opline.

Restructure the code a bit to set the flag before calling
zend_emit_op_data().
This commit is contained in:
Nikita Popov
2019-09-13 17:09:24 +02:00
parent c25104bb5b
commit 4226c8247f
+6 -6
View File
@@ -2822,7 +2822,7 @@ void zend_compile_assign_ref(znode *result, zend_ast *ast) /* {{{ */
znode target_node, source_node;
zend_op *opline;
uint32_t offset;
uint32_t offset, flags;
if (is_this_fetch(target_ast)) {
zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
@@ -2851,9 +2851,12 @@ void zend_compile_assign_ref(znode *result, zend_ast *ast) /* {{{ */
zend_error_noreturn(E_COMPILE_ERROR, "Cannot use result of built-in function in write context");
}
flags = zend_is_call(source_ast) ? ZEND_RETURNS_FUNCTION : 0;
if (opline && opline->opcode == ZEND_FETCH_OBJ_W) {
opline->opcode = ZEND_ASSIGN_OBJ_REF;
opline->extended_value &= ~ZEND_FETCH_REF;
opline->extended_value |= flags;
zend_emit_op_data(&source_node);
if (result != NULL) {
*result = target_node;
@@ -2861,17 +2864,14 @@ void zend_compile_assign_ref(znode *result, zend_ast *ast) /* {{{ */
} else if (opline && opline->opcode == ZEND_FETCH_STATIC_PROP_W) {
opline->opcode = ZEND_ASSIGN_STATIC_PROP_REF;
opline->extended_value &= ~ZEND_FETCH_REF;
opline->extended_value |= flags;
zend_emit_op_data(&source_node);
if (result != NULL) {
*result = target_node;
}
} else {
opline = zend_emit_op(result, ZEND_ASSIGN_REF, &target_node, &source_node);
opline->extended_value = 0;
}
if (zend_is_call(source_ast)) {
opline->extended_value |= ZEND_RETURNS_FUNCTION;
opline->extended_value = flags;
}
}
/* }}} */