Index: Zend/zend_API.c =================================================================== RCS file: /repository/ZendEngine2/zend_API.c,v retrieving revision 1.296.2.27.2.34.2.31 diff -u -r1.296.2.27.2.34.2.31 zend_API.c --- Zend/zend_API.c 6 Mar 2008 17:28:26 -0000 1.296.2.27.2.34.2.31 +++ Zend/zend_API.c 13 Mar 2008 03:14:56 -0000 @@ -2312,7 +2312,7 @@ } /* }}} */ -static int zend_is_callable_check_func(int check_flags, zval ***zobj_ptr_ptr, zend_class_entry *ce_org, zval *callable, zend_class_entry **ce_ptr, zend_function **fptr_ptr, char **error TSRMLS_DC) /* {{{ */ +static int zend_is_callable_check_func(int check_flags, zval ***zobj_ptr_ptr, zend_class_entry *ce_org, zval *callable, zend_class_entry **ce_ptr, zend_uint *fetch_type, zend_function **fptr_ptr, char **error TSRMLS_DC) /* {{{ */ { int retval; char *lmname, *colon; @@ -2371,6 +2371,7 @@ EG(scope) = ce_org; } *ce_ptr = zend_fetch_class(Z_STRVAL_P(callable), clen, ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_SILENT TSRMLS_CC); + *fetch_type = zend_get_class_fetch_type(Z_STRVAL_P(callable), clen); EG(scope) = last_scope; if (!*ce_ptr) { if (error) zend_spprintf(error, 0, "class '%.*Z' not found", clen, callable); @@ -2472,11 +2473,12 @@ } /* }}} */ -ZEND_API zend_bool zend_is_callable_ex(zval *callable, uint check_flags, char **callable_name, int *callable_name_len, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zval ***zobj_ptr_ptr, char **error TSRMLS_DC) /* {{{ */ +ZEND_API zend_bool zend_is_callable_ex(zval *callable, uint check_flags, char **callable_name, int *callable_name_len, zend_class_entry **ce_ptr, zend_uint *fetch_type, zend_function **fptr_ptr, zval ***zobj_ptr_ptr, char **error TSRMLS_DC) /* {{{ */ { char *lcname; int callable_name_len_local; zend_class_entry *ce_local, **pce; + zend_uint fetch_type_local; zend_function *fptr_local; zval **zobj_ptr_local; @@ -2498,7 +2500,12 @@ if (error) { *error = NULL; } + if (fetch_type == NULL) { + fetch_type = &fetch_type_local; + } + *ce_ptr = NULL; + *fetch_type = 0; *fptr_ptr = NULL; *zobj_ptr_ptr = NULL; @@ -2512,7 +2519,7 @@ return 1; } - return zend_is_callable_check_func(check_flags, zobj_ptr_ptr, NULL, callable, ce_ptr, fptr_ptr, error TSRMLS_CC); + return zend_is_callable_check_func(check_flags, zobj_ptr_ptr, NULL, callable, ce_ptr, fetch_type, fptr_ptr, error TSRMLS_CC); case IS_ARRAY: { @@ -2552,13 +2559,16 @@ Z_STRLEN_PP(obj) == sizeof("self") - 1 && !memcmp(lcname, "self", sizeof("self") - 1)) { ce = EG(active_op_array)->scope; + *fetch_type = ZEND_FETCH_CLASS_SELF; } else if (EG(active_op_array) && EG(active_op_array)->scope && Z_STRLEN_PP(obj) == sizeof("parent") - 1 && !memcmp(lcname, "parent", sizeof("parent") - 1)) { ce = EG(active_op_array)->scope->parent; + *fetch_type = ZEND_FETCH_CLASS_PARENT; } else if (Z_STRLEN_PP(obj) == sizeof("static") - 1 && !memcmp(lcname, "static", sizeof("static") - 1)) { ce = EG(called_scope); + *fetch_type = ZEND_FETCH_CLASS_STATIC; } else if (zend_lookup_class(Z_STRVAL_PP(obj), Z_STRLEN_PP(obj), &pce TSRMLS_CC) == SUCCESS) { ce = *pce; } @@ -2587,7 +2597,7 @@ } if (ce) { - return zend_is_callable_check_func(check_flags, zobj_ptr_ptr, ce, *method, ce_ptr, fptr_ptr, error TSRMLS_CC); + return zend_is_callable_check_func(check_flags, zobj_ptr_ptr, ce, *method, ce_ptr, fetch_type, fptr_ptr, error TSRMLS_CC); } else { if (error) zend_spprintf(error, 0, "first array member is not a valid %s", Z_TYPE_PP(obj) == IS_STRING ? "class name" : "object"); } @@ -2630,7 +2640,7 @@ { TSRMLS_FETCH(); - return zend_is_callable_ex(callable, check_flags, callable_name, NULL, NULL, NULL, NULL, NULL TSRMLS_CC); + return zend_is_callable_ex(callable, check_flags, callable_name, NULL, NULL, NULL, NULL, NULL, NULL TSRMLS_CC); } /* }}} */ @@ -2640,7 +2650,7 @@ zend_function *fptr; zval **zobj_ptr; - if (zend_is_callable_ex(callable, IS_CALLABLE_STRICT, callable_name, NULL, &ce, &fptr, &zobj_ptr, NULL TSRMLS_CC)) { + if (zend_is_callable_ex(callable, IS_CALLABLE_STRICT, callable_name, NULL, &ce, NULL, &fptr, &zobj_ptr, NULL TSRMLS_CC)) { if (Z_TYPE_P(callable) == IS_STRING && ce) { zval_dtor(callable); array_init(callable); @@ -2660,8 +2670,9 @@ zend_class_entry *ce; zend_function *func; zval **obj; + zend_uint fetch_type; - if (!zend_is_callable_ex(callable, check_flags, callable_name, NULL, &ce, &func, &obj, error TSRMLS_CC)) { + if (!zend_is_callable_ex(callable, check_flags, callable_name, NULL, &ce, &fetch_type, &func, &obj, error TSRMLS_CC)) { return FAILURE; } @@ -2687,7 +2698,11 @@ } else { fcc->initialized = 1; fcc->function_handler = func; - fcc->calling_scope = ce; + if (fetch_type == ZEND_FETCH_CLASS_PARENT) { + fcc->calling_scope = EG(called_scope); + } else { + fcc->calling_scope = ce; + } fcc->object_pp = obj; } efree(lcname); Index: Zend/zend_API.h =================================================================== RCS file: /repository/ZendEngine2/zend_API.h,v retrieving revision 1.207.2.8.2.8.2.9 diff -u -r1.207.2.8.2.8.2.9 zend_API.h --- Zend/zend_API.h 10 Mar 2008 22:02:41 -0000 1.207.2.8.2.8.2.9 +++ Zend/zend_API.h 13 Mar 2008 03:14:57 -0000 @@ -229,7 +229,7 @@ #define IS_CALLABLE_STRICT (IS_CALLABLE_CHECK_IS_STATIC) -ZEND_API zend_bool zend_is_callable_ex(zval *callable, uint check_flags, char **callable_name, int *callable_name_len, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zval ***zobj_ptr_ptr, char **error TSRMLS_DC); +ZEND_API zend_bool zend_is_callable_ex(zval *callable, uint check_flags, char **callable_name, int *callable_name_len, zend_class_entry **ce_ptr, zend_uint *fetch_type, zend_function **fptr_ptr, zval ***zobj_ptr_ptr, char **error TSRMLS_DC); ZEND_API zend_bool zend_is_callable(zval *callable, uint check_flags, char **callable_name); ZEND_API zend_bool zend_make_callable(zval *callable, char **callable_name TSRMLS_DC); ZEND_API const char *zend_get_module_version(const char *module_name); Index: Zend/zend_execute_API.c =================================================================== RCS file: /repository/ZendEngine2/zend_execute_API.c,v retrieving revision 1.331.2.20.2.24.2.28 diff -u -r1.331.2.20.2.24.2.28 zend_execute_API.c --- Zend/zend_execute_API.c 9 Mar 2008 20:52:29 -0000 1.331.2.20.2.24.2.28 +++ Zend/zend_execute_API.c 13 Mar 2008 03:14:57 -0000 @@ -773,6 +773,7 @@ found = (*ce != NULL?SUCCESS:FAILURE); fci->object_pp = EG(This)?&EG(This):NULL; EX(object) = EG(This); + calling_scope = *ce; } else if (strcmp(Z_STRVAL_PP(fci->object_pp), "parent") == 0 && EG(active_op_array)) { if (!EG(active_op_array)->scope) { @@ -785,6 +786,11 @@ found = (*ce != NULL?SUCCESS:FAILURE); fci->object_pp = EG(This)?&EG(This):NULL; EX(object) = EG(This); + if (EG(called_scope)) { + calling_scope = EG(called_scope); + } else { + calling_scope = *ce; + } } else if (Z_STRLEN_PP(fci->object_pp) == sizeof("static") - 1 && !memcmp(Z_STRVAL_PP(fci->object_pp), "static", sizeof("static") - 1) ) { @@ -795,6 +801,7 @@ found = (*ce != NULL?SUCCESS:FAILURE); fci->object_pp = EG(This)?&EG(This):NULL; EX(object) = EG(This); + calling_scope = *ce; } else { zend_class_entry *scope; scope = EG(active_op_array) ? EG(active_op_array)->scope : NULL; @@ -811,12 +818,12 @@ } else { fci->object_pp = NULL; } + calling_scope = *ce; } if (found == FAILURE) return FAILURE; fci->function_table = &(*ce)->function_table; - calling_scope = *ce; } else { zend_error(E_NOTICE, "Non-callable array passed to zend_call_function()"); return FAILURE; Index: Zend/zend_vm_def.h =================================================================== RCS file: /repository/ZendEngine2/zend_vm_def.h,v retrieving revision 1.59.2.29.2.48.2.42 diff -u -r1.59.2.29.2.48.2.42 zend_vm_def.h --- Zend/zend_vm_def.h 12 Mar 2008 10:32:11 -0000 1.59.2.29.2.48.2.42 +++ Zend/zend_vm_def.h 13 Mar 2008 03:14:58 -0000 @@ -1936,8 +1936,15 @@ if (!ce) { zend_error(E_ERROR, "Class '%s' not found", Z_STRVAL(opline->op1.u.constant)); } + EX(called_scope) = ce; } else { ce = EX_T(opline->op1.u.var).class_entry; + + if (opline->op1.u.EA.type == ZEND_FETCH_CLASS_PARENT) { + EX(called_scope) = EG(called_scope); + } else { + EX(called_scope) = ce; + } } if(OP2_TYPE != IS_UNUSED) { char *function_name_strval; @@ -1977,8 +1984,6 @@ EX(fbc) = ce->constructor; } - EX(called_scope) = ce; - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { Index: Zend/zend_vm_execute.h =================================================================== RCS file: /repository/ZendEngine2/zend_vm_execute.h,v retrieving revision 1.62.2.30.2.49.2.41 diff -u -r1.62.2.30.2.49.2.41 zend_vm_execute.h --- Zend/zend_vm_execute.h 12 Mar 2008 10:32:12 -0000 1.62.2.30.2.49.2.41 +++ Zend/zend_vm_execute.h 13 Mar 2008 03:15:06 -0000 @@ -2383,8 +2383,15 @@ if (!ce) { zend_error(E_ERROR, "Class '%s' not found", Z_STRVAL(opline->op1.u.constant)); } + EX(called_scope) = ce; } else { ce = EX_T(opline->op1.u.var).class_entry; + + if (opline->op1.u.EA.type == ZEND_FETCH_CLASS_PARENT) { + EX(called_scope) = EG(called_scope); + } else { + EX(called_scope) = ce; + } } if(IS_CONST != IS_UNUSED) { char *function_name_strval; @@ -2424,8 +2431,6 @@ EX(fbc) = ce->constructor; } - EX(called_scope) = ce; - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -2953,8 +2958,15 @@ if (!ce) { zend_error(E_ERROR, "Class '%s' not found", Z_STRVAL(opline->op1.u.constant)); } + EX(called_scope) = ce; } else { ce = EX_T(opline->op1.u.var).class_entry; + + if (opline->op1.u.EA.type == ZEND_FETCH_CLASS_PARENT) { + EX(called_scope) = EG(called_scope); + } else { + EX(called_scope) = ce; + } } if(IS_TMP_VAR != IS_UNUSED) { char *function_name_strval; @@ -2994,8 +3006,6 @@ EX(fbc) = ce->constructor; } - EX(called_scope) = ce; - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -3418,8 +3428,15 @@ if (!ce) { zend_error(E_ERROR, "Class '%s' not found", Z_STRVAL(opline->op1.u.constant)); } + EX(called_scope) = ce; } else { ce = EX_T(opline->op1.u.var).class_entry; + + if (opline->op1.u.EA.type == ZEND_FETCH_CLASS_PARENT) { + EX(called_scope) = EG(called_scope); + } else { + EX(called_scope) = ce; + } } if(IS_VAR != IS_UNUSED) { char *function_name_strval; @@ -3459,8 +3476,6 @@ EX(fbc) = ce->constructor; } - EX(called_scope) = ce; - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -3640,8 +3655,15 @@ if (!ce) { zend_error(E_ERROR, "Class '%s' not found", Z_STRVAL(opline->op1.u.constant)); } + EX(called_scope) = ce; } else { ce = EX_T(opline->op1.u.var).class_entry; + + if (opline->op1.u.EA.type == ZEND_FETCH_CLASS_PARENT) { + EX(called_scope) = EG(called_scope); + } else { + EX(called_scope) = ce; + } } if(IS_UNUSED != IS_UNUSED) { char *function_name_strval; @@ -3681,8 +3703,6 @@ EX(fbc) = ce->constructor; } - EX(called_scope) = ce; - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -4073,8 +4093,15 @@ if (!ce) { zend_error(E_ERROR, "Class '%s' not found", Z_STRVAL(opline->op1.u.constant)); } + EX(called_scope) = ce; } else { ce = EX_T(opline->op1.u.var).class_entry; + + if (opline->op1.u.EA.type == ZEND_FETCH_CLASS_PARENT) { + EX(called_scope) = EG(called_scope); + } else { + EX(called_scope) = ce; + } } if(IS_CV != IS_UNUSED) { char *function_name_strval; @@ -4114,8 +4141,6 @@ EX(fbc) = ce->constructor; } - EX(called_scope) = ce; - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -9942,8 +9967,15 @@ if (!ce) { zend_error(E_ERROR, "Class '%s' not found", Z_STRVAL(opline->op1.u.constant)); } + EX(called_scope) = ce; } else { ce = EX_T(opline->op1.u.var).class_entry; + + if (opline->op1.u.EA.type == ZEND_FETCH_CLASS_PARENT) { + EX(called_scope) = EG(called_scope); + } else { + EX(called_scope) = ce; + } } if(IS_CONST != IS_UNUSED) { char *function_name_strval; @@ -9983,8 +10015,6 @@ EX(fbc) = ce->constructor; } - EX(called_scope) = ce; - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -11771,8 +11801,15 @@ if (!ce) { zend_error(E_ERROR, "Class '%s' not found", Z_STRVAL(opline->op1.u.constant)); } + EX(called_scope) = ce; } else { ce = EX_T(opline->op1.u.var).class_entry; + + if (opline->op1.u.EA.type == ZEND_FETCH_CLASS_PARENT) { + EX(called_scope) = EG(called_scope); + } else { + EX(called_scope) = ce; + } } if(IS_TMP_VAR != IS_UNUSED) { char *function_name_strval; @@ -11812,8 +11849,6 @@ EX(fbc) = ce->constructor; } - EX(called_scope) = ce; - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -13570,8 +13605,15 @@ if (!ce) { zend_error(E_ERROR, "Class '%s' not found", Z_STRVAL(opline->op1.u.constant)); } + EX(called_scope) = ce; } else { ce = EX_T(opline->op1.u.var).class_entry; + + if (opline->op1.u.EA.type == ZEND_FETCH_CLASS_PARENT) { + EX(called_scope) = EG(called_scope); + } else { + EX(called_scope) = ce; + } } if(IS_VAR != IS_UNUSED) { char *function_name_strval; @@ -13611,8 +13653,6 @@ EX(fbc) = ce->constructor; } - EX(called_scope) = ce; - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -14473,8 +14513,15 @@ if (!ce) { zend_error(E_ERROR, "Class '%s' not found", Z_STRVAL(opline->op1.u.constant)); } + EX(called_scope) = ce; } else { ce = EX_T(opline->op1.u.var).class_entry; + + if (opline->op1.u.EA.type == ZEND_FETCH_CLASS_PARENT) { + EX(called_scope) = EG(called_scope); + } else { + EX(called_scope) = ce; + } } if(IS_UNUSED != IS_UNUSED) { char *function_name_strval; @@ -14514,8 +14561,6 @@ EX(fbc) = ce->constructor; } - EX(called_scope) = ce; - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -15973,8 +16018,15 @@ if (!ce) { zend_error(E_ERROR, "Class '%s' not found", Z_STRVAL(opline->op1.u.constant)); } + EX(called_scope) = ce; } else { ce = EX_T(opline->op1.u.var).class_entry; + + if (opline->op1.u.EA.type == ZEND_FETCH_CLASS_PARENT) { + EX(called_scope) = EG(called_scope); + } else { + EX(called_scope) = ce; + } } if(IS_CV != IS_UNUSED) { char *function_name_strval; @@ -16014,8 +16066,6 @@ EX(fbc) = ce->constructor; } - EX(called_scope) = ce; - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { Index: ext/spl/php_spl.c =================================================================== RCS file: /repository/php-src/ext/spl/php_spl.c,v retrieving revision 1.52.2.28.2.17.2.14 diff -u -r1.52.2.28.2.17.2.14 php_spl.c --- ext/spl/php_spl.c 29 Feb 2008 13:55:23 -0000 1.52.2.28.2.17.2.14 +++ ext/spl/php_spl.c 13 Mar 2008 03:15:09 -0000 @@ -427,7 +427,7 @@ } } - if (!zend_is_callable_ex(zcallable, IS_CALLABLE_STRICT, &func_name, &func_name_len, &alfi.ce, &alfi.func_ptr, &obj_ptr, &error TSRMLS_CC)) { + if (!zend_is_callable_ex(zcallable, IS_CALLABLE_STRICT, &func_name, &func_name_len, &alfi.ce, NULL, &alfi.func_ptr, &obj_ptr, &error TSRMLS_CC)) { if (Z_TYPE_P(zcallable) == IS_ARRAY) { if (!obj_ptr && alfi.func_ptr && !(alfi.func_ptr->common.fn_flags & ZEND_ACC_STATIC)) { if (do_throw) { @@ -534,7 +534,7 @@ return; } - if (!zend_is_callable_ex(zcallable, IS_CALLABLE_CHECK_SYNTAX_ONLY, &func_name, &func_name_len, NULL, NULL, &obj_ptr, &error TSRMLS_CC)) { + if (!zend_is_callable_ex(zcallable, IS_CALLABLE_CHECK_SYNTAX_ONLY, &func_name, &func_name_len, NULL, NULL, NULL, &obj_ptr, &error TSRMLS_CC)) { zend_throw_exception_ex(spl_ce_LogicException, 0 TSRMLS_CC, "Unable to unregister invalid function (%s)", error); if (error) { efree(error);