Index: Zend/zend_API.c =================================================================== RCS file: /repository/ZendEngine2/zend_API.c,v retrieving revision 1.472 diff -u -w -p -r1.472 zend_API.c --- Zend/zend_API.c 27 May 2008 10:28:25 -0000 1.472 +++ Zend/zend_API.c 3 Jun 2008 14:32:37 -0000 @@ -2856,7 +2856,7 @@ static int zend_is_callable_check_func(i retval = 0; } } else if ((fptr->common.fn_flags & ZEND_ACC_PROTECTED)) { - if (!zend_check_protected(fptr->common.scope, EG(scope))) { + if (!zend_check_protected_function(fptr, EG(scope))) { if (error) { if (*error) { efree(*error); @@ -3388,6 +3388,7 @@ ZEND_API int zend_u_declare_property_ex( property_info.doc_comment_len = doc_comment_len; property_info.ce = ce; + property_info.root_ce = NULL; zend_u_hash_update(&ce->properties_info, type, name, name_length + 1, &property_info, sizeof(zend_property_info), NULL); Index: Zend/zend_builtin_functions.c =================================================================== RCS file: /repository/ZendEngine2/zend_builtin_functions.c,v retrieving revision 1.372 diff -u -w -p -r1.372 zend_builtin_functions.c --- Zend/zend_builtin_functions.c 27 May 2008 10:28:25 -0000 1.372 +++ Zend/zend_builtin_functions.c 2 Jun 2008 16:56:03 -0000 @@ -905,7 +905,7 @@ ZEND_FUNCTION(get_class_methods) if ((mptr->common.fn_flags & ZEND_ACC_PUBLIC) || (EG(scope) && (((mptr->common.fn_flags & ZEND_ACC_PROTECTED) && - zend_check_protected(mptr->common.scope, EG(scope))) + zend_check_protected_function(mptr, EG(scope))) || ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) && EG(scope) == mptr->common.scope)))) { zstr key; Index: Zend/zend_compile.c =================================================================== RCS file: /repository/ZendEngine2/zend_compile.c,v retrieving revision 1.825 diff -u -w -p -r1.825 zend_compile.c --- Zend/zend_compile.c 3 Jun 2008 13:55:47 -0000 1.825 +++ Zend/zend_compile.c 3 Jun 2008 14:44:10 -0000 @@ -2756,10 +2756,13 @@ static zend_bool do_inherit_property_acc child_info->flags &= ~ZEND_ACC_PRIVATE; /* it's not private anymore */ child_info->flags |= ZEND_ACC_SHADOW; /* but it's a shadow of private */ } + child_info->root_ce = parent_info->root_ce ? parent_info->root_ce : parent_info->ce; return 0; /* don't copy access information to child */ } if (zend_u_hash_quick_find(&ce->properties_info, hash_key->type, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void **) &child_info)==SUCCESS) { + child_info->root_ce = parent_info->root_ce ? parent_info->root_ce : parent_info->ce; + if ((parent_info->flags & ZEND_ACC_STATIC) != (child_info->flags & ZEND_ACC_STATIC)) { zend_error(E_COMPILE_ERROR, "Cannot redeclare %s%v::$%R as %s%v::$%R", (parent_info->flags & ZEND_ACC_STATIC) ? "static " : "non static ", parent_ce->name, hash_key->type, hash_key->arKey, Index: Zend/zend_compile.h =================================================================== RCS file: /repository/ZendEngine2/zend_compile.h,v retrieving revision 1.381 diff -u -w -p -r1.381 zend_compile.h --- Zend/zend_compile.h 12 May 2008 09:09:28 -0000 1.381 +++ Zend/zend_compile.h 3 Jun 2008 14:19:36 -0000 @@ -162,6 +162,7 @@ typedef struct _zend_property_info { zstr doc_comment; int doc_comment_len; zend_class_entry *ce; + zend_class_entry *root_ce; } zend_property_info; Index: Zend/zend_object_handlers.c =================================================================== RCS file: /repository/ZendEngine2/zend_object_handlers.c,v retrieving revision 1.201 diff -u -w -p -r1.201 zend_object_handlers.c --- Zend/zend_object_handlers.c 27 May 2008 10:28:25 -0000 1.201 +++ Zend/zend_object_handlers.c 3 Jun 2008 14:33:02 -0000 @@ -162,7 +162,7 @@ static int zend_verify_property_access(z case ZEND_ACC_PUBLIC: return 1; case ZEND_ACC_PROTECTED: - return zend_check_protected(property_info->ce, EG(scope)); + return zend_check_protected(property_info->root_ce ? property_info->root_ce : property_info->ce, EG(scope)); case ZEND_ACC_PRIVATE: if ((ce==EG(scope) || property_info->ce == EG(scope)) && EG(scope)) { return 1; @@ -743,15 +743,28 @@ ZEND_API int zend_check_private(zend_fun } /* }}} */ +static inline zend_class_entry * zend_get_function_root_class(zend_function *fbc) /* {{{ */ +{ + return fbc->common.prototype ? fbc->common.prototype->common.scope : fbc->common.scope; +} +/* }}} */ + /* Ensures that we're allowed to call a protected method. */ +ZEND_API int zend_check_protected_function(zend_function *fbc, zend_class_entry *scope) /* {{{ */ +{ + zend_class_entry *fbc_root = zend_get_function_root_class(fbc); + return zend_check_protected(fbc_root, scope); +} +/* }}} */ + +/* Checks whether a protected member from ce is visible from scope. + */ ZEND_API int zend_check_protected(zend_class_entry *ce, zend_class_entry *scope) /* {{{ */ { zend_class_entry *fbc_scope = ce; - /* Is the context that's calling the function, the same as one of - * the function's parents? - */ + /* Is the current object context the same as one of the member's parents? */ while (fbc_scope) { if (fbc_scope==scope) { return 1; @@ -759,7 +772,7 @@ ZEND_API int zend_check_protected(zend_c fbc_scope = fbc_scope->parent; } - /* Is the function's scope the same as our current object context, + /* Is the member's scope the same as our current object context, * or any of the parents of our context? */ while (scope) { @@ -772,12 +785,6 @@ ZEND_API int zend_check_protected(zend_c } /* }}} */ -static inline zend_class_entry * zend_get_function_root_class(zend_function *fbc) /* {{{ */ -{ - return fbc->common.prototype ? fbc->common.prototype->common.scope : fbc->common.scope; -} -/* }}} */ - static union _zend_function *zend_std_get_method(zval **object_ptr, zstr method_name, int method_len TSRMLS_DC) /* {{{ */ { zend_object *zobj; @@ -847,7 +854,7 @@ static union _zend_function *zend_std_ge if ((fbc->common.fn_flags & ZEND_ACC_PROTECTED)) { /* Ensure that if we're calling a protected function, we're allowed to do so. */ - if (!zend_check_protected(zend_get_function_root_class(fbc), EG(scope))) { + if (!zend_check_protected_function(fbc, EG(scope))) { zend_error(E_ERROR, "Call to %s method %v::%v() from context '%v'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), method_name, EG(scope) ? EG(scope)->name : EMPTY_ZSTR); } } @@ -995,7 +1002,7 @@ ZEND_API zend_function *zend_std_get_sta } else if ((fbc->common.fn_flags & ZEND_ACC_PROTECTED)) { /* Ensure that if we're calling a protected function, we're allowed to do so. */ - if (!zend_check_protected(zend_get_function_root_class(fbc), EG(scope))) { + if (!zend_check_protected_function(fbc, EG(scope))) { zend_error(E_ERROR, "Call to %s method %v::%v() from context '%v'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), fbc->common.function_name, EG(scope) ? EG(scope)->name : EMPTY_ZSTR); } } @@ -1017,6 +1024,7 @@ ZEND_API zval **zend_std_get_static_prop std_property_info.name_length = property_name_len; std_property_info.h = zend_u_get_hash_value(UG(unicode)?IS_UNICODE:IS_STRING, std_property_info.name, std_property_info.name_length+1); std_property_info.ce = ce; + std_property_info.root_ce = NULL; property_info = &std_property_info; } @@ -1077,7 +1085,7 @@ ZEND_API union _zend_function *zend_std_ * Constructors only have prototype if they are defined by an interface but * it is the compilers responsibility to take care of the prototype. */ - if (!zend_check_protected(zend_get_function_root_class(constructor), EG(scope))) { + if (!zend_check_protected_function(constructor, EG(scope))) { if (EG(scope)) { zend_error(E_ERROR, "Call to protected %v::%v() from context '%v'", constructor->common.scope->name, constructor->common.function_name, EG(scope)->name); } else { @@ -1342,3 +1350,4 @@ ZEND_API zend_object_handlers std_object * indent-tabs-mode: t * End: */ + Index: Zend/zend_object_handlers.h =================================================================== RCS file: /repository/ZendEngine2/zend_object_handlers.h,v retrieving revision 1.64 diff -u -w -p -r1.64 zend_object_handlers.h --- Zend/zend_object_handlers.h 31 Dec 2007 07:12:07 -0000 1.64 +++ Zend/zend_object_handlers.h 2 Jun 2008 16:55:53 -0000 @@ -155,6 +155,7 @@ ZEND_API int zend_std_cast_object_tostri ZEND_API int zend_check_private(union _zend_function *fbc, zend_class_entry *ce, zstr function_name_strval, int function_name_strlen TSRMLS_DC); +ZEND_API int zend_check_protected_function(union _zend_function *fbc, zend_class_entry *scope); ZEND_API int zend_check_protected(zend_class_entry *ce, zend_class_entry *scope); ZEND_API int zend_check_property_access(zend_object *zobj, zend_uchar utype, zstr prop_info_name, int prop_info_name_len TSRMLS_DC); Index: Zend/zend_objects.c =================================================================== RCS file: /repository/ZendEngine2/zend_objects.c,v retrieving revision 1.76 diff -u -w -p -r1.76 zend_objects.c --- Zend/zend_objects.c 31 Dec 2007 07:12:07 -0000 1.76 +++ Zend/zend_objects.c 2 Jun 2008 16:56:34 -0000 @@ -74,7 +74,7 @@ ZEND_API void zend_objects_destroy_objec } else { /* Ensure that if we're calling a protected function, we're allowed to do so. */ - if (!zend_check_protected(destructor->common.scope, EG(scope))) { + if (!zend_check_protected_function(destructor, EG(scope))) { zend_class_entry *ce = object->ce; zend_error(EG(in_execution) ? E_ERROR : E_WARNING, Index: Zend/zend_vm_def.h =================================================================== RCS file: /repository/ZendEngine2/zend_vm_def.h,v retrieving revision 1.231 diff -u -w -p -r1.231 zend_vm_def.h --- Zend/zend_vm_def.h 12 May 2008 09:09:28 -0000 1.231 +++ Zend/zend_vm_def.h 2 Jun 2008 16:56:38 -0000 @@ -2842,7 +2842,7 @@ ZEND_VM_HANDLER(110, ZEND_CLONE, CONST|T } else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) { /* Ensure that if we're calling a protected function, we're allowed to do so. */ - if (!zend_check_protected(clone->common.scope, EG(scope))) { + if (!zend_check_protected_function(clone, EG(scope))) { zend_error_noreturn(E_ERROR, "Call to protected %v::__clone() from context '%v'", ce->name, EG(scope) ? EG(scope)->name : EMPTY_ZSTR); } } Index: Zend/zend_vm_execute.h =================================================================== RCS file: /repository/ZendEngine2/zend_vm_execute.h,v retrieving revision 1.235 diff -u -w -p -r1.235 zend_vm_execute.h --- Zend/zend_vm_execute.h 12 May 2008 09:09:28 -0000 1.235 +++ Zend/zend_vm_execute.h 2 Jun 2008 16:56:52 -0000 @@ -1569,7 +1569,7 @@ static int ZEND_CLONE_SPEC_CONST_HANDLER } else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) { /* Ensure that if we're calling a protected function, we're allowed to do so. */ - if (!zend_check_protected(clone->common.scope, EG(scope))) { + if (!zend_check_protected_function(clone, EG(scope))) { zend_error_noreturn(E_ERROR, "Call to protected %v::__clone() from context '%v'", ce->name, EG(scope) ? EG(scope)->name : EMPTY_ZSTR); } } @@ -4922,7 +4922,7 @@ static int ZEND_CLONE_SPEC_TMP_HANDLER(Z } else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) { /* Ensure that if we're calling a protected function, we're allowed to do so. */ - if (!zend_check_protected(clone->common.scope, EG(scope))) { + if (!zend_check_protected_function(clone, EG(scope))) { zend_error_noreturn(E_ERROR, "Call to protected %v::__clone() from context '%v'", ce->name, EG(scope) ? EG(scope)->name : EMPTY_ZSTR); } } @@ -8316,7 +8316,7 @@ static int ZEND_CLONE_SPEC_VAR_HANDLER(Z } else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) { /* Ensure that if we're calling a protected function, we're allowed to do so. */ - if (!zend_check_protected(clone->common.scope, EG(scope))) { + if (!zend_check_protected_function(clone, EG(scope))) { zend_error_noreturn(E_ERROR, "Call to protected %v::__clone() from context '%v'", ce->name, EG(scope) ? EG(scope)->name : EMPTY_ZSTR); } } @@ -17221,7 +17221,7 @@ static int ZEND_CLONE_SPEC_UNUSED_HANDLE } else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) { /* Ensure that if we're calling a protected function, we're allowed to do so. */ - if (!zend_check_protected(clone->common.scope, EG(scope))) { + if (!zend_check_protected_function(clone, EG(scope))) { zend_error_noreturn(E_ERROR, "Call to protected %v::__clone() from context '%v'", ce->name, EG(scope) ? EG(scope)->name : EMPTY_ZSTR); } } @@ -22625,7 +22625,7 @@ static int ZEND_CLONE_SPEC_CV_HANDLER(ZE } else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) { /* Ensure that if we're calling a protected function, we're allowed to do so. */ - if (!zend_check_protected(clone->common.scope, EG(scope))) { + if (!zend_check_protected_function(clone, EG(scope))) { zend_error_noreturn(E_ERROR, "Call to protected %v::__clone() from context '%v'", ce->name, EG(scope) ? EG(scope)->name : EMPTY_ZSTR); } }