summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS2
-rwxr-xr-xZend/tests/bug38772.phpt42
-rw-r--r--Zend/zend_compile.c4
-rw-r--r--Zend/zend_object_handlers.c33
4 files changed, 64 insertions, 17 deletions
diff --git a/NEWS b/NEWS
index 555d3d9e8c..0a4cb5c958 100644
--- a/NEWS
+++ b/NEWS
@@ -7,6 +7,8 @@
readded it for other SAPIs (restore to pre 5.1.x behavior). (Edin)
- Fixed bug #38779 (engine crashes when require()'ing file with syntax error
through userspace stream wrapper). (Tony, Dmitry)
+- Fixed bug #38772 (inconsistent overriding of methods in different visibility
+ contexts). (Dmitry)
- Fixed bug #38759 (PDO sqlite2 empty query causes segfault). (Tony)
- Fixed bug #38721 (Invalid memory read in date_parse()). (Tony, Derick)
- Fixed bug #38700 (SoapClient::__getTypes never returns). (Dmitry)
diff --git a/Zend/tests/bug38772.phpt b/Zend/tests/bug38772.phpt
new file mode 100755
index 0000000000..0e97c291c3
--- /dev/null
+++ b/Zend/tests/bug38772.phpt
@@ -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
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 7f9bf757b0..bb04271e2e 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -2025,7 +2025,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))) {
diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c
index 9785cc0b69..32521f68d2 100644
--- a/Zend/zend_object_handlers.c
+++ b/Zend/zend_object_handlers.c
@@ -783,7 +783,17 @@ static union _zend_function *zend_std_get_method(zval **object_ptr, char *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 %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), method_name, EG(scope) ? EG(scope)->name : "");
+ }
+ fbc = updated_fbc;
+ } else {
/* Ensure that we haven't overridden a private function and end up calling
* the overriding public function...
*/
@@ -796,21 +806,12 @@ static union _zend_function *zend_std_get_method(zval **object_ptr, char *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 %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), method_name, EG(scope) ? EG(scope)->name : "");
- }
- fbc = updated_fbc;
- } 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))) {
- zend_error(E_ERROR, "Call to %s method %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), method_name, EG(scope) ? EG(scope)->name : "");
+ 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 %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), method_name, EG(scope) ? EG(scope)->name : "");
+ }
}
}