diff options
| author | Dmitry Stogov <dmitry@zend.com> | 2016-06-08 00:23:33 +0300 |
|---|---|---|
| committer | Dmitry Stogov <dmitry@zend.com> | 2016-06-08 00:23:33 +0300 |
| commit | 2bae4e18a2a0041bdbf0511cb4fed73c595f4050 (patch) | |
| tree | 2cac4b617801f1cc7eaabf3c02cc653b5a7cd9af | |
| parent | 421843977f3f2f65c2e7d6d2827b322a54042422 (diff) | |
| download | php-git-2bae4e18a2a0041bdbf0511cb4fed73c595f4050.tar.gz | |
Fixed bug #70228 (Memleak if return in finally block)
| -rw-r--r-- | NEWS | 1 | ||||
| -rw-r--r-- | Zend/tests/try/bug70228.phpt | 2 | ||||
| -rw-r--r-- | Zend/zend_vm_def.h | 13 | ||||
| -rw-r--r-- | Zend/zend_vm_execute.h | 13 |
4 files changed, 21 insertions, 8 deletions
@@ -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) |
