ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HANDLER(42, ZEND_JMP, ANY, ANY)
+ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
{
- USE_OPLINE
+ zend_bool nested;
+ zend_op_array *op_array = EX(op_array);
-#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 */
-}
+ 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++;
+ }
+ }
-ZEND_VM_HANDLER(43, ZEND_JMPZ, CONST|TMP|VAR|CV, ANY)
-{
- USE_OPLINE
- zend_free_op free_op1;
- zval *val;
- int ret;
+ if ((op_array->fn_flags & ZEND_ACC_CLOSURE) && op_array->prototype) {
+ zval_ptr_dtor((zval**)&op_array->prototype);
+ }
- SAVE_OPLINE();
- val = GET_OP1_ZVAL_PTR(BP_VAR_R);
+ nested = EX(nested);
- if (OP1_TYPE == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) {
- ret = Z_LVAL_P(val);
- } else {
- ret = i_zend_is_true(val);
- FREE_OP1();
- if (UNEXPECTED(EG(exception) != NULL)) {
- HANDLE_EXCEPTION();
- }
- }
- if (!ret) {
-#if DEBUG_ZEND>=2
- printf("Conditional jmp to %d\n", opline->op2.opline_num);
-#endif
- ZEND_VM_SET_OPCODE(opline->op2.jmp_addr);
- ZEND_VM_CONTINUE();
+ zend_vm_stack_free(execute_data TSRMLS_CC);
+
+ if (nested) {
+ execute_data = EG(current_execute_data);
}
+ if (nested) {
+ USE_OPLINE
- ZEND_VM_NEXT_OPCODE();
-}
+ LOAD_REGS();
+ LOAD_OPLINE();
+ if (UNEXPECTED(opline->opcode == ZEND_INCLUDE_OR_EVAL)) {
-ZEND_VM_HANDLER(44, ZEND_JMPNZ, CONST|TMP|VAR|CV, ANY)
-{
- USE_OPLINE
- zend_free_op free_op1;
- zval *val;
- int ret;
+ EX(function_state).function = (zend_function *) EX(op_array);
+ EX(function_state).arguments = NULL;
+ EX(object) = EX(current_object);
- SAVE_OPLINE();
- val = GET_OP1_ZVAL_PTR(BP_VAR_R);
+ 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;
- if (OP1_TYPE == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) {
- ret = Z_LVAL_P(val);
- } else {
- ret = i_zend_is_true(val);
- FREE_OP1();
- if (UNEXPECTED(EG(exception) != NULL)) {
- HANDLE_EXCEPTION();
- }
- }
- if (ret) {
-#if DEBUG_ZEND>=2
- printf("Conditional jmp to %d\n", opline->op2.opline_num);
-#endif
- ZEND_VM_SET_OPCODE(opline->op2.jmp_addr);
- ZEND_VM_CONTINUE();
- }
+ ALLOC_ZVAL(retval);
+ ZVAL_BOOL(retval, 1);
+ INIT_PZVAL(retval);
+ EX_T(opline->result.var).var.ptr = retval;
+ }
+ }
- ZEND_VM_NEXT_OPCODE();
-}
+ ZEND_VM_INC_OPCODE();
+ ZEND_VM_LEAVE();
+ } else {
-ZEND_VM_HANDLER(45, ZEND_JMPZNZ, CONST|TMP|VAR|CV, ANY)
-{
- USE_OPLINE
- zend_free_op free_op1;
- zval *val;
- int retval;
+ 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);
- SAVE_OPLINE();
- val = GET_OP1_ZVAL_PTR(BP_VAR_R);
+ EX(function_state).function = (zend_function *) EX(op_array);
+ EX(function_state).arguments = NULL;
- if (OP1_TYPE == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) {
- retval = Z_LVAL_P(val);
- } else {
- retval = i_zend_is_true(val);
- FREE_OP1();
- if (UNEXPECTED(EG(exception) != NULL)) {
- HANDLE_EXCEPTION();
+ 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();
}
}
- if (EXPECTED(retval != 0)) {
-#if DEBUG_ZEND>=2
- printf("Conditional jmp on true to %d\n", opline->extended_value);
-#endif
- ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->extended_value]);
- ZEND_VM_CONTINUE(); /* CHECK_ME */
- } else {
-#if DEBUG_ZEND>=2
- printf("Conditional jmp on false to %d\n", opline->op2.opline_num);
-#endif
- ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.opline_num]);
- ZEND_VM_CONTINUE(); /* CHECK_ME */
- }
+ ZEND_VM_RETURN();
}
-ZEND_VM_HANDLER(46, ZEND_JMPZ_EX, CONST|TMP|VAR|CV, ANY)
+ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
{
USE_OPLINE
- zend_free_op free_op1;
- zval *val;
- int retval;
+ zend_bool should_change_scope = 0;
+ zend_function *fbc = EX(function_state).function;
SAVE_OPLINE();
- val = GET_OP1_ZVAL_PTR(BP_VAR_R);
+ 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 (OP1_TYPE == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) {
- retval = Z_LVAL_P(val);
- } else {
- retval = i_zend_is_true(val);
- FREE_OP1();
- if (UNEXPECTED(EG(exception) != NULL)) {
- HANDLE_EXCEPTION();
+ 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);
}
}
- Z_LVAL(EX_T(opline->result.var).tmp_var) = retval;
- Z_TYPE(EX_T(opline->result.var).tmp_var) = IS_BOOL;
- if (!retval) {
-#if DEBUG_ZEND>=2
- printf("Conditional jmp to %d\n", opline->op2.opline_num);
-#endif
- ZEND_VM_SET_OPCODE(opline->op2.jmp_addr);
- ZEND_VM_CONTINUE();
+
+ 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_VM_NEXT_OPCODE();
-}
-ZEND_VM_HANDLER(47, ZEND_JMPNZ_EX, CONST|TMP|VAR|CV, ANY)
-{
- USE_OPLINE
- zend_free_op free_op1;
- zval *val;
- int retval;
+ 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();
- SAVE_OPLINE();
- val = GET_OP1_ZVAL_PTR(BP_VAR_R);
+ if (fbc->type == ZEND_INTERNAL_FUNCTION) {
+ temp_variable *ret = &EX_T(opline->result.var);
- if (OP1_TYPE == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) {
- retval = Z_LVAL_P(val);
- } else {
- retval = i_zend_is_true(val);
- FREE_OP1();
- if (UNEXPECTED(EG(exception) != NULL)) {
- HANDLE_EXCEPTION();
+ 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;
}
}
- Z_LVAL(EX_T(opline->result.var).tmp_var) = retval;
- Z_TYPE(EX_T(opline->result.var).tmp_var) = IS_BOOL;
- if (retval) {
-#if DEBUG_ZEND>=2
- printf("Conditional jmp to %d\n", opline->op2.opline_num);
-#endif
- ZEND_VM_SET_OPCODE(opline->op2.jmp_addr);
- ZEND_VM_CONTINUE();
+
+ 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(70, ZEND_FREE, TMP|VAR, ANY)
+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();
- if (OP1_TYPE == IS_TMP_VAR) {
- zendi_zval_dtor(EX_T(opline->op1.var).tmp_var);
- } else {
- zval_ptr_dtor(&EX_T(opline->op1.var).var.ptr);
+
+ 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;
}
- CHECK_EXCEPTION();
- ZEND_VM_NEXT_OPCODE();
+ ZEND_VM_CONTINUE();
}
-ZEND_VM_HANDLER(53, ZEND_INIT_STRING, ANY, ANY)
+ZEND_VM_HANDLER(42, ZEND_JMP, ANY, ANY)
{
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();
+#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 */
}
-ZEND_VM_HANDLER(54, ZEND_ADD_CHAR, TMP|UNUSED, CONST)
+ZEND_VM_HANDLER(43, ZEND_JMPZ, CONST|TMP|VAR|CV, ANY)
{
USE_OPLINE
- zval *str = &EX_T(opline->result.var).tmp_var;
+ zend_free_op free_op1;
+ zval *val;
+ int ret;
SAVE_OPLINE();
+ val = GET_OP1_ZVAL_PTR(BP_VAR_R);
- if (OP1_TYPE == IS_UNUSED) {
- /* Initialize for erealloc in add_char_to_string */
- Z_STRVAL_P(str) = NULL;
- Z_STRLEN_P(str) = 0;
- Z_TYPE_P(str) = IS_STRING;
-
- INIT_PZVAL(str);
+ if (OP1_TYPE == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) {
+ ret = Z_LVAL_P(val);
+ } else {
+ ret = i_zend_is_true(val);
+ FREE_OP1();
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ HANDLE_EXCEPTION();
+ }
+ }
+ if (!ret) {
+#if DEBUG_ZEND>=2
+ printf("Conditional jmp to %d\n", opline->op2.opline_num);
+#endif
+ ZEND_VM_SET_OPCODE(opline->op2.jmp_addr);
+ ZEND_VM_CONTINUE();
}
- add_char_to_string(str, str, opline->op2.zv);
-
- /* FREE_OP is missing intentionally here - we're always working on the same temporary variable */
- /*CHECK_EXCEPTION();*/
ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HANDLER(55, ZEND_ADD_STRING, TMP|UNUSED, CONST)
+ZEND_VM_HANDLER(44, ZEND_JMPNZ, CONST|TMP|VAR|CV, ANY)
{
USE_OPLINE
- zval *str = &EX_T(opline->result.var).tmp_var;
+ zend_free_op free_op1;
+ zval *val;
+ int ret;
SAVE_OPLINE();
+ val = GET_OP1_ZVAL_PTR(BP_VAR_R);
- if (OP1_TYPE == IS_UNUSED) {
- /* Initialize for erealloc in add_string_to_string */
- Z_STRVAL_P(str) = NULL;
- Z_STRLEN_P(str) = 0;
- Z_TYPE_P(str) = IS_STRING;
-
- INIT_PZVAL(str);
+ if (OP1_TYPE == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) {
+ ret = Z_LVAL_P(val);
+ } else {
+ ret = i_zend_is_true(val);
+ FREE_OP1();
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ HANDLE_EXCEPTION();
+ }
+ }
+ if (ret) {
+#if DEBUG_ZEND>=2
+ printf("Conditional jmp to %d\n", opline->op2.opline_num);
+#endif
+ ZEND_VM_SET_OPCODE(opline->op2.jmp_addr);
+ ZEND_VM_CONTINUE();
+ }
+
+ ZEND_VM_NEXT_OPCODE();
+}
+
+ZEND_VM_HANDLER(45, ZEND_JMPZNZ, CONST|TMP|VAR|CV, ANY)
+{
+ USE_OPLINE
+ zend_free_op free_op1;
+ zval *val;
+ int retval;
+
+ SAVE_OPLINE();
+ val = GET_OP1_ZVAL_PTR(BP_VAR_R);
+
+ if (OP1_TYPE == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) {
+ retval = Z_LVAL_P(val);
+ } else {
+ retval = i_zend_is_true(val);
+ FREE_OP1();
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ HANDLE_EXCEPTION();
+ }
+ }
+ if (EXPECTED(retval != 0)) {
+#if DEBUG_ZEND>=2
+ printf("Conditional jmp on true to %d\n", opline->extended_value);
+#endif
+ ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->extended_value]);
+ ZEND_VM_CONTINUE(); /* CHECK_ME */
+ } else {
+#if DEBUG_ZEND>=2
+ printf("Conditional jmp on false to %d\n", opline->op2.opline_num);
+#endif
+ ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.opline_num]);
+ ZEND_VM_CONTINUE(); /* CHECK_ME */
+ }
+}
+
+ZEND_VM_HANDLER(46, ZEND_JMPZ_EX, CONST|TMP|VAR|CV, ANY)
+{
+ USE_OPLINE
+ zend_free_op free_op1;
+ zval *val;
+ int retval;
+
+ SAVE_OPLINE();
+ val = GET_OP1_ZVAL_PTR(BP_VAR_R);
+
+ if (OP1_TYPE == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) {
+ retval = Z_LVAL_P(val);
+ } else {
+ retval = i_zend_is_true(val);
+ FREE_OP1();
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ HANDLE_EXCEPTION();
+ }
+ }
+ Z_LVAL(EX_T(opline->result.var).tmp_var) = retval;
+ Z_TYPE(EX_T(opline->result.var).tmp_var) = IS_BOOL;
+ if (!retval) {
+#if DEBUG_ZEND>=2
+ printf("Conditional jmp to %d\n", opline->op2.opline_num);
+#endif
+ ZEND_VM_SET_OPCODE(opline->op2.jmp_addr);
+ ZEND_VM_CONTINUE();
+ }
+ ZEND_VM_NEXT_OPCODE();
+}
+
+ZEND_VM_HANDLER(47, ZEND_JMPNZ_EX, CONST|TMP|VAR|CV, ANY)
+{
+ USE_OPLINE
+ zend_free_op free_op1;
+ zval *val;
+ int retval;
+
+ SAVE_OPLINE();
+ val = GET_OP1_ZVAL_PTR(BP_VAR_R);
+
+ if (OP1_TYPE == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) {
+ retval = Z_LVAL_P(val);
+ } else {
+ retval = i_zend_is_true(val);
+ FREE_OP1();
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ HANDLE_EXCEPTION();
+ }
+ }
+ Z_LVAL(EX_T(opline->result.var).tmp_var) = retval;
+ Z_TYPE(EX_T(opline->result.var).tmp_var) = IS_BOOL;
+ if (retval) {
+#if DEBUG_ZEND>=2
+ printf("Conditional jmp to %d\n", opline->op2.opline_num);
+#endif
+ ZEND_VM_SET_OPCODE(opline->op2.jmp_addr);
+ ZEND_VM_CONTINUE();
+ }
+ ZEND_VM_NEXT_OPCODE();
+}
+
+ZEND_VM_HANDLER(70, ZEND_FREE, TMP|VAR, ANY)
+{
+ USE_OPLINE
+
+ SAVE_OPLINE();
+ if (OP1_TYPE == IS_TMP_VAR) {
+ zendi_zval_dtor(EX_T(opline->op1.var).tmp_var);
+ } else {
+ zval_ptr_dtor(&EX_T(opline->op1.var).var.ptr);
+ }
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+ZEND_VM_HANDLER(53, ZEND_INIT_STRING, ANY, ANY)
+{
+ 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();
+}
+
+ZEND_VM_HANDLER(54, ZEND_ADD_CHAR, TMP|UNUSED, CONST)
+{
+ USE_OPLINE
+ zval *str = &EX_T(opline->result.var).tmp_var;
+
+ SAVE_OPLINE();
+
+ if (OP1_TYPE == IS_UNUSED) {
+ /* Initialize for erealloc in add_char_to_string */
+ Z_STRVAL_P(str) = NULL;
+ Z_STRLEN_P(str) = 0;
+ Z_TYPE_P(str) = IS_STRING;
+
+ INIT_PZVAL(str);
+ }
+
+ add_char_to_string(str, str, opline->op2.zv);
+
+ /* FREE_OP is missing intentionally here - we're always working on the same temporary variable */
+ /*CHECK_EXCEPTION();*/
+ ZEND_VM_NEXT_OPCODE();
+}
+
+ZEND_VM_HANDLER(55, ZEND_ADD_STRING, TMP|UNUSED, CONST)
+{
+ USE_OPLINE
+ zval *str = &EX_T(opline->result.var).tmp_var;
+
+ SAVE_OPLINE();
+
+ if (OP1_TYPE == IS_UNUSED) {
+ /* Initialize for erealloc in add_string_to_string */
+ Z_STRVAL_P(str) = NULL;
+ Z_STRLEN_P(str) = 0;
+ Z_TYPE_P(str) = IS_STRING;
+
+ INIT_PZVAL(str);
}
add_string_to_string(str, str, opline->op2.zv);
EX(fbc)->common.fn_flags & ZEND_ACC_CLOSURE) {
/* Delay closure destruction until its invocation */
EX(fbc)->common.prototype = (zend_function*)function_name;
- } else {
- FREE_OP2();
- }
- CHECK_EXCEPTION();
- ZEND_VM_NEXT_OPCODE();
- } else if (OP2_TYPE != IS_CONST &&
- EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY) &&
- zend_hash_num_elements(Z_ARRVAL_P(function_name)) == 2) {
- zend_class_entry *ce;
- zval **method = NULL;
- zval **obj = NULL;
-
- zend_hash_index_find(Z_ARRVAL_P(function_name), 0, (void **) &obj);
- zend_hash_index_find(Z_ARRVAL_P(function_name), 1, (void **) &method);
-
- if (Z_TYPE_PP(obj) != IS_STRING && Z_TYPE_PP(obj) != IS_OBJECT) {
- zend_error_noreturn(E_ERROR, "First array member is not a valid class name or object");
- }
-
- if (Z_TYPE_PP(method) != IS_STRING) {
- zend_error_noreturn(E_ERROR, "Second array member is not a valid method");
- }
-
- if (Z_TYPE_PP(obj) == IS_STRING) {
- ce = zend_fetch_class_by_name(Z_STRVAL_PP(obj), Z_STRLEN_PP(obj), NULL, 0 TSRMLS_CC);
- if (UNEXPECTED(ce == NULL)) {
- CHECK_EXCEPTION();
- ZEND_VM_NEXT_OPCODE();
- }
- EX(called_scope) = ce;
- EX(object) = NULL;
-
- if (ce->get_static_method) {
- EX(fbc) = ce->get_static_method(ce, Z_STRVAL_PP(method), Z_STRLEN_PP(method) TSRMLS_CC);
- } else {
- EX(fbc) = zend_std_get_static_method(ce, Z_STRVAL_PP(method), Z_STRLEN_PP(method), NULL TSRMLS_CC);
- }
- } else {
- EX(object) = *obj;
- ce = EX(called_scope) = Z_OBJCE_PP(obj);
-
- EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), Z_STRVAL_PP(method), Z_STRLEN_PP(method), NULL TSRMLS_CC);
- if (UNEXPECTED(EX(fbc) == NULL)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), Z_STRVAL_PP(method));
- }
-
- if ((EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) {
- EX(object) = NULL;
- } else {
- if (!PZVAL_IS_REF(EX(object))) {
- Z_ADDREF_P(EX(object)); /* For $this pointer */
- } else {
- zval *this_ptr;
- ALLOC_ZVAL(this_ptr);
- INIT_PZVAL_COPY(this_ptr, EX(object));
- zval_copy_ctor(this_ptr);
- EX(object) = this_ptr;
- }
- }
- }
-
- if (UNEXPECTED(EX(fbc) == NULL)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, Z_STRVAL_PP(method));
- }
- FREE_OP2();
- CHECK_EXCEPTION();
- ZEND_VM_NEXT_OPCODE();
- } else {
- zend_error_noreturn(E_ERROR, "Function name must be a string");
- }
- }
-}
-
-
-ZEND_VM_HANDLER(69, ZEND_INIT_NS_FCALL_BY_NAME, ANY, CONST)
-{
- USE_OPLINE
- zend_literal *func_name;
-
- zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
-
- func_name = opline->op2.literal + 1;
- if (CACHED_PTR(opline->op2.literal->cache_slot)) {
- EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot);
- } else if (zend_hash_quick_find(EG(function_table), Z_STRVAL(func_name->constant), Z_STRLEN(func_name->constant)+1, func_name->hash_value, (void **) &EX(fbc))==FAILURE) {
- func_name++;
- if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL(func_name->constant), Z_STRLEN(func_name->constant)+1, func_name->hash_value, (void **) &EX(fbc))==FAILURE)) {
- SAVE_OPLINE();
- zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(opline->op2.zv));
- } else {
- CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc));
- }
- } else {
- CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc));
- }
-
- EX(object) = NULL;
- 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--;
+ } else {
+ FREE_OP2();
}
- }
-
- 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);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ } else if (OP2_TYPE != IS_CONST &&
+ EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY) &&
+ zend_hash_num_elements(Z_ARRVAL_P(function_name)) == 2) {
+ zend_class_entry *ce;
+ zval **method = NULL;
+ zval **obj = NULL;
- 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;
- }
+ zend_hash_index_find(Z_ARRVAL_P(function_name), 0, (void **) &obj);
+ zend_hash_index_find(Z_ARRVAL_P(function_name), 1, (void **) &method);
- if (EXPECTED(zend_execute == execute)) {
- if (EXPECTED(EG(exception) == NULL)) {
- ZEND_VM_ENTER();
+ if (Z_TYPE_PP(obj) != IS_STRING && Z_TYPE_PP(obj) != IS_OBJECT) {
+ zend_error_noreturn(E_ERROR, "First array member is not a valid class name or object");
}
- } 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);
+ if (Z_TYPE_PP(method) != IS_STRING) {
+ zend_error_noreturn(E_ERROR, "Second array member is not a valid method");
}
- }
- 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;
- }
- }
+ if (Z_TYPE_PP(obj) == IS_STRING) {
+ ce = zend_fetch_class_by_name(Z_STRVAL_PP(obj), Z_STRLEN_PP(obj), NULL, 0 TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ EX(called_scope) = ce;
+ EX(object) = NULL;
- EX(function_state).function = (zend_function *) EX(op_array);
- EX(function_state).arguments = NULL;
+ if (ce->get_static_method) {
+ EX(fbc) = ce->get_static_method(ce, Z_STRVAL_PP(method), Z_STRLEN_PP(method) TSRMLS_CC);
+ } else {
+ EX(fbc) = zend_std_get_static_method(ce, Z_STRVAL_PP(method), Z_STRLEN_PP(method), NULL TSRMLS_CC);
+ }
+ } else {
+ EX(object) = *obj;
+ ce = EX(called_scope) = Z_OBJCE_PP(obj);
- 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));
+ EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), Z_STRVAL_PP(method), Z_STRLEN_PP(method), NULL TSRMLS_CC);
+ if (UNEXPECTED(EX(fbc) == NULL)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), Z_STRVAL_PP(method));
}
- if (Z_REFCOUNT_P(EG(This)) == 1) {
- zend_object_store_ctor_failed(EG(This) TSRMLS_CC);
+
+ if ((EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) {
+ EX(object) = NULL;
+ } else {
+ if (!PZVAL_IS_REF(EX(object))) {
+ Z_ADDREF_P(EX(object)); /* For $this pointer */
+ } else {
+ zval *this_ptr;
+ ALLOC_ZVAL(this_ptr);
+ INIT_PZVAL_COPY(this_ptr, EX(object));
+ zval_copy_ctor(this_ptr);
+ EX(object) = this_ptr;
+ }
}
}
- zval_ptr_dtor(&EG(This));
+
+ if (UNEXPECTED(EX(fbc) == NULL)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, Z_STRVAL_PP(method));
+ }
+ FREE_OP2();
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ } else {
+ zend_error_noreturn(E_ERROR, "Function name must be a string");
}
- 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);
+ZEND_VM_HANDLER(69, ZEND_INIT_NS_FCALL_BY_NAME, ANY, CONST)
+{
+ USE_OPLINE
+ zend_literal *func_name;
- 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);
+ zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
+
+ func_name = opline->op2.literal + 1;
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else if (zend_hash_quick_find(EG(function_table), Z_STRVAL(func_name->constant), Z_STRLEN(func_name->constant)+1, func_name->hash_value, (void **) &EX(fbc))==FAILURE) {
+ func_name++;
+ if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL(func_name->constant), Z_STRLEN(func_name->constant)+1, func_name->hash_value, (void **) &EX(fbc))==FAILURE)) {
+ SAVE_OPLINE();
+ zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(opline->op2.zv));
+ } else {
+ CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc));
}
- HANDLE_EXCEPTION();
+ } else {
+ CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc));
}
+ EX(object) = NULL;
ZEND_VM_NEXT_OPCODE();
}
}
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)
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)
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
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);
}
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);
}
}
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);
}
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");
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;
}
}
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;
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
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;
}
}
}
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
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;
}
}
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);
}
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);
}
}
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);
}
*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)
}
} 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)
*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)
}
} 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)
}
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)
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)
*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)
}
} 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)