From 7c88d5607d7fcb93f28136092b655f604ca2dde7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Kocsis?= Date: Tue, 25 Oct 2022 13:01:28 +0200 Subject: [PATCH] Allow extending readonly classes by non-readonly ones --- .../readonly_class_inheritance_error1.phpt | 8 ++-- .../readonly_class_inheritance_error2.phpt | 16 ------- ... readonly_class_inheritance_success1.phpt} | 0 .../readonly_class_inheritance_success2.phpt | 15 +++++++ .../readonly_class_inheritance_success3.phpt | 19 +++++++++ .../readonly_class_inheritance_success4.phpt | 20 +++++++++ .../readonly_class_inheritance_success5.phpt | 37 ++++++++++++++++ .../readonly_class_inheritance_success6.phpt | 42 +++++++++++++++++++ Zend/zend_inheritance.c | 2 +- 9 files changed, 138 insertions(+), 21 deletions(-) delete mode 100644 Zend/tests/readonly_classes/readonly_class_inheritance_error2.phpt rename Zend/tests/readonly_classes/{readonly_class_inheritance_success.phpt => readonly_class_inheritance_success1.phpt} (100%) create mode 100644 Zend/tests/readonly_classes/readonly_class_inheritance_success2.phpt create mode 100644 Zend/tests/readonly_classes/readonly_class_inheritance_success3.phpt create mode 100644 Zend/tests/readonly_classes/readonly_class_inheritance_success4.phpt create mode 100644 Zend/tests/readonly_classes/readonly_class_inheritance_success5.phpt create mode 100644 Zend/tests/readonly_classes/readonly_class_inheritance_success6.phpt diff --git a/Zend/tests/readonly_classes/readonly_class_inheritance_error1.phpt b/Zend/tests/readonly_classes/readonly_class_inheritance_error1.phpt index 2d76d844cfa49..0996653681e5c 100644 --- a/Zend/tests/readonly_classes/readonly_class_inheritance_error1.phpt +++ b/Zend/tests/readonly_classes/readonly_class_inheritance_error1.phpt @@ -1,16 +1,16 @@ --TEST-- -Non-readonly class cannot extend a readonly class +Readonly class cannot extend a non-readonly class --FILE-- --EXPECTF-- -Fatal error: Non-readonly class Bar cannot extend readonly class Foo in %s on line %d +Fatal error: Readonly class Bar cannot extend non-readonly class Foo in %s on line %d diff --git a/Zend/tests/readonly_classes/readonly_class_inheritance_error2.phpt b/Zend/tests/readonly_classes/readonly_class_inheritance_error2.phpt deleted file mode 100644 index 0996653681e5c..0000000000000 --- a/Zend/tests/readonly_classes/readonly_class_inheritance_error2.phpt +++ /dev/null @@ -1,16 +0,0 @@ ---TEST-- -Readonly class cannot extend a non-readonly class ---FILE-- - ---EXPECTF-- -Fatal error: Readonly class Bar cannot extend non-readonly class Foo in %s on line %d diff --git a/Zend/tests/readonly_classes/readonly_class_inheritance_success.phpt b/Zend/tests/readonly_classes/readonly_class_inheritance_success1.phpt similarity index 100% rename from Zend/tests/readonly_classes/readonly_class_inheritance_success.phpt rename to Zend/tests/readonly_classes/readonly_class_inheritance_success1.phpt diff --git a/Zend/tests/readonly_classes/readonly_class_inheritance_success2.phpt b/Zend/tests/readonly_classes/readonly_class_inheritance_success2.phpt new file mode 100644 index 0000000000000..bd6ef1d8347b2 --- /dev/null +++ b/Zend/tests/readonly_classes/readonly_class_inheritance_success2.phpt @@ -0,0 +1,15 @@ +--TEST-- +Non-readonly class can extend a readonly class +--FILE-- + +--EXPECT-- diff --git a/Zend/tests/readonly_classes/readonly_class_inheritance_success3.phpt b/Zend/tests/readonly_classes/readonly_class_inheritance_success3.phpt new file mode 100644 index 0000000000000..b6e43ca7ff86c --- /dev/null +++ b/Zend/tests/readonly_classes/readonly_class_inheritance_success3.phpt @@ -0,0 +1,19 @@ +--TEST-- +Non-readonly child of a readonly class can create dynamic properties +--FILE-- +baz = 1; + +?> +--EXPECTF-- +Deprecated: Creation of dynamic property Bar::$baz is deprecated in %s on line %d diff --git a/Zend/tests/readonly_classes/readonly_class_inheritance_success4.phpt b/Zend/tests/readonly_classes/readonly_class_inheritance_success4.phpt new file mode 100644 index 0000000000000..850d202d5b3c5 --- /dev/null +++ b/Zend/tests/readonly_classes/readonly_class_inheritance_success4.phpt @@ -0,0 +1,20 @@ +--TEST-- +Non-readonly child of a readonly class can accept the AllowDynamicProperties attribute +--FILE-- +baz = 1; + +?> +--EXPECTF-- diff --git a/Zend/tests/readonly_classes/readonly_class_inheritance_success5.phpt b/Zend/tests/readonly_classes/readonly_class_inheritance_success5.phpt new file mode 100644 index 0000000000000..1cb1a47b0d8f3 --- /dev/null +++ b/Zend/tests/readonly_classes/readonly_class_inheritance_success5.phpt @@ -0,0 +1,37 @@ +--TEST-- +Non-readonly child of a readonly class can declare non-readonly properties +--FILE-- +property3 = 4; +$bar->property4 = 5; + +var_dump(Bar::$property1); +var_dump(Bar::$property2); +var_dump($bar); + +?> +--EXPECT-- +int(2) +int(3) +object(Bar)#1 (2) { + ["property3"]=> + int(4) + ["property4"]=> + int(5) +} diff --git a/Zend/tests/readonly_classes/readonly_class_inheritance_success6.phpt b/Zend/tests/readonly_classes/readonly_class_inheritance_success6.phpt new file mode 100644 index 0000000000000..ad183c786d8d6 --- /dev/null +++ b/Zend/tests/readonly_classes/readonly_class_inheritance_success6.phpt @@ -0,0 +1,42 @@ +--TEST-- +Non-readonly child of a readonly class can declare non-readonly properties indirectly via a trait +--FILE-- +property3 = 4; +$bar->property4 = 5; + +var_dump(Bar::$property1); +var_dump(Bar::$property2); +var_dump($bar); + +?> +--EXPECT-- +int(2) +int(3) +object(Bar)#1 (2) { + ["property3"]=> + int(4) + ["property4"]=> + int(5) +} diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index 0dbdaa2b35ec4..29ccb12116127 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -1461,7 +1461,7 @@ ZEND_API void zend_do_inheritance_ex(zend_class_entry *ce, zend_class_entry *par } } - if (UNEXPECTED((ce->ce_flags & ZEND_ACC_READONLY_CLASS) != (parent_ce->ce_flags & ZEND_ACC_READONLY_CLASS))) { + if (UNEXPECTED((ce->ce_flags & ZEND_ACC_READONLY_CLASS) && !(parent_ce->ce_flags & ZEND_ACC_READONLY_CLASS))) { zend_error_noreturn(E_COMPILE_ERROR, "%s class %s cannot extend %s class %s", ce->ce_flags & ZEND_ACC_READONLY_CLASS ? "Readonly" : "Non-readonly", ZSTR_VAL(ce->name), parent_ce->ce_flags & ZEND_ACC_READONLY_CLASS ? "readonly" : "non-readonly", ZSTR_VAL(parent_ce->name)