summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2019-10-24 18:11:41 +0200
committerNikita Popov <nikita.ppv@gmail.com>2019-10-25 10:19:42 +0200
commit184ba0c91c3b688538d0274625241c640a8952eb (patch)
treeaeaeee37ed45ccd03e7f0a395d4489b6ed387e7b
parentc63a0e005abe4b00ab097dc47ca53d20788a6361 (diff)
downloadphp-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.c25
-rw-r--r--Zend/zend_operators.c2
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;
}
}