diff options
| author | Xinchen Hui <laruence@php.net> | 2014-07-18 15:52:52 +0800 |
|---|---|---|
| committer | Xinchen Hui <laruence@php.net> | 2014-07-18 16:25:43 +0800 |
| commit | 110bf9c720d02b49a1a5d0c6e8affe65f9aa01db (patch) | |
| tree | 9d377d071e33efcbbc3c60f3218a557216edfd71 /Zend | |
| parent | 4e378844abbfbc7fec88d063ee0bf2e9026b6b6a (diff) | |
| parent | f6f621ef69a5a9bf20e94c2714bdebae73860927 (diff) | |
| download | php-git-110bf9c720d02b49a1a5d0c6e8affe65f9aa01db.tar.gz | |
Merge remote-tracking branch 'origin/master' into phpng
Conflicts:
Zend/zend_compile.h
ext/openssl/xp_ssl.c
Diffstat (limited to 'Zend')
| -rw-r--r-- | Zend/tests/bug66608.phpt | 39 | ||||
| -rw-r--r-- | Zend/zend_compile.h | 3 | ||||
| -rw-r--r-- | Zend/zend_opcode.c | 25 | ||||
| -rw-r--r-- | Zend/zend_vm_def.h | 9 | ||||
| -rw-r--r-- | Zend/zend_vm_execute.h | 9 |
5 files changed, 78 insertions, 7 deletions
diff --git a/Zend/tests/bug66608.phpt b/Zend/tests/bug66608.phpt new file mode 100644 index 0000000000..6329506d06 --- /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 3124c35208..a838a58144 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -840,6 +840,9 @@ int zend_add_literal(zend_op_array *op_array, 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 + #define ZEND_ARRAY_ELEMENT_REF (1<<0) #define ZEND_ARRAY_NOT_PACKED (1<<1) #define ZEND_ARRAY_SIZE_SHIFT 2 diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index 41cfb8904a..2f0f0aeecd 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -509,7 +509,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; } @@ -574,6 +574,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; @@ -615,6 +635,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 b9c45fe0ed..618f90267f 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -5757,13 +5757,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(func)->op_array.opcodes[opline->op2.opline_num]); ZEND_VM_CONTINUE(); } - EX(fast_ret) = opline + 1; + EX(fast_ret) = opline; EX(delayed_exception) = NULL; ZEND_VM_SET_OPCODE(opline->op1.jmp_addr); ZEND_VM_CONTINUE(); @@ -5772,7 +5772,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(func)->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 214ab51beb..c6c8f8ee38 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -1466,13 +1466,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(func)->op_array.opcodes[opline->op2.opline_num]); ZEND_VM_CONTINUE(); } - EX(fast_ret) = opline + 1; + EX(fast_ret) = opline; EX(delayed_exception) = NULL; ZEND_VM_SET_OPCODE(opline->op1.jmp_addr); ZEND_VM_CONTINUE(); @@ -1481,7 +1481,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(func)->op_array.opcodes[EX(fast_ret)->op2.opline_num]; + } ZEND_VM_CONTINUE(); } else { /* special case for unhandled exceptions */ |
