cvs: ZendEngine2 / zend_compile.c zend_compile.h zend_execute.c

From: Date: Thu, 02 Jan 2003 13:58:08 +0000
Subject: cvs: ZendEngine2 / zend_compile.c zend_compile.h zend_execute.c
Groups: php.zend-engine.cvs 
Request: Send a blank email to php-zend-engine-cvs+get-746@lists.php.net to get a copy of this message
zeev Thu Jan 2 08:58:08 2003 EDT Modified files: /ZendEngine2 zend_compile.c zend_compile.h zend_execute.c Log: Fix incorrect linkage of access-levels, when using private methods Index: ZendEngine2/zend_compile.c diff -u ZendEngine2/zend_compile.c:1.337 ZendEngine2/zend_compile.c:1.338 --- ZendEngine2/zend_compile.c:1.337 Tue Dec 31 10:54:07 2002 +++ ZendEngine2/zend_compile.c Thu Jan 2 08:58:07 2003 @@ -1592,10 +1592,17 @@ zend_error(E_COMPILE_ERROR, "Cannot make non abstract method %s::%s() abstract in class %s", ZEND_FN_SCOPE_NAME(parent), child->common.function_name, ZEND_FN_SCOPE_NAME(child)); } - /* Prevent derived classes from restricting access that was available in parent classes - */ - if ((child_flags & ZEND_ACC_PPP_MASK) > (parent_flags & ZEND_ACC_PPP_MASK)) { - zend_error(E_COMPILE_ERROR, "Access level to %s::%s() must be %s (as in class %s)%s", ZEND_FN_SCOPE_NAME(parent), child->common.function_name, zend_visibility_string(parent_flags), ZEND_FN_SCOPE_NAME(child), (parent_flags&ZEND_ACC_PUBLIC) ? "" : " or weaker"); + if (parent_flags & ZEND_ACC_CHANGED) { + child->common.fn_flags |= ZEND_ACC_CHANGED; + } else { + /* Prevent derived classes from restricting access that was available in parent classes + */ + if ((child_flags & ZEND_ACC_PPP_MASK) > (parent_flags & ZEND_ACC_PPP_MASK)) { + zend_error(E_COMPILE_ERROR, "Access level to %s::%s() must be %s (as in class %s)%s", ZEND_FN_SCOPE_NAME(parent), child->common.function_name, zend_visibility_string(parent_flags), ZEND_FN_SCOPE_NAME(child), (parent_flags&ZEND_ACC_PUBLIC) ? "" : " or weaker"); + } else if (((child_flags & ZEND_ACC_PPP_MASK) < (parent_flags & ZEND_ACC_PPP_MASK)) + && ((parent_flags & ZEND_ACC_PPP_MASK) & ZEND_ACC_PRIVATE)) { + child->common.fn_flags |= ZEND_ACC_CHANGED; + } } return 0; Index: ZendEngine2/zend_compile.h diff -u ZendEngine2/zend_compile.h:1.201 ZendEngine2/zend_compile.h:1.202 --- ZendEngine2/zend_compile.h:1.201 Tue Dec 31 10:54:08 2002 +++ ZendEngine2/zend_compile.h Thu Jan 2 08:58:08 2003 @@ -92,10 +92,12 @@ #define ZEND_ACC_ABSTRACT 0x02 /* The order of those must be kept - public < protected < private */ -#define ZEND_ACC_PUBLIC 0x10 -#define ZEND_ACC_PROTECTED 0x20 -#define ZEND_ACC_PRIVATE 0x40 +#define ZEND_ACC_PUBLIC 0x10 +#define ZEND_ACC_PROTECTED 0x20 +#define ZEND_ACC_PRIVATE 0x40 #define ZEND_ACC_PPP_MASK (ZEND_ACC_PUBLIC | ZEND_ACC_PROTECTED | ZEND_ACC_PRIVATE) + +#define ZEND_ACC_CHANGED 0x80 char *zend_visibility_string(zend_uint fn_flags); Index: ZendEngine2/zend_execute.c diff -u ZendEngine2/zend_execute.c:1.404 ZendEngine2/zend_execute.c:1.405 --- ZendEngine2/zend_execute.c:1.404 Tue Dec 31 10:54:08 2002 +++ ZendEngine2/zend_execute.c Thu Jan 2 08:58:08 2003 @@ -2228,19 +2228,23 @@ return 0; } - /* We may call a private function in one of two cases: - * 1. The scope of the function is the same as the class entry of our object - * 2. The class of our object is different, but a private function exists - * in one of the ancestor that corresponds to our object's ce. + /* We may call a private function if: + * 1. The class of our object is the same as the scope, and the private + * function (EX(fbc)) has the same scope. + * 2. One of our parent classes are the same as the scope, and it contains + * a private function with the same name that has the same scope. */ - if (EX(fbc)->common.scope == ce) { + if (EX(fbc)->common.scope == ce + && EG(scope) == ce) { /* rule #1 checks out ok, allow the function call */ return 1; } - orig_fbc = EX(fbc); /* Check rule #2 */ + orig_fbc = EX(fbc); + + ce = ce->parent; while (ce) { if (ce == EG(scope)) { if (zend_hash_find(&ce->function_table, function_name_strval, function_name_strlen+1, (void **) &EX(fbc))==SUCCESS @@ -2296,7 +2300,7 @@ EX(fbc) = EX(fbc_constructor); if (EX(fbc)->type == ZEND_USER_FUNCTION) { /* HACK!! */ if (EX(fbc)->op_array.fn_flags & ZEND_ACC_PUBLIC) { - /* No further checks necessary, most common case */ + /* No further checks necessary */ } else if (EX(fbc)->op_array.fn_flags & ZEND_ACC_PRIVATE) { /* Ensure that if we're calling a private function, we're allowed to do so. */ @@ -2347,7 +2351,17 @@ } if (EX(fbc)->op_array.fn_flags & ZEND_ACC_PUBLIC) { - /* No further checks necessary, most common case */ + /* Ensure that we haven't overridden a private function and end up calling + * the overriding public function... + */ + if (EX(fbc)->op_array.fn_flags & ZEND_ACC_CHANGED) { + zend_function *priv_fbc; + + if (zend_hash_find(&EG(scope)->function_table, function_name_strval, function_name_strlen+1, (void **) &priv_fbc)==SUCCESS + && priv_fbc->common.fn_flags & ZEND_ACC_PRIVATE) { + EX(fbc) = priv_fbc; + } + } } else if (EX(fbc)->op_array.fn_flags & ZEND_ACC_PRIVATE) { /* Ensure that if we're calling a private function, we're allowed to do so. */

« previous php.zend-engine.cvs (#746) next »