com php-src: Fixed bug #61970: Allow a child class to restrict access to ctor: NEWS Zend/tests/bug61970.phpt Zend/tests/bug6197 0_1.phpt Zend/tests/bug61970_2.phpt Zend/zend_inheritance.c ext/mysqli/tests/bug380 03.phpt

[email protected] (Nikita Popov)
Newsgroups php.cvs
Message-ID <[email protected]>
Commit:    5324fb1f348f5bc979d9b5f13ac74177b73f9bf7
Author:    Pedro Magalhães <[email protected]>         Fri, 10 Mar 2017 20:08:15 +0100
Committer: Nikita Popov <[email protected]>      Mon, 1 May 2017 14:15:57 +0200
Parents:   92124f9cdc20c6a9c22f9b54092ef945c41f2bb5
Branches:  master

Link:       http://git.php.net/?p=php-src.git;a=commitdiff;h=5324fb1f348f5bc979d9b5f13ac74177b73f9bf7

Log:
Fixed bug #61970: Allow a child class to restrict access to ctor

Bugs:
https://bugs.php.net/61970

Changed paths:
  M  NEWS
  A  Zend/tests/bug61970.phpt
  A  Zend/tests/bug61970_1.phpt
  A  Zend/tests/bug61970_2.phpt
  M  Zend/zend_inheritance.c
  M  ext/mysqli/tests/bug38003.phpt


Diff:
diff --git a/NEWS b/NEWS
index 80aa4ec..2e20313 100644
--- 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
index 0000000..9cdb87a
--- /dev/null
+++ b/Zend/tests/bug61970.phpt
@@ -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
index 0000000..978884a
--- /dev/null
+++ b/Zend/tests/bug61970_1.phpt
@@ -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
index 0000000..56203f7
--- /dev/null
+++ b/Zend/tests/bug61970_2.phpt
@@ -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
diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c
index 675d8c4..85c5c57 100644
--- a/Zend/zend_inheritance.c
+++ b/Zend/zend_inheritance.c
@@ -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");
 	}
 
diff --git a/ext/mysqli/tests/bug38003.phpt b/ext/mysqli/tests/bug38003.phpt
index f3a4823..a974815 100644
--- a/ext/mysqli/tests/bug38003.phpt
+++ b/ext/mysqli/tests/bug38003.phpt
@@ -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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.