summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXinchen Hui <laruence@gmail.com>2016-06-28 15:36:50 +0800
committerXinchen Hui <laruence@gmail.com>2016-06-28 15:36:50 +0800
commitce7e180a04009e821c87e7ae2b704294a2a97c03 (patch)
tree7b3d6f67754206b0e6e2314916428c83958abb8f
parentde7a6b1232ac863fb604cdec361a6b7e8e94384e (diff)
downloadphp-git-ce7e180a04009e821c87e7ae2b704294a2a97c03.tar.gz
Fixed bug #72508 (strange references after recursive function call and "switch" statement)
-rw-r--r--NEWS4
-rw-r--r--Zend/tests/bug72508.phpt30
-rw-r--r--Zend/zend_compile.c20
3 files changed, 52 insertions, 2 deletions
diff --git a/NEWS b/NEWS
index 816a20f451..33e4f5f015 100644
--- a/NEWS
+++ b/NEWS
@@ -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];