Fixed bug #38772 (inconsistent overriding of methods in different visibility contexts)

This commit is contained in:
Dmitry Stogov 2006-09-12 11:01:31 +00:00
parent a98f411f80
commit 5574651edb
3 changed files with 62 additions and 17 deletions

42
Zend/tests/bug38772.phpt Executable file
View File

@ -0,0 +1,42 @@
--TEST--
Bug #38772 (inconsistent overriding of methods in different visibility contexts)
--FILE--
<?php
class A {
public function __construct() {
$this -> foo();
}
private function foo() {
echo __METHOD__ . "\r\n";
}
}
class B extends A {
public function foo() {
echo __METHOD__ . "\r\n";
}
}
class C extends A {
protected function foo() {
echo __METHOD__ . "\r\n";
}
}
class D extends A {
private function foo() {
echo __METHOD__ . "\r\n";
}
}
$a = new A();
$b = new B();
$c = new C();
$d = new D();
--EXPECT--
A::foo
A::foo
A::foo
A::foo

View File

@ -2160,7 +2160,9 @@ static zend_bool do_inherit_method_check(HashTable *child_function_table, zend_f
}
}
if (parent_flags & ZEND_ACC_ABSTRACT) {
if (parent_flags & ZEND_ACC_PRIVATE) {
child->common.prototype = NULL;
} else if (parent_flags & ZEND_ACC_ABSTRACT) {
child->common.fn_flags |= ZEND_ACC_IMPLEMENTED_ABSTRACT;
child->common.prototype = parent;
} else if (!(parent->common.fn_flags & ZEND_ACC_CTOR) || (parent->common.prototype && (parent->common.prototype->common.scope->ce_flags & ZEND_ACC_INTERFACE))) {

View File

@ -798,7 +798,17 @@ static union _zend_function *zend_std_get_method(zval **object_ptr, zstr method_
}
/* Check access level */
if (fbc->op_array.fn_flags & ZEND_ACC_PUBLIC) {
if (fbc->op_array.fn_flags & ZEND_ACC_PRIVATE) {
zend_function *updated_fbc;
/* Ensure that if we're calling a private function, we're allowed to do so.
*/
updated_fbc = zend_check_private_int(fbc, Z_OBJ_HANDLER_P(object, get_class_entry)(object TSRMLS_CC), lc_method_name, method_len TSRMLS_CC);
if (!updated_fbc) {
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);
}
fbc = updated_fbc;
} else {
/* Ensure that we haven't overridden a private function and end up calling
* the overriding public function...
*/
@ -811,23 +821,14 @@ static union _zend_function *zend_std_get_method(zval **object_ptr, zstr method_
fbc = priv_fbc;
}
}
} else if (fbc->op_array.fn_flags & ZEND_ACC_PRIVATE) {
zend_function *updated_fbc;
/* Ensure that if we're calling a private function, we're allowed to do so.
*/
updated_fbc = zend_check_private_int(fbc, Z_OBJ_HANDLER_P(object, get_class_entry)(object TSRMLS_CC), lc_method_name, method_len TSRMLS_CC);
if (!updated_fbc) {
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);
}
fbc = updated_fbc;
} else if ((fbc->common.fn_flags & ZEND_ACC_PROTECTED)) {
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))) {
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);
}
}
}
efree(lc_method_name.v);
return fbc;