diff options
author | Nikita Popov <nikita.ppv@gmail.com> | 2020-11-03 14:15:05 +0100 |
---|---|---|
committer | Nikita Popov <nikita.ppv@gmail.com> | 2020-11-03 14:19:15 +0100 |
commit | ee934f8245b58e1a557ed7b3f303f2d9d7cd23a6 (patch) | |
tree | 36afbbd345d25af61a7e14a01b5c8d97a7f19175 /Zend/zend_inheritance.c | |
parent | 51b5f7d67d639fedcc12451a457f09f493f7db34 (diff) | |
download | php-git-ee934f8245b58e1a557ed7b3f303f2d9d7cd23a6.tar.gz |
Fix variance checks on resolved union types
This is a bit annoying: When preloading is used, types might be
resolved during inheritance checks, so we need to deal with CE
types rather than just NAME types everywhere.
Diffstat (limited to 'Zend/zend_inheritance.c')
-rw-r--r-- | Zend/zend_inheritance.c | 110 |
1 files changed, 57 insertions, 53 deletions
diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index 191126eed7..34489938a9 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -364,11 +364,10 @@ typedef enum { } inheritance_status; static inheritance_status zend_perform_covariant_class_type_check( - zend_class_entry *fe_scope, zend_string *fe_class_name, + zend_class_entry *fe_scope, zend_string *fe_class_name, zend_class_entry *fe_ce, zend_class_entry *proto_scope, zend_type proto_type, zend_bool register_unresolved) { zend_bool have_unresolved = 0; - zend_class_entry *fe_ce = NULL; if (ZEND_TYPE_FULL_MASK(proto_type) & MAY_BE_OBJECT) { /* Currently, any class name would be allowed here. We still perform a class lookup * for forward-compatibility reasons, as we may have named types in the future that @@ -391,6 +390,7 @@ static inheritance_status zend_perform_covariant_class_type_check( zend_type *single_type; ZEND_TYPE_FOREACH(proto_type, single_type) { + zend_class_entry *proto_ce; if (ZEND_TYPE_HAS_NAME(*single_type)) { zend_string *proto_class_name = resolve_class_name(proto_scope, ZEND_TYPE_NAME(*single_type)); @@ -398,16 +398,20 @@ static inheritance_status zend_perform_covariant_class_type_check( return INHERITANCE_SUCCESS; } - /* Make sure to always load both classes, to avoid only registering one of them as - * a delayed autoload. */ if (!fe_ce) fe_ce = lookup_class(fe_scope, fe_class_name, register_unresolved); - zend_class_entry *proto_ce = + proto_ce = lookup_class(proto_scope, proto_class_name, register_unresolved); - if (!fe_ce || !proto_ce) { - have_unresolved = 1; - } else if (unlinked_instanceof(fe_ce, proto_ce)) { - return INHERITANCE_SUCCESS; - } + } else if (ZEND_TYPE_HAS_CE(*single_type)) { + if (!fe_ce) fe_ce = lookup_class(fe_scope, fe_class_name, register_unresolved); + proto_ce = ZEND_TYPE_CE(*single_type); + } else { + continue; + } + + if (!fe_ce || !proto_ce) { + have_unresolved = 1; + } else if (unlinked_instanceof(fe_ce, proto_ce)) { + return INHERITANCE_SUCCESS; } } ZEND_TYPE_FOREACH_END(); @@ -448,56 +452,56 @@ static inheritance_status zend_perform_covariant_type_check( } } - if (ZEND_TYPE_HAS_NAME(fe_type)) { - zend_string *fe_class_name = resolve_class_name(fe_scope, ZEND_TYPE_NAME(fe_type)); - inheritance_status status = zend_perform_covariant_class_type_check( - fe_scope, fe_class_name, proto_scope, proto_type, /* register_unresolved */ 0); - if (status != INHERITANCE_UNRESOLVED) { - return status; - } - - zend_perform_covariant_class_type_check( - fe_scope, fe_class_name, proto_scope, proto_type, /* register_unresolved */ 1); - return INHERITANCE_UNRESOLVED; - } - - if (ZEND_TYPE_HAS_LIST(fe_type)) { - zend_type *list_type; - zend_bool all_success = 1; + zend_type *single_type; + zend_bool all_success = 1; - /* First try to check whether we can succeed without resolving anything */ - ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(fe_type), list_type) { - ZEND_ASSERT(ZEND_TYPE_HAS_NAME(*list_type)); + /* First try to check whether we can succeed without resolving anything */ + ZEND_TYPE_FOREACH(fe_type, single_type) { + inheritance_status status; + if (ZEND_TYPE_HAS_NAME(*single_type)) { zend_string *fe_class_name = - resolve_class_name(fe_scope, ZEND_TYPE_NAME(*list_type)); - inheritance_status status = zend_perform_covariant_class_type_check( - fe_scope, fe_class_name, proto_scope, proto_type, /* register_unresolved */ 0); - if (status == INHERITANCE_ERROR) { - return INHERITANCE_ERROR; - } - - if (status != INHERITANCE_SUCCESS) { - all_success = 0; - } - } ZEND_TYPE_LIST_FOREACH_END(); + resolve_class_name(fe_scope, ZEND_TYPE_NAME(*single_type)); + status = zend_perform_covariant_class_type_check( + fe_scope, fe_class_name, NULL, + proto_scope, proto_type, /* register_unresolved */ 0); + } else if (ZEND_TYPE_HAS_CE(*single_type)) { + zend_class_entry *fe_ce = ZEND_TYPE_CE(*single_type); + status = zend_perform_covariant_class_type_check( + fe_scope, fe_ce->name, fe_ce, + proto_scope, proto_type, /* register_unresolved */ 0); + } else { + continue; + } - /* All individual checks succeeded, overall success */ - if (all_success) { - return INHERITANCE_SUCCESS; + if (status == INHERITANCE_ERROR) { + return INHERITANCE_ERROR; } + if (status != INHERITANCE_SUCCESS) { + all_success = 0; + } + } ZEND_TYPE_FOREACH_END(); - /* Register all classes that may have to be resolved */ - ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(fe_type), list_type) { - ZEND_ASSERT(ZEND_TYPE_HAS_NAME(*list_type)); - zend_string *fe_class_name = - resolve_class_name(fe_scope, ZEND_TYPE_NAME(*list_type)); - zend_perform_covariant_class_type_check( - fe_scope, fe_class_name, proto_scope, proto_type, /* register_unresolved */ 1); - } ZEND_TYPE_LIST_FOREACH_END(); - return INHERITANCE_UNRESOLVED; + /* All individual checks succeeded, overall success */ + if (all_success) { + return INHERITANCE_SUCCESS; } - return INHERITANCE_SUCCESS; + /* Register all classes that may have to be resolved */ + ZEND_TYPE_FOREACH(fe_type, single_type) { + if (ZEND_TYPE_HAS_NAME(*single_type)) { + zend_string *fe_class_name = + resolve_class_name(fe_scope, ZEND_TYPE_NAME(*single_type)); + zend_perform_covariant_class_type_check( + fe_scope, fe_class_name, NULL, + proto_scope, proto_type, /* register_unresolved */ 1); + } else if (ZEND_TYPE_HAS_CE(*single_type)) { + zend_class_entry *fe_ce = ZEND_TYPE_CE(*single_type); + zend_perform_covariant_class_type_check( + fe_scope, fe_ce->name, fe_ce, + proto_scope, proto_type, /* register_unresolved */ 1); + } + } ZEND_TYPE_FOREACH_END(); + return INHERITANCE_UNRESOLVED; } /* }}} */ |