Index: Zend/zend_API.c =================================================================== RCS file: /repository/ZendEngine2/zend_API.c,v retrieving revision 1.296.2.27.2.34.2.12 diff -u -r1.296.2.27.2.34.2.12 zend_API.c --- Zend/zend_API.c 22 Nov 2007 13:27:11 -0000 1.296.2.27.2.34.2.12 +++ Zend/zend_API.c 25 Nov 2007 23:07:52 -0000 @@ -2287,7 +2287,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 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 TSRMLS_DC) /* {{{ */ { int retval; char *lmname, *colon; @@ -2333,6 +2333,7 @@ /* This is a compound name. * Try to fetch class and then find static method. */ *ce_ptr = zend_fetch_class(Z_STRVAL_P(callable), clen, ZEND_FETCH_CLASS_AUTO TSRMLS_CC); + *fetch_type = zend_get_class_fetch_type(Z_STRVAL_P(callable), clen); if (!*ce_ptr) { return 0; } @@ -2395,11 +2396,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 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 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; @@ -2418,7 +2420,12 @@ if (zobj_ptr_ptr == NULL) { zobj_ptr_ptr = &zobj_ptr_local; } + if (fetch_type == NULL) { + fetch_type = &fetch_type_local; + } + *ce_ptr = NULL; + *fetch_type = 0; *fptr_ptr = NULL; *zobj_ptr_ptr = NULL; @@ -2432,7 +2439,7 @@ return 1; } - return zend_is_callable_check_func(check_flags|IS_CALLABLE_CHECK_IS_STATIC, zobj_ptr_ptr, NULL, callable, ce_ptr, fptr_ptr TSRMLS_CC); + return zend_is_callable_check_func(check_flags|IS_CALLABLE_CHECK_IS_STATIC, zobj_ptr_ptr, NULL, callable, ce_ptr, fetch_type, fptr_ptr TSRMLS_CC); case IS_ARRAY: { @@ -2470,13 +2477,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; } @@ -2505,7 +2515,7 @@ } if (ce) { - return zend_is_callable_check_func(check_flags, zobj_ptr_ptr, ce, *method, ce_ptr, fptr_ptr TSRMLS_CC); + return zend_is_callable_check_func(check_flags, zobj_ptr_ptr, ce, *method, ce_ptr, fetch_type, fptr_ptr TSRMLS_CC); } } else if (callable_name) { *callable_name = estrndup("Array", sizeof("Array")-1); @@ -2534,7 +2544,7 @@ { TSRMLS_FETCH(); - return zend_is_callable_ex(callable, check_flags, callable_name, NULL, NULL, NULL, NULL TSRMLS_CC); + return zend_is_callable_ex(callable, check_flags, callable_name, NULL, NULL, NULL, NULL, NULL TSRMLS_CC); } /* }}} */ @@ -2544,7 +2554,7 @@ zend_function *fptr; zval **zobj_ptr; - if (zend_is_callable_ex(callable, 0, callable_name, NULL, &ce, &fptr, &zobj_ptr TSRMLS_CC)) { + if (zend_is_callable_ex(callable, 0, callable_name, NULL, &ce, NULL, &fptr, &zobj_ptr TSRMLS_CC)) { if (Z_TYPE_P(callable) == IS_STRING && ce) { zval_dtor(callable); array_init(callable); @@ -2564,8 +2574,9 @@ zend_class_entry *ce; zend_function *func; zval **obj; + zend_uint fetch_type; - if (!zend_is_callable_ex(callable, IS_CALLABLE_STRICT, callable_name, NULL, &ce, &func, &obj TSRMLS_CC)) { + if (!zend_is_callable_ex(callable, IS_CALLABLE_STRICT, callable_name, NULL, &ce, &fetch_type, &func, &obj TSRMLS_CC)) { return FAILURE; } @@ -2591,7 +2602,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.5 diff -u -r1.207.2.8.2.8.2.5 zend_API.h --- Zend/zend_API.h 2 Nov 2007 19:40:37 -0000 1.207.2.8.2.8.2.5 +++ Zend/zend_API.h 25 Nov 2007 23:07:53 -0000 @@ -228,7 +228,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 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 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.13 diff -u -r1.331.2.20.2.24.2.13 zend_execute_API.c --- Zend/zend_execute_API.c 22 Nov 2007 13:27:11 -0000 1.331.2.20.2.24.2.13 +++ Zend/zend_execute_API.c 25 Nov 2007 23:07:53 -0000 @@ -719,6 +719,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) { @@ -731,6 +732,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) ) { @@ -741,6 +747,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; @@ -757,12 +764,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.23 diff -u -r1.59.2.29.2.48.2.23 zend_vm_def.h --- Zend/zend_vm_def.h 22 Nov 2007 09:02:54 -0000 1.59.2.29.2.48.2.23 +++ Zend/zend_vm_def.h 25 Nov 2007 23:07:54 -0000 @@ -1807,8 +1807,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; @@ -1849,8 +1856,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.24 diff -u -r1.62.2.30.2.49.2.24 zend_vm_execute.h --- Zend/zend_vm_execute.h 23 Nov 2007 15:03:02 -0000 1.62.2.30.2.49.2.24 +++ Zend/zend_vm_execute.h 25 Nov 2007 23:08:01 -0000 @@ -2390,8 +2390,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; @@ -2432,8 +2439,6 @@ EX(fbc) = ce->constructor; } - EX(called_scope) = ce; - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -2938,8 +2943,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; @@ -2980,8 +2992,6 @@ EX(fbc) = ce->constructor; } - EX(called_scope) = ce; - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -3386,8 +3396,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; @@ -3428,8 +3445,6 @@ EX(fbc) = ce->constructor; } - EX(called_scope) = ce; - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -3600,8 +3615,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; @@ -3642,8 +3664,6 @@ EX(fbc) = ce->constructor; } - EX(called_scope) = ce; - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -4016,8 +4036,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; @@ -4058,8 +4085,6 @@ EX(fbc) = ce->constructor; } - EX(called_scope) = ce; - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -9710,8 +9735,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; @@ -9752,8 +9784,6 @@ EX(fbc) = ce->constructor; } - EX(called_scope) = ce; - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -11403,8 +11433,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; @@ -11445,8 +11482,6 @@ EX(fbc) = ce->constructor; } - EX(called_scope) = ce; - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -13068,8 +13103,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; @@ -13110,8 +13152,6 @@ EX(fbc) = ce->constructor; } - EX(called_scope) = ce; - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -13906,8 +13946,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; @@ -13948,8 +13995,6 @@ EX(fbc) = ce->constructor; } - EX(called_scope) = ce; - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -15272,8 +15317,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; @@ -15314,8 +15366,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.5 diff -u -r1.52.2.28.2.17.2.5 php_spl.c --- ext/spl/php_spl.c 22 Nov 2007 13:27:13 -0000 1.52.2.28.2.17.2.5 +++ ext/spl/php_spl.c 25 Nov 2007 23:10:20 -0000 @@ -423,7 +423,7 @@ } } - if (!zend_is_callable_ex(zcallable, IS_CALLABLE_STRICT, &func_name, &func_name_len, &alfi.ce, &alfi.func_ptr, &obj_ptr TSRMLS_CC)) { + if (!zend_is_callable_ex(zcallable, IS_CALLABLE_STRICT, &func_name, &func_name_len, &alfi.ce, NULL, &alfi.func_ptr, &obj_ptr 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) { @@ -515,7 +515,7 @@ return; } - if (!zend_is_callable_ex(zcallable, IS_CALLABLE_CHECK_SYNTAX_ONLY, &func_name, &func_name_len, NULL, NULL, &obj_ptr TSRMLS_CC)) { + if (!zend_is_callable_ex(zcallable, IS_CALLABLE_CHECK_SYNTAX_ONLY, &func_name, &func_name_len, NULL, NULL, NULL, &obj_ptr TSRMLS_CC)) { if (func_name) { efree(func_name); }