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 26 Nov 2007 00:04:24 -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,7 +2333,8 @@ /* 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; } ftable = &(*ce_ptr)->function_table; @@ -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,20 @@ 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 (Z_STRLEN_PP(obj) == sizeof("__parentf") - 1 && + !memcmp(lcname, "__parentf", sizeof("__parentf") - 1)) { + ce = EG(active_op_array)->scope->parent; + *fetch_type = ZEND_FETCH_CLASS___PARENTF; } else if (zend_lookup_class(Z_STRVAL_PP(obj), Z_STRLEN_PP(obj), &pce TSRMLS_CC) == SUCCESS) { ce = *pce; } @@ -2505,7 +2519,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 +2548,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 +2558,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 +2578,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 +2606,11 @@ } else { fcc->initialized = 1; fcc->function_handler = func; - fcc->calling_scope = ce; + if (fetch_type == ZEND_FETCH_CLASS___PARENTF) { + 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 26 Nov 2007 00:04:25 -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_compile.c =================================================================== RCS file: /repository/ZendEngine2/zend_compile.c,v retrieving revision 1.647.2.27.2.41.2.26 diff -u -r1.647.2.27.2.41.2.26 zend_compile.c --- Zend/zend_compile.c 22 Nov 2007 13:27:11 -0000 1.647.2.27.2.41.2.26 +++ Zend/zend_compile.c 26 Nov 2007 00:04:26 -0000 @@ -1631,6 +1631,7 @@ case ZEND_FETCH_CLASS_SELF: case ZEND_FETCH_CLASS_PARENT: case ZEND_FETCH_CLASS_STATIC: + case ZEND_FETCH_CLASS___PARENTF: SET_UNUSED(opline->op2); opline->extended_value = fetch_type; zval_dtor(&class_name->u.constant); @@ -3059,7 +3060,7 @@ lcname = zend_str_tolower_dup(class_name->u.constant.value.str.val, class_name->u.constant.value.str.len); - if (!(strcmp(lcname, "self") && strcmp(lcname, "parent"))) { + if (!(strcmp(lcname, "self") && strcmp(lcname, "parent") && strcmp(lcname, "__parentf"))) { efree(lcname); zend_error(E_COMPILE_ERROR, "Cannot use '%s' as class name as it is reserved", class_name->u.constant.value.str.val); } @@ -3113,6 +3114,9 @@ case ZEND_FETCH_CLASS_STATIC: zend_error(E_COMPILE_ERROR, "Cannot use 'static' as class name as it is reserved"); break; + case ZEND_FETCH_CLASS___PARENTF: + zend_error(E_COMPILE_ERROR, "Cannot use '__parentf' as class name as it is reserved"); + break; default: break; } @@ -3223,6 +3227,9 @@ case ZEND_FETCH_CLASS_STATIC: zend_error(E_COMPILE_ERROR, "Cannot use 'static' as interface name as it is reserved"); break; + case ZEND_FETCH_CLASS___PARENTF: + zend_error(E_COMPILE_ERROR, "Cannot use '__parentf' as interface name as it is reserved"); + break; default: if (CG(active_op_array)->last > 0) { opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1]; @@ -4668,6 +4675,9 @@ } else if ((class_name_len == sizeof("static")-1) && !memcmp(class_name, "static", sizeof("static")-1)) { return ZEND_FETCH_CLASS_STATIC; + } else if ((class_name_len == sizeof("__parentf")-1) && + !memcmp(class_name, "__parentf", sizeof("__parentf")-1)) { + return ZEND_FETCH_CLASS___PARENTF; } else { return ZEND_FETCH_CLASS_DEFAULT; } @@ -4728,7 +4738,9 @@ if (((Z_STRLEN(name->u.constant) == sizeof("self")-1) && !memcmp(lcname, "self", sizeof("self")-1)) || ((Z_STRLEN(name->u.constant) == sizeof("parent")-1) && - !memcmp(lcname, "parent", sizeof("parent")-1))) { + !memcmp(lcname, "parent", sizeof("parent")-1)) || + ((Z_STRLEN(name->u.constant) == sizeof("__parentf")-1) && + !memcmp(lcname, "__parentf", sizeof("__parentf")-1))) { zend_error(E_COMPILE_ERROR, "Cannot use '%s' as namespace name", Z_STRVAL(name->u.constant)); } efree(lcname); @@ -4774,7 +4786,9 @@ if (((Z_STRLEN_P(name) == sizeof("self")-1) && !memcmp(lcname, "self", sizeof("self")-1)) || ((Z_STRLEN_P(name) == sizeof("parent")-1) && - !memcmp(lcname, "parent", sizeof("parent")-1))) { + !memcmp(lcname, "parent", sizeof("parent")-1)) || + ((Z_STRLEN_P(name) == sizeof("__parentf")-1) && + !memcmp(lcname, "__parentf", sizeof("__parentf")-1))) { zend_error(E_COMPILE_ERROR, "Cannot use %s as %s because '%s' is a special class name", Z_STRVAL_P(ns), Z_STRVAL_P(name), Z_STRVAL_P(name)); } Index: Zend/zend_compile.h =================================================================== RCS file: /repository/ZendEngine2/zend_compile.h,v retrieving revision 1.316.2.8.2.12.2.10 diff -u -r1.316.2.8.2.12.2.10 zend_compile.h --- Zend/zend_compile.h 22 Nov 2007 13:27:11 -0000 1.316.2.8.2.12.2.10 +++ Zend/zend_compile.h 26 Nov 2007 00:04:26 -0000 @@ -601,6 +601,7 @@ #define ZEND_FETCH_CLASS_AUTO 5 #define ZEND_FETCH_CLASS_INTERFACE 6 #define ZEND_FETCH_CLASS_STATIC 7 +#define ZEND_FETCH_CLASS___PARENTF 8 #define ZEND_FETCH_CLASS_MASK 0x0f #define ZEND_FETCH_CLASS_RT_NS_CHECK 0x20 #define ZEND_FETCH_CLASS_RT_NS_NAME 0x40 Index: Zend/zend_constants.c =================================================================== RCS file: /repository/ZendEngine2/zend_constants.c,v retrieving revision 1.71.2.5.2.7.2.6 diff -u -r1.71.2.5.2.7.2.6 zend_constants.c --- Zend/zend_constants.c 20 Nov 2007 16:34:25 -0000 1.71.2.5.2.7.2.6 +++ Zend/zend_constants.c 26 Nov 2007 00:04:26 -0000 @@ -331,6 +331,16 @@ zend_error(E_ERROR, "Cannot access static:: when no class scope is active"); } efree(lcname); + } else if (class_name_len == sizeof("__parentf")-1 && + !memcmp(lcname, "__parentf", sizeof("__parentf")-1)) { + if (!scope) { + zend_error(E_ERROR, "Cannot access __parentf:: when no class scope is active"); + } else if (!scope->parent) { + zend_error(E_ERROR, "Cannot access __parentf:: when current class scope has no parent"); + } else { + ce = scope->parent; + } + efree(lcname); } else { /* Check for namespace constant */ char *nsname; 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 26 Nov 2007 00:04:27 -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,7 @@ found = (*ce != NULL?SUCCESS:FAILURE); fci->object_pp = EG(This)?&EG(This):NULL; EX(object) = EG(This); + 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 +743,26 @@ found = (*ce != NULL?SUCCESS:FAILURE); fci->object_pp = EG(This)?&EG(This):NULL; EX(object) = EG(This); + calling_scope = *ce; + } else if (Z_STRLEN_PP(fci->object_pp) == sizeof("__parentf") - 1 && + !memcmp(Z_STRVAL_PP(fci->object_pp), "__parentf", sizeof("__parentf") - 1) + ) { + + if (!EG(active_op_array)->scope) { + zend_error(E_ERROR, "Cannot access __parentf:: when no class scope is active"); + } + if (!EG(active_op_array)->scope->parent) { + zend_error(E_ERROR, "Cannot access __parentf:: when current class scope has no parent"); + } + ce = EG(active_op_array)->scope->parent; + 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 { zend_class_entry *scope; scope = EG(active_op_array) ? EG(active_op_array)->scope : NULL; @@ -757,12 +779,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; @@ -820,6 +842,10 @@ memcmp(lcname, "static", sizeof("static") - 1) ) { ce_child = EG(called_scope); + } else if (clen == sizeof("__parentf") - 1 && + memcmp(lcname, "__parentf", sizeof("__parentf") - 1) + ) { + ce_child = EG(active_op_array) && EG(active_op_array)->scope ? EG(scope)->parent : NULL; } else if (zend_lookup_class(lcname, clen, &pce TSRMLS_CC) == SUCCESS) { ce_child = *pce; } @@ -1555,6 +1581,15 @@ zend_error(E_ERROR, "Cannot access static:: when no class scope is active"); } return EG(called_scope); + case ZEND_FETCH_CLASS___PARENTF: + if (!EG(scope)) { + zend_error(E_ERROR, "Cannot access __parentf:: when no class scope is active"); + } + if (!EG(scope)->parent) { + zend_error(E_ERROR, "Cannot access __parentf:: when current class scope has no parent"); + } + return EG(scope)->parent; + return EG(called_scope); case ZEND_FETCH_CLASS_AUTO: { fetch_type = zend_get_class_fetch_type(class_name, class_name_len); if (fetch_type!=ZEND_FETCH_CLASS_DEFAULT) { 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 26 Nov 2007 00:04:28 -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___PARENTF) { + 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 26 Nov 2007 00:04:35 -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___PARENTF) { + 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___PARENTF) { + 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___PARENTF) { + 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___PARENTF) { + 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___PARENTF) { + 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___PARENTF) { + 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___PARENTF) { + 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___PARENTF) { + 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___PARENTF) { + 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___PARENTF) { + 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 26 Nov 2007 00:04:47 -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); }