mirror of
https://github.com/php/php-src.git
synced 2026-04-18 05:21:02 +02:00
Merge branch 'PHP-5.5' into PHP-5.6
Conflicts: Zend/zend_vm_def.h Zend/zend_vm_execute.h
This commit is contained in:
39
Zend/tests/bug66608.phpt
Normal file
39
Zend/tests/bug66608.phpt
Normal file
@@ -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
|
||||
@@ -864,6 +864,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"
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -5625,13 +5625,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;
|
||||
EX(delayed_exception) = NULL;
|
||||
ZEND_VM_SET_OPCODE(opline->op1.jmp_addr);
|
||||
ZEND_VM_CONTINUE();
|
||||
@@ -5640,7 +5640,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 */
|
||||
|
||||
@@ -1344,13 +1344,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;
|
||||
EX(delayed_exception) = NULL;
|
||||
ZEND_VM_SET_OPCODE(opline->op1.jmp_addr);
|
||||
ZEND_VM_CONTINUE();
|
||||
@@ -1359,7 +1359,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 */
|
||||
|
||||
Reference in New Issue
Block a user