From 9b30f33c5e5e35ff13b9e9c47f8e27cfb1e970f9 Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Mon, 19 Sep 2022 15:50:42 +0100 Subject: [PATCH 1/3] Fix UPGRADING by adding DBA constants --- UPGRADING | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/UPGRADING b/UPGRADING index 505828cb21fc0..0cf33b6344652 100644 --- a/UPGRADING +++ b/UPGRADING @@ -231,7 +231,7 @@ PHP 8.2 UPGRADE NOTES - OpenSSL: . openssl_cipher_key_length(): Returns a key length for the supplied - cipher. + cipher. - Reflection: . ReflectionFunction::isAnonymous() @@ -400,6 +400,10 @@ PHP 8.2 UPGRADE NOTES . CURL_VERSION_UNICODE (libcurl >= 7.72.0) . CURL_VERSION_ZSTD (libcurl >= 7.72.0) +- DBA + . DBA_LMDB_USE_SUB_DIR + . DBA_LMDB_NO_SUB_DIR + - Filter . FILTER_FLAG_GLOBAL_RANGE From 9e7d6102ba32fd8b8b5ed3276534d14b1af342e8 Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Mon, 19 Sep 2022 14:08:55 +0100 Subject: [PATCH 2/3] Move object/class redundancy check into union type handling As such a redundancy can only happen for union types --- Zend/zend_compile.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 3b686176894b6..f1dce379ae86a 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -6455,6 +6455,14 @@ static zend_type zend_compile_typename( } free_alloca(type_list, use_heap); + + uint32_t type_mask = ZEND_TYPE_FULL_MASK(type); + if ((type_mask & MAY_BE_OBJECT) && (ZEND_TYPE_IS_COMPLEX(type) || (type_mask & MAY_BE_STATIC))) { + zend_string *type_str = zend_type_to_string(type); + zend_error_noreturn(E_COMPILE_ERROR, + "Type %s contains both object and a class type, which is redundant", + ZSTR_VAL(type_str)); + } } else if (ast->kind == ZEND_AST_TYPE_INTERSECTION) { zend_ast_list *list = zend_ast_get_list(ast); zend_type_list *type_list; @@ -6515,13 +6523,6 @@ static zend_type zend_compile_typename( zend_error_noreturn(E_COMPILE_ERROR, "Type mixed cannot be marked as nullable since mixed already includes null"); } - if ((type_mask & MAY_BE_OBJECT) && (ZEND_TYPE_IS_COMPLEX(type) || (type_mask & MAY_BE_STATIC))) { - zend_string *type_str = zend_type_to_string(type); - zend_error_noreturn(E_COMPILE_ERROR, - "Type %s contains both object and a class type, which is redundant", - ZSTR_VAL(type_str)); - } - if ((type_mask & MAY_BE_NULL) && is_marked_nullable) { zend_error_noreturn(E_COMPILE_ERROR, "null cannot be marked as nullable"); } @@ -8083,7 +8084,7 @@ static void zend_compile_use(zend_ast *ast) /* {{{ */ /* Check that we are not attempting to alias a built-in type */ if (type == ZEND_SYMBOL_CLASS && zend_is_reserved_class_name(old_name)) { - zend_error_noreturn(E_COMPILE_ERROR, + zend_error_noreturn(E_COMPILE_ERROR, "Cannot alias '%s' as it is a built-in type", ZSTR_VAL(old_name)); } From 91b25fd60801c01e83ca48530621ad64591c0c2d Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Fri, 16 Sep 2022 15:21:04 +0100 Subject: [PATCH 3/3] Fix GH-9556 "iterable" alias "array|Traversable" breaks PHP 8.1 code --- .../redundant_types/object_and_dnf_type.phpt | 14 ++++++++++++++ .../redundant_types/object_and_dnf_type2.phpt | 14 ++++++++++++++ .../iterable_alias_redundancy_array_1.phpt | 12 ++++++++++++ .../iterable_alias_redundancy_array_2.phpt | 12 ++++++++++++ .../iterable_alias_redundancy_iterable.phpt | 12 ++++++++++++ .../iterable_alias_redundancy_object_1.phpt | 13 +++++++++++++ .../iterable_alias_redundancy_object_2.phpt | 13 +++++++++++++ .../iterable_alias_redundancy_object_3.phpt | 12 ++++++++++++ .../iterable_alias_redundancy_object_4.phpt | 12 ++++++++++++ .../iterable_alias_redundancy_object_5.phpt | 12 ++++++++++++ .../iterable_alias_redundancy_object_6.phpt | 12 ++++++++++++ ...rable_alias_redundancy_object_variance.phpt | 18 ++++++++++++++++++ .../object_and_class_type2.phpt | 11 +++++++++++ .../redundant_types/object_and_static2.phpt | 12 ++++++++++++ Zend/zend_compile.c | 17 +++++++++++++---- 15 files changed, 192 insertions(+), 4 deletions(-) create mode 100644 Zend/tests/type_declarations/dnf_types/redundant_types/object_and_dnf_type.phpt create mode 100644 Zend/tests/type_declarations/dnf_types/redundant_types/object_and_dnf_type2.phpt create mode 100644 Zend/tests/type_declarations/iterable/iterable_alias_redundancy_array_1.phpt create mode 100644 Zend/tests/type_declarations/iterable/iterable_alias_redundancy_array_2.phpt create mode 100644 Zend/tests/type_declarations/iterable/iterable_alias_redundancy_iterable.phpt create mode 100644 Zend/tests/type_declarations/iterable/iterable_alias_redundancy_object_1.phpt create mode 100644 Zend/tests/type_declarations/iterable/iterable_alias_redundancy_object_2.phpt create mode 100644 Zend/tests/type_declarations/iterable/iterable_alias_redundancy_object_3.phpt create mode 100644 Zend/tests/type_declarations/iterable/iterable_alias_redundancy_object_4.phpt create mode 100644 Zend/tests/type_declarations/iterable/iterable_alias_redundancy_object_5.phpt create mode 100644 Zend/tests/type_declarations/iterable/iterable_alias_redundancy_object_6.phpt create mode 100644 Zend/tests/type_declarations/iterable/iterable_alias_redundancy_object_variance.phpt create mode 100644 Zend/tests/type_declarations/union_types/redundant_types/object_and_class_type2.phpt create mode 100644 Zend/tests/type_declarations/union_types/redundant_types/object_and_static2.phpt diff --git a/Zend/tests/type_declarations/dnf_types/redundant_types/object_and_dnf_type.phpt b/Zend/tests/type_declarations/dnf_types/redundant_types/object_and_dnf_type.phpt new file mode 100644 index 0000000000000..3a99d3a5d5202 --- /dev/null +++ b/Zend/tests/type_declarations/dnf_types/redundant_types/object_and_dnf_type.phpt @@ -0,0 +1,14 @@ +--TEST-- +A DNF type which contains object is redundant +--FILE-- + +===DONE=== +--EXPECTF-- +Fatal error: Type (A&B)|object contains both object and a class type, which is redundant in %s on line %d diff --git a/Zend/tests/type_declarations/dnf_types/redundant_types/object_and_dnf_type2.phpt b/Zend/tests/type_declarations/dnf_types/redundant_types/object_and_dnf_type2.phpt new file mode 100644 index 0000000000000..c37f08d6dc41e --- /dev/null +++ b/Zend/tests/type_declarations/dnf_types/redundant_types/object_and_dnf_type2.phpt @@ -0,0 +1,14 @@ +--TEST-- +A DNF type which contains object is redundant 2 +--FILE-- + +===DONE=== +--EXPECTF-- +Fatal error: Type (A&B)|object contains both object and a class type, which is redundant in %s on line %d diff --git a/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_array_1.phpt b/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_array_1.phpt new file mode 100644 index 0000000000000..b11671bc09242 --- /dev/null +++ b/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_array_1.phpt @@ -0,0 +1,12 @@ +--TEST-- +iterable type with array should be redundant +--FILE-- + +--EXPECTF-- +Fatal error: Duplicate type array is redundant in %s on line %d diff --git a/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_array_2.phpt b/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_array_2.phpt new file mode 100644 index 0000000000000..6973901cb5a2b --- /dev/null +++ b/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_array_2.phpt @@ -0,0 +1,12 @@ +--TEST-- +iterable type with array should be redundant +--FILE-- + +--EXPECTF-- +Fatal error: Duplicate type array is redundant in %s on line %d diff --git a/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_iterable.phpt b/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_iterable.phpt new file mode 100644 index 0000000000000..e8fa3c040261a --- /dev/null +++ b/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_iterable.phpt @@ -0,0 +1,12 @@ +--TEST-- +iterable type with second iterable should be redundant +--FILE-- + +--EXPECTF-- +Fatal error: Duplicate type array is redundant in %s on line %d diff --git a/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_object_1.phpt b/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_object_1.phpt new file mode 100644 index 0000000000000..b7a70191145ff --- /dev/null +++ b/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_object_1.phpt @@ -0,0 +1,13 @@ +--TEST-- +iterable type with object should NOT be redundant 1 +--FILE-- + +===DONE=== +--EXPECT-- +===DONE=== diff --git a/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_object_2.phpt b/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_object_2.phpt new file mode 100644 index 0000000000000..07a6668232957 --- /dev/null +++ b/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_object_2.phpt @@ -0,0 +1,13 @@ +--TEST-- +iterable type with object should NOT be redundant 2 +--FILE-- + +===DONE=== +--EXPECT-- +===DONE=== diff --git a/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_object_3.phpt b/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_object_3.phpt new file mode 100644 index 0000000000000..eedf16fd76491 --- /dev/null +++ b/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_object_3.phpt @@ -0,0 +1,12 @@ +--TEST-- +iterable type with object and class T should be redundant +--FILE-- + +--EXPECTF-- +Fatal error: Type Traversable|T|object|array|null contains both object and a class type, which is redundant in %s on line %d diff --git a/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_object_4.phpt b/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_object_4.phpt new file mode 100644 index 0000000000000..acad787130a6c --- /dev/null +++ b/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_object_4.phpt @@ -0,0 +1,12 @@ +--TEST-- +iterable type with object and class T should be redundant +--FILE-- + +--EXPECTF-- +Fatal error: Type Traversable|T|object|array|null contains both object and a class type, which is redundant in %s on line %d diff --git a/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_object_5.phpt b/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_object_5.phpt new file mode 100644 index 0000000000000..84ba505aa7dac --- /dev/null +++ b/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_object_5.phpt @@ -0,0 +1,12 @@ +--TEST-- +iterable type with object and class T should be redundant +--FILE-- + +--EXPECTF-- +Fatal error: Type T|Traversable|object|array|null contains both object and a class type, which is redundant in %s on line %d diff --git a/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_object_6.phpt b/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_object_6.phpt new file mode 100644 index 0000000000000..541317d1d6961 --- /dev/null +++ b/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_object_6.phpt @@ -0,0 +1,12 @@ +--TEST-- +iterable type with object and class T should be redundant +--FILE-- + +--EXPECTF-- +Fatal error: Type T|Traversable|object|array|null contains both object and a class type, which is redundant in %s on line %d diff --git a/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_object_variance.phpt b/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_object_variance.phpt new file mode 100644 index 0000000000000..158b6c2214f41 --- /dev/null +++ b/Zend/tests/type_declarations/iterable/iterable_alias_redundancy_object_variance.phpt @@ -0,0 +1,18 @@ +--TEST-- +iterable type with object should be allowed in variance checks +--FILE-- + +===DONE=== +--EXPECT-- +===DONE=== diff --git a/Zend/tests/type_declarations/union_types/redundant_types/object_and_class_type2.phpt b/Zend/tests/type_declarations/union_types/redundant_types/object_and_class_type2.phpt new file mode 100644 index 0000000000000..bc9852da83d11 --- /dev/null +++ b/Zend/tests/type_declarations/union_types/redundant_types/object_and_class_type2.phpt @@ -0,0 +1,11 @@ +--TEST-- +Using both object and a class type 2 +--FILE-- + +--EXPECTF-- +Fatal error: Type Test|object contains both object and a class type, which is redundant in %s on line %d diff --git a/Zend/tests/type_declarations/union_types/redundant_types/object_and_static2.phpt b/Zend/tests/type_declarations/union_types/redundant_types/object_and_static2.phpt new file mode 100644 index 0000000000000..3fbb9a29fe5a5 --- /dev/null +++ b/Zend/tests/type_declarations/union_types/redundant_types/object_and_static2.phpt @@ -0,0 +1,12 @@ +--TEST-- +object and static are redundant 2 +--FILE-- + +--EXPECTF-- +Fatal error: Type static|object contains both object and a class type, which is redundant in %s on line %d diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index f1dce379ae86a..154c5a810ba6a 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -6363,6 +6363,7 @@ static zend_type zend_compile_typename( zend_ast_list *list = zend_ast_get_list(ast); zend_type_list *type_list; bool is_composite = false; + bool has_only_iterable_class = true; ALLOCA_FLAG(use_heap) type_list = do_alloca(ZEND_TYPE_LIST_SIZE(list->children), use_heap); @@ -6371,8 +6372,10 @@ static zend_type zend_compile_typename( for (uint32_t i = 0; i < list->children; i++) { zend_ast *type_ast = list->child[i]; zend_type single_type; + uint32_t type_mask = ZEND_TYPE_FULL_MASK(type); if (type_ast->kind == ZEND_AST_TYPE_INTERSECTION) { + has_only_iterable_class = false; is_composite = true; /* The first class type can be stored directly as the type ptr payload. */ if (ZEND_TYPE_IS_COMPLEX(type) && !ZEND_TYPE_HAS_LIST(type)) { @@ -6380,8 +6383,9 @@ static zend_type zend_compile_typename( type_list->num_types = 1; type_list->types[0] = type; ZEND_TYPE_FULL_MASK(type_list->types[0]) &= ~_ZEND_TYPE_MAY_BE_MASK; - ZEND_TYPE_SET_LIST(type, type_list); } + /* Mark type as list type */ + ZEND_TYPE_SET_LIST(type, type_list); single_type = zend_compile_typename(type_ast, false); ZEND_ASSERT(ZEND_TYPE_IS_INTERSECTION(single_type)); @@ -6406,6 +6410,9 @@ static zend_type zend_compile_typename( if (single_type_mask == MAY_BE_ANY) { zend_error_noreturn(E_COMPILE_ERROR, "Type mixed can only be used as a standalone type"); } + if (ZEND_TYPE_IS_COMPLEX(single_type) && !ZEND_TYPE_IS_ITERABLE_FALLBACK(single_type)) { + has_only_iterable_class = false; + } uint32_t type_mask_overlap = ZEND_TYPE_PURE_MASK(type) & single_type_mask; if (type_mask_overlap) { @@ -6414,8 +6421,9 @@ static zend_type zend_compile_typename( zend_error_noreturn(E_COMPILE_ERROR, "Duplicate type %s is redundant", ZSTR_VAL(overlap_type_str)); } - if ( ((ZEND_TYPE_PURE_MASK(type) & MAY_BE_TRUE) && (single_type_mask == MAY_BE_FALSE)) - || ((ZEND_TYPE_PURE_MASK(type) & MAY_BE_FALSE) && (single_type_mask == MAY_BE_TRUE)) ) { + + if ( ((type_mask & MAY_BE_TRUE) && (single_type_mask == MAY_BE_FALSE)) + || ((type_mask & MAY_BE_FALSE) && (single_type_mask == MAY_BE_TRUE)) ) { zend_error_noreturn(E_COMPILE_ERROR, "Type contains both true and false, bool should be used instead"); } @@ -6457,7 +6465,8 @@ static zend_type zend_compile_typename( free_alloca(type_list, use_heap); uint32_t type_mask = ZEND_TYPE_FULL_MASK(type); - if ((type_mask & MAY_BE_OBJECT) && (ZEND_TYPE_IS_COMPLEX(type) || (type_mask & MAY_BE_STATIC))) { + if ((type_mask & MAY_BE_OBJECT) && + ((!has_only_iterable_class && ZEND_TYPE_IS_COMPLEX(type)) || (type_mask & MAY_BE_STATIC))) { zend_string *type_str = zend_type_to_string(type); zend_error_noreturn(E_COMPILE_ERROR, "Type %s contains both object and a class type, which is redundant",