diff --git a/NEWS b/NEWS index 482dfcb09134..ae0f6f3e8ff5 100644 --- a/NEWS +++ b/NEWS @@ -122,6 +122,8 @@ PHP NEWS - Standard: . Fixed bug GH-19926 (reset internal pointer earlier while splicing array while COW violation flag is still set). (alexandre-daubois) + . Added form feed (\f) in the default trimmed characters of trim(), rtrim() + and ltrim(). (Weilin Du) . Invalid mode values now throw in array_filter() instead of being silently defaulted to 0. (Jorg Sowa) . Fixed bug GH-21058 (error_log() crashes with message_type 3 and diff --git a/UPGRADING b/UPGRADING index 732d6f1d4859..595a49e41e4d 100644 --- a/UPGRADING +++ b/UPGRADING @@ -47,6 +47,8 @@ PHP 8.6 UPGRADE NOTES - Standard: . Invalid mode values now throw in array_filter() instead of being silently defaulted to 0. + . Form feed (\f) is now added in the default trimmed characters of trim(), + rtrim() and ltrim(). RFC: https://wiki.php.net/rfc/trim_form_feed ======================================== 2. New Features diff --git a/Zend/tests/enum/no-class-implements-backed-enum.phpt b/Zend/tests/enum/no-class-implements-backed-enum.phpt index f6f37818da5a..f8d4fd13a423 100644 --- a/Zend/tests/enum/no-class-implements-backed-enum.phpt +++ b/Zend/tests/enum/no-class-implements-backed-enum.phpt @@ -7,4 +7,4 @@ class Foo implements BackedEnum {} ?> --EXPECTF-- -Fatal error: Non-enum class Foo cannot implement interface BackedEnum in %s on line %d +Fatal error: Non-enum class Foo cannot implement interface UnitEnum in %s on line %d diff --git a/Zend/tests/inheritance/enum_only_interfaces_error_via_indirect_interface.phpt b/Zend/tests/inheritance/enum_only_interfaces_error_via_indirect_interface.phpt new file mode 100644 index 000000000000..66a921532055 --- /dev/null +++ b/Zend/tests/inheritance/enum_only_interfaces_error_via_indirect_interface.phpt @@ -0,0 +1,15 @@ +--TEST-- +Interface that is extended from Enum only interface shouldn't be implementable by non-enum class +--FILE-- + +--EXPECTF-- +Fatal error: Non-enum class C cannot implement interface UnitEnum in %s on line %d diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 23db72bb4fda..3147fda23e9f 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -1417,7 +1417,7 @@ static zend_string *resolve_class_name(zend_string *name, const zend_class_entry } static zend_string *add_intersection_type(zend_string *str, - const zend_type_list *intersection_type_list, zend_class_entry *scope, + const zend_type_list *intersection_type_list, bool is_bracketed) { const zend_type *single_type; @@ -1442,19 +1442,19 @@ static zend_string *add_intersection_type(zend_string *str, return str; } -zend_string *zend_type_to_string_resolved(const zend_type type, zend_class_entry *scope) { +zend_string *zend_type_to_string_resolved(const zend_type type, const zend_class_entry *scope) { zend_string *str = NULL; /* Pure intersection type */ if (ZEND_TYPE_IS_INTERSECTION(type)) { ZEND_ASSERT(!ZEND_TYPE_IS_UNION(type)); - str = add_intersection_type(str, ZEND_TYPE_LIST(type), scope, /* is_bracketed */ false); + str = add_intersection_type(str, ZEND_TYPE_LIST(type), /* is_bracketed */ false); } else if (ZEND_TYPE_HAS_LIST(type)) { /* A union type might not be a list */ const zend_type *list_type; ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(type), list_type) { if (ZEND_TYPE_IS_INTERSECTION(*list_type)) { - str = add_intersection_type(str, ZEND_TYPE_LIST(*list_type), scope, /* is_bracketed */ true); + str = add_intersection_type(str, ZEND_TYPE_LIST(*list_type), /* is_bracketed */ true); continue; } ZEND_ASSERT(!ZEND_TYPE_HAS_LIST(*list_type)); diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 0b38084a107c..5414467f3f87 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -1034,7 +1034,7 @@ int ZEND_FASTCALL zendlex(zend_parser_stack_elem *elem); void zend_assert_valid_class_name(const zend_string *const_name, const char *type); -zend_string *zend_type_to_string_resolved(zend_type type, zend_class_entry *scope); +zend_string *zend_type_to_string_resolved(zend_type type, const zend_class_entry *scope); ZEND_API zend_string *zend_type_to_string(zend_type type); /* class fetches */ diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index 9b3b6312cf25..ba13a3233ed2 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -60,8 +60,8 @@ static void add_property_hook_obligation( zend_class_entry *ce, const zend_property_info *hooked_prop, const zend_function *hook_func); static void ZEND_COLD emit_incompatible_method_error( - const zend_function *child, zend_class_entry *child_scope, - const zend_function *parent, zend_class_entry *parent_scope, + const zend_function *child, const zend_class_entry *child_scope, + const zend_function *parent, const zend_class_entry *parent_scope, inheritance_status status); static void zend_type_copy_ctor(zend_type *const type, bool use_arena, bool persistent); @@ -320,7 +320,7 @@ static bool unlinked_instanceof(const zend_class_entry *ce1, const zend_class_en } if (ce1->parent) { - zend_class_entry *parent_ce; + const zend_class_entry *parent_ce; if (ce1->ce_flags & ZEND_ACC_RESOLVED_PARENT) { parent_ce = ce1->parent; } else { @@ -671,7 +671,7 @@ static inheritance_status zend_is_intersection_subtype_of_type( return early_exit_status == INHERITANCE_ERROR ? INHERITANCE_SUCCESS : INHERITANCE_ERROR; } -ZEND_API inheritance_status zend_perform_covariant_type_check( +static inheritance_status zend_perform_covariant_type_check( zend_class_entry *fe_scope, const zend_type fe_type, zend_class_entry *proto_scope, const zend_type proto_type) { @@ -763,8 +763,8 @@ ZEND_API inheritance_status zend_perform_covariant_type_check( } static inheritance_status zend_do_perform_arg_type_hint_check( - zend_class_entry *fe_scope, zend_arg_info *fe_arg_info, - zend_class_entry *proto_scope, zend_arg_info *proto_arg_info) /* {{{ */ + zend_class_entry *fe_scope, const zend_arg_info *fe_arg_info, + zend_class_entry *proto_scope, const zend_arg_info *proto_arg_info) /* {{{ */ { if (!ZEND_TYPE_IS_SET(fe_arg_info->type) || ZEND_TYPE_PURE_MASK(fe_arg_info->type) == MAY_BE_ANY) { /* Child with no type or mixed type is always compatible */ @@ -897,7 +897,7 @@ static inheritance_status zend_do_perform_implementation_check( /* }}} */ static ZEND_COLD void zend_append_type_hint( - smart_str *str, zend_class_entry *scope, const zend_arg_info *arg_info, bool return_hint) /* {{{ */ + smart_str *str, const zend_class_entry *scope, const zend_arg_info *arg_info, bool return_hint) /* {{{ */ { if (ZEND_TYPE_IS_SET(arg_info->type)) { zend_string *type_str = zend_type_to_string_resolved(arg_info->type, scope); @@ -911,7 +911,7 @@ static ZEND_COLD void zend_append_type_hint( /* }}} */ static ZEND_COLD zend_string *zend_get_function_declaration( - const zend_function *fptr, zend_class_entry *scope) /* {{{ */ + const zend_function *fptr, const zend_class_entry *scope) /* {{{ */ { smart_str str = {0}; @@ -1054,8 +1054,8 @@ static zend_always_inline uint32_t func_lineno(const zend_function *fn) { } static void ZEND_COLD emit_incompatible_method_error( - const zend_function *child, zend_class_entry *child_scope, - const zend_function *parent, zend_class_entry *parent_scope, + const zend_function *child, const zend_class_entry *child_scope, + const zend_function *parent, const zend_class_entry *parent_scope, inheritance_status status) { zend_string *parent_prototype = zend_get_function_declaration(parent, parent_scope); zend_string *child_prototype = zend_get_function_declaration(child, child_scope); @@ -2168,6 +2168,10 @@ static void do_interface_implementation(zend_class_entry *ce, zend_class_entry * zend_class_constant *c; uint32_t flags = ZEND_INHERITANCE_CHECK_PROTO | ZEND_INHERITANCE_CHECK_VISIBILITY; + if (iface->num_interfaces) { + zend_do_inherit_interfaces(ce, iface); + } + if (!(ce->ce_flags & ZEND_ACC_INTERFACE)) { /* We are not setting the prototype of overridden interface methods because of abstract * constructors. See Zend/tests/interface_constructor_prototype_001.phpt. */ @@ -2199,9 +2203,6 @@ static void do_interface_implementation(zend_class_entry *ce, zend_class_entry * } ZEND_HASH_FOREACH_END(); do_implement_interface(ce, iface); - if (iface->num_interfaces) { - zend_do_inherit_interfaces(ce, iface); - } } /* }}} */ diff --git a/ext/pcntl/php_pcntl.h b/ext/pcntl/php_pcntl.h index fb151e207b94..e02f93246e88 100644 --- a/ext/pcntl/php_pcntl.h +++ b/ext/pcntl/php_pcntl.h @@ -48,7 +48,8 @@ ZEND_BEGIN_MODULE_GLOBALS(pcntl) bool processing_signal_queue; volatile bool pending_signals; bool async_signals; - uint8_t num_signals; + /* some OSes define NSIG to be > UINT8_MAX */ + uint16_t num_signals; int last_error; struct php_pcntl_pending_signal *head, *tail, *spares; ZEND_END_MODULE_GLOBALS(pcntl) diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c index 2d8ee9c435ed..d4b084217b5b 100644 --- a/ext/phar/phar_object.c +++ b/ext/phar/phar_object.c @@ -46,9 +46,8 @@ static zend_class_entry *phar_ce_entry; static int phar_file_type(const HashTable *mimes, const char *file, char **mime_type) /* {{{ */ { - char *ext; phar_mime_type *mime; - ext = strrchr(file, '.'); + const char *ext = strrchr(file, '.'); if (!ext) { *mime_type = "text/plain"; /* no file extension = assume text/plain */ @@ -347,10 +346,9 @@ static void phar_do_404(phar_archive_data *phar, char *fname, size_t fname_len, /* post-process REQUEST_URI and retrieve the actual request URI. This is for cases like http://localhost/blah.phar/path/to/file.php/extra/stuff which calls "blah.phar" file "path/to/file.php" with PATH_INFO "/extra/stuff" */ -static void phar_postprocess_ru_web(const char *fname, size_t fname_len, const char *entry, size_t *entry_len, char **ru, size_t *ru_len) /* {{{ */ +static void phar_postprocess_ru_web(char *fname, size_t fname_len, char *entry, size_t *entry_len, char **ru, size_t *ru_len) /* {{{ */ { - const char *e = entry + 1; - char *u = NULL, *u1 = NULL, *saveu = NULL; + char *e = entry + 1, *u1 = NULL, *u = NULL, *saveu = NULL; size_t e_len = *entry_len - 1, u_len = 0; phar_archive_data *pphar; diff --git a/ext/phar/tar.c b/ext/phar/tar.c index 6a3840b3671c..0c93de243adc 100644 --- a/ext/phar/tar.c +++ b/ext/phar/tar.c @@ -105,7 +105,8 @@ bool phar_is_tar(const char *buf, const char *fname) /* {{{ */ tar_header *header = (tar_header *) buf; uint32_t checksum = phar_tar_number(header->checksum, sizeof(header->checksum)); bool is_tar; - char save[sizeof(header->checksum)], *bname; + char save[sizeof(header->checksum)]; + const char *bname; /* assume that the first filename in a tar won't begin with default (' \t\n\r\v\0') + * what indicates which chars are to be trimmed. NULL->default (' \f\t\n\r\v\0') */ static zend_always_inline zend_string *php_trim_int(zend_string *str, const char *what, size_t what_len, int mode) { @@ -573,10 +578,7 @@ static zend_always_inline zend_string *php_trim_int(zend_string *str, const char } else { if (mode & 1) { while (start != end) { - unsigned char c = (unsigned char)*start; - - if (c <= ' ' && - (c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == '\v' || c == '\0')) { + if (php_is_whitespace((unsigned char)*start)) { start++; } else { break; @@ -585,10 +587,7 @@ static zend_always_inline zend_string *php_trim_int(zend_string *str, const char } if (mode & 2) { while (start != end) { - unsigned char c = (unsigned char)*(end-1); - - if (c <= ' ' && - (c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == '\v' || c == '\0')) { + if (php_is_whitespace((unsigned char)*(end-1))) { end--; } else { break; @@ -611,7 +610,7 @@ static zend_always_inline zend_string *php_trim_int(zend_string *str, const char * mode 1 : trim left * mode 2 : trim right * mode 3 : trim left and right - * what indicates which chars are to be trimmed. NULL->default (' \t\n\r\v\0') + * what indicates which chars are to be trimmed. NULL->default (' \f\t\n\r\v\0') */ PHPAPI zend_string *php_trim(zend_string *str, const char *what, size_t what_len, int mode) { diff --git a/ext/standard/tests/strings/trim.phpt b/ext/standard/tests/strings/trim.phpt index fd0c26d7794a..9ce5e1dfff02 100644 --- a/ext/standard/tests/strings/trim.phpt +++ b/ext/standard/tests/strings/trim.phpt @@ -18,6 +18,9 @@ var_dump("ABC" === trim("ABC\x50\xC1\x60\x90","\x50..\xC1")); var_dump("ABC\x50\xC1" === trim("ABC\x50\xC1\x60\x90","\x51..\xC0")); var_dump("ABC\x50" === trim("ABC\x50\xC1\x60\x90","\x51..\xC1")); var_dump("ABC" === trim("ABC\x50\xC1\x60\x90","\x50..\xC1")); +var_dump("ABC" === trim("\fABC\f")); +var_dump("ABC" === ltrim("\fABC")); +var_dump("ABC" === rtrim("ABC\f")); ?> --EXPECT-- @@ -36,3 +39,6 @@ bool(true) bool(true) bool(true) bool(true) +bool(true) +bool(true) +bool(true)