com php-src: Fixed bug #66608 (Incorrect behavior with nested "finally" blocks): NEWS Zend/tests/bug66608.phpt Zend/zend_compile.h Zend/zend_opcode.c
Zend/zend_vm_def.h Zend/zen d_vm_execute.h

From: Date: Fri, 18 Jul 2014 07:45:31 +0000
Subject: com php-src: Fixed bug #66608 (Incorrect behavior with nested "finally" blocks): NEWS Zend/tests/bug66608.phpt Zend/zend_compile.h Zend/zend_opcode.c
Zend/zend_vm_def.h Zend/zen d_vm_execute.h
Groups: php.cvs 
Request: Send a blank email to php-cvs+get-79501@lists.php.net to get a copy of this message
Commit: de433d4c4756e18515e4b394298f9e3e60009692 Author: Xinchen Hui <laruence@php.net> Fri, 18 Jul 2014 15:45:31 +0800 Parents: 7446c81aed7d085f05dae0d785c7f49109bc44ec Branches: PHP-5.5 PHP-5.6 master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=de433d4c4756e18515e4b394298f9e3e60009692 Log: Fixed bug #66608 (Incorrect behavior with nested "finally" blocks) Bugs: https://bugs.php.net/66608 Changed paths: M NEWS A Zend/tests/bug66608.phpt M Zend/zend_compile.h M Zend/zend_opcode.c M Zend/zend_vm_def.h M Zend/zend_vm_execute.h Diff: diff --git a/NEWS b/NEWS index cea0051..44c09d0 100644 --- a/NEWS +++ b/NEWS @@ -17,6 +17,8 @@ PHP NEWS . Fixed bug #67151 (strtr with empty array crashes). (Nikita) . Fixed bug #67407 (Windows 8.1/Server 2012 R2 reported as Windows 8/Server 2012). (Christian Wenz) + . Fixed bug #66608 (Incorrect behavior with nested "finally" blocks). + (Laruence, Dmitry) . Implemented FR #34407 (ucwords and Title Case). (Tjerk) - CLI server: diff --git a/Zend/tests/bug66608.phpt b/Zend/tests/bug66608.phpt new file mode 100644 index 0000000..6329506 --- /dev/null +++ b/Zend/tests/bug66608.phpt @@ -0,0 +1,39 @@ +--TEST-- +Bug #66608 (Incorrect behavior with nested "finally" blocks) +--FILE-- +<?php +function bar() { + try { + echo "1\n"; + } finally { + try { + throw new Exception (""); + } catch (Exception $ab) { + echo "2\n"; + } finally { + try { + } finally { + echo "3\n"; + try { + } finally { + } + echo "4\n"; + } + } + echo "5\n"; + try { + } finally { + echo "6\n"; + } + } + echo "7\n"; +} +bar(); +--EXPECT-- +1 +2 +3 +4 +5 +6 +7 diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 2a3d58e..e6e30f3 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -843,6 +843,9 @@ int zend_add_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC); #define ZEND_FAST_RET_TO_CATCH 1 #define ZEND_FAST_RET_TO_FINALLY 2 +#define ZEND_FAST_CALL_FOR_CATCH 1 +#define ZEND_FAST_CALL_FOR_FINALLY 2 + END_EXTERN_C() #define ZEND_CLONE_FUNC_NAME "__clone" diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index 025e8fa..cd810ec 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -538,7 +538,7 @@ static void zend_resolve_finally_call(zend_op_array *op_array, zend_uint op_num, SET_UNUSED(opline->op2); opline->op1.opline_num = op_array->try_catch_array[i].finally_op; if (op_array->try_catch_array[i].catch_op) { - opline->extended_value = 1; + opline->extended_value = ZEND_FAST_CALL_FOR_CATCH; opline->op2.opline_num = op_array->try_catch_array[i].catch_op; } @@ -603,6 +603,26 @@ static void zend_resolve_finally_ret(zend_op_array *op_array, zend_uint op_num T } } +static void zend_resolve_fast_call(zend_op_array *op_array, zend_uint op_num TSRMLS_DC) +{ + int i; + zend_uint finally_op_num = 0; + + for (i = 0; i < op_array->last_try_catch; i++) { + if (op_array->try_catch_array[i].finally_op > op_num) { + break; + } + if (op_num < op_array->try_catch_array[i].finally_end) { + finally_op_num = op_array->try_catch_array[i].finally_op; + } + } + + if (finally_op_num) { + op_array->opcodes[op_num].extended_value = ZEND_FAST_CALL_FOR_FINALLY; + op_array->opcodes[op_num].op2.opline_num = finally_op_num - 2; /* it must be ZEND_FAST_CALL */ + } +} + static void zend_resolve_finally_calls(zend_op_array *op_array TSRMLS_DC) { zend_uint i; @@ -644,6 +664,9 @@ static void zend_resolve_finally_calls(zend_op_array *op_array TSRMLS_DC) case ZEND_JMP: zend_resolve_finally_call(op_array, i, opline->op1.opline_num TSRMLS_CC); break; + case ZEND_FAST_CALL: + zend_resolve_fast_call(op_array, i TSRMLS_CC); + break; case ZEND_FAST_RET: zend_resolve_finally_ret(op_array, i TSRMLS_CC); break; diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index f76e529..161dd77 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -5396,13 +5396,13 @@ ZEND_VM_HANDLER(162, ZEND_FAST_CALL, ANY, ANY) { USE_OPLINE - if (opline->extended_value && + if ((opline->extended_value & ZEND_FAST_CALL_FOR_CATCH) && UNEXPECTED(EG(prev_exception) != NULL)) { /* in case of unhandled exception jump to catch block instead of finally */ ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2..opline_num]); ZEND_VM_CONTINUE(); } - EX(fast_ret) = opline + 1; + EX(fast_ret) = opline; ZEND_VM_SET_OPCODE(opline->op1.jmp_addr); ZEND_VM_CONTINUE(); } @@ -5410,7 +5410,10 @@ ZEND_VM_HANDLER(162, ZEND_FAST_CALL, ANY, ANY) ZEND_VM_HANDLER(163, ZEND_FAST_RET, ANY, ANY) { if (EX(fast_ret)) { - ZEND_VM_SET_OPCODE(EX(fast_ret)); + ZEND_VM_SET_OPCODE(EX(fast_ret) + 1); + if ((EX(fast_ret)->extended_value & ZEND_FAST_CALL_FOR_FINALLY)) { + EX(fast_ret) = &EX(op_array)->opcodes[EX(fast_ret)->op2.opline_num]; + } ZEND_VM_CONTINUE(); } else { /* special case for unhandled exceptions */ diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 94026a0..c94c2d7 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -1137,13 +1137,13 @@ static int ZEND_FASTCALL ZEND_FAST_CALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - if (opline->extended_value && + if ((opline->extended_value & ZEND_FAST_CALL_FOR_CATCH) && UNEXPECTED(EG(prev_exception) != NULL)) { /* in case of unhandled exception jump to catch block instead of finally */ ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.opline_num]); ZEND_VM_CONTINUE(); } - EX(fast_ret) = opline + 1; + EX(fast_ret) = opline; ZEND_VM_SET_OPCODE(opline->op1.jmp_addr); ZEND_VM_CONTINUE(); } @@ -1151,7 +1151,10 @@ static int ZEND_FASTCALL ZEND_FAST_CALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) static int ZEND_FASTCALL ZEND_FAST_RET_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { if (EX(fast_ret)) { - ZEND_VM_SET_OPCODE(EX(fast_ret)); + ZEND_VM_SET_OPCODE(EX(fast_ret) + 1); + if ((EX(fast_ret)->extended_value & ZEND_FAST_CALL_FOR_FINALLY)) { + EX(fast_ret) = &EX(op_array)->opcodes[EX(fast_ret)->op2.opline_num]; + } ZEND_VM_CONTINUE(); } else { /* special case for unhandled exceptions */

« previous php.cvs (#79501) next »