Browse Source

Fixed bug that jmp in try block jmp over finally block

Refactor the implemention,  make codes clear
pull/196/head
Xinchen Hui 14 years ago
parent
commit
60a29791e4
  1. 2
      Zend/tests/catch_finally_001.phpt
  2. 2
      Zend/tests/catch_finally_002.phpt
  3. 2
      Zend/tests/catch_finally_003.phpt
  4. 2
      Zend/tests/catch_finally_004.phpt
  5. 2
      Zend/tests/catch_finally_005.phpt
  6. 2
      Zend/tests/catch_finally_006.phpt
  7. 52
      Zend/tests/try_catch_finally_005.phpt
  8. 39
      Zend/tests/try_catch_finally_006.phpt
  9. 46
      Zend/tests/try_catch_finally_007.phpt
  10. 3
      Zend/tests/try_finally_001.phpt
  11. 2
      Zend/tests/try_finally_002.phpt
  12. 2
      Zend/tests/try_finally_003.phpt
  13. 2
      Zend/tests/try_finally_004.phpt
  14. 2
      Zend/tests/try_finally_005.phpt
  15. 2
      Zend/tests/try_finally_006.phpt
  16. 2
      Zend/tests/try_finally_007.phpt
  17. 2
      Zend/tests/try_finally_008.phpt
  18. 2
      Zend/tests/try_finally_009.phpt
  19. 24
      Zend/zend_compile.c
  20. 6
      Zend/zend_compile.h
  21. 6
      Zend/zend_opcode.c
  22. 1363
      Zend/zend_vm_def.h
  23. 363
      Zend/zend_vm_execute.h

2
Zend/tests/catch_finally_001.phpt

