diff options
author | Nikita Popov <nikita.ppv@gmail.com> | 2019-10-24 18:11:41 +0200 |
---|---|---|
committer | Nikita Popov <nikita.ppv@gmail.com> | 2019-10-25 10:19:42 +0200 |
commit | 184ba0c91c3b688538d0274625241c640a8952eb (patch) | |
tree | aeaeee37ed45ccd03e7f0a395d4489b6ed387e7b | |
parent | c63a0e005abe4b00ab097dc47ca53d20788a6361 (diff) | |
download | php-git-184ba0c91c3b688538d0274625241c640a8952eb.tar.gz |
Remove recursive check from instanceof_interface
Parent interfaces are copied into the interface list during
inheritance, so there's no need to perform a recursive check.
Only exception are instanceof checks performed during inheritance
itself. However, we already have unlinked_instanceof for this
purpose, it just needs to be taught to handle this case.
Closes GH-4857.
-rw-r--r-- | Zend/zend_inheritance.c | 25 | ||||
-rw-r--r-- | Zend/zend_operators.c | 2 |
2 files changed, 18 insertions, 9 deletions
diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index cc85af6859..c7002d313f 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -258,7 +258,7 @@ static zend_bool unlinked_instanceof(zend_class_entry *ce1, zend_class_entry *ce return 1; } - if (ce1->ce_flags & (ZEND_ACC_LINKED|ZEND_ACC_RESOLVED_INTERFACES)) { + if (ce1->ce_flags & ZEND_ACC_LINKED) { return instanceof_function(ce1, ce2); } @@ -280,13 +280,22 @@ static zend_bool unlinked_instanceof(zend_class_entry *ce1, zend_class_entry *ce if (ce1->num_interfaces) { uint32_t i; - ZEND_ASSERT(!(ce1->ce_flags & ZEND_ACC_RESOLVED_INTERFACES)); - for (i = 0; i < ce1->num_interfaces; i++) { - 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)) { - return 1; + if (ce1->ce_flags & ZEND_ACC_RESOLVED_INTERFACES) { + /* Unlike the normal instanceof_function(), we have to perform a recursive + * check here, as the parent interfaces might not have been fully copied yet. */ + for (i = 0; i < ce1->num_interfaces; i++) { + if (unlinked_instanceof(ce1->interfaces[i], ce2)) { + return 1; + } + } + } else { + for (i = 0; i < ce1->num_interfaces; i++) { + 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)) { + return 1; + } } } } diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index c2ea3cd65a..656316cc4e 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -2328,7 +2328,7 @@ static zend_bool ZEND_FASTCALL instanceof_interface(const zend_class_entry *inst if (instance_ce->num_interfaces) { ZEND_ASSERT(instance_ce->ce_flags & ZEND_ACC_RESOLVED_INTERFACES); for (i = 0; i < instance_ce->num_interfaces; i++) { - if (instanceof_interface(instance_ce->interfaces[i], ce)) { + if (instance_ce->interfaces[i] == ce) { return 1; } } |