From abee5c138f961aee20de7eacb7af643f062b2ac0 Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Tue, 29 Jul 2025 20:22:19 +0100 Subject: [PATCH 1/4] ext/intl: convert C part to C++ step 1. (#19231) --- ext/intl/config.m4 | 12 ++-- ext/intl/config.w32 | 10 +-- ext/intl/idn/{idn.c => idn.cpp} | 7 +- ext/intl/locale/{locale.c => locale.cpp} | 0 .../{locale_class.c => locale_class.cpp} | 4 +- ext/intl/locale/locale_class.h | 2 +- .../{locale_methods.c => locale_methods.cpp} | 68 ++++++++++--------- ext/intl/uchar/{uchar.c => uchar.cpp} | 6 +- 8 files changed, 59 insertions(+), 50 deletions(-) rename ext/intl/idn/{idn.c => idn.cpp} (98%) rename ext/intl/locale/{locale.c => locale.cpp} (100%) rename ext/intl/locale/{locale_class.c => locale_class.cpp} (95%) rename ext/intl/locale/{locale_methods.c => locale_methods.cpp} (96%) rename ext/intl/uchar/{uchar.c => uchar.cpp} (98%) diff --git a/ext/intl/config.m4 b/ext/intl/config.m4 index 20adc3a4ce3a7..d60068e5ad480 100644 --- a/ext/intl/config.m4 +++ b/ext/intl/config.m4 @@ -33,12 +33,8 @@ if test "$PHP_INTL" != "no"; then formatter/formatter_parse.c grapheme/grapheme_string.c grapheme/grapheme_util.c - idn/idn.c intl_convert.c intl_error.c - locale/locale_class.c - locale/locale_methods.c - locale/locale.c listformatter/listformatter_class.c msgformat/msgformat_attr.c msgformat/msgformat_class.c @@ -57,7 +53,6 @@ if test "$PHP_INTL" != "no"; then spoofchecker/spoofchecker_main.c transliterator/transliterator_class.c transliterator/transliterator_methods.c - uchar/uchar.c ]), [$ext_shared],, [$INTL_COMMON_FLAGS], @@ -83,7 +78,12 @@ if test "$PHP_INTL" != "no"; then breakiterator/breakiterator_methods.cpp \ breakiterator/rulebasedbreakiterator_methods.cpp \ breakiterator/codepointiterator_internal.cpp \ - breakiterator/codepointiterator_methods.cpp" + breakiterator/codepointiterator_methods.cpp \ + idn/idn.cpp \ + locale/locale_class.cpp \ + locale/locale_methods.cpp \ + locale/locale.cpp \ + uchar/uchar.cpp" PHP_REQUIRE_CXX() diff --git a/ext/intl/config.w32 b/ext/intl/config.w32 index b8161865d2540..dcec448c4621f 100644 --- a/ext/intl/config.w32 +++ b/ext/intl/config.w32 @@ -43,9 +43,9 @@ if (PHP_INTL != "no") { listformatter_class.c \ ", "intl"); ADD_SOURCES(configure_module_dirname + "/locale", "\ - locale.c \ - locale_class.c \ - locale_methods.c \ + locale.cpp \ + locale_class.cpp \ + locale_methods.cpp \ ", "intl"); ADD_SOURCES(configure_module_dirname + "/msgformat", "\ msgformat.c \ @@ -78,10 +78,10 @@ if (PHP_INTL != "no") { datepatterngenerator_methods.cpp \ ", "intl"); ADD_SOURCES(configure_module_dirname + "/uchar", "\ - uchar.c", + uchar.cpp", "intl"); ADD_SOURCES(configure_module_dirname + "/idn", "\ - idn.c", + idn.cpp", "intl"); ADD_SOURCES(configure_module_dirname + "/resourcebundle", "\ resourcebundle.c \ diff --git a/ext/intl/idn/idn.c b/ext/intl/idn/idn.cpp similarity index 98% rename from ext/intl/idn/idn.c rename to ext/intl/idn/idn.cpp index cd4546ad7f8bb..94990baff4832 100644 --- a/ext/intl/idn/idn.c +++ b/ext/intl/idn/idn.cpp @@ -26,7 +26,10 @@ #include #include "idn.h" + +extern "C" { #include "intl_error.h" +} /* }}} */ enum { @@ -145,7 +148,7 @@ static void php_intl_idn_handoff(INTERNAL_FUNCTION_PARAMETERS, int mode) } /* {{{ Converts an Unicode domain to ASCII representation, as defined in the IDNA RFC */ -PHP_FUNCTION(idn_to_ascii) +U_CFUNC PHP_FUNCTION(idn_to_ascii) { php_intl_idn_handoff(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTL_IDN_TO_ASCII); } @@ -153,7 +156,7 @@ PHP_FUNCTION(idn_to_ascii) /* {{{ Converts an ASCII representation of the domain to Unicode (UTF-8), as defined in the IDNA RFC */ -PHP_FUNCTION(idn_to_utf8) +U_CFUNC PHP_FUNCTION(idn_to_utf8) { php_intl_idn_handoff(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTL_IDN_TO_UTF8); } diff --git a/ext/intl/locale/locale.c b/ext/intl/locale/locale.cpp similarity index 100% rename from ext/intl/locale/locale.c rename to ext/intl/locale/locale.cpp diff --git a/ext/intl/locale/locale_class.c b/ext/intl/locale/locale_class.cpp similarity index 95% rename from ext/intl/locale/locale_class.c rename to ext/intl/locale/locale_class.cpp index cbde2a5fb0701..75fde45d53d60 100644 --- a/ext/intl/locale/locale_class.c +++ b/ext/intl/locale/locale_class.cpp @@ -13,11 +13,13 @@ */ #include +extern "C" { #include "php_intl.h" #include "intl_error.h" #include "locale_class.h" #include "locale.h" #include "locale_arginfo.h" +} zend_class_entry *Locale_ce_ptr = NULL; @@ -28,7 +30,7 @@ zend_class_entry *Locale_ce_ptr = NULL; /* {{{ locale_register_Locale_class * Initialize 'Locale' class */ -void locale_register_Locale_class( void ) +U_CFUNC void locale_register_Locale_class( void ) { /* Create and register 'Locale' class. */ Locale_ce_ptr = register_class_Locale(); diff --git a/ext/intl/locale/locale_class.h b/ext/intl/locale/locale_class.h index aa339d75db9b0..64a661ca2b44b 100644 --- a/ext/intl/locale/locale_class.h +++ b/ext/intl/locale/locale_class.h @@ -31,7 +31,7 @@ typedef struct { } Locale_object; -void locale_register_Locale_class( void ); +U_CFUNC void locale_register_Locale_class( void ); extern zend_class_entry *Locale_ce_ptr; diff --git a/ext/intl/locale/locale_methods.c b/ext/intl/locale/locale_methods.cpp similarity index 96% rename from ext/intl/locale/locale_methods.c rename to ext/intl/locale/locale_methods.cpp index 8b63007c5d820..716b69b034b2e 100644 --- a/ext/intl/locale/locale_methods.c +++ b/ext/intl/locale/locale_methods.cpp @@ -21,6 +21,7 @@ #include #include +extern "C" { #include "php_intl.h" #include "locale.h" #include "locale_class.h" @@ -32,6 +33,7 @@ #include #include "main/php_ini.h" #include "zend_smart_str.h" +} ZEND_EXTERN_MODULE_GLOBALS( intl ) @@ -296,7 +298,7 @@ static zend_off_t getSingletonPos(const char* str) /* {{{ Get default locale */ /* }}} */ /* {{{ Get default locale */ -PHP_NAMED_FUNCTION(zif_locale_get_default) +U_CFUNC PHP_NAMED_FUNCTION(zif_locale_get_default) { ZEND_PARSE_PARAMETERS_NONE(); @@ -308,7 +310,7 @@ PHP_NAMED_FUNCTION(zif_locale_get_default) /* {{{ Set default locale */ /* }}} */ /* {{{ Set default locale */ -PHP_NAMED_FUNCTION(zif_locale_set_default) +U_CFUNC PHP_NAMED_FUNCTION(zif_locale_set_default) { zend_string* locale_name; zend_string *ini_name; @@ -520,21 +522,21 @@ static void get_icu_value_src_php( char* tag_name, INTERNAL_FUNCTION_PARAMETERS) /* }}} */ /* {{{ gets the script for the $locale */ -PHP_FUNCTION( locale_get_script ) +U_CFUNC PHP_FUNCTION( locale_get_script ) { get_icu_value_src_php( LOC_SCRIPT_TAG , INTERNAL_FUNCTION_PARAM_PASSTHRU ); } /* }}} */ /* {{{ gets the region for the $locale */ -PHP_FUNCTION( locale_get_region ) +U_CFUNC PHP_FUNCTION( locale_get_region ) { get_icu_value_src_php( LOC_REGION_TAG , INTERNAL_FUNCTION_PARAM_PASSTHRU ); } /* }}} */ /* {{{ gets the primary language for the $locale */ -PHP_FUNCTION(locale_get_primary_language ) +U_CFUNC PHP_FUNCTION(locale_get_primary_language ) { get_icu_value_src_php( LOC_LANG_TAG , INTERNAL_FUNCTION_PARAM_PASSTHRU ); } @@ -610,7 +612,7 @@ static void get_icu_disp_value_src_php( char* tag_name, INTERNAL_FUNCTION_PARAME /* Get the disp_value for the given locale */ do{ - disp_name = erealloc( disp_name , buflen * sizeof(UChar) ); + disp_name = reinterpret_cast(erealloc( disp_name , buflen * sizeof(UChar) )); disp_name_len = buflen; if( strcmp(tag_name , LOC_LANG_TAG)==0 ){ @@ -674,28 +676,28 @@ static void get_icu_disp_value_src_php( char* tag_name, INTERNAL_FUNCTION_PARAME /* }}} */ /* {{{ gets the name for the $locale in $in_locale or default_locale */ -PHP_FUNCTION(locale_get_display_name) +U_CFUNC PHP_FUNCTION(locale_get_display_name) { get_icu_disp_value_src_php( DISP_NAME , INTERNAL_FUNCTION_PARAM_PASSTHRU ); } /* }}} */ /* {{{ gets the language for the $locale in $in_locale or default_locale */ -PHP_FUNCTION(locale_get_display_language) +U_CFUNC PHP_FUNCTION(locale_get_display_language) { get_icu_disp_value_src_php( LOC_LANG_TAG , INTERNAL_FUNCTION_PARAM_PASSTHRU ); } /* }}} */ /* {{{ gets the script for the $locale in $in_locale or default_locale */ -PHP_FUNCTION(locale_get_display_script) +U_CFUNC PHP_FUNCTION(locale_get_display_script) { get_icu_disp_value_src_php( LOC_SCRIPT_TAG , INTERNAL_FUNCTION_PARAM_PASSTHRU ); } /* }}} */ /* {{{ gets the region for the $locale in $in_locale or default_locale */ -PHP_FUNCTION(locale_get_display_region) +U_CFUNC PHP_FUNCTION(locale_get_display_region) { get_icu_disp_value_src_php( LOC_REGION_TAG , INTERNAL_FUNCTION_PARAM_PASSTHRU ); } @@ -709,7 +711,7 @@ PHP_FUNCTION(locale_get_display_region) * proto static string get_display_variant($locale, $in_locale = null) * gets the variant for the $locale in $in_locale or default_locale */ -PHP_FUNCTION(locale_get_display_variant) +U_CFUNC PHP_FUNCTION(locale_get_display_variant) { get_icu_disp_value_src_php( LOC_VARIANT_TAG , INTERNAL_FUNCTION_PARAM_PASSTHRU ); } @@ -721,7 +723,7 @@ PHP_FUNCTION(locale_get_display_variant) /* {{{ return an associative array containing keyword-value * pairs for this locale. The keys are keys to the array (doh!) */ -PHP_FUNCTION( locale_get_keywords ) +U_CFUNC PHP_FUNCTION( locale_get_keywords ) { UEnumeration* e = NULL; UErrorCode status = U_ZERO_ERROR; @@ -791,7 +793,7 @@ PHP_FUNCTION( locale_get_keywords ) /* {{{ @return string the canonicalized locale * }}} */ /* {{{ @param string $locale The locale string to canonicalize */ -PHP_FUNCTION(locale_canonicalize) +U_CFUNC PHP_FUNCTION(locale_canonicalize) { get_icu_value_src_php( LOC_CANONICALIZE_TAG , INTERNAL_FUNCTION_PARAM_PASSTHRU ); } @@ -936,7 +938,7 @@ static int handleAppendResult( int result, smart_str* loc_name) * }}} */ /* {{{ Creates a locale by combining the parts of locale-ID passed * }}} */ -PHP_FUNCTION(locale_compose) +U_CFUNC PHP_FUNCTION(locale_compose) { smart_str loc_name_s = {0}; smart_str *loc_name = &loc_name_s; @@ -1083,7 +1085,7 @@ static int add_array_entry(const char* loc_name, zval* hash_arr, char* key_name) } /* Over-allocates a few bytes for the integer so we don't have to reallocate. */ size_t cur_key_name_size = (sizeof("-2147483648") - 1) + strlen(key_name) + 1; - cur_key_name = emalloc(cur_key_name_size); + cur_key_name = reinterpret_cast(emalloc(cur_key_name_size)); snprintf( cur_key_name, cur_key_name_size , "%s%d", key_name , cnt++); add_assoc_string( hash_arr, cur_key_name , token); /* tokenize on the "_" or "-" and stop at singleton if any */ @@ -1117,7 +1119,7 @@ static int add_array_entry(const char* loc_name, zval* hash_arr, char* key_name) /* }}} */ /* {{{ parses a locale-id into an array the different parts of it */ -PHP_FUNCTION(locale_parse) +U_CFUNC PHP_FUNCTION(locale_parse) { char* loc_name = NULL; size_t loc_name_len = 0; @@ -1153,7 +1155,7 @@ PHP_FUNCTION(locale_parse) /* }}} */ /* {{{ gets an array containing the list of variants, or null */ -PHP_FUNCTION(locale_get_all_variants) +U_CFUNC PHP_FUNCTION(locale_get_all_variants) { char* loc_name = NULL; size_t loc_name_len = 0; @@ -1237,7 +1239,7 @@ static int strToMatch(const char* str ,char *retstr) /* {{{ Checks if a $langtag filter matches with $locale according to RFC 4647's basic filtering algorithm */ /* }}} */ /* {{{ Checks if a $langtag filter matches with $locale according to RFC 4647's basic filtering algorithm */ -PHP_FUNCTION(locale_filter_matches) +U_CFUNC PHP_FUNCTION(locale_filter_matches) { char* lang_tag = NULL; size_t lang_tag_len = 0; @@ -1296,7 +1298,7 @@ PHP_FUNCTION(locale_filter_matches) } /* Convert to lower case for case-insensitive comparison */ - cur_lang_tag = ecalloc( 1, can_lang_tag->len + 1); + cur_lang_tag = reinterpret_cast(ecalloc( 1, can_lang_tag->len + 1)); /* Convert to lower case for case-insensitive comparison */ result = strToMatch( can_lang_tag->val , cur_lang_tag); @@ -1306,7 +1308,7 @@ PHP_FUNCTION(locale_filter_matches) RETURN_FALSE; } - cur_loc_range = ecalloc( 1, can_loc_range->len + 1); + cur_loc_range = reinterpret_cast(ecalloc( 1, can_loc_range->len + 1)); result = strToMatch( can_loc_range->val , cur_loc_range ); if( result == 0) { efree( cur_lang_tag ); @@ -1353,14 +1355,14 @@ PHP_FUNCTION(locale_filter_matches) } /* end of if isCanonical */ else{ /* Convert to lower case for case-insensitive comparison */ - cur_lang_tag = ecalloc( 1, strlen(lang_tag ) + 1); + cur_lang_tag = reinterpret_cast(ecalloc( 1, strlen(lang_tag ) + 1)); result = strToMatch( lang_tag , cur_lang_tag); if( result == 0) { efree( cur_lang_tag ); RETURN_FALSE; } - cur_loc_range = ecalloc( 1, strlen(loc_range ) + 1); + cur_loc_range = reinterpret_cast(ecalloc( 1, strlen(loc_range ) + 1)); result = strToMatch( loc_range , cur_loc_range ); if( result == 0) { efree( cur_lang_tag ); @@ -1425,7 +1427,7 @@ static zend_string* lookup_loc_range(const char* loc_range, HashTable* hash_arr, zend_string* return_value = NULL; - char **cur_arr = ecalloc(zend_hash_num_elements(hash_arr)*2, sizeof(char *)); + char **cur_arr = reinterpret_cast(ecalloc(zend_hash_num_elements(hash_arr)*2, sizeof(char *))); ZEND_HASH_FOREACH_VAL(hash_arr, ele_value) { ZVAL_DEREF(ele_value); /* convert the array to lowercase , also replace hyphens with the underscore and store it in cur_arr */ @@ -1459,7 +1461,7 @@ static zend_string* lookup_loc_range(const char* loc_range, HashTable* hash_arr, intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "lookup_loc_range: unable to canonicalize lang_tag" , 0); LOOKUP_CLEAN_RETURN(NULL); } - cur_arr[i*2] = erealloc(cur_arr[i*2], lang_tag->len+1); + cur_arr[i*2] = reinterpret_cast(erealloc(cur_arr[i*2], lang_tag->len+1)); result = strToMatch(lang_tag->val, cur_arr[i*2]); zend_string_release_ex(lang_tag, 0); if(result == 0) { @@ -1485,7 +1487,7 @@ static zend_string* lookup_loc_range(const char* loc_range, HashTable* hash_arr, } } - cur_loc_range = ecalloc(1, strlen(loc_range)+1); + cur_loc_range = reinterpret_cast(ecalloc(1, strlen(loc_range)+1)); /* convert to lower and replace hyphens */ result = strToMatch(loc_range, cur_loc_range); if(can_loc_range) { @@ -1525,7 +1527,7 @@ static zend_string* lookup_loc_range(const char* loc_range, HashTable* hash_arr, /* {{{ Searches the items in $langtag for the best match to the language * range */ -PHP_FUNCTION(locale_lookup) +U_CFUNC PHP_FUNCTION(locale_lookup) { zend_string* fallback_loc_str = NULL; char* loc_range = NULL; @@ -1580,12 +1582,12 @@ PHP_FUNCTION(locale_lookup) /* {{{ Tries to find out best available locale based on HTTP "Accept-Language" header */ /* }}} */ /* {{{ Tries to find out best available locale based on HTTP "Accept-Language" header */ -PHP_FUNCTION(locale_accept_from_http) +U_CFUNC PHP_FUNCTION(locale_accept_from_http) { UEnumeration *available; char *http_accept = NULL; size_t http_accept_len; - UErrorCode status = 0; + UErrorCode status = U_ZERO_ERROR; int len; char resultLocale[INTL_MAX_LOCALE_LEN+1]; UAcceptResult outResult; @@ -1625,7 +1627,7 @@ PHP_FUNCTION(locale_accept_from_http) } /* }}} */ -PHP_FUNCTION(locale_is_right_to_left) +U_CFUNC PHP_FUNCTION(locale_is_right_to_left) { char *locale; size_t locale_len; @@ -1641,10 +1643,10 @@ PHP_FUNCTION(locale_is_right_to_left) RETURN_BOOL(uloc_isRightToLeft(locale)); } -PHP_FUNCTION(locale_add_likely_subtags) +U_CFUNC PHP_FUNCTION(locale_add_likely_subtags) { char *locale, maximized_locale[ULOC_FULLNAME_CAPACITY]; - UErrorCode status = 0; + UErrorCode status = U_ZERO_ERROR; size_t locale_len; ZEND_PARSE_PARAMETERS_START(1, 1) @@ -1664,10 +1666,10 @@ PHP_FUNCTION(locale_add_likely_subtags) RETURN_STRINGL(maximized_locale, maximized_locale_len); } -PHP_FUNCTION(locale_minimize_subtags) +U_CFUNC PHP_FUNCTION(locale_minimize_subtags) { char *locale, minimized_locale[ULOC_FULLNAME_CAPACITY]; - UErrorCode status = 0; + UErrorCode status = U_ZERO_ERROR; size_t locale_len; ZEND_PARSE_PARAMETERS_START(1, 1) diff --git a/ext/intl/uchar/uchar.c b/ext/intl/uchar/uchar.cpp similarity index 98% rename from ext/intl/uchar/uchar.c rename to ext/intl/uchar/uchar.cpp index ecfcd8fbe624a..88cab368b69ab 100644 --- a/ext/intl/uchar/uchar.c +++ b/ext/intl/uchar/uchar.cpp @@ -1,3 +1,4 @@ +extern "C" { #include "uchar.h" #include "intl_data.h" #include "intl_convert.h" @@ -6,6 +7,7 @@ #include #include "uchar_arginfo.h" +} #define IC_METHOD(mname) PHP_METHOD(IntlChar, mname) @@ -314,7 +316,7 @@ IC_METHOD(enumCharNames) { RETURN_FALSE; } - u_enumCharNames(start, limit, (UEnumCharNamesFn*)enumCharNames_callback, &context, nameChoice, &error); + u_enumCharNames(start, limit, (UEnumCharNamesFn*)enumCharNames_callback, &context, static_cast(nameChoice), &error); INTL_CHECK_STATUS(error, NULL); RETURN_TRUE; } @@ -515,7 +517,7 @@ IC_METHOD(getFC_NFKC_Closure) { if (closure_len == 0) { RETURN_EMPTY_STRING(); } - closure = safe_emalloc(sizeof(UChar), closure_len + 1, 0); + closure = reinterpret_cast(safe_emalloc(sizeof(UChar), closure_len + 1, 0)); error = U_ZERO_ERROR; closure_len = u_getFC_NFKC_Closure(cp, closure, closure_len, &error); if (U_FAILURE(error)) { From c9e91bfbab77dbfcdc718e526c67d3e885e7789d Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Fri, 4 Jul 2025 11:29:11 +0100 Subject: [PATCH 2/4] Zend/zend_exceptions: Add const modifiers --- Zend/zend_exceptions.c | 8 ++++---- Zend/zend_exceptions.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Zend/zend_exceptions.c b/Zend/zend_exceptions.c index 99c4a48a9482f..e95fa4d62df55 100644 --- a/Zend/zend_exceptions.c +++ b/Zend/zend_exceptions.c @@ -67,7 +67,7 @@ static int zend_implement_throwable(zend_class_entry *interface, zend_class_entr { /* zend_ce_exception and zend_ce_error may not be initialized yet when this is called (e.g when * implementing Throwable for Exception itself). Perform a manual inheritance check. */ - zend_class_entry *root = class_type; + const zend_class_entry *root = class_type; while (root->parent) { root = root->parent; } @@ -89,13 +89,13 @@ static int zend_implement_throwable(zend_class_entry *interface, zend_class_entr } /* }}} */ -static inline zend_class_entry *i_get_exception_base(zend_object *object) /* {{{ */ +static inline zend_class_entry *i_get_exception_base(const zend_object *object) /* {{{ */ { return instanceof_function(object->ce, zend_ce_exception) ? zend_ce_exception : zend_ce_error; } /* }}} */ -ZEND_API zend_class_entry *zend_get_exception_base(zend_object *object) /* {{{ */ +ZEND_API zend_class_entry *zend_get_exception_base(const zend_object *object) /* {{{ */ { return i_get_exception_base(object); } @@ -192,7 +192,7 @@ ZEND_API ZEND_COLD void zend_throw_exception_internal(zend_object *exception) /* #endif /* HAVE_DTRACE */ if (exception != NULL) { - zend_object *previous = EG(exception); + const zend_object *previous = EG(exception); if (previous && zend_is_unwind_exit(previous)) { /* Don't replace unwinding exception with different exception. */ OBJ_RELEASE(exception); diff --git a/Zend/zend_exceptions.h b/Zend/zend_exceptions.h index 5df49dcd6a3a6..24d9f4efd80a3 100644 --- a/Zend/zend_exceptions.h +++ b/Zend/zend_exceptions.h @@ -48,7 +48,7 @@ ZEND_API ZEND_COLD void zend_throw_exception_internal(zend_object *exception); void zend_register_default_exception(void); -ZEND_API zend_class_entry *zend_get_exception_base(zend_object *object); +ZEND_API zend_class_entry *zend_get_exception_base(const zend_object *object); ZEND_API void zend_register_default_classes(void); From a95a81000ddfff5c8090c07fb6983a30b47c8273 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Thu, 3 Jul 2025 17:11:14 +0100 Subject: [PATCH 3/4] Zend: Exception::__toString() no need to allocate the method name We can create the FCI/FCC pair ourself outside of the loop as the method getTraceAsString is final Co-authored-by: Niels Dossche <7771979+nielsdos@users.noreply.github.com> --- Zend/zend_exceptions.c | 44 +++++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/Zend/zend_exceptions.c b/Zend/zend_exceptions.c index e95fa4d62df55..0b0945aac0f44 100644 --- a/Zend/zend_exceptions.c +++ b/Zend/zend_exceptions.c @@ -695,16 +695,33 @@ ZEND_METHOD(Exception, __toString) zval trace, *exception; zend_class_entry *base_ce; zend_string *str; - zend_fcall_info fci; zval rv, tmp; - zend_string *fname; ZEND_PARSE_PARAMETERS_NONE(); str = ZSTR_EMPTY_ALLOC(); exception = ZEND_THIS; - fname = ZSTR_INIT_LITERAL("gettraceasstring", 0); + base_ce = i_get_exception_base(Z_OBJ_P(exception)); + + /* As getTraceAsString method is final we can grab it once */ + zend_function *getTraceAsString = zend_hash_str_find_ptr(&base_ce->function_table, ZEND_STRL("gettraceasstring")); + ZEND_ASSERT(getTraceAsString && "Method getTraceAsString must exist"); + + + zend_fcall_info fci; + fci.size = sizeof(fci); + ZVAL_UNDEF(&fci.function_name); + fci.retval = &trace; + fci.param_count = 0; + fci.params = NULL; + fci.object = NULL; + fci.named_params = NULL; + + zend_fcall_info_cache fcc; + fcc.function_handler = getTraceAsString; + fcc.called_scope = base_ce; + fcc.closure = NULL; while (exception && Z_TYPE_P(exception) == IS_OBJECT && instanceof_function(Z_OBJCE_P(exception), zend_ce_throwable)) { zend_string *prev_str = str; @@ -712,15 +729,9 @@ ZEND_METHOD(Exception, __toString) zend_string *file = zval_get_string(GET_PROPERTY(exception, ZEND_STR_FILE)); zend_long line = zval_get_long(GET_PROPERTY(exception, ZEND_STR_LINE)); - fci.size = sizeof(fci); - ZVAL_STR(&fci.function_name, fname); - fci.object = Z_OBJ_P(exception); - fci.retval = &trace; - fci.param_count = 0; - fci.params = NULL; - fci.named_params = NULL; - - zend_call_function(&fci, NULL); + fcc.object = Z_OBJ_P(exception); + fcc.calling_scope = Z_OBJCE_P(exception); + zend_call_function(&fci, &fcc); if (Z_TYPE(trace) != IS_STRING) { zval_ptr_dtor(&trace); @@ -765,11 +776,11 @@ ZEND_METHOD(Exception, __toString) break; } } - zend_string_release_ex(fname, 0); exception = ZEND_THIS; /* Reset apply counts */ - while (Z_TYPE_P(exception) == IS_OBJECT && (base_ce = i_get_exception_base(Z_OBJ_P(exception))) && instanceof_function(Z_OBJCE_P(exception), base_ce)) { + zend_class_entry *previous_base_ce; + while (Z_TYPE_P(exception) == IS_OBJECT && (previous_base_ce = i_get_exception_base(Z_OBJ_P(exception))) && instanceof_function(Z_OBJCE_P(exception), previous_base_ce)) { if (Z_IS_RECURSIVE_P(exception)) { Z_UNPROTECT_RECURSION_P(exception); } else { @@ -779,13 +790,10 @@ ZEND_METHOD(Exception, __toString) ZVAL_DEREF(exception); } - exception = ZEND_THIS; - base_ce = i_get_exception_base(Z_OBJ_P(exception)); - /* We store the result in the private property string so we can access * the result in uncaught exception handlers without memleaks. */ ZVAL_STR(&tmp, str); - zend_update_property_ex(base_ce, Z_OBJ_P(exception), ZSTR_KNOWN(ZEND_STR_STRING), &tmp); + zend_update_property_ex(base_ce, Z_OBJ_P(ZEND_THIS), ZSTR_KNOWN(ZEND_STR_STRING), &tmp); RETURN_STR(str); } From c1b129bd182991515c78835249c1514b480cfbea Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Tue, 29 Jul 2025 13:59:19 -0700 Subject: [PATCH 4/4] [ci skip] Update NEWS for PHP 8.5.0 beta1 --- NEWS | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 28963162e7c55..61c39295db5bd 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? ????, PHP 8.5.0alpha3 +?? ??? ????, PHP 8.5.0beta1 + + +31 Jul 2025, PHP 8.5.0alpha3 - Core: . Add clone-with support to the clone() function. (timwolla, edorian)