@ -1,5 +1,5 @@
--TEST--
Try catch finally
Try catch finally (basic test)
--FILE--
<?php
function foo ($throw = FALSE) {

2
Zend/tests/catch_finally_002.phpt

@ -1,5 +1,5 @@
--TEST--
Try catch finally return
Try catch finally (basic test with return)
--FILE--
<?php
function foo () {

2
Zend/tests/catch_finally_003.phpt

@ -1,5 +1,5 @@
--TEST--
Try catch finally multi-return
Try catch finally (with multi-returns)
--FILE--
<?php
function dummy($msg) {

2
Zend/tests/catch_finally_004.phpt

@ -1,5 +1,5 @@
--TEST--
Nesting try catch finally
Try catch finally (nesting try-catch-finally)
--FILE--
<?php

2
Zend/tests/catch_finally_005.phpt

@ -1,5 +1,5 @@
--TEST--
Try catch finally with return
Try catch finally (with multi-returns and exception)
--FILE--
<?php
function foo ($a) {

2
Zend/tests/catch_finally_006.phpt

@ -1,5 +1,5 @@
--TEST--
Try catch finally: re-throw exception in catch block
Try catch finally (re-throw exception in catch block)
--FILE--
<?php
function foo ($a) {

52
Zend/tests/try_catch_finally_005.phpt

@ -0,0 +1,52 @@
--TEST--
Try catch finally (break / cont in try block)
--CREDITS--
adoy
--FILE--
<?php
for ($i = 0; $i < 100 ; $i ++) {
try {
break;
} finally {
var_dump("break");
}
}
for ($i = 0; $i < 2; $i ++) {
try {
continue;
} finally {
var_dump("continue1");
}
}
for ($i = 0; $i < 3; $i ++) {
try {
try {
continue;
} finally {
var_dump("continue2");
if ($i == 1) {
throw new Exception("continue exception");
}
}
} catch (Exception $e) {
var_dump("cactched");
} finally {
var_dump("finally");
}
}
?>
--EXPECTF--
string(5) "break"
string(9) "continue1"
string(9) "continue1"
string(9) "continue2"
string(7) "finally"
string(9) "continue2"
string(8) "cactched"
string(7) "finally"
string(9) "continue2"
string(7) "finally"

39
Zend/tests/try_catch_finally_006.phpt

@ -0,0 +1,39 @@
--TEST--
Try catch finally (goto in try/catch block)
--CREDITS--
adoy
--FILE--
<?php
function foo($ex = NULL) {
try {
try {
goto label;
} finally {
var_dump("finally1");
if ($ex) throw $ex;
}
} catch (Exception $e) {
var_dump("catched");
if ($ex) return "return1";
} finally {
var_dump("finally2");
}
label:
var_dump("label");
return "return2";
}
var_dump(foo());
var_dump(foo(new Exception()));
?>
--EXPECTF--
string(8) "finally1"
string(8) "finally2"
string(5) "label"
string(7) "return2"
string(8) "finally1"
string(7) "catched"
string(8) "finally2"
string(7) "return1"

46
Zend/tests/try_catch_finally_007.phpt

@ -0,0 +1,46 @@
--TEST--
Try catch finally (goto in try/catch block)
--CREDITS--
adoy
--FILE--
<?php
function foo($ret = FALSE) {
try {
try {
do {
goto label;
} while(0);
foreach (array() as $val) {
continue;
}
} finally {
var_dump("finally1");
throw new Exception("exception");
}
} catch (Exception $e) {
goto local;
local:
var_dump("catched");
if ($ret) return "return";
} finally {
var_dump("finally2");
}
label:
var_dump("label");
}
var_dump(foo());
var_dump(foo(true));
?>
--EXPECTF--
string(8) "finally1"
string(7) "catched"
string(8) "finally2"
string(5) "label"
NULL
string(8) "finally1"
string(7) "catched"
string(8) "finally2"
string(6) "return"

3
Zend/tests/try_finally_001.phpt

@ -1,5 +1,5 @@
--TEST--
Try finally
Try finally (basic test)
--FILE--
<?php
function foo ($a) {
@ -20,4 +20,3 @@ Stack trace:
#0 %stry_finally_001.php(%d): foo('finally')
#1 {main}
thrown in %stry_finally_001.php on line %d

2
Zend/tests/try_finally_002.phpt

@ -1,5 +1,5 @@
--TEST--
Try finally
Try finally (re-throw exception in finally block)
--FILE--
<?php
function foo () {

2
Zend/tests/try_finally_003.phpt

@ -1,5 +1,5 @@
--TEST--
Try finally
Try finally (call sequence test)
--FILE--
<?php
function foo () {

2
Zend/tests/try_finally_004.phpt

@ -1,5 +1,5 @@
--TEST--
Try without catch/finally block
Try finally (without catch/finally block)
--FILE--
<?php
function foo () {

2
Zend/tests/try_finally_005.phpt

@ -1,5 +1,5 @@
--TEST--
Finally with long goto
Try finally (with long goto)
--FILE--
<?php
function foo () {

2
Zend/tests/try_finally_006.phpt

@ -1,5 +1,5 @@
--TEST--
Finally with near goto
Try finally (with near goto)
--FILE--
<?php
function foo () {

2
Zend/tests/try_finally_007.phpt

@ -1,5 +1,5 @@
--TEST--
Finally with goto previous label
Try finally (with goto previous label)
--FILE--
<?php
function foo () {

2
Zend/tests/try_finally_008.phpt

@ -1,5 +1,5 @@
--TEST--
Finally with jmp (do while)
Try finally (with break in do...while)
--FILE--
<?php
function foo () {

2
Zend/tests/try_finally_009.phpt

@ -1,5 +1,5 @@
--TEST--
Finally with jmp (for continue)
Try finally (with for continue)
--FILE--
<?php
function foo () {

24
Zend/zend_compile.c

@ -2696,7 +2696,7 @@ void zend_initialize_try_catch_element(znode *catch_token TSRMLS_DC) /* {{{ */
zend_stack_top(&CG(bp_stack), (void **) &jmp_list_ptr);
zend_llist_add_element(jmp_list_ptr, &jmp_op_number);
catch_token->EA = get_next_op_number(CG(active_op_array));
catch_token->EA = get_next_op_number(CG(active_op_array));
}
/* }}} */
@ -2792,7 +2792,7 @@ void zend_do_end_finally(znode *try_token, znode* catch_token, znode *finally_to
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
CG(active_op_array)->try_catch_array[try_token->u.op.opline_num].finally_op = finally_token->u.op.opline_num;
CG(active_op_array)->try_catch_array[try_token->u.op.opline_num].finally_end = get_next_op_number(CG(active_op_array));
CG(active_op_array)->has_finally_block = 1;
CG(active_op_array)->has_finally_block = 1;
opline->opcode = ZEND_LEAVE;
SET_UNUSED(opline->op1);
@ -4059,9 +4059,9 @@ static void zend_traits_init_trait_structures(zend_class_entry *ce TSRMLS_DC) /*
/** And, ensure that the referenced method is resolvable, too. */
lcname = zend_str_tolower_dup(cur_method_ref->method_name,
cur_method_ref->mname_len);
cur_method_ref->mname_len);
method_exists = zend_hash_exists(&cur_method_ref->ce->function_table,
lcname, cur_method_ref->mname_len + 1);
lcname, cur_method_ref->mname_len + 1);
efree(lcname);
if (!method_exists) {
@ -5043,11 +5043,11 @@ void zend_do_begin_class_declaration(const znode *class_token, znode *class_name
opline->op2_type = IS_CONST;
if (doing_inheritance) {
/* Make sure a trait does not try to extend a class */
if ((new_class_entry->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
zend_error(E_COMPILE_ERROR, "A trait (%s) cannot extend a class. Traits can only be composed from other traits with the 'use' keyword. Error", new_class_entry->name);
}
/* Make sure a trait does not try to extend a class */
if ((new_class_entry->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
zend_error(E_COMPILE_ERROR, "A trait (%s) cannot extend a class. Traits can only be composed from other traits with the 'use' keyword. Error", new_class_entry->name);
}
opline->extended_value = parent_class_name->u.op.var;
opline->opcode = ZEND_DECLARE_INHERITED_CLASS;
} else {
@ -6998,9 +6998,9 @@ void zend_do_use(znode *ns_name, znode *new_name, int is_global TSRMLS_DC) /* {{
lcname = zend_str_tolower_dup(Z_STRVAL_P(name), Z_STRLEN_P(name));
if (((Z_STRLEN_P(name) == sizeof("self")-1) &&
!memcmp(lcname, "self", sizeof("self")-1)) ||
((Z_STRLEN_P(name) == sizeof("parent")-1) &&
!memcmp(lcname, "parent", sizeof("parent")-1))) {
!memcmp(lcname, "self", sizeof("self")-1)) ||
((Z_STRLEN_P(name) == sizeof("parent")-1) &&
!memcmp(lcname, "parent", sizeof("parent")-1))) {
zend_error(E_COMPILE_ERROR, "Cannot use %s as %s because '%s' is a special class name", Z_STRVAL_P(ns), Z_STRVAL_P(name), Z_STRVAL_P(name));
}

6
Zend/zend_compile.h

@ -281,7 +281,7 @@ struct _zend_op_array {
zend_try_catch_element *try_catch_array;
int last_try_catch;
zend_bool has_finally_block;
zend_bool has_finally_block;
/* static variables support */
HashTable *static_variables;
@ -384,8 +384,8 @@ struct _zend_execute_data {
zend_class_entry *current_called_scope;
zval *current_this;
zval *current_object;
zend_uint leaving;
zend_uint leaving_dest;
zend_uint leaving;
zend_uint leaving_dest;
};
#define EX(element) execute_data.element

6
Zend/zend_opcode.c

@ -87,7 +87,7 @@ void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_siz
op_array->static_variables = NULL;
op_array->last_try_catch = 0;
op_array->has_finally_block = 0;
op_array->has_finally_block = 0;
op_array->this_var = -1;
@ -552,8 +552,8 @@ ZEND_API int pass_two(zend_op_array *op_array TSRMLS_DC)
}
opline->op1.jmp_addr = &op_array->opcodes[opline->op1.opline_num];
break;
case ZEND_BRK:
case ZEND_CONT:
case ZEND_BRK:
case ZEND_CONT:
if (op_array->last_try_catch) {
int nest_levels, array_offset;
zend_brk_cont_element *jmp_to;

1363
Zend/zend_vm_def.h
File diff suppressed because it is too large
View File

363
Zend/zend_vm_execute.h

@ -427,33 +427,6 @@ zend_vm_enter:
zend_error_noreturn(E_ERROR, "Arrived at end of main loop which shouldn't happen");
}
static int ZEND_FASTCALL ZEND_JMP_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
#if DEBUG_ZEND>=2
printf("Jumping to %d\n", opline->op1.opline_num);
#endif
ZEND_VM_SET_OPCODE(opline->op1.jmp_addr);
ZEND_VM_CONTINUE(); /* CHECK_ME */
}
static int ZEND_FASTCALL ZEND_INIT_STRING_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
zval *tmp = &EX_T(opline->result.var).tmp_var;
SAVE_OPLINE();
tmp->value.str.val = emalloc(1);
tmp->value.str.val[0] = 0;
tmp->value.str.len = 0;
Z_SET_REFCOUNT_P(tmp, 1);
tmp->type = IS_STRING;
Z_UNSET_ISREF_P(tmp);
/*CHECK_EXCEPTION();*/
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
{
zend_bool nested;
@ -747,53 +720,6 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
EX(function_state).function = EX(fbc);
return zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
static int ZEND_FASTCALL ZEND_RECV_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
zend_uint arg_num = opline->op1.num;
zval **param = zend_vm_stack_get_arg(arg_num TSRMLS_CC);
SAVE_OPLINE();
if (UNEXPECTED(param == NULL)) {
if (zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, NULL, opline->extended_value TSRMLS_CC)) {
const char *space;
const char *class_name;
zend_execute_data *ptr;
if (EG(active_op_array)->scope) {
class_name = EG(active_op_array)->scope->name;
space = "::";
} else {
class_name = space = "";
}
ptr = EX(prev_execute_data);
if(ptr && ptr->op_array) {
zend_error(E_WARNING, "Missing argument %u for %s%s%s(), called in %s on line %d and defined", opline->op1.num, class_name, space, get_active_function_name(TSRMLS_C), ptr->op_array->filename, ptr->opline->lineno);
} else {
zend_error(E_WARNING, "Missing argument %u for %s%s%s()", opline->op1.num, class_name, space, get_active_function_name(TSRMLS_C));
}
}
} else {
zval **var_ptr;
zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, *param, opline->extended_value TSRMLS_CC);
var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->result.var TSRMLS_CC);
Z_DELREF_PP(var_ptr);
*var_ptr = *param;
Z_ADDREF_PP(var_ptr);
}
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL zend_finally_handler_leaving_SPEC(int type, ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@ -806,26 +732,27 @@ static int ZEND_FASTCALL zend_finally_handler_leaving_SPEC(int type, ZEND_OPCODE
case ZEND_THROW:
case ZEND_RETURN:
case ZEND_RETURN_BY_REF:
case ZEND_LEAVE:
{
if (EG(prev_exception)) {
for (i=0; i<EG(active_op_array)->last_try_catch; i++) {
if (EG(active_op_array)->try_catch_array[i].try_op > op_num) {
if (EG(prev_exception) || (type == ZEND_LEAVE && EG(exception))) {
for (i=0; i<EX(op_array)->last_try_catch; i++) {
if (EX(op_array)->try_catch_array[i].try_op > op_num) {
break;
}
if (op_num < EG(active_op_array)->try_catch_array[i].finally_op) {
finally_op_num = EG(active_op_array)->try_catch_array[i].finally_op;
if (op_num < EX(op_array)->try_catch_array[i].finally_op) {
finally_op_num = EX(op_array)->try_catch_array[i].finally_op;
}
if (op_num < EG(active_op_array)->try_catch_array[i].catch_op) {
catch_op_num = EG(active_op_array)->try_catch_array[i].catch_op;
if (op_num < EX(op_array)->try_catch_array[i].catch_op) {
catch_op_num = EX(op_array)->try_catch_array[i].catch_op;
}
}
} else {
for (i=0; i<EG(active_op_array)->last_try_catch; i++) {
if (EG(active_op_array)->try_catch_array[i].try_op > op_num) {
for (i=0; i<EX(op_array)->last_try_catch; i++) {
if (EX(op_array)->try_catch_array[i].try_op > op_num) {
break;
}
if (op_num < EG(active_op_array)->try_catch_array[i].finally_op) {
finally_op_num = EG(active_op_array)->try_catch_array[i].finally_op;
if (op_num < EX(op_array)->try_catch_array[i].finally_op) {
finally_op_num = EX(op_array)->try_catch_array[i].finally_op;
}
}
}
@ -843,44 +770,127 @@ static int ZEND_FASTCALL zend_finally_handler_leaving_SPEC(int type, ZEND_OPCODE
EX(leaving) = 0;
ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[catch_op_num]);
} else if (finally_op_num) {
EX(leaving) = type;
if (type != ZEND_LEAVE) {
EX(leaving) = type;
}
ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]);
} else if (EX(leaving)) {
} else if (EX(leaving) && type != ZEND_LEAVE) {
/* leave it to ZEND_LEAVE */
EX(leaving) = type;
ZEND_VM_NEXT_OPCODE();
} else {
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
}
break;
case ZEND_JMP:
case ZEND_BRK:
case ZEND_CONT:
case ZEND_GOTO:
{
for (i=0; i<EG(active_op_array)->last_try_catch; i++) {
if (EG(active_op_array)->try_catch_array[i].try_op > op_num) {
break;
}
if (op_num < EG(active_op_array)->try_catch_array[i].finally_op
&& (EX(leaving_dest) < EG(active_op_array)->try_catch_array[i].try_op
|| EX(leaving_dest) >= EG(active_op_array)->try_catch_array[i].finally_end)) {
finally_op_num = EG(active_op_array)->try_catch_array[i].finally_op;
}
}
if (finally_op_num) {
EX(leaving) = type;
ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]);
} else {
EX(leaving) = 0;
ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[EX(leaving_dest)]);
}
}
/* these can not occurred in exception context */
for (i=0; i<EG(active_op_array)->last_try_catch; i++) {
if (EG(active_op_array)->try_catch_array[i].try_op > op_num) {
break;
}
if (op_num < EG(active_op_array)->try_catch_array[i].finally_op
&& (EX(leaving_dest) < EG(active_op_array)->try_catch_array[i].try_op
|| EX(leaving_dest) >= EG(active_op_array)->try_catch_array[i].finally_end)) {
finally_op_num = EG(active_op_array)->try_catch_array[i].finally_op;
}
}
if (finally_op_num) {
EX(leaving) = type;
ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]);
} else {
EX(leaving) = 0;
ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[EX(leaving_dest)]);
}
}
break;
}
ZEND_VM_CONTINUE();
}
static int ZEND_FASTCALL ZEND_JMP_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
#if DEBUG_ZEND>=2
printf("Jumping to %d\n", opline->op1.opline_num);
#endif
if (EX(op_array)->has_finally_block) {
EX(leaving_dest) = opline->op1.jmp_addr - EX(op_array)->opcodes;
return zend_finally_handler_leaving_SPEC(ZEND_JMP, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
ZEND_VM_SET_OPCODE(opline->op1.jmp_addr);
ZEND_VM_CONTINUE(); /* CHECK_ME */
}
static int ZEND_FASTCALL ZEND_INIT_STRING_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
zval *tmp = &EX_T(opline->result.var).tmp_var;
SAVE_OPLINE();
tmp->value.str.val = emalloc(1);
tmp->value.str.val[0] = 0;
tmp->value.str.len = 0;
Z_SET_REFCOUNT_P(tmp, 1);
tmp->type = IS_STRING;
Z_UNSET_ISREF_P(tmp);
/*CHECK_EXCEPTION();*/
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
EX(function_state).function = EX(fbc);
return zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
static int ZEND_FASTCALL ZEND_RECV_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
zend_uint arg_num = opline->op1.num;
zval **param = zend_vm_stack_get_arg(arg_num TSRMLS_CC);
SAVE_OPLINE();
if (UNEXPECTED(param == NULL)) {
if (zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, NULL, opline->extended_value TSRMLS_CC)) {
const char *space;
const char *class_name;
zend_execute_data *ptr;
if (EG(active_op_array)->scope) {
class_name = EG(active_op_array)->scope->name;
space = "::";
} else {
class_name = space = "";
}
ptr = EX(prev_execute_data);
if(ptr && ptr->op_array) {
zend_error(E_WARNING, "Missing argument %u for %s%s%s(), called in %s on line %d and defined", opline->op1.num, class_name, space, get_active_function_name(TSRMLS_C), ptr->op_array->filename, ptr->opline->lineno);
} else {
zend_error(E_WARNING, "Missing argument %u for %s%s%s()", opline->op1.num, class_name, space, get_active_function_name(TSRMLS_C));
}
}
} else {
zval **var_ptr;
zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, *param, opline->extended_value TSRMLS_CC);
var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->result.var TSRMLS_CC);
Z_DELREF_PP(var_ptr);
*var_ptr = *param;
Z_ADDREF_PP(var_ptr);
}
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_NEW_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@ -1264,64 +1274,21 @@ static int ZEND_FASTCALL ZEND_USER_OPCODE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS
static int ZEND_FASTCALL ZEND_LEAVE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
zend_exception_restore(TSRMLS_C);
if (!EX(leaving)) {
ZEND_VM_NEXT_OPCODE();
} else {
zend_uint i, op_num = opline - EX(op_array)->opcodes;
zend_uint catch_op_num = 0, finally_op_num = 0;
switch (EX(leaving)) {
zend_uint leaving = EX(leaving);
switch (leaving) {
case ZEND_RETURN:
case ZEND_RETURN_BY_REF:
case ZEND_THROW:
{
if (EG(exception)) {
for (i = 0; i < EX(leaving); i++) {
if (EG(active_op_array)->try_catch_array[i].try_op > op_num) {
break;
}
if (op_num < EG(active_op_array)->try_catch_array[i].finally_op) {
finally_op_num = EG(active_op_array)->try_catch_array[i].finally_op;
}
if (op_num < EG(active_op_array)->try_catch_array[i].catch_op) {
catch_op_num = EG(active_op_array)->try_catch_array[i].catch_op;
}
}
} else {
for (i = 0; i < EX(leaving); i++) {
if (EG(active_op_array)->try_catch_array[i].try_op > op_num) {
break;
}
if (op_num < EG(active_op_array)->try_catch_array[i].finally_op) {
finally_op_num = EG(active_op_array)->try_catch_array[i].finally_op;
}
}
}
if (catch_op_num && finally_op_num) {
if (catch_op_num > finally_op_num) {
EX(leaving) = ZEND_THROW;
ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]);
} else {
EX(leaving) = 0;
ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[catch_op_num]);
}
} else if (catch_op_num) {
EX(leaving) = 0;
ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[catch_op_num]);
} else if (finally_op_num) {
ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]);
} else {
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
}
break;
leaving = ZEND_LEAVE;
case ZEND_JMP:
case ZEND_BRK:
case ZEND_CONT:
case ZEND_GOTO:
return zend_finally_handler_leaving_SPEC(EX(leaving), ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
return zend_finally_handler_leaving_SPEC(leaving, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
break;
}
}
@ -1563,10 +1530,10 @@ static int ZEND_FASTCALL ZEND_BRK_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
el = zend_brk_cont(Z_LVAL_P(opline->op2.zv), opline->op1.opline_num,
EX(op_array), EX_Ts() TSRMLS_CC);
if (EG(active_op_array)->has_finally_block) {
EX(leaving_dest) = el->brk;
return zend_finally_handler_leaving_SPEC(ZEND_BRK, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
if (EX(op_array)->has_finally_block) {
EX(leaving_dest) = el->brk;
return zend_finally_handler_leaving_SPEC(ZEND_BRK, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
ZEND_VM_JMP(EX(op_array)->opcodes + el->brk);
}
@ -1579,10 +1546,10 @@ static int ZEND_FASTCALL ZEND_CONT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
el = zend_brk_cont(Z_LVAL_P(opline->op2.zv), opline->op1.opline_num,
EX(op_array), EX_Ts() TSRMLS_CC);
if (EG(active_op_array)->has_finally_block) {
EX(leaving_dest) = el->cont;
return zend_finally_handler_leaving_SPEC(ZEND_CONT, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
if (EG(active_op_array)->has_finally_block) {
EX(leaving_dest) = el->cont;
return zend_finally_handler_leaving_SPEC(ZEND_CONT, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
ZEND_VM_JMP(EX(op_array)->opcodes + el->cont);
}
@ -1610,10 +1577,10 @@ static int ZEND_FASTCALL ZEND_GOTO_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
}
break;
}
if ((EG(active_op_array)->has_finally_block)) {
EX(leaving_dest) = opline->op1.jmp_addr - EG(active_op_array)->opcodes;
return zend_finally_handler_leaving_SPEC(ZEND_CONT, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
if (EX(op_array)->has_finally_block) {
EX(leaving_dest) = opline->op1.jmp_addr - EX(op_array)->opcodes;
return zend_finally_handler_leaving_SPEC(ZEND_GOTO, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
ZEND_VM_JMP(opline->op1.jmp_addr);
}
@ -2465,10 +2432,10 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARG
*EG(return_value_ptr_ptr) = ret;
}
if (EG(active_op_array)->has_finally_block) {
return zend_finally_handler_leaving_SPEC(ZEND_RETURN, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
if (EX(op_array)->has_finally_block) {
return zend_finally_handler_leaving_SPEC(ZEND_RETURN, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@ -2539,10 +2506,10 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CONST_HANDLER(ZEND_OPCODE_HAND
}
} while (0);
if (EG(active_op_array)->has_finally_block) {
return zend_finally_handler_leaving_SPEC(ZEND_RETURN_BY_REF, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
if (EX(op_array)->has_finally_block) {
return zend_finally_handler_leaving_SPEC(ZEND_RETURN_BY_REF, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
static int ZEND_FASTCALL ZEND_THROW_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@ -7015,10 +6982,10 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
*EG(return_value_ptr_ptr) = ret;
}
if (EG(active_op_array)->has_finally_block) {
return zend_finally_handler_leaving_SPEC(ZEND_RETURN, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
if (EX(op_array)->has_finally_block) {
return zend_finally_handler_leaving_SPEC(ZEND_RETURN, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@ -7089,10 +7056,10 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLE
}
} while (0);
if (EG(active_op_array)->has_finally_block) {
return zend_finally_handler_leaving_SPEC(ZEND_RETURN_BY_REF, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
if (EX(op_array)->has_finally_block) {
return zend_finally_handler_leaving_SPEC(ZEND_RETURN_BY_REF, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
static int ZEND_FASTCALL ZEND_THROW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@ -11471,10 +11438,10 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
if (EG(active_op_array)->has_finally_block) {
return zend_finally_handler_leaving_SPEC(ZEND_RETURN, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
if (EX(op_array)->has_finally_block) {
return zend_finally_handler_leaving_SPEC(ZEND_RETURN, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@ -11547,10 +11514,10 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLE
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
if (EG(active_op_array)->has_finally_block) {
return zend_finally_handler_leaving_SPEC(ZEND_RETURN_BY_REF, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
if (EX(op_array)->has_finally_block) {
return zend_finally_handler_leaving_SPEC(ZEND_RETURN_BY_REF, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
static int ZEND_FASTCALL ZEND_THROW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@ -27490,10 +27457,10 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
*EG(return_value_ptr_ptr) = ret;
}
if (EG(active_op_array)->has_finally_block) {
return zend_finally_handler_leaving_SPEC(ZEND_RETURN, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
if (EX(op_array)->has_finally_block) {
return zend_finally_handler_leaving_SPEC(ZEND_RETURN, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@ -27564,10 +27531,10 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER
}
} while (0);
if (EG(active_op_array)->has_finally_block) {
return zend_finally_handler_leaving_SPEC(ZEND_RETURN_BY_REF, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
if (EX(op_array)->has_finally_block) {
return zend_finally_handler_leaving_SPEC(ZEND_RETURN_BY_REF, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
static int ZEND_FASTCALL ZEND_THROW_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)

Loading…
Cancel
Save