diff options
author | Xinchen Hui <laruence@gmail.com> | 2016-06-28 15:36:50 +0800 |
---|---|---|
committer | Xinchen Hui <laruence@gmail.com> | 2016-06-28 15:36:50 +0800 |
commit | ce7e180a04009e821c87e7ae2b704294a2a97c03 (patch) | |
tree | 7b3d6f67754206b0e6e2314916428c83958abb8f | |
parent | de7a6b1232ac863fb604cdec361a6b7e8e94384e (diff) | |
download | php-git-ce7e180a04009e821c87e7ae2b704294a2a97c03.tar.gz |
Fixed bug #72508 (strange references after recursive function call and "switch" statement)
-rw-r--r-- | NEWS | 4 | ||||
-rw-r--r-- | Zend/tests/bug72508.phpt | 30 | ||||
-rw-r--r-- | Zend/zend_compile.c | 20 |
3 files changed, 52 insertions, 2 deletions
@@ -2,6 +2,10 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? 2016 PHP 7.0.9 +- Core: + . Fixed bug #72508 (strange references after recursive function call and + "switch" statement). (Laruence) + - CLI: . Fixed bug #72484 (SCRIPT_FILENAME shows wrong path if the user specify router.php). (Laruence) diff --git a/Zend/tests/bug72508.phpt b/Zend/tests/bug72508.phpt new file mode 100644 index 0000000000..60196bfc18 --- /dev/null +++ b/Zend/tests/bug72508.phpt @@ -0,0 +1,30 @@ +--TEST-- +Bug #72508 (strange references after recursive function call and "switch" statement) +--FILE-- +<?php +function a ($option) { + b($option['bla']); + c($option); + var_dump($option); +} +function b (&$string) { + $string = 'changed'; +} +function c ($option) { + switch ($option['bla']) { + default: + $copy = $option; + $copy['bla'] = 'copy'; + break; + case NULL: + break; + } +} +a(array('bla' => 'fasel')); + +?> +--EXPECT-- +array(1) { + ["bla"]=> + string(7) "changed" +} diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 593c19e015..3af1fb3861 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -4035,16 +4035,32 @@ void zend_compile_switch(zend_ast *ast) /* {{{ */ znode expr_node, case_node; zend_op *opline; - uint32_t *jmpnz_opnums = safe_emalloc(sizeof(uint32_t), cases->children, 0); - uint32_t opnum_default_jmp; + uint32_t *jmpnz_opnums, opnum_default_jmp; zend_compile_expr(&expr_node, expr_ast); + if (cases->children == 1 && cases->child[0]->child[0] == NULL) { + /* we have to take care about the case that only have one default branch, + * expr result will not be unrefed in this case, but it should be like in ZEND_CASE */ + zend_ast *stmt_ast = cases->child[0]->child[1]; + if (expr_node.op_type == IS_VAR || expr_node.op_type == IS_TMP_VAR) { + zend_emit_op(NULL, ZEND_FREE, &expr_node, NULL); + } else if (expr_node.op_type == IS_CONST) { + zval_dtor(&expr_node.u.constant); + } + + zend_begin_loop(ZEND_NOP, NULL); + zend_compile_stmt(stmt_ast); + zend_end_loop(get_next_op_number(CG(active_op_array))); + return; + } + zend_begin_loop(ZEND_FREE, &expr_node); case_node.op_type = IS_TMP_VAR; case_node.u.op.var = get_temporary_variable(CG(active_op_array)); + jmpnz_opnums = safe_emalloc(sizeof(uint32_t), cases->children, 0); for (i = 0; i < cases->children; ++i) { zend_ast *case_ast = cases->child[i]; zend_ast *cond_ast = case_ast->child[0]; |