summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS1
-rw-r--r--Zend/tests/try/bug70228.phpt2
-rw-r--r--Zend/zend_vm_def.h13
-rw-r--r--Zend/zend_vm_execute.h13
4 files changed, 21 insertions, 8 deletions
diff --git a/NEWS b/NEWS
index a97fb14b03..de57cceff7 100644
--- 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).
diff --git a/Zend/tests/try/bug70228.phpt b/Zend/tests/try/bug70228.phpt
index e85724765e..8b812517a3 100644
--- a/Zend/tests/try/bug70228.phpt
+++ b/Zend/tests/try/bug70228.phpt
@@ -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
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index 5922275762..57de22e518 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -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)
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index 4b0454b0e0..21f94fd1a2 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -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)