]> granicus.if.org Git - php/commitdiff
Fixed bug #61970: Allow a child class to restrict access to ctor
authorPedro Magalhães <mail@pmmaga.net>
Fri, 10 Mar 2017 19:08:15 +0000 (20:08 +0100)
committerNikita Popov <nikita.ppv@gmail.com>
Mon, 1 May 2017 12:15:57 +0000 (14:15 +0200)
NEWS
Zend/tests/bug61970.phpt [new file with mode: 0644]
Zend/tests/bug61970_1.phpt [new file with mode: 0644]
Zend/tests/bug61970_2.phpt [new file with mode: 0644]
Zend/zend_inheritance.c
ext/mysqli/tests/bug38003.phpt

diff --git a/NEWS b/NEWS
index 80aa4ec8cc0d34d56086cbf482a0917c6e4b59dc..2e203137fe96050c2655d05f511405f619834343 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -43,6 +43,8 @@ PHP                                                                        NEWS
     (Sammy Kaye Powers)
   . Fixed bug #74269 (It's possible to override trait property with different
     loosely-equal value). (pmmaga)
+  . Fixed bug #61970 (Restraining __construct() access level in subclass gives
+    a fatal error). (pmmaga)
 
 - BCMath:
   . Fixed bug #46564 (bcmod truncates fractionals). (liborm85)
diff --git a/Zend/tests/bug61970.phpt b/Zend/tests/bug61970.phpt
new file mode 100644 (file)
index 0000000..9cdb87a
--- /dev/null
@@ -0,0 +1,16 @@
+--TEST--
+Bug #61970 (Restraining __construct() access level in subclass gives a fatal error)
+--FILE--
+<?php
+
+class Foo {
+    public function __construct(){}
+}
+
+class Bar extends Foo {
+    protected function __construct(){}
+}
+
+echo 'DONE';
+--EXPECT--
+DONE
diff --git a/Zend/tests/bug61970_1.phpt b/Zend/tests/bug61970_1.phpt
new file mode 100644 (file)
index 0000000..978884a
--- /dev/null
@@ -0,0 +1,15 @@
+--TEST--
+Bug #61970 (Restraining __construct() access level in subclass gives a fatal error - stays when implementing abstract)
+--FILE--
+<?php
+
+abstract class Foo {
+    abstract public function __construct();
+}
+
+class Bar extends Foo {
+    protected function __construct(){}
+}
+
+--EXPECTF--
+Fatal error: Access level to Bar::__construct() must be public (as in class Foo) in %s
diff --git a/Zend/tests/bug61970_2.phpt b/Zend/tests/bug61970_2.phpt
new file mode 100644 (file)
index 0000000..56203f7
--- /dev/null
@@ -0,0 +1,19 @@
+--TEST--
+Bug #61970 (Restraining __construct() access level in subclass gives a fatal error - stays when inheriting implemented abstract)
+--FILE--
+<?php
+
+abstract class Foo {
+    abstract public function __construct();
+}
+
+class Bar extends Foo {
+    public function __construct(){}
+}
+
+class Baz extends Bar {
+    protected function __construct(){}
+}
+
+--EXPECTF--
+Fatal error: Access level to Baz::__construct() must be public (as in class Bar) in %s
index 675d8c4b75d0c581c82a9b3128065be04cd24e4f..85c5c5794f3976fa7ed28b5000af9c8a76a4fcc8 100644 (file)
@@ -578,8 +578,9 @@ static void do_inheritance_check_on_method(zend_function *child, zend_function *
                zend_error_noreturn(E_COMPILE_ERROR, "Cannot make non abstract method %s::%s() abstract in class %s", ZEND_FN_SCOPE_NAME(parent), ZSTR_VAL(child->common.function_name), ZEND_FN_SCOPE_NAME(child));
        }
 
-       /* Prevent derived classes from restricting access that was available in parent classes */
-       if (UNEXPECTED((child_flags & ZEND_ACC_PPP_MASK) > (parent_flags & ZEND_ACC_PPP_MASK))) {
+       /* Prevent derived classes from restricting access that was available in parent classes (except deriving from non-abstract ctors) */
+       if (UNEXPECTED((!(child_flags & ZEND_ACC_CTOR) || (parent_flags & (ZEND_ACC_ABSTRACT | ZEND_ACC_IMPLEMENTED_ABSTRACT))) &&
+               (child_flags & ZEND_ACC_PPP_MASK) > (parent_flags & ZEND_ACC_PPP_MASK))) {
                zend_error_noreturn(E_COMPILE_ERROR, "Access level to %s::%s() must be %s (as in class %s)%s", ZEND_FN_SCOPE_NAME(child), ZSTR_VAL(child->common.function_name), zend_visibility_string(parent_flags), ZEND_FN_SCOPE_NAME(parent), (parent_flags&ZEND_ACC_PUBLIC) ? "" : " or weaker");
        }
 
index f3a4823b9d0e8853dc2e282ccc49bd941c93a8bc..a974815d4d24e96a314775e71145d1d36a2c53ae 100644 (file)
@@ -17,5 +17,7 @@ $DB = new DB();
 echo "Done\n";
 ?>
 --EXPECTF--    
-Fatal error: Access level to DB::__construct() must be public (as in class mysqli) in %s%ebug38003.php on line %d
-
+Fatal error: Uncaught Error: Call to private DB::__construct() from invalid context in %s
+Stack trace:
+#0 {main}
+  thrown in %s