]> granicus.if.org Git - php/commitdiff
Fixed bug #70228 (Memleak if return in finally block)
authorDmitry Stogov <dmitry@zend.com>
Tue, 7 Jun 2016 21:23:33 +0000 (00:23 +0300)
committerDmitry Stogov <dmitry@zend.com>
Tue, 7 Jun 2016 21:23:33 +0000 (00:23 +0300)
NEWS
Zend/tests/try/bug70228.phpt
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

diff --git a/NEWS b/NEWS
index a97fb14b03bf786c44fbe63cdff7c093522796fb..de57cceff7f97815f104ae03d38e572242c3116e 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -20,6 +20,7 @@ PHP                                                                        NEWS
   . Fixed bug #62814 (It is possible to stiffen child class members visibility).
     (Nikita)
   . Fixed bug #69989 (Generators don't participate in cycle GC). (Nikita)
+  . Fixed bug #70228 (Memleak if return in finally block). (Dmitry)
   . Fixed bug #71266 (Missing separation of properties HT in foreach etc).
     (Dmitry)
   . Fixed bug #71604 (Aborted Generators continue after nested finally).
index e85724765e6b902c318a893bee4d647378ab8726..8b812517a30545f2f58128207812b444a270c3b5 100644 (file)
@@ -1,7 +1,5 @@
 --TEST--
 Bug #70228 (memleak if return in finally block)
---XFAIL--
-See https://bugs.php.net/bug.php?id=70228
 --FILE--
 <?php
 
index 5922275762b67198ac813fc162b481c301e51a28..57de22e518202698facbedb10e898d7afd37bcb3 100644 (file)
@@ -7589,17 +7589,24 @@ ZEND_VM_HANDLER(159, ZEND_DISCARD_EXCEPTION, ANY, ANY)
 {
        USE_OPLINE
        zval *fast_call = EX_VAR(opline->op1.var);
+       SAVE_OPLINE();
+
+       /* check for incomplete RETURN statement */
+       if (fast_call->u2.lineno != (uint32_t)-1
+        && (EX(func)->op_array.opcodes[fast_call->u2.lineno + 1].opcode == ZEND_RETURN
+         || EX(func)->op_array.opcodes[fast_call->u2.lineno + 1].opcode == ZEND_RETURN_BY_REF)
+        && (EX(func)->op_array.opcodes[fast_call->u2.lineno + 1].op1_type & (IS_VAR|IS_TMP_VAR))) {
+               cleanup_live_vars(execute_data, fast_call->u2.lineno, fast_call->u2.lineno + 1);
+       }
 
        /* check for delayed exception */
        if (Z_OBJ_P(fast_call) != NULL) {
-               SAVE_OPLINE();
                /* discard the previously thrown exception */
                OBJ_RELEASE(Z_OBJ_P(fast_call));
                Z_OBJ_P(fast_call) = NULL;
-               ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
        }
 
-       ZEND_VM_NEXT_OPCODE();
+       ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
 }
 
 ZEND_VM_HANDLER(162, ZEND_FAST_CALL, JMP_ADDR, ANY)
index 4b0454b0e0c251677c059018561419ffd8ea56c2..21f94fd1a24600f591ef4437bf3bedb94ca09454 100644 (file)
@@ -1828,17 +1828,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DISCARD_EXCEPTION_SPEC_HANDLER
 {
        USE_OPLINE
        zval *fast_call = EX_VAR(opline->op1.var);
+       SAVE_OPLINE();
+
+       /* check for incomplete RETURN statement */
+       if (fast_call->u2.lineno != (uint32_t)-1
+        && (EX(func)->op_array.opcodes[fast_call->u2.lineno + 1].opcode == ZEND_RETURN
+         || EX(func)->op_array.opcodes[fast_call->u2.lineno + 1].opcode == ZEND_RETURN_BY_REF)
+        && (EX(func)->op_array.opcodes[fast_call->u2.lineno + 1].op1_type & (IS_VAR|IS_TMP_VAR))) {
+               cleanup_live_vars(execute_data, fast_call->u2.lineno, fast_call->u2.lineno + 1);
+       }
 
        /* check for delayed exception */
        if (Z_OBJ_P(fast_call) != NULL) {
-               SAVE_OPLINE();
                /* discard the previously thrown exception */
                OBJ_RELEASE(Z_OBJ_P(fast_call));
                Z_OBJ_P(fast_call) = NULL;
-               ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
        }
 
-       ZEND_VM_NEXT_OPCODE();
+       ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
 }
 
 static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)