From 3b7c8bb973cb4b37ae5f034651d9e4cd4147729f Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Tue, 6 Oct 2020 16:30:58 +0200 Subject: Fix bug #80126 When performing an unlinked instanceof, we also need to consider interfaces of parent classes, as they may not have been inherited yet. --- NEWS | 1 + Zend/tests/bug80126.phpt | 23 +++++++++++++++++++++++ Zend/tests/bug80126_2.phpt | 27 +++++++++++++++++++++++++++ Zend/zend_inheritance.c | 22 ++++++++++------------ 4 files changed, 61 insertions(+), 12 deletions(-) create mode 100644 Zend/tests/bug80126.phpt create mode 100644 Zend/tests/bug80126_2.phpt diff --git a/NEWS b/NEWS index cc2f44a7db..8d02664ab7 100644 --- a/NEWS +++ b/NEWS @@ -7,6 +7,7 @@ PHP NEWS (cmb) . Fixed bug #79423 (copy command is limited to size of file it can copy). (cmb) + . Fixed bug #80126 (Covariant return types failing compilation). (Nikita) - MySQLnd: . Fixed bug #80115 (mysqlnd.debug doesn't recognize absolute paths with diff --git a/Zend/tests/bug80126.phpt b/Zend/tests/bug80126.phpt new file mode 100644 index 0000000000..3087a40629 --- /dev/null +++ b/Zend/tests/bug80126.phpt @@ -0,0 +1,23 @@ +--TEST-- +Bug #80126: Covariant return types failing compilation +--FILE-- + +===DONE=== +--EXPECT-- +===DONE=== diff --git a/Zend/tests/bug80126_2.phpt b/Zend/tests/bug80126_2.phpt new file mode 100644 index 0000000000..707d1b5a45 --- /dev/null +++ b/Zend/tests/bug80126_2.phpt @@ -0,0 +1,27 @@ +--TEST-- +Bug #80126: Covariant return types failing compilation (variation 2) +--FILE-- + +===DONE=== +--EXPECT-- +===DONE=== diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index e7dcf54e0d..190ec57813 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -259,8 +259,6 @@ static zend_class_entry *lookup_class(zend_class_entry *scope, zend_string *name /* Instanceof that's safe to use on unlinked classes. */ static zend_bool unlinked_instanceof(zend_class_entry *ce1, zend_class_entry *ce2) { - zend_class_entry *ce; - if (ce1 == ce2) { return 1; } @@ -269,18 +267,18 @@ static zend_bool unlinked_instanceof(zend_class_entry *ce1, zend_class_entry *ce return instanceof_function(ce1, ce2); } - ce = ce1; - while (ce->parent) { - if (ce->ce_flags & ZEND_ACC_RESOLVED_PARENT) { - ce = ce->parent; + if (ce1->parent) { + zend_class_entry *parent_ce; + if (ce1->ce_flags & ZEND_ACC_RESOLVED_PARENT) { + parent_ce = ce1->parent; } else { - ce = zend_lookup_class_ex(ce->parent_name, NULL, + parent_ce = zend_lookup_class_ex(ce1->parent_name, NULL, ZEND_FETCH_CLASS_ALLOW_UNLINKED | ZEND_FETCH_CLASS_NO_AUTOLOAD); - if (!ce) { - break; - } } - if (ce == ce2) { + + /* It's not sufficient to only check the parent chain itself, as need to do a full + * recursive instanceof in case the parent interfaces haven't been copied yet. */ + if (parent_ce && unlinked_instanceof(parent_ce, ce2)) { return 1; } } @@ -297,7 +295,7 @@ static zend_bool unlinked_instanceof(zend_class_entry *ce1, zend_class_entry *ce } } else { for (i = 0; i < ce1->num_interfaces; i++) { - ce = zend_lookup_class_ex( + zend_class_entry *ce = zend_lookup_class_ex( ce1->interface_names[i].name, ce1->interface_names[i].lc_name, ZEND_FETCH_CLASS_ALLOW_UNLINKED | ZEND_FETCH_CLASS_NO_AUTOLOAD); if (ce && unlinked_instanceof(ce, ce2)) { -- cgit v1.2.1