Commit:    96e5f5eb05af913f8a9b9297393f153c561bf51b
Author:    Dmitry Stogov <dmi...@zend.com>         Mon, 25 Mar 2013 15:47:45 
+0400
Parents:   6a7088fd187f071df47fa09c6e215c916bfd699c 
e9f996c00d5cb6448dac1457dd9dae320c16904f
Branches:  PHP-5.5 master

Link:       
http://git.php.net/?p=php-src.git;a=commitdiff;h=96e5f5eb05af913f8a9b9297393f153c561bf51b

Log:
Merge branch 'PHP-5.4' into PHP-5.5

* PHP-5.4:
  Fixed bug #63914 (zend_do_fcall_common_helper_SPEC does not handle exceptions 
properly). (Jeff Welch)

Conflicts:
        NEWS
        Zend/zend_vm_def.h
        Zend/zend_vm_execute.h

Bugs:
https://bugs.php.net/63914

Changed paths:
  MM  Zend/zend_vm_def.h
  MM  Zend/zend_vm_execute.h

diff --cc Zend/zend_vm_def.h
index 206a233,ffa94a1..31a5fac
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@@ -1829,266 -1819,6 +1829,268 @@@ ZEND_VM_HANDLER(39, ZEND_ASSIGN_REF, VA
        ZEND_VM_NEXT_OPCODE();
  }
  
 +ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
 +{
 +      zend_bool nested = EX(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)) {
 +              i_free_compiled_variables(execute_data);
 +      }
 +
 +      zend_vm_stack_free((char*)execute_data - 
(ZEND_MM_ALIGNED_SIZE(sizeof(temp_variable)) * op_array->T) TSRMLS_CC);
 +
 +      if ((op_array->fn_flags & ZEND_ACC_CLOSURE) && op_array->prototype) {
 +              zval_ptr_dtor((zval**)&op_array->prototype);
 +      }
 +
 +      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;
 +
 +                      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();
 +                      }
 +
 +                      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)) {
 +                              
zend_clean_and_cache_symbol_table(EG(active_symbol_table) TSRMLS_CC);
 +                      }
 +                      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) && 
EX(call)->is_ctor_call) {
 +                                      if (EX(call)->is_ctor_result_used) {
 +                                              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(call)--;
 +
 +                      zend_vm_stack_clear_multiple(1 TSRMLS_CC);
 +
 +                      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();
 +      EX(object) = EX(call)->object;
 +      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(call)->called_scope;
 +      }
 +
 +      EX(function_state).arguments = zend_vm_stack_top(TSRMLS_C);
 +      zend_vm_stack_push((void*)(zend_uintptr_t)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, NULL, 
RETURN_VALUE_USED(opline) TSRMLS_CC);
-               }
++              if (EXPECTED(EG(exception) == NULL)) {
++                      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 (!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, NULL, 
RETURN_VALUE_USED(opline) TSRMLS_CC);
++                      }
 +
-               if (!RETURN_VALUE_USED(opline)) {
-                       zval_ptr_dtor(&ret->var.ptr);
++                      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 (UNEXPECTED((EG(active_op_array)->fn_flags & 
ZEND_ACC_GENERATOR) != 0)) {
 +                      if (RETURN_VALUE_USED(opline)) {
 +                              EX_T(opline->result.var).var.ptr = 
zend_generator_create_zval(EG(active_op_array) TSRMLS_CC);
 +                      }
 +              } else if (EXPECTED(zend_execute_ex == execute_ex)) {
 +                      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)) {
 +                      
zend_clean_and_cache_symbol_table(EG(active_symbol_table) TSRMLS_CC);
 +              }
 +              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) && 
EX(call)->is_ctor_call) {
 +                              if (EX(call)->is_ctor_result_used) {
 +                                      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(call)--;
 +
 +      zend_vm_stack_clear_multiple(1 TSRMLS_CC);
 +
 +      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(42, ZEND_JMP, ANY, ANY)
  {
        USE_OPLINE
diff --cc Zend/zend_vm_execute.h
index d65dfc4,1860a0f..7fe6ee1
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@@ -519,13 -619,8 +519,6 @@@ static int ZEND_FASTCALL zend_do_fcall_
        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;
@@@ -537,15 -632,22 +530,24 @@@
                        }
                }
  
-               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, NULL, 
RETURN_VALUE_USED(opline) TSRMLS_CC);
-               }
+               if (EXPECTED(EG(exception) == NULL)) {
++                      temp_variable *ret = &EX_T(opline->result.var);
 +
-               if (!RETURN_VALUE_USED(opline)) {
-                       zval_ptr_dtor(&ret->var.ptr);
+                       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 (!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);
++                              zend_execute_internal(execute_data, NULL, 
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);
-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to