PHP 8.6 INTERNALS UPGRADE NOTES 1. Internal API changes 2. Build system changes 3. Module changes 4. OpCode changes 5. SAPI changes ======================== 1. Internal API changes ======================== - Breaking changes: . String formatting functions now support the custom conversion specifiers 'pS' (zend_string*) and 'pp' (same as 'p'). Following the 'p' specifier with an alpha-numeric character other than 'S' or 'p' is now an error. Examples: zend_string *str; zend_spprintf("%pS", str); // valid, same as "%S" zend_spprintf("%pp", str); // valid, same as "%p" zend_spprintf("%pA", str); // invalid zend_spprintf("%ppA", str); // valid, same as zend_spprintf("%p%c", str, 'A') - Removed: . The misnamed ZVAL_IS_NULL() has been removed. Use Z_ISNULL() instead. . The zval_is_true() alias of zend_is_true() has been removed. Call zend_is_true() directly instead. . The _zval_get_*() compatibility macros for PHP 7.2 have been removed call the variant without the leading underscore instead. Affected: _zval_get_long, _zval_get_double, _zval_get_string, _zval_get_long_func, _zval_get_double_func, _zval_get_string_func . CHECK_ZVAL_NULL_PATH() and CHECK_NULL_PATH() have been removed, use zend_str_has_nul_byte(Z_STR_P(...)) and zend_char_has_nul_byte() respectively. . ZEND_LTOA() (and ZEND_LTOA_BUF_LEN) has been removed, as it was unsafe. Directly use ZEND_LONG_FMT with a function from the printf family. . The zval_dtor() alias of zval_ptr_dtor_nogc() has been removed. Call zval_ptr_dtor_nogc() directly instead. . The internal zend_copy_parameters_array() function is no longer exposed. . The internal zend_hash_minmax() function is no longer exposed. Scan the HashTable directly and use zend_compare() for value comparisons instead. . The zend_make_callable() function has been removed, if a callable zval needs to be obtained use the zend_get_callable_zval_from_fcc() function instead. If this was used to store a callable, then an FCC should be stored instead. . The zend_exception_save() and zend_exception_restore() functions were removed. . The zend_set_hash_symbol() API has been removed. . The WRONG_PARAM_COUNT and ZEND_WRONG_PARAM_COUNT() macros have been removed. Call zend_wrong_param_count(); followed by RETURN_THROWS(); instead. . PHP_HAVE_STREAMS macro removed from . . The INI_STR(), INI_INT(), INI_FLT(), and INI_BOOL() macros have been removed. Instead new zend_ini_{bool|long|double|str|string}_literal() macros have been added. This fixes an internal naming inconsistency as "str" usually means zend_string*, and "string" means char*. However INI_STR() returned a char* . The INI_ORIG_{INT|STR|FLT|BOOL}() macros have been removed as they are unused. If this behaviour is required fall back to the zend_ini_* functions. . The unused ZEND_AST_PARENT_PROPERTY_HOOK_CALL has been removed. . The EMPTY_SWITCH_DEFAULT_CASE() macro has been removed. Use default: ZEND_UNREACHABLE(); instead. . The ZEND_RESULT_CODE type has been removed. Use zend_result directly. . The zend_parse_parameters_none_throw(), zend_parse_parameters_throw(), and ZEND_PARSE_PARAMS_THROW have been removed due to being misleading, since ZPP always throws, unless ZEND_PARSE_PARAMS_QUIET is given. Use the non-throw versions. . The XtOffsetOf() alias of C’s offsetof() macro has been removed. Use offsetof() directly. . The deprecated Z_COPYABLE(), Z_COPYABLE_P(), Z_OPT_COPYABLE(), and Z_OPT_COPYABLE_P() macros have been removed. Check for IS_ARRAY directly. . The deprecated Z_IMMUTABLE(), Z_IMMUTABLE_P(), Z_OPT_IMMUTABLE(), and Z_OPT_IMMUTABLE_P() macros have been removed. Check for IS_ARRAY && !REFCOUNTED directly. . The unused Z_GC_*() macros have been removed. Use the corresponding GC_*() macro on the result of Z_COUNTED(). . The zend_binary_zval_strcmp() and zend_binary_zval_strncmp() functions have been removed, because they are unsafe by relying on the zvals having a specific type. Use zend_binary_strcmp() / zend_binary_strncmp(), string_compare_function() or similar instead. . The OPENBASEDIR_CHECKPATH() compatibility macro has been removed, instead use php_check_open_basedir() directly. . The Z_CONSTANT(), Z_CONSTANT_P(), Z_OPT_CONSTANT(), and Z_OPT_CONSTANT_P() macros have been removed. Check for IS_CONSTANT_AST directly. . The {_}php_stream_fopen_with_path() functions have been removed as they are unused. . The php_error_docref1() and php_error_docref2() functions have been removed, instead rely on the error_include_args INI option to show the arguments to functions in a consistent manner. . The following PHP stream functions prefixed with _ have been removed, and the macro without it has become the canonical function name: * _php_stream_cast() * _php_stream_free_enclosed() * _php_stream_free() * _php_stream_seek() * _php_stream_tell() * _php_stream_read() * _php_stream_write() * _php_stream_fill_read_buffer() * _php_stream_printf() * _php_stream_eof() * _php_stream_getc() * _php_stream_putc() * _php_stream_flush() * _php_stream_sync() * _php_stream_get_line() * _php_stream_puts() * _php_stream_stat() * _php_stream_mkdir() * _php_stream_rmdir() * _php_stream_readdir() * _php_stream_set_option() * _php_stream_get_url_stream_wrappers_hash() * _php_get_stream_filters_hash() * _php_stream_mmap_unmap() * _php_stream_mmap_unmap_ex() * _php_stream_filter_prepend() * _php_stream_filter_append() * _php_stream_filter_flush() . The PHP stream function _php_stream_stat_path() has been renamed to php_stream_stat_path_ex() . The PHP stream function _php_stream_scandir() was removed, insted the PHP macro php_stream_scandir() is now a function as the flags parameter was never used. . The PHP stream function _php_stream_flush() was removed, instead the PHP macro php_stream_flush() is now a proper function. . The zend_save_error_handling() function was removed. . The zend_parse_parameter() function has been removed, use one fo the zend_parse_arg_TYPE() APIs instead. - Changed: . Internal functions that return by reference are now expected to automatically unwrap references when the result of the call is stored in an IS_TMP_VAR variable. This may be achieved by calling the zend_return_unwrap_ref() function. . ZEND_AST_METHOD_REFERENCE has been renamed to ZEND_AST_TRAIT_METHOD_REFERENCE. . Functions using zend_forbid_dynamic_call() *must* be flagged with ZEND_ACC2_FORBID_DYN_CALLS (@forbid-dynamic-calls in stubs). In debug builds, failing to include that flag will lead to assertion failures. . The zend_get_call_trampoline_func() API now takes the __call or __callStatic zend_function* instead of a CE and a boolean argument. . ZSTR_INIT_LITERAL(), zend_string_starts_with_literal(), and zend_string_starts_with_literal_ci() now support strings containing NUL bytes. Passing non-literal char* is no longer supported. . The zend_active_function{_ex}() functions now return a const zend_function pointer. . zend_function.arg_info is now always a zend_arg_info*. Before, it was a zend_internal_arg_info on internal functions, unless the ZEND_ACC_USER_ARG_INFO flag was set. . ZEND_INI_GET_ADDR() is now a void* pointer instead of a char* pointer. This more correctly represents the generic nature of the returned pointer and allows to remove explicit casts, but possibly breaks pointer arithmetic performed on the result. . The zend_dval_to_lval_cap() function no longer takes a second zend_string* parameter. . EG(in_autoload) was renamed to EG(autoload_current_classnames) and no longer is a pointer, but a directly embedded HashTable struct. . Extended php_stream_filter_ops with seek method. . php_print_info_htmlhead() now takes a title argument. . zend_argument_error_variadic() now takes a new 'function' parameter. . The param argument in the php_verror() function has been removed. . The php_stream_wrapper_log_error() signature changed from (wrapper, options, fmt, ...) to (wrapper, context, options, severity, terminating, code, fmt, ...). To keep the previous behaviour pass NULL for the context, or the context at hand if there is one, E_WARNING for the severity, and ZEND_ENUM_StreamErrorCode_Generic for the code. terminating should be true only if the error aborts the operation. - Added: . New zend_class_entry.ce_flags2 and zend_function.fn_flags2 fields were added, given the primary flags were running out of bits. . Added zend_hash_str_lookup(). . Added zend_ast_call_get_args() to fetch the argument node from any call node. . Added Z_PARAM_ENUM(). . Added zend_enum_fetch_case_id(). . Added zend_enum_get_case_by_id(). . Added zend_bin2hex() and zend_bin2hex_str() as helper functions to remove dependencies on /ext/hash in various extensions. . Added a C23_ENUM() helper macro to define forward-compatible fixed-size enums. . Added zend_fcall_info.consumed_args together with zend_fci_consumed_arg(), which allows moving a selected callback argument instead of copying it in zend_call_function(). Currently only a single consumed argument is supported. . Added ZEND_CONTAINER_OF(). . Added zend_reflection_property_set_raw_value_without_lazy_initialization(), zend_reflection_property_set_raw_value() to expose the functionality of ReflectionProperty::setRawValueWithoutLazyInitialization() and ReflectionProperty::setRawValue() to C extensions. . Added zend_object_set_properties_reinitable() to centralise temporarily allowing reinitialisation of initialised readonly properties during controlled operations such as cloning and unserialisation. . Added zend_argument_error_ex(), zend_argument_type_error_ex(), zend_argument_value_error_ex(). . Added zend_ast_dup(). . Added zend_compile_ast(). . Added zend_check_type_ex(). . Added zend_create_partial_closure(). . Added a new IO copy API in . php_io_copy() copies bytes between file descriptors using the most efficient platform primitive available (sendfile, splice, copy_file_range, TransmitFile), and is now used by php_stream_copy_to_stream_ex(). The mmap-based copy fallback was removed. . Added zend_string_equals_cstr_ci(). . Added zend_cstr_append_char(), zend_cstr_concat(), and zend_cstr_concat3() as helper functions to allocate NUL-terminated raw C strings from one or more buffers. . Added zend_string_ends_with() and related variants. . Added trait support for internal classes. . Added do_php_cli(). ======================== 2. Build system changes ======================== - Abstract: . run-tests.php now runs in parallel by default, using up to 10 automatically detected workers. Pass -j1 for sequential execution. --asan, --msan, and Valgrind default to at most two workers. . Minimum required PHP version found on the host system for running scripts like build/gen_stub.php during development has been updated from 7.4 to 8.1. . build/gen_stub.php may now generate a _decl.h file in addition to the _arginfo.h file, if the stub declares enums and is annotated with @generate-c-enums. For each enum the file will contain a C enum. Enum values can be compared to the result of zend_enum_fetch_case_id(zend_object*). - Unix build system changes: . scripts/dev/update-autoconf.sh has been added to update config.*/libtool. . libtool has been upgraded to 2.5.4 (serial 63), which fixes many bugs. . As part of the upgrade to the new libtool: . libtool is now spread across multiple files. phpize has been updated to handle this. . On macOS, libtool now uses -undefined dynamic_lookup for shared objects, instead of -undefined suppress -flat_namespace. . --with-pic is now --enable-pic. The old flag will result in an error. . Symbol HAVE_ST_BLOCKS has been removed from php_config.h (use HAVE_STRUCT_STAT_ST_BLOCKS). . Added a new configure option --disable-apache2-conf to prevent apxs from editing httpd.conf during installation. - Windows build system changes: . Function SETUP_OPENSSL() doesn't accept 6th argument anymore and doesn't define the HAVE_OPENSSL_SSL_H preprocessor macro anymore. . Function SETUP_SQLITE3() doesn't define HAVE_SQLITE3_H and HAVE_SQLITE3EXT_H preprocessor macros anymore. . Added a new function CHECK_HEADER() which is intended to be used instead of the CHECK_HEADER_ADD_INCLUDE(). - Embed: . The CLI SAPI can not be disabled when building the embed SAPI (--enable-embed is incompatible with --disable-cli). ======================== 3. Module changes ======================== - ext/date: . php_idate() now returns the result state, and moves the return value into an out parameter. - ext/intl: . Added intl_icu_compat.h with helpers and feature macros for ICU version-specific API differences. Code in ext/intl should use the intl_icu_compat_* helpers and INTL_ICU_HAS_* macros instead of adding direct U_ICU_VERSION_* guards for supported ICU API variants. . The internal grapheme_get_break_iterator() helper no longer accepts a stack buffer argument; pass only the UErrorCode* status argument. . Added PHP_INTL_FUNCTION_WITH_ERROR_RESET() for procedural functions that reset the global error. Use it instead of PHP_FUNCTION() followed by a manual intl_error_reset(NULL) call. . IC_METHOD() now resets the global error before entering the method implementation. IntlChar methods should no longer reset it manually. - ext/mbstring: . Added GB18030-2022 to default encoding list for zh-CN. - ext/mysqlnd: . Dropped session_options parameter from all methods in mysqlnd_auth. The same information is present in conn->options and should be used instead. . Removed charsets plugin. - ext/session: . php_session_flush() now returns a bool rather than a zend_result. . The mod_user_names global has been removed. . The mod_user_uses_object_methods_as_handlers global has been added, it indicates whether the session handlers are methods of an object or not. . Removed session_adapt_url(). . PS_OPEN_ARGS is now defined as `void **mod_data, zend_string *save_path, zend_string *session_name` rather than `void **mod_data, const char *save_path, const char *session_name` . PS_FUNCS() now includes the PS_VALIDATE_SID_FUNC() . PS_MOD() now requires that the PS_CREATE_SID_FUNC() and PS_VALIDATE_SID_FUNC() functions are defined. . PS_FUNCS_SID() and PS_MOD_SID() have been removed. Either use PS_FUNCS()/PS_MOD() or PS_FUNCS_UPDATE_TIMESTAMP()/ PS_MOD_UPDATE_TIMESTAMP() if timestamp support exists. - ext/standard: . _php_error_log() now has a formal return type of zend_result. . _php_error_log() now accepts zend_string* values instead of char*. . _php_error_log_ex() has been removed. . php_mail()'s extra_cmd parameter is now a zend_string*. . The php_math_round_mode_from_enum() function now takes a zend_enum_RoundingMode parameter. - ext/uri: . The value parameter of the php_uri_property_handler_write callback is now const zval * instead of zval *, reflecting that write handlers must not modify the input zval. - ext/xml: . Removed the XML_ExpatVersion() libxml compatibility wrapper, as it was unused. . Removed the XML_GetCurrentByteCount() libxml compatibility wrapper, as it was unused and could return the wrong result. ======================== 4. OpCode changes ======================== - Added ZEND_TYPE_ASSERT to check a value's type against the parameter type of a function, throwing a TypeError on failure as if the function was called. Used in optimizations that elide function calls. ======================== 5. SAPI changes ======================== - SAPIs should explicitly release a thread's resources by calling ts_free_thread() before terminating it. tsrm_shutdown() can only release the resources of the calling thread, for resources allocated with ts_allocate_tls_id(). - AG and SCNG are now allocated with ts_allocate_tls_id() and live in native __thread storage on ZTS builds. - php-cli functionality is now available in embed builds via the do_php_cli() function.