summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXinchen Hui <laruence@php.net>2012-08-22 18:32:03 +0800
committerXinchen Hui <laruence@php.net>2012-08-22 18:32:03 +0800
commit60a29791e4b66844e5dfff698141074d48fc3da8 (patch)
tree7b2df724455d4d152d2870161c8249b18b0b5f05
parent3d4f91da4b6e1c4e918fa330782b9cae98334b11 (diff)
downloadphp-git-60a29791e4b66844e5dfff698141074d48fc3da8.tar.gz
Fixed bug that jmp in try block jmp over finally block
Refactor the implemention, make codes clear
-rw-r--r--Zend/tests/catch_finally_001.phpt2
-rw-r--r--Zend/tests/catch_finally_002.phpt2
-rw-r--r--Zend/tests/catch_finally_003.phpt2
-rw-r--r--Zend/tests/catch_finally_004.phpt2
-rw-r--r--Zend/tests/catch_finally_005.phpt2
-rw-r--r--Zend/tests/catch_finally_006.phpt2
-rw-r--r--Zend/tests/try_catch_finally_005.phpt52
-rw-r--r--Zend/tests/try_catch_finally_006.phpt39
-rw-r--r--Zend/tests/try_catch_finally_007.phpt46
-rw-r--r--Zend/tests/try_finally_001.phpt3
-rw-r--r--Zend/tests/try_finally_002.phpt2
-rw-r--r--Zend/tests/try_finally_003.phpt2
-rw-r--r--Zend/tests/try_finally_004.phpt2
-rw-r--r--Zend/tests/try_finally_005.phpt2
-rw-r--r--Zend/tests/try_finally_006.phpt2
-rw-r--r--Zend/tests/try_finally_007.phpt2
-rw-r--r--Zend/tests/try_finally_008.phpt2
-rw-r--r--Zend/tests/try_finally_009.phpt2
-rw-r--r--Zend/zend_compile.c24
-rw-r--r--Zend/zend_compile.h6
-rw-r--r--Zend/zend_opcode.c6
-rw-r--r--Zend/zend_vm_def.h865
-rw-r--r--Zend/zend_vm_execute.h363
23 files changed, 751 insertions, 681 deletions
diff --git a/Zend/tests/catch_finally_001.phpt b/Zend/tests/catch_finally_001.phpt
index 2b58fa7132..0c3f597a0a 100644
--- a/Zend/tests/catch_finally_001.phpt
+++ b/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) {
diff --git a/Zend/tests/catch_finally_002.phpt b/Zend/tests/catch_finally_002.phpt
index 5f36ae2aa8..c54477ff8c 100644
--- a/Zend/tests/catch_finally_002.phpt
+++ b/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 () {
diff --git a/Zend/tests/catch_finally_003.phpt b/Zend/tests/catch_finally_003.phpt
index a47c6f0f2c..24e468d335 100644
--- a/Zend/tests/catch_finally_003.phpt
+++ b/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) {
diff --git a/Zend/tests/catch_finally_004.phpt b/Zend/tests/catch_finally_004.phpt
index be32a435c3..a2c22beab1 100644
--- a/Zend/tests/catch_finally_004.phpt
+++ b/Zend/tests/catch_finally_004.phpt
@@ -1,5 +1,5 @@
--TEST--
-Nesting try catch finally
+Try catch finally (nesting try-catch-finally)
--FILE--
<?php
diff --git a/Zend/tests/catch_finally_005.phpt b/Zend/tests/catch_finally_005.phpt
index d8573bd4e2..c2fd55df27 100644
--- a/Zend/tests/catch_finally_005.phpt
+++ b/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) {
diff --git a/Zend/tests/catch_finally_006.phpt b/Zend/tests/catch_finally_006.phpt
index 48937c40d4..9759eab37e 100644
--- a/Zend/tests/catch_finally_006.phpt
+++ b/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) {
diff --git a/Zend/tests/try_catch_finally_005.phpt b/Zend/tests/try_catch_finally_005.phpt
new file mode 100644
index 0000000000..dafeb6bbe0
--- /dev/null
+++ b/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"
diff --git a/Zend/tests/try_catch_finally_006.phpt b/Zend/tests/try_catch_finally_006.phpt
new file mode 100644
index 0000000000..dab6af6a58
--- /dev/null
+++ b/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"
diff --git a/Zend/tests/try_catch_finally_007.phpt b/Zend/tests/try_catch_finally_007.phpt
new file mode 100644
index 0000000000..ad33c68131
--- /dev/null
+++ b/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"
diff --git a/Zend/tests/try_finally_001.phpt b/Zend/tests/try_finally_001.phpt
index 1c168da275..0f740872c2 100644
--- a/Zend/tests/try_finally_001.phpt
+++ b/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
-
diff --git a/Zend/tests/try_finally_002.phpt b/Zend/tests/try_finally_002.phpt
index 44676966fe..99a34f62fb 100644
--- a/Zend/tests/try_finally_002.phpt
+++ b/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 () {
diff --git a/Zend/tests/try_finally_003.phpt b/Zend/tests/try_finally_003.phpt
index c5a380995a..c1294911bd 100644
--- a/Zend/tests/try_finally_003.phpt
+++ b/Zend/tests/try_finally_003.phpt
@@ -1,5 +1,5 @@
--TEST--
-Try finally
+Try finally (call sequence test)
--FILE--
<?php
function foo () {
diff --git a/Zend/tests/try_finally_004.phpt b/Zend/tests/try_finally_004.phpt
index 8caa8fb18f..08930a40c5 100644
--- a/Zend/tests/try_finally_004.phpt
+++ b/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 () {
diff --git a/Zend/tests/try_finally_005.phpt b/Zend/tests/try_finally_005.phpt
index 2c6c2c9e6c..8664d6b1bf 100644
--- a/Zend/tests/try_finally_005.phpt
+++ b/Zend/tests/try_finally_005.phpt
@@ -1,5 +1,5 @@
--TEST--
-Finally with long goto
+Try finally (with long goto)
--FILE--
<?php
function foo () {
diff --git a/Zend/tests/try_finally_006.phpt b/Zend/tests/try_finally_006.phpt
index 2bfa4caea9..f53e6b5bc1 100644
--- a/Zend/tests/try_finally_006.phpt
+++ b/Zend/tests/try_finally_006.phpt
@@ -1,5 +1,5 @@
--TEST--
-Finally with near goto
+Try finally (with near goto)
--FILE--
<?php
function foo () {
diff --git a/Zend/tests/try_finally_007.phpt b/Zend/tests/try_finally_007.phpt
index b13bd59e50..634937495c 100644
--- a/Zend/tests/try_finally_007.phpt
+++ b/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 () {
diff --git a/Zend/tests/try_finally_008.phpt b/Zend/tests/try_finally_008.phpt
index 9025d8824d..cee37aedab 100644
--- a/Zend/tests/try_finally_008.phpt
+++ b/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 () {
diff --git a/Zend/tests/try_finally_009.phpt b/Zend/tests/try_finally_009.phpt
index 7c3da6760b..b29930a75e 100644
--- a/Zend/tests/try_finally_009.phpt
+++ b/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 () {
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 2ae8cc510f..cb0be0890a 100644
--- a/Zend/zend_compile.c
+++ b/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));
}
diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h
index 80e02ab309..971860602e 100644
--- a/Zend/zend_compile.h
+++ b/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
diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c
index 2552d2ebd6..6c15829100 100644
--- a/Zend/zend_opcode.c
+++ b/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;
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index d921f81efc..ce1674e4f3 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -1840,6 +1840,392 @@ ZEND_VM_HANDLER(39, ZEND_ASSIGN_REF, VAR|CV, VAR|CV)
ZEND_VM_NEXT_OPCODE();
}
+ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
+{
+ zend_bool nested;
+ zend_op_array *op_array = EX(op_array);
+
+ EG(current_execute_data) = EX(prev_execute_data);
+ EG(opline_ptr) = NULL;
+ if (!EG(active_symbol_table)) {
+ zval ***cv = EX_CVs();
+ zval ***end = cv + op_array->last_var;
+ while (cv != end) {
+ if (*cv) {
+ zval_ptr_dtor(*cv);
+ }
+ cv++;
+ }
+ }
+
+ if ((op_array->fn_flags & ZEND_ACC_CLOSURE) && op_array->prototype) {
+ zval_ptr_dtor((zval**)&op_array->prototype);
+ }
+
+ nested = EX(nested);
+
+ zend_vm_stack_free(execute_data TSRMLS_CC);
+
+ if (nested) {
+ execute_data = EG(current_execute_data);
+ }
+ if (nested) {
+ USE_OPLINE
+
+ LOAD_REGS();
+ LOAD_OPLINE();
+ if (UNEXPECTED(opline->opcode == ZEND_INCLUDE_OR_EVAL)) {
+
+ EX(function_state).function = (zend_function *) EX(op_array);
+ EX(function_state).arguments = NULL;
+ EX(object) = EX(current_object);
+
+ EG(opline_ptr) = &EX(opline);
+ EG(active_op_array) = EX(op_array);
+ EG(return_value_ptr_ptr) = EX(original_return_value);
+ destroy_op_array(op_array TSRMLS_CC);
+ efree(op_array);
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ zend_throw_exception_internal(NULL TSRMLS_CC);
+ HANDLE_EXCEPTION_LEAVE();
+ } else if (RETURN_VALUE_USED(opline)) {
+ if (!EX_T(opline->result.var).var.ptr) { /* there was no return statement */
+ zval *retval;
+
+ ALLOC_ZVAL(retval);
+ ZVAL_BOOL(retval, 1);
+ INIT_PZVAL(retval);
+ EX_T(opline->result.var).var.ptr = retval;
+ }
+ }
+
+ ZEND_VM_INC_OPCODE();
+ ZEND_VM_LEAVE();
+ } else {
+
+ EG(opline_ptr) = &EX(opline);
+ EG(active_op_array) = EX(op_array);
+ EG(return_value_ptr_ptr) = EX(original_return_value);
+ if (EG(active_symbol_table)) {
+ if (EG(symtable_cache_ptr)>=EG(symtable_cache_limit)) {
+ zend_hash_destroy(EG(active_symbol_table));
+ FREE_HASHTABLE(EG(active_symbol_table));
+ } else {
+ /* clean before putting into the cache, since clean
+ could call dtors, which could use cached hash */
+ zend_hash_clean(EG(active_symbol_table));
+ *(++EG(symtable_cache_ptr)) = EG(active_symbol_table);
+ }
+ }
+ EG(active_symbol_table) = EX(symbol_table);
+
+ EX(function_state).function = (zend_function *) EX(op_array);
+ EX(function_state).arguments = NULL;
+
+ if (EG(This)) {
+ if (UNEXPECTED(EG(exception) != NULL) && IS_CTOR_CALL(EX(called_scope))) {
+ if (IS_CTOR_USED(EX(called_scope))) {
+ Z_DELREF_P(EG(This));
+ }
+ if (Z_REFCOUNT_P(EG(This)) == 1) {
+ zend_object_store_ctor_failed(EG(This) TSRMLS_CC);
+ }
+ }
+ zval_ptr_dtor(&EG(This));
+ }
+ EG(This) = EX(current_this);
+ EG(scope) = EX(current_scope);
+ EG(called_scope) = EX(current_called_scope);
+
+ EX(object) = EX(current_object);
+ EX(called_scope) = DECODE_CTOR(EX(called_scope));
+
+ zend_vm_stack_clear_multiple(TSRMLS_C);
+
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ zend_throw_exception_internal(NULL TSRMLS_CC);
+ if (RETURN_VALUE_USED(opline) && EX_T(opline->result.var).var.ptr) {
+ zval_ptr_dtor(&EX_T(opline->result.var).var.ptr);
+ }
+ HANDLE_EXCEPTION_LEAVE();
+ }
+
+ ZEND_VM_INC_OPCODE();
+ ZEND_VM_LEAVE();
+ }
+ }
+ ZEND_VM_RETURN();
+}
+
+ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
+{
+ USE_OPLINE
+ zend_bool should_change_scope = 0;
+ zend_function *fbc = EX(function_state).function;
+
+ SAVE_OPLINE();
+ if (UNEXPECTED((fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) != 0)) {
+ if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_ABSTRACT) != 0)) {
+ zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", fbc->common.scope->name, fbc->common.function_name);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE(); /* Never reached */
+ }
+ if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) {
+ zend_error(E_DEPRECATED, "Function %s%s%s() is deprecated",
+ fbc->common.scope ? fbc->common.scope->name : "",
+ fbc->common.scope ? "::" : "",
+ fbc->common.function_name);
+ }
+ }
+ if (fbc->common.scope &&
+ !(fbc->common.fn_flags & ZEND_ACC_STATIC) &&
+ !EX(object)) {
+
+ if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
+ /* FIXME: output identifiers properly */
+ zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically", fbc->common.scope->name, fbc->common.function_name);
+ } else {
+ /* FIXME: output identifiers properly */
+ /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
+ zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically", fbc->common.scope->name, fbc->common.function_name);
+ }
+ }
+
+ if (fbc->type == ZEND_USER_FUNCTION || fbc->common.scope) {
+ should_change_scope = 1;
+ EX(current_this) = EG(This);
+ EX(current_scope) = EG(scope);
+ EX(current_called_scope) = EG(called_scope);
+ EG(This) = EX(object);
+ EG(scope) = (fbc->type == ZEND_USER_FUNCTION || !EX(object)) ? fbc->common.scope : NULL;
+ EG(called_scope) = EX(called_scope);
+ }
+
+ zend_arg_types_stack_3_pop(&EG(arg_types_stack), &EX(called_scope), &EX(current_object), &EX(fbc));
+ EX(function_state).arguments = zend_vm_stack_push_args(opline->extended_value TSRMLS_CC);
+ LOAD_OPLINE();
+
+ if (fbc->type == ZEND_INTERNAL_FUNCTION) {
+ temp_variable *ret = &EX_T(opline->result.var);
+
+ MAKE_STD_ZVAL(ret->var.ptr);
+ ZVAL_NULL(ret->var.ptr);
+ ret->var.ptr_ptr = &ret->var.ptr;
+ ret->var.fcall_returned_reference = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
+
+ if (fbc->common.arg_info) {
+ zend_uint i=0;
+ zval **p = (zval**)EX(function_state).arguments;
+ ulong arg_count = opline->extended_value;
+
+ while (arg_count>0) {
+ zend_verify_arg_type(fbc, ++i, *(p-arg_count), 0 TSRMLS_CC);
+ arg_count--;
+ }
+ }
+
+ if (!zend_execute_internal) {
+ /* saves one function call if zend_execute_internal is not used */
+ fbc->internal_function.handler(opline->extended_value, ret->var.ptr, (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? &ret->var.ptr : NULL, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC);
+ } else {
+ zend_execute_internal(EXECUTE_DATA, RETURN_VALUE_USED(opline) TSRMLS_CC);
+ }
+
+ if (!RETURN_VALUE_USED(opline)) {
+ zval_ptr_dtor(&ret->var.ptr);
+ }
+ } else if (fbc->type == ZEND_USER_FUNCTION) {
+ EX(original_return_value) = EG(return_value_ptr_ptr);
+ EG(active_symbol_table) = NULL;
+ EG(active_op_array) = &fbc->op_array;
+ EG(return_value_ptr_ptr) = NULL;
+ if (RETURN_VALUE_USED(opline)) {
+ temp_variable *ret = &EX_T(opline->result.var);
+
+ ret->var.ptr = NULL;
+ EG(return_value_ptr_ptr) = &ret->var.ptr;
+ ret->var.ptr_ptr = &ret->var.ptr;
+ ret->var.fcall_returned_reference = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
+ }
+
+ if (EXPECTED(zend_execute == execute)) {
+ if (EXPECTED(EG(exception) == NULL)) {
+ ZEND_VM_ENTER();
+ }
+ } else {
+ zend_execute(EG(active_op_array) TSRMLS_CC);
+ }
+
+ EG(opline_ptr) = &EX(opline);
+ EG(active_op_array) = EX(op_array);
+ EG(return_value_ptr_ptr) = EX(original_return_value);
+ if (EG(active_symbol_table)) {
+ if (EG(symtable_cache_ptr)>=EG(symtable_cache_limit)) {
+ zend_hash_destroy(EG(active_symbol_table));
+ FREE_HASHTABLE(EG(active_symbol_table));
+ } else {
+ /* clean before putting into the cache, since clean
+ could call dtors, which could use cached hash */
+ zend_hash_clean(EG(active_symbol_table));
+ *(++EG(symtable_cache_ptr)) = EG(active_symbol_table);
+ }
+ }
+ EG(active_symbol_table) = EX(symbol_table);
+ } else { /* ZEND_OVERLOADED_FUNCTION */
+ MAKE_STD_ZVAL(EX_T(opline->result.var).var.ptr);
+ ZVAL_NULL(EX_T(opline->result.var).var.ptr);
+
+ /* Not sure what should be done here if it's a static method */
+ if (EXPECTED(EX(object) != NULL)) {
+ Z_OBJ_HT_P(EX(object))->call_method(fbc->common.function_name, opline->extended_value, EX_T(opline->result.var).var.ptr, &EX_T(opline->result.var).var.ptr, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC);
+ } else {
+ zend_error_noreturn(E_ERROR, "Cannot call overloaded function for non-object");
+ }
+
+ if (fbc->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) {
+ efree((char*)fbc->common.function_name);
+ }
+ efree(fbc);
+
+ if (!RETURN_VALUE_USED(opline)) {
+ zval_ptr_dtor(&EX_T(opline->result.var).var.ptr);
+ } else {
+ Z_UNSET_ISREF_P(EX_T(opline->result.var).var.ptr);
+ Z_SET_REFCOUNT_P(EX_T(opline->result.var).var.ptr, 1);
+ EX_T(opline->result.var).var.fcall_returned_reference = 0;
+ EX_T(opline->result.var).var.ptr_ptr = &EX_T(opline->result.var).var.ptr;
+ }
+ }
+
+ EX(function_state).function = (zend_function *) EX(op_array);
+ EX(function_state).arguments = NULL;
+
+ if (should_change_scope) {
+ if (EG(This)) {
+ if (UNEXPECTED(EG(exception) != NULL) && IS_CTOR_CALL(EX(called_scope))) {
+ if (IS_CTOR_USED(EX(called_scope))) {
+ Z_DELREF_P(EG(This));
+ }
+ if (Z_REFCOUNT_P(EG(This)) == 1) {
+ zend_object_store_ctor_failed(EG(This) TSRMLS_CC);
+ }
+ }
+ zval_ptr_dtor(&EG(This));
+ }
+ EG(This) = EX(current_this);
+ EG(scope) = EX(current_scope);
+ EG(called_scope) = EX(current_called_scope);
+ }
+
+ EX(object) = EX(current_object);
+ EX(called_scope) = DECODE_CTOR(EX(called_scope));
+
+ zend_vm_stack_clear_multiple(TSRMLS_C);
+
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ zend_throw_exception_internal(NULL TSRMLS_CC);
+ if (RETURN_VALUE_USED(opline) && EX_T(opline->result.var).var.ptr) {
+ zval_ptr_dtor(&EX_T(opline->result.var).var.ptr);
+ }
+ HANDLE_EXCEPTION();
+ }
+
+ ZEND_VM_NEXT_OPCODE();
+}
+
+ZEND_VM_HELPER_EX(zend_finally_handler_leaving, ANY, ANY, int type)
+{
+ USE_OPLINE
+ zend_uint i, op_num = opline - EX(op_array)->opcodes;
+ zend_uint catch_op_num = 0, finally_op_num = 0;
+
+ SAVE_OPLINE();
+
+ switch (type) {
+ case ZEND_THROW:
+ case ZEND_RETURN:
+ case ZEND_RETURN_BY_REF:
+ case ZEND_LEAVE:
+ {
+ 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 < EX(op_array)->try_catch_array[i].finally_op) {
+ finally_op_num = EX(op_array)->try_catch_array[i].finally_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<EX(op_array)->last_try_catch; i++) {
+ if (EX(op_array)->try_catch_array[i].try_op > op_num) {
+ break;
+ }
+ 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 (catch_op_num && finally_op_num) {
+ /* EG(exception) || EG(prev_exception) */
+ 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) {
+ if (type != ZEND_LEAVE) {
+ EX(leaving) = type;
+ }
+ ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]);
+ } else if (EX(leaving) && type != ZEND_LEAVE) {
+ /* leave it to ZEND_LEAVE */
+ EX(leaving) = type;
+ ZEND_VM_NEXT_OPCODE();
+ } else {
+ ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
+ }
+ }
+ break;
+ case ZEND_JMP:
+ case ZEND_BRK:
+ case ZEND_CONT:
+ case ZEND_GOTO:
+ {
+ /* 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();
+}
+
ZEND_VM_HANDLER(42, ZEND_JMP, ANY, ANY)
{
USE_OPLINE
@@ -1847,6 +2233,10 @@ ZEND_VM_HANDLER(42, ZEND_JMP, ANY, ANY)
#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;
+ ZEND_VM_DISPATCH_TO_HELPER_EX(zend_finally_handler_leaving, type, ZEND_JMP);
+ }
ZEND_VM_SET_OPCODE(opline->op1.jmp_addr);
ZEND_VM_CONTINUE(); /* CHECK_ME */
}
@@ -2508,299 +2898,6 @@ ZEND_VM_HANDLER(69, ZEND_INIT_NS_FCALL_BY_NAME, ANY, CONST)
ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
-{
- zend_bool nested;
- zend_op_array *op_array = EX(op_array);
-
- EG(current_execute_data) = EX(prev_execute_data);
- EG(opline_ptr) = NULL;
- if (!EG(active_symbol_table)) {
- zval ***cv = EX_CVs();
- zval ***end = cv + op_array->last_var;
- while (cv != end) {
- if (*cv) {
- zval_ptr_dtor(*cv);
- }
- cv++;
- }
- }
-
- if ((op_array->fn_flags & ZEND_ACC_CLOSURE) && op_array->prototype) {
- zval_ptr_dtor((zval**)&op_array->prototype);
- }
-
- nested = EX(nested);
-
- zend_vm_stack_free(execute_data TSRMLS_CC);
-
- if (nested) {
- execute_data = EG(current_execute_data);
- }
- if (nested) {
- USE_OPLINE
-
- LOAD_REGS();
- LOAD_OPLINE();
- if (UNEXPECTED(opline->opcode == ZEND_INCLUDE_OR_EVAL)) {
-
- EX(function_state).function = (zend_function *) EX(op_array);
- EX(function_state).arguments = NULL;
- EX(object) = EX(current_object);
-
- EG(opline_ptr) = &EX(opline);
- EG(active_op_array) = EX(op_array);
- EG(return_value_ptr_ptr) = EX(original_return_value);
- destroy_op_array(op_array TSRMLS_CC);
- efree(op_array);
- if (UNEXPECTED(EG(exception) != NULL)) {
- zend_throw_exception_internal(NULL TSRMLS_CC);
- HANDLE_EXCEPTION_LEAVE();
- } else if (RETURN_VALUE_USED(opline)) {
- if (!EX_T(opline->result.var).var.ptr) { /* there was no return statement */
- zval *retval;
-
- ALLOC_ZVAL(retval);
- ZVAL_BOOL(retval, 1);
- INIT_PZVAL(retval);
- EX_T(opline->result.var).var.ptr = retval;
- }
- }
-
- ZEND_VM_INC_OPCODE();
- ZEND_VM_LEAVE();
- } else {
-
- EG(opline_ptr) = &EX(opline);
- EG(active_op_array) = EX(op_array);
- EG(return_value_ptr_ptr) = EX(original_return_value);
- if (EG(active_symbol_table)) {
- if (EG(symtable_cache_ptr)>=EG(symtable_cache_limit)) {
- zend_hash_destroy(EG(active_symbol_table));
- FREE_HASHTABLE(EG(active_symbol_table));
- } else {
- /* clean before putting into the cache, since clean
- could call dtors, which could use cached hash */
- zend_hash_clean(EG(active_symbol_table));
- *(++EG(symtable_cache_ptr)) = EG(active_symbol_table);
- }
- }
- EG(active_symbol_table) = EX(symbol_table);
-
- EX(function_state).function = (zend_function *) EX(op_array);
- EX(function_state).arguments = NULL;
-
- if (EG(This)) {
- if (UNEXPECTED(EG(exception) != NULL) && IS_CTOR_CALL(EX(called_scope))) {
- if (IS_CTOR_USED(EX(called_scope))) {
- Z_DELREF_P(EG(This));
- }
- if (Z_REFCOUNT_P(EG(This)) == 1) {
- zend_object_store_ctor_failed(EG(This) TSRMLS_CC);
- }
- }
- zval_ptr_dtor(&EG(This));
- }
- EG(This) = EX(current_this);
- EG(scope) = EX(current_scope);
- EG(called_scope) = EX(current_called_scope);
-
- EX(object) = EX(current_object);
- EX(called_scope) = DECODE_CTOR(EX(called_scope));
-
- zend_vm_stack_clear_multiple(TSRMLS_C);
-
- if (UNEXPECTED(EG(exception) != NULL)) {
- zend_throw_exception_internal(NULL TSRMLS_CC);
- if (RETURN_VALUE_USED(opline) && EX_T(opline->result.var).var.ptr) {
- zval_ptr_dtor(&EX_T(opline->result.var).var.ptr);
- }
- HANDLE_EXCEPTION_LEAVE();
- }
-
- ZEND_VM_INC_OPCODE();
- ZEND_VM_LEAVE();
- }
- }
- ZEND_VM_RETURN();
-}
-
-ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
-{
- USE_OPLINE
- zend_bool should_change_scope = 0;
- zend_function *fbc = EX(function_state).function;
-
- SAVE_OPLINE();
- if (UNEXPECTED((fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) != 0)) {
- if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_ABSTRACT) != 0)) {
- zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", fbc->common.scope->name, fbc->common.function_name);
- CHECK_EXCEPTION();
- ZEND_VM_NEXT_OPCODE(); /* Never reached */
- }
- if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) {
- zend_error(E_DEPRECATED, "Function %s%s%s() is deprecated",
- fbc->common.scope ? fbc->common.scope->name : "",
- fbc->common.scope ? "::" : "",
- fbc->common.function_name);
- }
- }
- if (fbc->common.scope &&
- !(fbc->common.fn_flags & ZEND_ACC_STATIC) &&
- !EX(object)) {
-
- if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
- /* FIXME: output identifiers properly */
- zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically", fbc->common.scope->name, fbc->common.function_name);
- } else {
- /* FIXME: output identifiers properly */
- /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
- zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically", fbc->common.scope->name, fbc->common.function_name);
- }
- }
-
- if (fbc->type == ZEND_USER_FUNCTION || fbc->common.scope) {
- should_change_scope = 1;
- EX(current_this) = EG(This);
- EX(current_scope) = EG(scope);
- EX(current_called_scope) = EG(called_scope);
- EG(This) = EX(object);
- EG(scope) = (fbc->type == ZEND_USER_FUNCTION || !EX(object)) ? fbc->common.scope : NULL;
- EG(called_scope) = EX(called_scope);
- }
-
- zend_arg_types_stack_3_pop(&EG(arg_types_stack), &EX(called_scope), &EX(current_object), &EX(fbc));
- EX(function_state).arguments = zend_vm_stack_push_args(opline->extended_value TSRMLS_CC);
- LOAD_OPLINE();
-
- if (fbc->type == ZEND_INTERNAL_FUNCTION) {
- temp_variable *ret = &EX_T(opline->result.var);
-
- MAKE_STD_ZVAL(ret->var.ptr);
- ZVAL_NULL(ret->var.ptr);
- ret->var.ptr_ptr = &ret->var.ptr;
- ret->var.fcall_returned_reference = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
-
- if (fbc->common.arg_info) {
- zend_uint i=0;
- zval **p = (zval**)EX(function_state).arguments;
- ulong arg_count = opline->extended_value;
-
- while (arg_count>0) {
- zend_verify_arg_type(fbc, ++i, *(p-arg_count), 0 TSRMLS_CC);
- arg_count--;
- }
- }
-
- if (!zend_execute_internal) {
- /* saves one function call if zend_execute_internal is not used */
- fbc->internal_function.handler(opline->extended_value, ret->var.ptr, (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? &ret->var.ptr : NULL, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC);
- } else {
- zend_execute_internal(EXECUTE_DATA, RETURN_VALUE_USED(opline) TSRMLS_CC);
- }
-
- if (!RETURN_VALUE_USED(opline)) {
- zval_ptr_dtor(&ret->var.ptr);
- }
- } else if (fbc->type == ZEND_USER_FUNCTION) {
- EX(original_return_value) = EG(return_value_ptr_ptr);
- EG(active_symbol_table) = NULL;
- EG(active_op_array) = &fbc->op_array;
- EG(return_value_ptr_ptr) = NULL;
- if (RETURN_VALUE_USED(opline)) {
- temp_variable *ret = &EX_T(opline->result.var);
-
- ret->var.ptr = NULL;
- EG(return_value_ptr_ptr) = &ret->var.ptr;
- ret->var.ptr_ptr = &ret->var.ptr;
- ret->var.fcall_returned_reference = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
- }
-
- if (EXPECTED(zend_execute == execute)) {
- if (EXPECTED(EG(exception) == NULL)) {
- ZEND_VM_ENTER();
- }
- } else {
- zend_execute(EG(active_op_array) TSRMLS_CC);
- }
-
- EG(opline_ptr) = &EX(opline);
- EG(active_op_array) = EX(op_array);
- EG(return_value_ptr_ptr) = EX(original_return_value);
- if (EG(active_symbol_table)) {
- if (EG(symtable_cache_ptr)>=EG(symtable_cache_limit)) {
- zend_hash_destroy(EG(active_symbol_table));
- FREE_HASHTABLE(EG(active_symbol_table));
- } else {
- /* clean before putting into the cache, since clean
- could call dtors, which could use cached hash */
- zend_hash_clean(EG(active_symbol_table));
- *(++EG(symtable_cache_ptr)) = EG(active_symbol_table);
- }
- }
- EG(active_symbol_table) = EX(symbol_table);
- } else { /* ZEND_OVERLOADED_FUNCTION */
- MAKE_STD_ZVAL(EX_T(opline->result.var).var.ptr);
- ZVAL_NULL(EX_T(opline->result.var).var.ptr);
-
- /* Not sure what should be done here if it's a static method */
- if (EXPECTED(EX(object) != NULL)) {
- Z_OBJ_HT_P(EX(object))->call_method(fbc->common.function_name, opline->extended_value, EX_T(opline->result.var).var.ptr, &EX_T(opline->result.var).var.ptr, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC);
- } else {
- zend_error_noreturn(E_ERROR, "Cannot call overloaded function for non-object");
- }
-
- if (fbc->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) {
- efree((char*)fbc->common.function_name);
- }
- efree(fbc);
-
- if (!RETURN_VALUE_USED(opline)) {
- zval_ptr_dtor(&EX_T(opline->result.var).var.ptr);
- } else {
- Z_UNSET_ISREF_P(EX_T(opline->result.var).var.ptr);
- Z_SET_REFCOUNT_P(EX_T(opline->result.var).var.ptr, 1);
- EX_T(opline->result.var).var.fcall_returned_reference = 0;
- EX_T(opline->result.var).var.ptr_ptr = &EX_T(opline->result.var).var.ptr;
- }
- }
-
- EX(function_state).function = (zend_function *) EX(op_array);
- EX(function_state).arguments = NULL;
-
- if (should_change_scope) {
- if (EG(This)) {
- if (UNEXPECTED(EG(exception) != NULL) && IS_CTOR_CALL(EX(called_scope))) {
- if (IS_CTOR_USED(EX(called_scope))) {
- Z_DELREF_P(EG(This));
- }
- if (Z_REFCOUNT_P(EG(This)) == 1) {
- zend_object_store_ctor_failed(EG(This) TSRMLS_CC);
- }
- }
- zval_ptr_dtor(&EG(This));
- }
- EG(This) = EX(current_this);
- EG(scope) = EX(current_scope);
- EG(called_scope) = EX(current_called_scope);
- }
-
- EX(object) = EX(current_object);
- EX(called_scope) = DECODE_CTOR(EX(called_scope));
-
- zend_vm_stack_clear_multiple(TSRMLS_C);
-
- if (UNEXPECTED(EG(exception) != NULL)) {
- zend_throw_exception_internal(NULL TSRMLS_CC);
- if (RETURN_VALUE_USED(opline) && EX_T(opline->result.var).var.ptr) {
- zval_ptr_dtor(&EX_T(opline->result.var).var.ptr);
- }
- HANDLE_EXCEPTION();
- }
-
- ZEND_VM_NEXT_OPCODE();
-}
-
ZEND_VM_HANDLER(61, ZEND_DO_FCALL_BY_NAME, ANY, ANY)
{
EX(function_state).function = EX(fbc);
@@ -2878,10 +2975,10 @@ ZEND_VM_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY)
}
FREE_OP1_IF_VAR();
- if (EG(active_op_array)->has_finally_block) {
- ZEND_VM_DISPATCH_TO_HELPER_EX(zend_finally_handler_leaving, type, ZEND_RETURN);
- }
- ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
+ if (EX(op_array)->has_finally_block) {
+ ZEND_VM_DISPATCH_TO_HELPER_EX(zend_finally_handler_leaving, type, ZEND_RETURN);
+ }
+ ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
}
ZEND_VM_HANDLER(111, ZEND_RETURN_BY_REF, CONST|TMP|VAR|CV, ANY)
@@ -2954,10 +3051,10 @@ ZEND_VM_HANDLER(111, ZEND_RETURN_BY_REF, CONST|TMP|VAR|CV, ANY)
FREE_OP1_IF_VAR();
- if (EG(active_op_array)->has_finally_block) {
- ZEND_VM_DISPATCH_TO_HELPER_EX(zend_finally_handler_leaving, type, ZEND_RETURN_BY_REF);
- }
- ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
+ if (EX(op_array)->has_finally_block) {
+ ZEND_VM_DISPATCH_TO_HELPER_EX(zend_finally_handler_leaving, type, ZEND_RETURN_BY_REF);
+ }
+ ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
}
ZEND_VM_HANDLER(108, ZEND_THROW, CONST|TMP|VAR|CV, ANY)
@@ -3292,93 +3389,6 @@ ZEND_VM_HANDLER(52, ZEND_BOOL, CONST|TMP|VAR|CV, ANY)
ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HELPER_EX(zend_finally_handler_leaving, ANY, ANY, int type)
-{
- USE_OPLINE
- zend_uint i, op_num = opline - EX(op_array)->opcodes;
- zend_uint catch_op_num = 0, finally_op_num = 0;
-
- SAVE_OPLINE();
-
- switch (type) {
- case ZEND_THROW:
- case ZEND_RETURN:
- case ZEND_RETURN_BY_REF:
- {
- 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) {
- 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<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) {
- finally_op_num = EG(active_op_array)->try_catch_array[i].finally_op;
- }
- }
- }
-
- if (catch_op_num && finally_op_num) {
- /* EG(exception) || EG(prev_exception) */
- 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) {
- EX(leaving) = type;
- ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]);
- } else if (EX(leaving)) {
- /* leave it to ZEND_LEAVE */
- ZEND_VM_NEXT_OPCODE();
- } else {
- ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
- }
- }
- break;
- 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)]);
- }
- }
- break;
- }
- ZEND_VM_CONTINUE();
-}
-
ZEND_VM_HANDLER(50, ZEND_BRK, ANY, CONST)
{
USE_OPLINE
@@ -3388,10 +3398,10 @@ ZEND_VM_HANDLER(50, ZEND_BRK, ANY, CONST)
el = zend_brk_cont(Z_LVAL_P(opline->op2.zv), opline->op1.opline_num,
EX(op_array), EX_Ts() TSRMLS_CC);
FREE_OP2();
- if (EG(active_op_array)->has_finally_block) {
- EX(leaving_dest) = el->brk;
- ZEND_VM_DISPATCH_TO_HELPER_EX(zend_finally_handler_leaving, type, ZEND_BRK);
- }
+ if (EX(op_array)->has_finally_block) {
+ EX(leaving_dest) = el->brk;
+ ZEND_VM_DISPATCH_TO_HELPER_EX(zend_finally_handler_leaving, type, ZEND_BRK);
+ }
ZEND_VM_JMP(EX(op_array)->opcodes + el->brk);
}
@@ -3404,10 +3414,10 @@ ZEND_VM_HANDLER(51, ZEND_CONT, ANY, CONST)
el = zend_brk_cont(Z_LVAL_P(opline->op2.zv), opline->op1.opline_num,
EX(op_array), EX_Ts() TSRMLS_CC);
FREE_OP2();
- if (EG(active_op_array)->has_finally_block) {
- EX(leaving_dest) = el->cont;
- ZEND_VM_DISPATCH_TO_HELPER_EX(zend_finally_handler_leaving, type, ZEND_CONT);
- }
+ if (EG(active_op_array)->has_finally_block) {
+ EX(leaving_dest) = el->cont;
+ ZEND_VM_DISPATCH_TO_HELPER_EX(zend_finally_handler_leaving, type, ZEND_CONT);
+ }
ZEND_VM_JMP(EX(op_array)->opcodes + el->cont);
}
@@ -3435,10 +3445,10 @@ ZEND_VM_HANDLER(100, ZEND_GOTO, ANY, CONST)
}
break;
}
- if ((EG(active_op_array)->has_finally_block)) {
- EX(leaving_dest) = opline->op1.jmp_addr - EG(active_op_array)->opcodes;
- ZEND_VM_DISPATCH_TO_HELPER_EX(zend_finally_handler_leaving, type, ZEND_GOTO);
- }
+ if (EX(op_array)->has_finally_block) {
+ EX(leaving_dest) = opline->op1.jmp_addr - EX(op_array)->opcodes;
+ ZEND_VM_DISPATCH_TO_HELPER_EX(zend_finally_handler_leaving, type, ZEND_GOTO);
+ }
ZEND_VM_JMP(opline->op1.jmp_addr);
}
@@ -5305,7 +5315,7 @@ ZEND_VM_HANDLER(153, ZEND_DECLARE_LAMBDA_FUNCTION, CONST, UNUSED)
zend_function *op_array;
SAVE_OPLINE();
-
+
if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), Z_HASH_P(opline->op1.zv), (void *) &op_array) == FAILURE) ||
UNEXPECTED(op_array->type != ZEND_USER_FUNCTION)) {
zend_error_noreturn(E_ERROR, "Base lambda function for closure not found");
@@ -5340,64 +5350,21 @@ ZEND_VM_HANDLER(156, ZEND_SEPARATE, VAR, UNUSED)
ZEND_VM_HANDLER(159, ZEND_LEAVE, ANY, ANY)
{
- 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 {
- ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
- }
- }
- break;
+ leaving = ZEND_LEAVE;
+ case ZEND_JMP:
case ZEND_BRK:
case ZEND_CONT:
case ZEND_GOTO:
- ZEND_VM_DISPATCH_TO_HELPER_EX(zend_finally_handler_leaving, type, EX(leaving));
+ ZEND_VM_DISPATCH_TO_HELPER_EX(zend_finally_handler_leaving, type, leaving);
break;
}
}
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index 9818583334..bd19124574 100644
--- a/Zend/zend_vm_execute.h
+++ b/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)