diff '--color=auto' -Naur php-8.4.18/build/gen_stub.php php-8.4.20RC1/build/gen_stub.php
--- php-8.4.18/build/gen_stub.php	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/build/gen_stub.php	2026-04-01 04:35:35.991525982 +0000
@@ -84,7 +84,7 @@
         }
 
         /* Because exit() and die() are proper token/keywords we need to hack-around */
-        $hasSpecialExitAsFunctionHandling = str_ends_with($stubFile, 'zend_builtin_functions.stub.php');
+        $hasSpecialExitAsFunctionHandling = basename($stubFile) == 'zend_builtin_functions.stub.php';
         if (!$fileInfo = $context->parsedFiles[$stubFile] ?? null) {
             initPhpParser();
             $stubContent = $stubCode ?? file_get_contents($stubFile);
diff '--color=auto' -Naur php-8.4.18/.circleci/config.yml php-8.4.20RC1/.circleci/config.yml
--- php-8.4.18/.circleci/config.yml	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/.circleci/config.yml	2026-04-01 04:35:35.979935853 +0000
@@ -5,7 +5,7 @@
     resource_class: arm.medium
     docker:
       - image: cimg/base:current-22.04
-      - image: mysql:8.3
+      - image: mysql:8.4
         environment:
           MYSQL_ALLOW_EMPTY_PASSWORD: true
           MYSQL_ROOT_PASSWORD: ''
@@ -167,6 +167,7 @@
           name: Test
           no_output_timeout: 30m
           command: |
+            export RUN_RESOURCE_HEAVY_TESTS=1
             sapi/cli/php run-tests.php \
               -d zend_extension=opcache.so \
               -d opcache.enable_cli=1 \
diff '--color=auto' -Naur php-8.4.18/configure.ac php-8.4.20RC1/configure.ac
--- php-8.4.18/configure.ac	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/configure.ac	2026-04-01 04:39:06.630074157 +0000
@@ -17,7 +17,7 @@
 dnl ----------------------------------------------------------------------------
 
 AC_PREREQ([2.68])
-AC_INIT([PHP],[8.4.18],[https://github.com/php/php-src/issues],[php],[https://www.php.net])
+AC_INIT([PHP],[8.4.20RC1],[https://github.com/php/php-src/issues],[php],[https://www.php.net])
 AC_CONFIG_SRCDIR([main/php_version.h])
 AC_CONFIG_AUX_DIR([build])
 AC_PRESERVE_HELP_ORDER
diff '--color=auto' -Naur php-8.4.18/configure.ac.orig php-8.4.20RC1/configure.ac.orig
--- php-8.4.18/configure.ac.orig	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/configure.ac.orig	2026-02-10 17:48:03.000000000 +0000
@@ -0,0 +1,1836 @@
+dnl Process this file with autoconf to produce a configure script.
+
+dnl Include external macro definitions before the AC_INIT to also remove
+dnl comments starting with # and empty newlines from the included files.
+dnl ----------------------------------------------------------------------------
+m4_include([build/ax_check_compile_flag.m4])
+m4_include([build/ax_func_which_gethostbyname_r.m4])
+m4_include([build/ax_gcc_func_attribute.m4])
+m4_include([build/libtool.m4])
+m4_include([build/php_cxx_compile_stdcxx.m4])
+m4_include([build/php.m4])
+m4_include([build/pkg.m4])
+m4_include([TSRM/threads.m4])
+m4_include([Zend/Zend.m4])
+
+dnl Basic autoconf initialization, generation of config.nice.
+dnl ----------------------------------------------------------------------------
+
+AC_PREREQ([2.68])
+AC_INIT([PHP],[8.4.18],[https://github.com/php/php-src/issues],[php],[https://www.php.net])
+AC_CONFIG_SRCDIR([main/php_version.h])
+AC_CONFIG_AUX_DIR([build])
+AC_PRESERVE_HELP_ORDER
+
+PHP_CONFIG_NICE([config.nice])
+
+PHP_CANONICAL_HOST_TARGET
+
+AC_CONFIG_HEADERS([main/php_config.h])
+
+AH_TOP([
+#ifndef PHP_CONFIG_H
+#define PHP_CONFIG_H
+
+#if defined(__GNUC__) && __GNUC__ >= 4
+# define ZEND_API __attribute__ ((visibility("default")))
+# define ZEND_DLEXPORT __attribute__ ((visibility("default")))
+#else
+# define ZEND_API
+# define ZEND_DLEXPORT
+#endif
+
+#define ZEND_DLIMPORT
+])
+AH_BOTTOM([
+#include <stdlib.h>
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+
+#include <string.h>
+
+#endif /* PHP_CONFIG_H */
+])
+
+ac_IFS=$IFS; IFS="."
+set $(echo AC_PACKAGE_VERSION | "${SED}" 's/\([[0-9\.]]*\)\(.*\)/\1\.\2/')
+IFS=$ac_IFS
+PHP_MAJOR_VERSION=[$]1
+PHP_MINOR_VERSION=[$]2
+PHP_RELEASE_VERSION=[$]3
+dnl Allow overriding PHP_EXTRA_VERSION through the homonymous env var
+AC_ARG_VAR([PHP_EXTRA_VERSION],
+  [Extra PHP version label suffix, e.g. '-dev', 'rc1', '-acme'])dnl
+AS_VAR_IF([PHP_EXTRA_VERSION],, [PHP_EXTRA_VERSION=[$]4])
+PHP_VERSION="$PHP_MAJOR_VERSION.$PHP_MINOR_VERSION.$PHP_RELEASE_VERSION$PHP_EXTRA_VERSION"
+PHP_VERSION_ID=$(expr [$]PHP_MAJOR_VERSION \* 10000 + [$]PHP_MINOR_VERSION \* 100 + [$]PHP_RELEASE_VERSION)
+
+dnl Allow version values to be used in Makefile.
+PHP_SUBST([PHP_MAJOR_VERSION])
+PHP_SUBST([PHP_MINOR_VERSION])
+PHP_SUBST([PHP_RELEASE_VERSION])
+PHP_SUBST([PHP_EXTRA_VERSION])
+
+dnl Setting up the PHP version based on the information above.
+dnl ----------------------------------------------------------------------------
+
+echo "/* automatically generated by configure */" > php_version.h.new
+echo "/* edit configure.ac to change version number */" >> php_version.h.new
+echo "#define PHP_MAJOR_VERSION $PHP_MAJOR_VERSION" >> php_version.h.new
+echo "#define PHP_MINOR_VERSION $PHP_MINOR_VERSION" >> php_version.h.new
+echo "#define PHP_RELEASE_VERSION $PHP_RELEASE_VERSION" >> php_version.h.new
+echo "#define PHP_EXTRA_VERSION \"$PHP_EXTRA_VERSION\"" >> php_version.h.new
+echo "#define PHP_VERSION \"$PHP_VERSION\"" >> php_version.h.new
+echo "#define PHP_VERSION_ID $PHP_VERSION_ID" >> php_version.h.new
+cmp php_version.h.new $srcdir/main/php_version.h >/dev/null 2>&1
+if test $? -ne 0 ; then
+  rm -f $srcdir/main/php_version.h && mv php_version.h.new $srcdir/main/php_version.h && \
+  echo 'Updated main/php_version.h'
+else
+  rm -f php_version.h.new
+fi
+
+dnl Settings we want to make before the checks.
+dnl ----------------------------------------------------------------------------
+
+PHP_INIT_BUILD_SYSTEM
+
+dnl Because 'make install' is often performed by the superuser, we create the
+dnl libs subdirectory as the user who configures PHP. Otherwise, the current
+dnl user will not be able to delete libs or the contents of libs.
+
+$php_shtool mkdir -p libs
+rm -f libs/*
+
+dnl Checks for programs.
+dnl ----------------------------------------------------------------------------
+
+PKG_PROG_PKG_CONFIG
+AC_PROG_CC([cc gcc])
+PHP_DETECT_ICC
+PHP_DETECT_SUNCC
+
+dnl AC_PROG_CC_C99 is obsolete with autoconf >= 2.70 yet necessary for <= 2.69.
+m4_version_prereq([2.70],,[AC_PROG_CC_C99])
+AC_PROG_CPP
+AC_USE_SYSTEM_EXTENSIONS
+AC_PROG_LN_S
+
+AS_VAR_IF([cross_compiling], [yes],
+  [AC_CHECK_PROGS([BUILD_CC], [gcc clang c99 c89 cc cl], [none])
+    AC_MSG_CHECKING([for native build C compiler])
+    AC_MSG_RESULT([$BUILD_CC])],
+  [BUILD_CC=$CC])
+
+dnl Support systems with system libraries in e.g. /usr/lib64.
+PHP_ARG_WITH([libdir],
+  [for system library directory],
+  [AS_HELP_STRING([--with-libdir=NAME],
+    [Look for libraries in .../NAME rather than .../lib])],
+  [lib],
+  [no])
+
+PHP_ARG_ENABLE([rpath],
+  [whether to enable runpaths],
+  [AS_HELP_STRING([--disable-rpath],
+    [Disable passing additional runtime library search paths])],
+  [yes],
+  [no])
+
+dnl Check for -R, etc. switch.
+PHP_RUNPATH_SWITCH
+
+dnl Checks for some support/generator progs.
+PHP_PROG_BISON([3.0.0])
+PHP_PROG_RE2C([1.0.3], [--no-generation-date])
+dnl Find installed PHP. Minimum supported version for gen_stub.php is PHP 7.4.
+PHP_PROG_PHP([7.4])
+
+PHP_ARG_ENABLE([re2c-cgoto],
+  [whether to enable computed goto extension with re2c],
+  [AS_HELP_STRING([--enable-re2c-cgoto],
+    [Enable re2c -g flag to optimize conditional jumps using computed goto
+    extension, if supported by the compiler])],
+  [no],
+  [no])
+
+AS_VAR_IF([PHP_RE2C_CGOTO], [no],,
+[AC_CACHE_CHECK([whether re2c -g works], [php_cv_have_re2c_cgoto],
+  [AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
+int main(void)
+{
+label1:
+  ;
+label2:
+  ;
+  static void *adr[] = { &&label1, &&label2 };
+  goto *adr[0];
+  return 0;
+}]])],
+  [php_cv_have_re2c_cgoto=yes],
+  [php_cv_have_re2c_cgoto=no])])
+AS_VAR_IF([php_cv_have_re2c_cgoto], [yes],
+  [AS_VAR_APPEND([RE2C_FLAGS], [" -g"])])
+])
+
+dnl Platform-specific compile settings.
+dnl ----------------------------------------------------------------------------
+
+dnl See bug #28605
+case $host_cpu in
+  alpha*)
+    if test "$GCC" = "yes"; then
+      CFLAGS="$CFLAGS -mieee"
+    else
+      CFLAGS="$CFLAGS -ieee"
+    fi
+    ;;
+  sparc*)
+    if test "$SUNCC" = "yes"; then
+      CFLAGS="$CFLAGS -xmemalign=8s"
+    fi
+    ;;
+esac
+
+dnl See https://github.com/php/php-src/issues/14140
+AX_CHECK_COMPILE_FLAG([-ffp-contract=off], [CFLAGS="$CFLAGS -ffp-contract=off"])
+
+dnl Mark symbols hidden by default if the compiler (for example, gcc >= 4)
+dnl supports it. This can help reduce the binary size and startup time.
+AX_CHECK_COMPILE_FLAG([-fvisibility=hidden],
+                       [CFLAGS="$CFLAGS -fvisibility=hidden"])
+
+case $host_alias in
+  *solaris*)
+    CPPFLAGS="$CPPFLAGS -D_POSIX_PTHREAD_SEMANTICS"
+    ;;
+  *hpux*)
+    if test "$GCC" = "yes"; then
+      CPPFLAGS="$CPPFLAGS -D_XOPEN_SOURCE_EXTENDED"
+    fi
+    ;;
+esac
+
+dnl Disable PIC mode by default where it is known to be safe to do so, to avoid
+dnl the performance hit from the lost register.
+AC_MSG_CHECKING([whether to force non-PIC code in shared modules])
+case $host_alias in
+  i?86-*-linux*|i?86-*-freebsd*)
+    if test "${with_pic+set}" != "set" || test "$with_pic" = "no"; then
+      with_pic=no
+      AC_MSG_RESULT([yes])
+    else
+      AC_MSG_RESULT([no])
+    fi
+    ;;
+  *)
+    AC_MSG_RESULT([no])
+    ;;
+esac
+
+dnl Detect musl libc
+AC_MSG_CHECKING([whether we are using musl libc])
+if command -v ldd >/dev/null && ldd --version 2>&1 | grep ^musl >/dev/null 2>&1
+then
+  AC_MSG_RESULT([yes])
+  AC_DEFINE([__MUSL__], [1], [Define to 1 when using musl libc.])
+else
+  AC_MSG_RESULT([no])
+fi
+
+dnl Add _GNU_SOURCE compile definition because the php_config.h with definitions
+dnl by AC_USE_SYSTEM_EXTENSIONS might be included after the system headers which
+dnl require extensions to C and POSIX.
+AS_VAR_APPEND([CPPFLAGS], [" -D_GNU_SOURCE"])
+
+PTHREADS_CHECK
+PHP_HELP_SEPARATOR([SAPI modules:])
+PHP_SHLIB_SUFFIX_NAMES
+PHP_BUILD_PROGRAM
+PHP_SAPI=none
+
+dnl SAPI configuration.
+dnl ----------------------------------------------------------------------------
+
+dnl Paths to the targets are relative to the build directory.
+SAPI_LIBNAME=libphp
+SAPI_LIBNAME_SHARED=$SAPI_LIBNAME.[]$SHLIB_DL_SUFFIX_NAME
+SAPI_LIBNAME_STATIC=$SAPI_LIBNAME.a
+SAPI_SHARED=libs/$SAPI_LIBNAME_SHARED
+SAPI_STATIC=libs/$SAPI_LIBNAME_STATIC
+SAPI_LIBTOOL=libphp.la
+
+PHP_CONFIGURE_PART([Configuring SAPI modules])
+
+esyscmd(./build/config-stubs sapi)
+
+dnl Show which main SAPI was selected.
+AC_MSG_CHECKING([for chosen SAPI module])
+AC_MSG_RESULT([$PHP_SAPI])
+
+dnl Show which binaries were selected.
+AC_MSG_CHECKING([for executable SAPI binaries])
+AS_VAR_IF([PHP_BINARIES],,
+  [AC_MSG_RESULT([none])],
+  [AC_MSG_RESULT([$PHP_BINARIES])])
+
+dnl Exit early.
+AS_VAR_IF([PHP_INSTALLED_SAPIS],, [AC_MSG_ERROR([Nothing to build.])])
+
+dnl Add POSIX threads compilation and linker flags when thread safety is enabled
+dnl with either the '--enable-zts' configure option or automatically enabled by
+dnl PHP SAPIs. For example, Apache SAPI.
+AS_VAR_IF([enable_zts], [yes], [
+  if test -n "$ac_cv_pthreads_lib"; then
+    LIBS="$LIBS -l$ac_cv_pthreads_lib"
+  fi
+  if test -n "$ac_cv_pthreads_cflags"; then
+    CFLAGS="$CFLAGS $ac_cv_pthreads_cflags"
+  fi
+
+  PTHREADS_FLAGS
+])
+
+dnl Starting system checks.
+dnl ----------------------------------------------------------------------------
+
+PHP_CONFIGURE_PART([Running system checks])
+
+dnl Find sendmail binary.
+PHP_PROG_SENDMAIL
+
+dnl Check whether the system uses EBCDIC (not ASCII) as its native codeset.
+PHP_EBCDIC
+
+dnl Check whether the system byte ordering is bigendian.
+PHP_C_BIGENDIAN
+
+dnl Check whether writing to stdout works.
+PHP_TEST_WRITE_STDOUT
+
+dnl Check for /usr/pkg/{lib,include} which is where NetBSD puts binary and
+dnl source packages. This should be harmless on other OSs.
+if test -d /usr/pkg/include && test -d /usr/pkg/lib; then
+   CPPFLAGS="$CPPFLAGS -I/usr/pkg/include"
+   LDFLAGS="$LDFLAGS -L/usr/pkg/lib"
+fi
+test -d /usr/ucblib && PHP_ADD_LIBPATH([/usr/ucblib])
+
+dnl First, library checks.
+dnl ----------------------------------------------------------------------------
+
+AC_SEARCH_LIBS([socket], [socket network])
+
+AC_CHECK_FUNCS([socketpair],,
+  [AC_SEARCH_LIBS([socketpair], [socket network],
+    [AC_DEFINE([HAVE_SOCKETPAIR], [1])])])
+
+AC_SEARCH_LIBS([gethostbyaddr], [nsl network])
+
+AC_SEARCH_LIBS([dlopen], [dl],
+  [AC_DEFINE([HAVE_LIBDL], [1],
+    [Define to 1 if you have the 'dl' library (-ldl).])])
+
+AC_SEARCH_LIBS([sin], [m])
+
+case $host_alias in
+  riscv64*)
+    PHP_CHECK_FUNC(__atomic_exchange_1, atomic)
+    ;;
+esac
+
+dnl Solaris/Illumos for process mapping.
+AC_SEARCH_LIBS([Pgrab], [proc])
+
+dnl Haiku does not have network api in libc.
+AC_SEARCH_LIBS([setsockopt], [network])
+
+dnl Check for openpty. It may require linking against libutil or libbsd.
+AC_CHECK_FUNCS([openpty],,
+  [AC_SEARCH_LIBS([openpty], [util bsd], [AC_DEFINE([HAVE_OPENPTY], [1])])])
+
+dnl Then headers.
+dnl ----------------------------------------------------------------------------
+
+dnl QNX requires unix.h to allow functions in libunix to work properly.
+AC_CHECK_HEADERS(m4_normalize([
+  dirent.h
+  sys/param.h
+  sys/types.h
+  sys/time.h
+  netinet/in.h
+  alloca.h
+  arpa/inet.h
+  arpa/nameser.h
+  dns.h
+  fcntl.h
+  grp.h
+  ieeefp.h
+  langinfo.h
+  linux/sock_diag.h
+  poll.h
+  pty.h
+  pwd.h
+  resolv.h
+  strings.h
+  syslog.h
+  sysexits.h
+  sys/ioctl.h
+  sys/file.h
+  sys/mman.h
+  sys/mount.h
+  sys/poll.h
+  sys/resource.h
+  sys/select.h
+  sys/socket.h
+  sys/stat.h
+  sys/statfs.h
+  sys/statvfs.h
+  sys/vfs.h
+  sys/sysexits.h
+  sys/uio.h
+  sys/wait.h
+  sys/loadavg.h
+  unistd.h
+  unix.h
+  utime.h
+  sys/utsname.h
+  sys/ipc.h
+  dlfcn.h
+  tmmintrin.h
+  nmmintrin.h
+  wmmintrin.h
+  immintrin.h
+]),,, [dnl
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_ARPA_NAMESER_H
+#include <arpa/nameser.h>
+#endif
+])
+
+PHP_FOPENCOOKIE
+PHP_BROKEN_GETCWD
+AS_VAR_IF([GCC], [yes], [PHP_BROKEN_GCC_STRLEN_OPT])
+
+dnl Detect the headers required to use makedev, major, and minor.
+dnl Autoconf <= 2.69 didn't check glibc 2.25 deprecated macros in sys/types.h.
+m4_version_prereq([2.70],,[ac_cv_header_sys_types_h_makedev=no])
+AC_HEADER_MAJOR
+
+dnl Checks for typedefs, structures, and compiler characteristics.
+dnl ----------------------------------------------------------------------------
+
+AC_STRUCT_TIMEZONE
+
+PHP_MISSING_TIME_R_DECL
+
+AC_CHECK_TYPES([struct flock],,,[#include <fcntl.h>])
+AC_CHECK_TYPES([socklen_t], [], [], [
+  #ifdef HAVE_SYS_TYPES_H
+  # include <sys/types.h>
+  #endif
+  #ifdef HAVE_SYS_SOCKET_H
+  # include <sys/socket.h>
+  #endif
+])
+
+dnl These are defined elsewhere than stdio.h.
+PHP_CHECK_SIZEOF([intmax_t], [0])
+PHP_CHECK_SIZEOF([ssize_t], [8])
+PHP_CHECK_SIZEOF([ptrdiff_t], [8])
+
+dnl Check stdint types (must be after header check).
+PHP_CHECK_STDINT_TYPES
+
+dnl Check GNU C builtins.
+PHP_CHECK_BUILTIN([__builtin_clz])
+PHP_CHECK_BUILTIN([__builtin_clzl])
+PHP_CHECK_BUILTIN([__builtin_clzll])
+PHP_CHECK_BUILTIN([__builtin_cpu_init])
+PHP_CHECK_BUILTIN([__builtin_cpu_supports])
+PHP_CHECK_BUILTIN([__builtin_ctzl])
+PHP_CHECK_BUILTIN([__builtin_ctzll])
+PHP_CHECK_BUILTIN([__builtin_expect])
+PHP_CHECK_BUILTIN([__builtin_frame_address])
+PHP_CHECK_BUILTIN([__builtin_saddl_overflow])
+PHP_CHECK_BUILTIN([__builtin_saddll_overflow])
+PHP_CHECK_BUILTIN([__builtin_smull_overflow])
+PHP_CHECK_BUILTIN([__builtin_smulll_overflow])
+PHP_CHECK_BUILTIN([__builtin_ssubl_overflow])
+PHP_CHECK_BUILTIN([__builtin_ssubll_overflow])
+PHP_CHECK_BUILTIN([__builtin_unreachable])
+PHP_CHECK_BUILTIN([__builtin_usub_overflow])
+
+dnl Check AVX512
+PHP_CHECK_AVX512_SUPPORTS
+dnl Check AVX512 VBMI
+PHP_CHECK_AVX512_VBMI_SUPPORTS
+
+dnl Check for __alignof__ support in the compiler
+AC_CACHE_CHECK([whether the compiler supports __alignof__],
+[php_cv_have_alignof],
+[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [
+  int align = __alignof__(int);
+  (void)align;
+])],
+[php_cv_have_alignof=yes],
+[php_cv_have_alignof=no])])
+AS_VAR_IF([php_cv_have_alignof], [yes],
+  [AC_DEFINE([HAVE_ALIGNOF], [1],
+    [Define to 1 if the compiler supports '__alignof__'.])])
+
+dnl Check for structure members.
+AC_CHECK_MEMBERS([struct tm.tm_gmtoff],,,[#include <time.h>])
+AC_CHECK_MEMBERS([struct stat.st_blksize, struct stat.st_rdev])
+dnl AC_STRUCT_ST_BLOCKS will screw QNX because fileblocks.o does not exist.
+if test "$(uname -s 2>/dev/null)" != "QNX"; then
+  AC_STRUCT_ST_BLOCKS
+fi
+
+dnl Checks for types.
+AC_TYPE_UID_T
+
+dnl Checks for sockaddr_storage and sockaddr.sa_len.
+AC_CHECK_TYPES([struct sockaddr_storage],,,[#include <sys/socket.h>])
+AC_CHECK_MEMBERS([struct sockaddr.sa_len],,,[#include <sys/socket.h>])
+
+dnl Checks for GCC function attributes on all systems except ones without glibc
+dnl Fix for these systems is already included in GCC 7, but not on GCC 6.
+dnl
+dnl At least some versions of FreeBSD seem to have buggy ifunc support, see
+dnl bug #77284. Conservatively don't use ifuncs on FreeBSD prior to version 12.
+AS_CASE([$host_alias], [*-*-*android*|*-*-*uclibc*|*-*-*musl*|*openbsd*], [true], [
+  if test "$(uname -s 2>/dev/null)" != "FreeBSD" || test "$(uname -U 2>/dev/null)" -ge 1200000; then
+    AX_GCC_FUNC_ATTRIBUTE([ifunc])
+    AX_GCC_FUNC_ATTRIBUTE([target])
+  fi
+])
+
+dnl Check for __attribute__ ((__aligned__)) support in the compiler.
+PHP_CHECK_VARIABLE_ATTRIBUTE([aligned])
+
+dnl Checks for library functions.
+dnl ----------------------------------------------------------------------------
+
+AC_CHECK_FUNCS(m4_normalize([
+  alphasort
+  asctime_r
+  asprintf
+  chroot
+  ctime_r
+  explicit_memset
+  fdatasync
+  flock
+  ftok
+  funopen
+  gai_strerror
+  getcwd
+  getgrnam_r
+  gethostname
+  getloadavg
+  getlogin
+  getprotobyname
+  getprotobynumber
+  getpwnam_r
+  getpwuid_r
+  getrusage
+  getservbyname
+  getservbyport
+  gettimeofday
+  getwd
+  glob
+  gmtime_r
+  lchown
+  localtime_r
+  memcntl
+  memfd_create
+  memmem
+  mempcpy
+  memrchr
+  mkstemp
+  mmap
+  nice
+  nl_langinfo
+  poll
+  pthread_jit_write_protect_np
+  putenv
+  scandir
+  setenv
+  setitimer
+  shutdown
+  sigprocmask
+  statfs
+  statvfs
+  std_syslog
+  strcasecmp
+  strnlen
+  strptime
+  strtok_r
+  symlink
+  tzset
+  unsetenv
+  usleep
+  utime
+  vasprintf
+]))
+
+AC_CHECK_FUNC([inet_ntop],, [AC_MSG_FAILURE([Required inet_ntop not found.])])
+AC_CHECK_FUNC([inet_pton],, [AC_MSG_FAILURE([Required inet_pton not found.])])
+
+dnl Check for strerror_r, and if its a POSIX-compatible or a GNU specific version.
+AC_FUNC_STRERROR_R
+
+dnl Check for functions inside their belonging headers.
+AC_CHECK_HEADER([sys/prctl.h], [AC_CHECK_FUNCS([prctl])])
+AC_CHECK_HEADER([sys/procctl.h], [AC_CHECK_FUNCS([procctl])])
+
+AX_FUNC_WHICH_GETHOSTBYNAME_R
+
+dnl Some systems (Solaris 10) do not have nanosleep in libc.
+AC_CHECK_FUNCS([nanosleep],,
+  [AC_SEARCH_LIBS([nanosleep], [rt], [AC_DEFINE([HAVE_NANOSLEEP], [1])])])
+
+dnl Check for getaddrinfo, should be a better way, but... Also check for working
+dnl getaddrinfo.
+AC_CACHE_CHECK([for getaddrinfo], [php_cv_func_getaddrinfo],
+[AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <netdb.h>],
+  [struct addrinfo *g,h;g=&h;getaddrinfo("","",g,&g);])],
+  [AC_RUN_IFELSE([AC_LANG_SOURCE([
+#include <netdb.h>
+#include <sys/types.h>
+#include <string.h>
+#include <stdlib.h>
+#ifndef AF_INET
+# include <sys/socket.h>
+#endif
+int main(void) {
+  struct addrinfo *ai, *pai, hints;
+
+  memset(&hints, 0, sizeof(hints));
+  hints.ai_flags = AI_NUMERICHOST;
+
+  if (getaddrinfo("127.0.0.1", 0, &hints, &ai) < 0) {
+    return 1;
+  }
+
+  if (ai == 0) {
+    return 1;
+  }
+
+  pai = ai;
+
+  while (pai) {
+    if (pai->ai_family != AF_INET) {
+      /* 127.0.0.1/NUMERICHOST should only resolve ONE way */
+      return 1;
+    }
+    if (pai->ai_addr->sa_family != AF_INET) {
+      /* 127.0.0.1/NUMERICHOST should only resolve ONE way */
+      return 1;
+    }
+    pai = pai->ai_next;
+  }
+  freeaddrinfo(ai);
+  return 0;
+}
+  ])],
+  [php_cv_func_getaddrinfo=yes],
+  [php_cv_func_getaddrinfo=no],
+  [AS_CASE([$host_alias],
+    [*linux*|*midipix], [php_cv_func_getaddrinfo=yes],
+    [php_cv_func_getaddrinfo=no])])],
+[php_cv_func_getaddrinfo=no])])
+AS_VAR_IF([php_cv_func_getaddrinfo], [yes],
+  [AC_DEFINE([HAVE_GETADDRINFO], [1],
+    [Define to 1 if you have the 'getaddrinfo' function.])])
+
+dnl on FreeBSD, copy_file_range() works only with the undocumented flag 0x01000000;
+dnl until the problem is fixed properly, copy_file_range() is used only on Linux
+AC_CACHE_CHECK([for copy_file_range], [php_cv_func_copy_file_range],
+[AC_COMPILE_IFELSE([AC_LANG_SOURCE([
+#ifndef __linux__
+# error "unsupported platform"
+#endif
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE
+#endif
+#include <linux/version.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(5,3,0)
+# error "kernel too old"
+#endif
+#include <unistd.h>
+int main(void)
+{
+  (void)copy_file_range(-1, 0, -1, 0, 0, 0);
+  return 0;
+}
+])],
+[php_cv_func_copy_file_range=yes],
+[php_cv_func_copy_file_range=no])
+])
+AS_VAR_IF([php_cv_func_copy_file_range], [yes],
+  [AC_DEFINE([HAVE_COPY_FILE_RANGE], [1],
+    [Define to 1 if you have the 'copy_file_range' function.])])
+
+AC_REPLACE_FUNCS([strlcat strlcpy explicit_bzero getopt])
+AC_FUNC_ALLOCA
+PHP_TIME_R_TYPE
+
+AC_CACHE_CHECK([for aarch64 CRC32 API], [php_cv_func___crc32d],
+[AC_LINK_IFELSE([AC_LANG_PROGRAM([
+#include <arm_acle.h>
+# if defined(__GNUC__)
+#  if!defined(__clang__)
+#   pragma GCC push_options
+#   pragma GCC target ("+nothing+crc")
+#  elif defined(__APPLE__)
+#   pragma clang attribute push(__attribute__((target("crc"))), apply_to=function)
+#  else
+#   pragma clang attribute push(__attribute__((target("+nothing+crc"))), apply_to=function)
+#  endif
+# endif
+], [__crc32d(0, 0);])],
+[php_cv_func___crc32d=yes],
+[php_cv_func___crc32d=no])])
+AS_VAR_IF([php_cv_func___crc32d], [yes],
+  [AC_DEFINE([HAVE_AARCH64_CRC32], [1],
+    [Define to 1 when aarch64 CRC32 API is available.])])
+
+dnl Check for asm goto support.
+AC_CACHE_CHECK([for asm goto], [php_cv_have__asm_goto],
+[AC_LINK_IFELSE([AC_LANG_PROGRAM([], [
+#if defined(__x86_64__) || defined(__i386__)
+  __asm__ goto("jmp %l0\n" :::: end);
+#elif defined(__aarch64__)
+  __asm__ goto("b %l0\n" :::: end);
+#endif
+end:
+  return 0;
+])],
+[php_cv_have__asm_goto=yes],
+[php_cv_have__asm_goto=no])])
+AS_VAR_IF([php_cv_have__asm_goto], [yes],
+  [AC_DEFINE([HAVE_ASM_GOTO], [1],
+    [Define to 1 if asm goto support is available.])])
+
+dnl Check Valgrind support.
+PHP_ARG_WITH([valgrind],
+  [whether to enable Valgrind support],
+  [AS_HELP_STRING([--with-valgrind],
+    [Enable Valgrind support])],
+  [no],
+  [no])
+
+AS_VAR_IF([PHP_VALGRIND], [no],, [
+  PKG_CHECK_MODULES([VALGRIND], [valgrind],
+     [PHP_EVAL_INCLINE([$VALGRIND_CFLAGS])
+       AC_DEFINE([HAVE_VALGRIND], [1],
+        [Define to 1 if Valgrind is enabled and supported.])])
+  save_CFLAGS=$CFLAGS
+  CFLAGS="$CFLAGS $VALGRIND_CFLAGS"
+  AC_CHECK_HEADERS([valgrind/cachegrind.h])
+  CFLAGS=$save_CFLAGS
+])
+
+dnl General settings.
+dnl ----------------------------------------------------------------------------
+PHP_CONFIGURE_PART([General settings])
+
+PHP_HELP_SEPARATOR([General settings:])
+
+PHP_ARG_ENABLE([gcov],
+  [whether to include gcov symbols],
+  [AS_HELP_STRING([--enable-gcov],
+    [Enable GCOV code coverage - FOR DEVELOPERS ONLY!!])],
+  [no],
+  [no])
+
+AS_VAR_IF([PHP_GCOV], [yes], [
+  AS_VAR_IF([GCC], [yes],,
+    [AC_MSG_ERROR([GNU C compatible compiler is required for --enable-gcov])])
+
+  dnl Check if ccache is being used.
+  AS_CASE([$($php_shtool path $CC)],
+    [*ccache*], [gcc_ccache=yes],
+    [gcc_ccache=no])
+
+  if test "$gcc_ccache" = "yes" && (test -z "$CCACHE_DISABLE" || test "$CCACHE_DISABLE" != "1"); then
+    AC_MSG_ERROR(m4_text_wrap([
+      ccache must be disabled when --enable-gcov option is used. You can disable
+      ccache by setting environment variable CCACHE_DISABLE=1.
+    ]))
+  fi
+
+  AC_DEFINE([HAVE_GCOV], [1], [Define to 1 if GCOV code coverage is enabled.])
+  PHP_ADD_MAKEFILE_FRAGMENT([$abs_srcdir/build/Makefile.gcov], [$abs_srcdir])
+
+  dnl Remove all optimization flags from CFLAGS.
+  PHP_REMOVE_OPTIMIZATION_FLAGS
+
+  dnl Add the special gcc flags.
+  CFLAGS="$CFLAGS -O0 -fprofile-arcs -ftest-coverage"
+  CXXFLAGS="$CXXFLAGS -O0 -fprofile-arcs -ftest-coverage"
+])
+
+PHP_ARG_ENABLE([debug],
+  [whether to include debugging symbols],
+  [AS_HELP_STRING([--enable-debug],
+    [Compile with debugging symbols])],
+  [no],
+  [no])
+
+AS_VAR_IF([PHP_DEBUG], [yes], [
+  PHP_DEBUG=1
+  ZEND_DEBUG=yes
+  PHP_REMOVE_OPTIMIZATION_FLAGS
+  dnl Add -O0 only if GCC or ICC is used.
+  if test "$GCC" = "yes" || test "$ICC" = "yes"; then
+    CFLAGS="$CFLAGS -O0"
+    CXXFLAGS="$CXXFLAGS -g -O0"
+  fi
+  if test "$SUNCC" = "yes"; then
+    if test -n "$auto_cflags"; then
+      CFLAGS="-g"
+      CXXFLAGS="-g"
+    else
+      CFLAGS="$CFLAGS -g"
+      CXXFLAGS="$CFLAGS -g"
+    fi
+  fi
+], [
+  PHP_DEBUG=0
+  ZEND_DEBUG=no
+])
+
+PHP_ARG_ENABLE([debug-assertions],
+  [whether to enable debug assertions in release mode],
+  [AS_HELP_STRING([--enable-debug-assertions],
+    [Compile with debug assertions even in release mode])],
+  [no],
+  [no])
+
+AS_VAR_IF([PHP_DEBUG_ASSERTIONS], [yes], [
+  PHP_DEBUG=1
+  ZEND_DEBUG=yes
+])
+
+AC_ARG_ENABLE([zts],
+  [AS_HELP_STRING([--enable-zts],
+    [Enable thread safety])],
+  [ZEND_ZTS=$enableval],
+  [ZEND_ZTS=no])
+
+AS_VAR_IF([ZEND_ZTS], [yes], [PHP_THREAD_SAFETY=yes], [PHP_THREAD_SAFETY=no])
+
+AS_VAR_IF([PHP_THREAD_SAFETY], [yes], [
+  AS_VAR_IF([pthreads_working], [yes], [],
+    [AC_MSG_FAILURE(m4_text_wrap([
+      Unable to verify system support for POSIX Threads, which are required for
+      PHP thread safety (ZTS) build.
+    ]))])
+
+  AC_MSG_CHECKING([for POSIX threads])
+  AC_MSG_RESULT([yes])
+])
+
+PHP_ARG_ENABLE([rtld-now],
+  [whether to dlopen extensions with RTLD_NOW instead of RTLD_LAZY],
+  [AS_HELP_STRING([--enable-rtld-now],
+    [Use dlopen with RTLD_NOW instead of RTLD_LAZY])],
+  [no],
+  [no])
+
+AS_VAR_IF([PHP_RTLD_NOW], [yes],
+  [AC_DEFINE([PHP_USE_RTLD_NOW], [1],
+    [Define to 1 if 'dlopen()' uses the 'RTLD_NOW' mode flag instead of
+    'RTLD_LAZY'.])])
+
+PHP_ARG_WITH([layout],
+  [layout of installed files],
+  [AS_HELP_STRING([--with-layout=TYPE],
+    [Set how installed files will be laid out. Type can be either PHP or GNU [PHP]])],
+  [PHP],
+  [no])
+
+AS_CASE([$PHP_LAYOUT], [GNU], [oldstyleextdir=no], [oldstyleextdir=yes])
+
+PHP_ARG_WITH([config-file-path],
+  [path to configuration file],
+  [AS_HELP_STRING([--with-config-file-path=PATH],
+    [Set the path in which to look for php.ini [PREFIX/lib]])],
+  [DEFAULT],
+  [no])
+
+AS_VAR_IF([PHP_CONFIG_FILE_PATH], [DEFAULT],
+  [AS_CASE([$PHP_LAYOUT],
+    [GNU], [PHP_CONFIG_FILE_PATH=$sysconfdir],
+    [PHP_CONFIG_FILE_PATH=$libdir])])
+
+AC_MSG_CHECKING([where to scan for configuration files])
+PHP_ARG_WITH([config-file-scan-dir],,
+  [AS_HELP_STRING([--with-config-file-scan-dir=PATH],
+    [Set the path where to scan for configuration files])],
+  [DEFAULT],
+  [no])
+
+AS_VAR_IF([PHP_CONFIG_FILE_SCAN_DIR], [DEFAULT], [PHP_CONFIG_FILE_SCAN_DIR=])
+AC_MSG_RESULT([$PHP_CONFIG_FILE_SCAN_DIR])
+
+PHP_ARG_ENABLE([sigchild],
+  [whether to enable PHP's own SIGCHLD handler],
+  [AS_HELP_STRING([--enable-sigchild],
+    [Enable PHP's own SIGCHLD handler])],
+  [no],
+  [no])
+
+AH_TEMPLATE([PHP_SIGCHILD],
+  [Define to 1 if PHP uses its own SIGCHLD handler, and to 0 if not.])
+AS_VAR_IF([PHP_SIGCHILD], [yes],
+  [AC_DEFINE([PHP_SIGCHILD], [1])],
+  [AC_DEFINE([PHP_SIGCHILD], [0])])
+
+PHP_ARG_ENABLE([libgcc],
+  [whether to explicitly link against libgcc],
+  [AS_HELP_STRING([--enable-libgcc],
+    [Enable explicitly linking against libgcc])],
+  [no],
+  [no])
+
+AS_VAR_IF([PHP_LIBGCC], [yes], [
+  PHP_LIBGCC_LIBPATH([gcc])
+  AS_VAR_IF([libgcc_libpath],,
+    [AC_MSG_ERROR([Cannot locate libgcc. Make sure that gcc is in your path])])
+  PHP_ADD_LIBPATH([$libgcc_libpath])
+  PHP_ADD_LIBRARY([gcc], [yes])
+])
+
+PHP_ARG_ENABLE([short-tags],
+  [whether to enable short tags by default],
+  [AS_HELP_STRING([--disable-short-tags],
+    [Disable the short-form <? start tag by default])],
+  [yes],
+  [no])
+
+AH_TEMPLATE([DEFAULT_SHORT_OPEN_TAG],
+  [Define to string "1" if PHP short open tags '<?' are enabled by default, and
+  to string "0" if they are not.])
+AS_VAR_IF([PHP_SHORT_TAGS], [yes],
+  [AC_DEFINE([DEFAULT_SHORT_OPEN_TAG], ["1"])],
+  [AC_DEFINE([DEFAULT_SHORT_OPEN_TAG], ["0"])])
+
+PHP_ARG_ENABLE([dmalloc],
+  [whether to enable dmalloc],
+  [AS_HELP_STRING([--enable-dmalloc],
+    [Enable dmalloc])],
+  [no],
+  [no])
+
+AS_VAR_IF([PHP_DMALLOC], [yes],
+  [AC_CHECK_LIB([dmalloc], [dmalloc_error],
+    [PHP_ADD_LIBRARY([dmalloc])
+      AC_DEFINE([HAVE_DMALLOC], [1], [Define to 1 if you have dmalloc.])
+      AS_VAR_APPEND([CPPFLAGS], [" -DDMALLOC_FUNC_CHECK"])],
+    [AC_MSG_FAILURE([The dmalloc check failed. Cannot enable dmalloc.])])])
+
+PHP_ARG_ENABLE([ipv6],
+  [whether to enable IPv6 support],
+  [AS_HELP_STRING([--disable-ipv6],
+    [Disable IPv6 support])],
+  [yes],
+  [no])
+
+AS_VAR_IF([PHP_IPV6], [yes],
+  [AC_CACHE_CHECK([for IPv6 support], [php_cv_have_ipv6],
+    [AC_LINK_IFELSE([AC_LANG_PROGRAM([
+      #include <sys/types.h>
+      #include <sys/socket.h>
+      #include <netinet/in.h>
+    ], [[
+      struct sockaddr_in6 s;
+      struct in6_addr t = in6addr_any;
+      int i = AF_INET6;
+      (void)s;
+      t.s6_addr[0] = 0;
+      (void)i;
+    ]])],
+    [php_cv_have_ipv6=yes],
+    [php_cv_have_ipv6=no])])
+])
+AS_VAR_IF([php_cv_have_ipv6], [yes],
+  [AC_DEFINE([HAVE_IPV6], [1],
+    [Define to 1 if IPv6 is enabled and supported.])])
+
+dnl DTRACE checks. Note: this has to be done after SAPI configuration.
+PHP_ARG_ENABLE([dtrace],
+  [whether to enable DTrace support],
+  [AS_HELP_STRING([--enable-dtrace],
+    [Enable DTrace support])],
+  [no],
+  [no])
+
+AS_VAR_IF([PHP_DTRACE], [yes], [
+  PHP_INIT_DTRACE([Zend/zend_dtrace.d], [Zend/zend_dtrace_gen.h], [
+    main/main.c
+    Zend/zend_API.c
+    Zend/zend_dtrace.c
+    Zend/zend_exceptions.c
+    Zend/zend_execute.c
+    Zend/zend.c
+  ])
+  AC_DEFINE([HAVE_DTRACE], [1], [Define to 1 if DTrace support is enabled.])
+])
+
+AC_MSG_CHECKING([how big to make fd sets])
+PHP_ARG_ENABLE([fd-setsize],,
+  [AS_HELP_STRING([--enable-fd-setsize],
+    [Set size of descriptor sets])],
+  [no],
+  [no])
+
+AS_VAR_IF([PHP_FD_SETSIZE], [no], [AC_MSG_RESULT([using system default])], [
+  if test "0$PHP_FD_SETSIZE" -gt 0 2>/dev/null; then
+    CPPFLAGS="$CPPFLAGS -DFD_SETSIZE=$PHP_FD_SETSIZE"
+    AC_MSG_RESULT([using $PHP_FD_SETSIZE])
+  else
+    AC_MSG_ERROR([Invalid value passed to --enable-fd-setsize!])
+  fi
+])
+
+PHP_ARG_ENABLE([werror],,
+  [AS_HELP_STRING([--enable-werror],
+    [Enable -Werror])],
+  [no],
+  [no])
+PHP_ARG_ENABLE([memory-sanitizer],,
+  [AS_HELP_STRING([--enable-memory-sanitizer],
+    [Enable memory sanitizer (clang only)])],
+  [no],
+  [no])
+PHP_ARG_ENABLE([address-sanitizer],,
+  [AS_HELP_STRING([--enable-address-sanitizer],
+    [Enable address sanitizer])],
+  [no],
+  [no])
+PHP_ARG_ENABLE([undefined-sanitizer],,
+  [AS_HELP_STRING([--enable-undefined-sanitizer],
+    [Enable undefined sanitizer])],
+  [no],
+  [no])
+
+dnl Extension configuration.
+dnl ----------------------------------------------------------------------------
+
+PHP_HELP_SEPARATOR([[Extensions:
+  --with-EXTENSION=[shared[,PATH]]
+
+    NOTE: Not all extensions can be built as 'shared'.
+
+    Example: --with-foobar=shared,/usr/local/foobar/
+
+      o Builds the foobar extension as shared extension.
+      o foobar package install prefix is /usr/local/foobar/
+]])
+
+PHP_CONFIGURE_PART([Configuring extensions])
+
+dnl Check if all enabled by default extensions should be disabled.
+AC_ARG_ENABLE([all],
+  [AS_HELP_STRING([--disable-all],
+    [Disable all extensions which are enabled by default])],
+  [PHP_ENABLE_ALL=$enableval])
+
+dnl Reading config stubs.
+esyscmd(./build/config-stubs ext)
+
+dnl Extensions post-config.
+dnl ----------------------------------------------------------------------------
+
+dnl Align segments on huge page boundary
+AS_CASE([$host_alias], [[i[3456]86-*-linux-* | x86_64-*-linux-*]],
+  [AC_CACHE_CHECK([linker support for -zcommon-page-size=2097152],
+    [php_cv_have_common_page_size], [
+    save_LDFLAGS=$LDFLAGS
+    LDFLAGS="$LDFLAGS -Wl,-zcommon-page-size=2097152 -Wl,-zmax-page-size=2097152"
+    AC_RUN_IFELSE([AC_LANG_PROGRAM()],
+      [php_cv_have_common_page_size=yes],
+      [php_cv_have_common_page_size=no],
+      [php_cv_have_common_page_size=no])
+    LDFLAGS=$save_LDFLAGS])
+  AS_VAR_IF([php_cv_have_common_page_size], [yes],
+    [EXTRA_LDFLAGS_PROGRAM="$EXTRA_LDFLAGS_PROGRAM -Wl,-zcommon-page-size=2097152 -Wl,-zmax-page-size=2097152"],
+    [AC_CACHE_CHECK([linker support for -zmax-page-size=2097152],
+      [php_cv_have_max_page_size], [
+      save_LDFLAGS=$LDFLAGS
+      LDFLAGS="$LDFLAGS -Wl,-zmax-page-size=2097152"
+      AC_RUN_IFELSE([AC_LANG_PROGRAM()],
+        [php_cv_have_max_page_size=yes],
+        [php_cv_have_max_page_size=no],
+        [php_cv_have_max_page_size=no])
+      LDFLAGS=$save_LDFLAGS])
+    AS_VAR_IF([php_cv_have_max_page_size], [yes],
+      [EXTRA_LDFLAGS_PROGRAM="$EXTRA_LDFLAGS_PROGRAM -Wl,-zmax-page-size=2097152"])
+  ])
+])
+
+enable_shared=yes
+enable_static=yes
+
+case $php_sapi_module in
+  shared[)]
+    if test "$PHP_CGI" = "no" && test "$PHP_CLI" = "no" && test "$PHP_FPM" = "no" && test "$PHP_LITESPEED" = "no" && test "$PHP_PHPDBG" = "no"; then
+      enable_static=no
+    fi
+    case $with_pic in
+      yes)
+        standard_libtool_flag='-prefer-pic'
+        ;;
+      no)
+        standard_libtool_flag='-prefer-non-pic'
+        ;;
+    esac
+    EXTRA_LDFLAGS="$EXTRA_LDFLAGS -avoid-version -module"
+    ;;
+  *[)]
+    standard_libtool_flag='-prefer-non-pic -static'
+    if test -z "$PHP_MODULES" && test -z "$PHP_ZEND_EX"; then
+      enable_shared=no
+    fi
+    ;;
+esac
+
+EXTRA_LIBS="$EXTRA_LIBS $DLIBS $LIBS"
+unset LIBS
+
+dnl PEAR
+dnl ----------------------------------------------------------------------------
+
+PHP_HELP_SEPARATOR([PEAR:])
+PHP_CONFIGURE_PART([Configuring PEAR])
+
+dnl If CLI is disabled disable PEAR.
+AS_VAR_IF([PHP_CLI], [no], [with_pear=no])
+
+PHP_ARG_WITH([pear],
+  [whether to install PEAR],
+  [AS_HELP_STRING([[--with-pear[=DIR]]],
+    [Install PEAR in DIR [PREFIX/lib/php]])],
+  [no],
+  [yes])
+
+AS_VAR_IF([PHP_PEAR], [no],, [
+  AC_MSG_WARN([The --with-pear option is deprecated])
+
+  dnl PEAR dependencies.
+  AS_VAR_IF([PHP_XML], [no], [AC_MSG_ERROR(m4_text_wrap([
+    PEAR requires XML to be enabled. Add '--enable-xml' to the configure line,
+    or disable PEAR (--without-pear).
+  ]))])
+
+  install_pear=install-pear
+
+  AS_VAR_IF([PHP_PEAR], [yes],
+    [AS_CASE([$PHP_LAYOUT],
+      [GNU], [PEAR_INSTALLDIR=$datadir/pear],
+      [PEAR_INSTALLDIR=$libdir/php])],
+    [PEAR_INSTALLDIR=$PHP_PEAR])
+
+  PHP_SUBST([PEAR_INSTALLDIR])
+  PHP_ADD_BUILD_DIR([pear])
+  PHP_ADD_MAKEFILE_FRAGMENT([$abs_srcdir/pear/Makefile.frag],
+    [$abs_srcdir/pear],
+    [pear])
+])
+
+dnl Configuring Zend and TSRM.
+dnl ----------------------------------------------------------------------------
+
+PHP_HELP_SEPARATOR([Zend:])
+PHP_CONFIGURE_PART([Configuring Zend])
+
+AC_ARG_ENABLE([fiber-asm],
+  [AS_HELP_STRING([--disable-fiber-asm],
+    [Disable the use of boost fiber assembly files])],
+  [fiber_asm=$enableval], [fiber_asm='yes'])
+
+AS_CASE([$host_cpu],
+  [x86_64*|amd64*], [fiber_cpu="x86_64"],
+  [x86*|amd*|i?86*|pentium], [fiber_cpu="i386"],
+  [aarch64*|arm64*], [fiber_cpu="arm64"],
+  [arm*], [fiber_cpu="arm32"],
+  [ppc64*|powerpc64*], [fiber_cpu="ppc64"],
+  [ppc*|powerpc*], [fiber_cpu="ppc32"],
+  [riscv64*], [fiber_cpu="riscv64"],
+  [sparc64], [fiber_cpu="sparc64"],
+  [s390x*], [fiber_cpu="s390x"],
+  [loongarch64*], [fiber_cpu="loongarch64"],
+  [mips64*], [fiber_cpu="mips64"],
+  [mips*], [fiber_cpu="mips32"],
+  [fiber_cpu="unknown"]
+)
+
+AS_CASE([$host_os],
+  [darwin*], [fiber_os="mac"],
+  [aix*|os400*], [fiber_os="aix"],
+  [freebsd*], [fiber_os="freebsd"],
+  [midipix], [fiber_os="midipix"],
+  [fiber_os="other"]
+)
+
+AS_CASE([$fiber_cpu],
+  [x86_64], [fiber_asm_file_prefix="x86_64_sysv"],
+  [i386], [fiber_asm_file_prefix="i386_sysv"],
+  [arm64], [fiber_asm_file_prefix="arm64_aapcs"],
+  [arm32], [fiber_asm_file_prefix="arm_aapcs"],
+  [ppc64], [fiber_asm_file_prefix="ppc64_sysv"],
+  [ppc32], [fiber_asm_file_prefix="ppc32_sysv"],
+  [riscv64], [fiber_asm_file_prefix="riscv64_sysv"],
+  [sparc64], [fiber_asm_file_prefix="sparc64_sysv"],
+  [s390x], [fiber_asm_file_prefix="s390x_sysv"],
+  [loongarch64], [fiber_asm_file_prefix="loongarch64_sysv"],
+  [mips64], [fiber_asm_file_prefix="mips64_n64"],
+  [mips32], [fiber_asm_file_prefix="mips32_o32"],
+  [fiber_asm_file_prefix="unknown"]
+)
+
+if test "$fiber_os" = 'mac'; then
+  fiber_asm_file="combined_sysv_macho_gas"
+elif test "$fiber_os" = 'aix'; then
+  # AIX uses a different calling convention (shared with non-_CALL_ELF Linux).
+  # The AIX assembler isn't GNU, but the file is compatible.
+  fiber_asm_file="${fiber_asm_file_prefix}_xcoff_gas"
+elif test "$fiber_os" = 'freebsd'; then
+  case $fiber_cpu in
+    i386*)
+      fiber_asm="no"
+      ;;
+    *)
+      fiber_asm_file="${fiber_asm_file_prefix}_elf_gas"
+      ;;
+  esac
+elif test "$fiber_os" = 'midipix'; then
+  case $fiber_cpu in
+    i386*)
+      fiber_asm="no"
+      ;;
+    x86_64)
+      fiber_asm_file="x86_64_ms_pe_gas"
+      ;;
+  esac
+elif test "$fiber_asm_file_prefix" != 'unknown'; then
+  fiber_asm_file="${fiber_asm_file_prefix}_elf_gas"
+else
+  fiber_asm="no"
+fi
+
+AC_CACHE_CHECK([whether syscall to create shadow stack exists],
+[php_cv_have_shadow_stack_syscall],
+[AC_RUN_IFELSE([AC_LANG_SOURCE([
+#include <unistd.h>
+#include <sys/mman.h>
+int main(void) {
+  /* test if syscall 451, i.e., map_shadow_stack is available */
+  void* base = (void *)syscall(451, 0, 0x20000, 0x1);
+  if (base != (void*)-1) {
+    munmap(base, 0x20000);
+    return 0;
+  }
+  return 1;
+}
+])],
+  [php_cv_have_shadow_stack_syscall=yes],
+  [php_cv_have_shadow_stack_syscall=no],
+  [php_cv_have_shadow_stack_syscall=no])
+])
+dnl The asm files can't see macro from AC_DEFINE, workaround this via cflag. If
+dnl the syscall doesn't exist, we may block the final ELF from __PROPERTY_SHSTK
+dnl via redefine macro as "-D__CET__=1".
+AS_VAR_IF([php_cv_have_shadow_stack_syscall], [yes],
+  [fiber_asm_cflag="-DSHADOW_STACK_SYSCALL=1"],
+  [fiber_asm_cflag="-DSHADOW_STACK_SYSCALL=0"])
+
+if test "$fiber_asm" = 'yes'; then
+  AC_MSG_CHECKING([for fiber switching context])
+  PHP_ADD_SOURCES([Zend/asm],
+    [make_${fiber_asm_file}.S jump_${fiber_asm_file}.S],
+    [$fiber_asm_cflag])
+  AC_MSG_RESULT([$fiber_asm_file])
+else
+  AS_VAR_IF([fiber_os], [mac], [AC_DEFINE([_XOPEN_SOURCE], [1], [ ])])
+  AC_CHECK_HEADER([ucontext.h],
+    [AC_DEFINE([ZEND_FIBER_UCONTEXT], [1],
+      [Define to 1 if Zend fiber uses ucontext instead of boost context.])],
+    [AC_MSG_FAILURE([fibers not available on this platform])])
+fi
+
+ZEND_INIT
+
+ZEND_EXTRA_LIBS=$LIBS
+unset LIBS
+
+PHP_ADD_INCLUDE([$abs_srcdir], [1])
+PHP_ADD_INCLUDE([$abs_srcdir/main], [1])
+PHP_ADD_INCLUDE([$abs_builddir], [1])
+PHP_ADD_INCLUDE([$abs_builddir/main], [1])
+PHP_ADD_INCLUDE([$abs_builddir/TSRM])
+PHP_ADD_INCLUDE([$abs_builddir/Zend])
+PHP_ADD_INCLUDE([$abs_srcdir/Zend])
+PHP_ADD_INCLUDE([$abs_srcdir/TSRM])
+
+EXTRA_LDFLAGS="$EXTRA_LDFLAGS $LDFLAGS"
+EXTRA_LDFLAGS_PROGRAM="$EXTRA_LDFLAGS_PROGRAM $LDFLAGS"
+unset LDFLAGS
+
+AC_ARG_PROGRAM
+
+AS_VAR_IF([prefix], [NONE], [prefix=/usr/local])
+AS_VAR_IF([exec_prefix], [NONE], [exec_prefix='${prefix}'])
+AS_VAR_IF([program_prefix], [NONE], [program_prefix=])
+AS_VAR_IF([program_suffix], [NONE], [program_suffix=])
+
+orig_libdir=$libdir
+AS_CASE([$libdir],
+  ['${exec_prefix}/lib'], [libdir=$libdir/php])
+
+AS_CASE([$(eval echo $datadir)],
+  ['${prefix}/share'], [datadir=$datadir/php])
+
+phptempdir=$(pwd)/libs
+
+old_exec_prefix=$exec_prefix
+old_libdir=$libdir
+old_datadir=$datadir
+exec_prefix=$(eval echo $exec_prefix)
+libdir=$(eval echo $libdir)
+datadir=$(eval eval echo $datadir)
+
+dnl Build extension directory path.
+ZEND_MODULE_API_NO=$($EGREP '#define ZEND_MODULE_API_NO ' $srcdir/Zend/zend_modules.h|"${SED}" 's/#define ZEND_MODULE_API_NO //')
+
+AC_ARG_VAR([EXTENSION_DIR],
+  [Default directory for dynamically loadable PHP extensions. If left empty, it
+  is determined automatically. Can be overridden using the PHP 'extension_dir'
+  INI directive.])
+AS_VAR_IF([EXTENSION_DIR],, [
+  extbasedir=$ZEND_MODULE_API_NO
+  AS_VAR_IF([oldstyleextdir], [yes], [
+    AS_VAR_IF([PHP_DEBUG], [1], [part1=debug], [part1=no-debug])
+    AS_VAR_IF([PHP_THREAD_SAFETY], [yes], [part2=zts], [part2=non-zts])
+    extbasedir=$part1-$part2-$extbasedir
+    EXTENSION_DIR=$libdir/extensions/$extbasedir
+  ], [
+    AS_VAR_IF([PHP_THREAD_SAFETY], [yes], [extbasedir=$extbasedir-zts])
+    AS_VAR_IF([PHP_DEBUG], [1], [extbasedir=$extbasedir-debug])
+    EXTENSION_DIR=$libdir/$extbasedir
+  ])
+])
+
+AS_CASE([$PHP_LAYOUT],
+  [GNU], [datarootdir=$prefix/share],
+  [datarootdir=$prefix/php])
+
+dnl Expand all directory names for use in macros/constants.
+EXPANDED_PEAR_INSTALLDIR=$(eval echo $PEAR_INSTALLDIR)
+EXPANDED_EXTENSION_DIR=$(eval echo $EXTENSION_DIR)
+EXPANDED_LOCALSTATEDIR=$(eval echo $localstatedir)
+EXPANDED_BINDIR=$(eval echo $bindir)
+EXPANDED_SBINDIR=$(eval echo $sbindir)
+EXPANDED_MANDIR=$(eval echo $mandir)
+EXPANDED_LIBDIR=$libdir
+EXPANDED_SYSCONFDIR=$(eval echo $sysconfdir)
+EXPANDED_DATADIR=$datadir
+EXPANDED_PHP_CONFIG_FILE_PATH=$(eval echo "$PHP_CONFIG_FILE_PATH")
+EXPANDED_PHP_CONFIG_FILE_SCAN_DIR=$(eval echo "$PHP_CONFIG_FILE_SCAN_DIR")
+INCLUDE_PATH=.:$EXPANDED_PEAR_INSTALLDIR
+
+exec_prefix=$old_exec_prefix
+libdir=$old_libdir
+datadir=$old_datadir
+
+AC_SUBST([INCLUDE_PATH])
+AC_SUBST([EXPANDED_PEAR_INSTALLDIR])
+AC_SUBST([EXPANDED_EXTENSION_DIR])
+AC_SUBST([EXPANDED_BINDIR])
+AC_SUBST([EXPANDED_SBINDIR])
+AC_SUBST([EXPANDED_MANDIR])
+AC_SUBST([EXPANDED_LIBDIR])
+AC_SUBST([EXPANDED_DATADIR])
+AC_SUBST([EXPANDED_SYSCONFDIR])
+AC_SUBST([EXPANDED_LOCALSTATEDIR])
+AC_SUBST([EXPANDED_PHP_CONFIG_FILE_PATH])
+AC_SUBST([EXPANDED_PHP_CONFIG_FILE_SCAN_DIR])
+AC_SUBST([PHP_INSTALLED_SAPIS])
+AC_SUBST([SAPI_LIBNAME_SHARED])
+AC_SUBST([SAPI_LIBNAME_STATIC])
+AC_SUBST([PHP_VERSION])
+AC_SUBST([PHP_VERSION_ID])
+AC_SUBST([PHP_LDFLAGS])
+
+PHP_UTILIZE_RPATHS
+
+PHP_REMOVE_USR_LIB([PHP_LDFLAGS])
+PHP_REMOVE_USR_LIB([LDFLAGS])
+
+EXTRA_LDFLAGS="$EXTRA_LDFLAGS $PHP_LDFLAGS"
+EXTRA_LDFLAGS_PROGRAM="$EXTRA_LDFLAGS_PROGRAM $PHP_LDFLAGS"
+
+AC_ARG_VAR([PHP_UNAME],
+  [System information (defaults to the 'uname -a' output)])
+AS_VAR_IF([PHP_UNAME],, [PHP_UNAME=$(uname -a | xargs)])
+AC_DEFINE_UNQUOTED([PHP_UNAME], ["$PHP_UNAME"], [The 'uname -a' output.])
+
+PHP_OS=$(uname | xargs)
+AC_DEFINE_UNQUOTED([PHP_OS], ["$PHP_OS"], [The 'uname' output.])
+
+AC_ARG_VAR([PHP_BUILD_SYSTEM],
+  [The system that PHP was built on (defaults to the 'uname -a' output)])
+AS_VAR_IF([PHP_BUILD_SYSTEM],, [PHP_BUILD_SYSTEM=$PHP_UNAME])
+AC_DEFINE_UNQUOTED([PHP_BUILD_SYSTEM], ["$PHP_BUILD_SYSTEM"],
+  [The system that PHP was built on.])
+
+AC_ARG_VAR([PHP_BUILD_PROVIDER], [The PHP build provider information])
+AS_VAR_IF([PHP_BUILD_PROVIDER],,,
+  [AC_DEFINE_UNQUOTED([PHP_BUILD_PROVIDER], ["$PHP_BUILD_PROVIDER"],
+    [The PHP build provider information.])])
+
+AC_ARG_VAR([PHP_BUILD_COMPILER],
+  [Information about the compiler used for the PHP build])
+AS_VAR_IF([PHP_BUILD_COMPILER],,,
+  [AC_DEFINE_UNQUOTED([PHP_BUILD_COMPILER], ["$PHP_BUILD_COMPILER"],
+    [The compiler used for the PHP build.])])
+
+AC_ARG_VAR([PHP_BUILD_ARCH], [The build architecture])
+AS_VAR_IF([PHP_BUILD_ARCH],,,
+  [AC_DEFINE_UNQUOTED([PHP_BUILD_ARCH], ["$PHP_BUILD_ARCH"],
+    [The build architecture.])])
+
+PHP_SUBST([PHP_FASTCGI_OBJS])
+PHP_SUBST([PHP_SAPI_OBJS])
+PHP_SUBST([PHP_BINARY_OBJS])
+PHP_SUBST([PHP_GLOBAL_OBJS])
+PHP_SUBST([PHP_BINARIES])
+PHP_SUBST([PHP_MODULES])
+PHP_SUBST([PHP_ZEND_EX])
+PHP_SUBST([bindir])
+PHP_SUBST([sbindir])
+PHP_SUBST([exec_prefix])
+PHP_SUBST_OLD([program_prefix])
+PHP_SUBST_OLD([program_suffix])
+PHP_SUBST([includedir])
+PHP_SUBST_OLD([orig_libdir])
+PHP_SUBST([libdir])
+PHP_SUBST([mandir])
+PHP_SUBST([phptempdir])
+PHP_SUBST([prefix])
+PHP_SUBST([localstatedir])
+PHP_SUBST([datadir])
+PHP_SUBST([datarootdir])
+PHP_SUBST([sysconfdir])
+PHP_SUBST([EXEEXT])
+PHP_SUBST([CC])
+PHP_SUBST([BUILD_CC])
+PHP_SUBST([CFLAGS])
+PHP_SUBST([CFLAGS_CLEAN])
+PHP_SUBST([CPP])
+PHP_SUBST([CPPFLAGS])
+PHP_SUBST([CXX])
+PHP_SUBST([CXXFLAGS])
+PHP_SUBST([CXXFLAGS_CLEAN])
+PHP_SUBST_OLD([EXTENSION_DIR])
+PHP_SUBST([EXTRA_LDFLAGS])
+PHP_SUBST([EXTRA_LDFLAGS_PROGRAM])
+PHP_SUBST_OLD([EXTRA_LIBS])
+PHP_SUBST([ZEND_EXTRA_LIBS])
+PHP_SUBST([INCLUDES])
+PHP_SUBST([EXTRA_INCLUDES])
+PHP_SUBST([INSTALL_IT])
+PHP_SUBST([LIBTOOL])
+PHP_SUBST([LN_S])
+PHP_SUBST([NATIVE_RPATHS])
+PHP_SUBST([OVERALL_TARGET])
+PHP_SUBST([PHP_RPATHS])
+PHP_SUBST([PHP_SAPI])
+PHP_SUBST([SHELL])
+PHP_SUBST([PHP_FRAMEWORKS])
+PHP_SUBST([PHP_FRAMEWORKPATH])
+PHP_SUBST([INSTALL_HEADERS])
+
+if test "$PHP_THREAD_SAFETY" = "yes" && test -n "$ac_cv_pthreads_cflags"; then
+  CXXFLAGS="$CXXFLAGS $ac_cv_pthreads_cflags"
+  CPPFLAGS="$CPPFLAGS $ac_cv_pthreads_cflags"
+fi
+
+dnl Enable -Werror late, because it may break configure checks throwing warnings.
+AS_VAR_IF([PHP_WERROR], [yes], [
+  CFLAGS="$CFLAGS -Werror"
+  CXXFLAGS="$CXXFLAGS -Werror"
+])
+
+if test "$PHP_MEMORY_SANITIZER" = "yes" &&
+   test "$PHP_ADDRESS_SANITIZER" = "yes"; then
+   AC_MSG_ERROR([MemorySanitizer and AddressSanitizer are mutually exclusive])
+fi
+
+dnl Enable -fsanitize=memory late, because interceptors may break linking detection.
+AS_VAR_IF([PHP_MEMORY_SANITIZER], [yes],
+  [AX_CHECK_COMPILE_FLAG([-fsanitize=memory -fsanitize-memory-track-origins], [
+    CFLAGS="$CFLAGS -fsanitize=memory -fsanitize-memory-track-origins"
+    CXXFLAGS="$CXXFLAGS -fsanitize=memory -fsanitize-memory-track-origins"
+  ], [AC_MSG_ERROR([MemorySanitizer is not available])])
+])
+
+AS_VAR_IF([PHP_ADDRESS_SANITIZER], [yes],
+  [AS_VAR_IF([PHP_VALGRIND], [no],, [AC_MSG_ERROR(m4_text_wrap([
+    Valgrind and address sanitizer are not compatible. Either disable Valgrind
+    (remove --with-valgrind) or disable address sanitizer (remove
+    --enable-address-sanitizer).
+  ]))])
+
+  AX_CHECK_COMPILE_FLAG([-fsanitize=address], [
+    CFLAGS="$CFLAGS -fsanitize=address -DZEND_TRACK_ARENA_ALLOC"
+    CXXFLAGS="$CXXFLAGS -fsanitize=address -DZEND_TRACK_ARENA_ALLOC"
+  ], [AC_MSG_ERROR([AddressSanitizer is not available])])
+])
+
+AS_VAR_IF([PHP_UNDEFINED_SANITIZER], [yes],
+  [AX_CHECK_COMPILE_FLAG([-fsanitize=undefined], [
+    CFLAGS="$CFLAGS -fsanitize=undefined -fno-sanitize-recover=undefined"
+    CXXFLAGS="$CXXFLAGS -fsanitize=undefined -fno-sanitize-recover=undefined"
+    AX_CHECK_COMPILE_FLAG([-fno-sanitize=object-size], [
+      dnl Disable object-size sanitizer, because it is incompatible with our zend_function
+      dnl union, and this can't be easily fixed.
+      CFLAGS="$CFLAGS -fno-sanitize=object-size"
+      CXXFLAGS="$CFLAGS -fno-sanitize=object-size"
+    ])
+
+    dnl Clang 17 adds stricter function pointer compatibility checks where pointer args cannot be
+    dnl cast to void*. In that case, set -fno-sanitize=function.
+    OLD_CFLAGS=$CFLAGS
+    CFLAGS="$CFLAGS -fno-sanitize-recover=undefined"
+    AC_CACHE_CHECK([whether to add -fno-sanitize=function],
+    [php_cv_ubsan_no_function],
+    [AC_RUN_IFELSE([AC_LANG_SOURCE([
+      void foo(char *string) { (void)string; }
+      int main(void) {
+        void (*f)(void *) = (void (*)(void *))foo;
+        f("foo");
+        return 0;
+      }
+    ])],
+    [php_cv_ubsan_no_function=no],
+    [php_cv_ubsan_no_function=yes],
+    [php_cv_ubsan_no_function=no])])
+    CFLAGS=$OLD_CFLAGS
+    AS_VAR_IF([php_cv_ubsan_no_function], [yes], [
+      CFLAGS="$CFLAGS -fno-sanitize=function"
+      CXXFLAGS="$CFLAGS -fno-sanitize=function"
+    ])
+  ], [AC_MSG_ERROR([UndefinedBehaviorSanitizer is not available])])
+])
+
+if test "$PHP_MEMORY_SANITIZER" = "yes" ||
+   test "$PHP_ADDRESS_SANITIZER" = "yes" ||
+   test "$PHP_UNDEFINED_SANITIZER" = "yes"; then
+    CFLAGS="$CFLAGS -fno-omit-frame-pointer"
+    CXXFLAGS="$CXXFLAGS -fno-omit-frame-pointer"
+fi
+
+dnl
+dnl Libtool creation.
+dnl
+
+PHP_HELP_SEPARATOR([Libtool:])
+PHP_CONFIGURE_PART([Configuring libtool])
+
+dnl Silence warning: "ar: 'u' modifier ignored since 'D' is the default".
+dnl See https://github.com/php/php-src/pull/3017
+AC_SUBST([AR_FLAGS], [cr])
+
+dnl Only allow AC_PROG_CXX and AC_PROG_CXXCPP if they are explicitly called (by
+dnl PHP_REQUIRE_CXX). Otherwise AC_PROG_LIBTOOL fails if there is no working C++
+dnl compiler.
+AC_PROVIDE_IFELSE([PHP_REQUIRE_CXX], [], [
+  undefine([AC_PROG_CXX])
+  AC_DEFUN([AC_PROG_CXX], [])
+  undefine([AC_PROG_CXXCPP])
+  AC_DEFUN([AC_PROG_CXXCPP], [php_prog_cxxcpp=disabled])
+])
+AC_PROG_LIBTOOL
+
+PHP_SET_LIBTOOL_VARIABLE([--silent])
+
+dnl libtool 1.4.3 needs this.
+PHP_SET_LIBTOOL_VARIABLE([--preserve-dup-deps])
+
+PHP_CONFIGURE_PART([Generating files])
+
+CXXFLAGS_CLEAN=$CXXFLAGS
+CFLAGS_CLEAN="$CFLAGS \$(PROF_FLAGS)"
+CFLAGS="\$(CFLAGS_CLEAN) $standard_libtool_flag"
+CXXFLAGS="$CXXFLAGS $standard_libtool_flag \$(PROF_FLAGS)"
+
+if test "$PHP_PHAR" != "no" && test "$PHP_CLI" != "no"; then
+  pharcmd=pharcmd
+  pharcmd_install=install-pharcmd
+else
+  pharcmd=
+  pharcmd_install=
+fi;
+
+all_targets="\$(OVERALL_TARGET) \$(PHP_MODULES) \$(PHP_ZEND_EX) \$(PHP_BINARIES) $pharcmd"
+install_targets="$install_sapi $install_modules $install_binaries install-build install-headers install-programs $install_pear $pharcmd_install"
+
+PHP_SUBST([all_targets])
+PHP_SUBST([install_targets])
+PHP_SUBST([install_binary_targets])
+
+PHP_INSTALL_HEADERS([Zend/ TSRM/ main/ main/streams/])
+PHP_INSTALL_HEADERS([Zend/Optimizer], m4_normalize([
+  zend_call_graph.h
+  zend_cfg.h
+  zend_dfg.h
+  zend_dump.h
+  zend_func_info.h
+  zend_inference.h
+  zend_optimizer.h
+  zend_ssa.h
+  zend_worklist.h
+]))
+
+PHP_ADD_SOURCES([TSRM], [TSRM.c], [-DZEND_ENABLE_STATIC_TSRMLS_CACHE=1])
+
+PHP_ADD_SOURCES([main], m4_normalize([
+    explicit_bzero.c
+    fopen_wrappers.c
+    getopt.c
+    main.c
+    network.c
+    output.c
+    php_content_types.c
+    php_ini_builder.c
+    php_ini.c
+    php_odbc_utils.c
+    php_open_temporary_file.c
+    php_scandir.c
+    php_syslog.c
+    php_ticks.c
+    php_variables.c
+    reentrancy.c
+    rfc1867.c
+    safe_bcmp.c
+    SAPI.c
+    snprintf.c
+    spprintf.c
+    strlcat.c
+    strlcpy.c
+  ]),
+  [-DZEND_ENABLE_STATIC_TSRMLS_CACHE=1])
+
+if printf "#if __ELF__\nelf\n#endif\n" | $CC -E - | grep elf > /dev/null; then
+  PHP_ADD_SOURCES([main], [debug_gdb_scripts.c])
+
+  cat >> Makefile.objects <<EOF
+$abs_srcdir/main/debug_gdb_scripts.c: $abs_srcdir/scripts/gdb/debug_gdb_scripts_gen.php $abs_srcdir/scripts/gdb/php_gdb.py $abs_srcdir/.gdbinit
+	@if test ! -z "\$(PHP)"; then \\
+		\$(PHP) $abs_srcdir/scripts/gdb/debug_gdb_scripts_gen.php; \\
+	fi;
+EOF
+fi
+
+PHP_ADD_SOURCES_X([main],
+  [fastcgi.c],
+  [-DZEND_ENABLE_STATIC_TSRMLS_CACHE=1],
+  [PHP_FASTCGI_OBJS],
+  [no])
+
+PHP_ADD_SOURCES([main/streams], m4_normalize([
+    cast.c
+    filter.c
+    glob_wrapper.c
+    memory.c
+    mmap.c
+    plain_wrapper.c
+    streams.c
+    transports.c
+    userspace.c
+    xp_socket.c
+  ]),
+  [-DZEND_ENABLE_STATIC_TSRMLS_CACHE=1])
+
+PHP_ADD_SOURCES([/main],
+  [internal_functions.c],
+  [-DZEND_ENABLE_STATIC_TSRMLS_CACHE=1],
+  [sapi])
+PHP_ADD_SOURCES_X([/main],
+  [internal_functions_cli.c],
+  [-DZEND_ENABLE_STATIC_TSRMLS_CACHE=1],
+  [PHP_BINARY_OBJS])
+
+PHP_ADD_SOURCES([Zend], m4_normalize([
+    Optimizer/block_pass.c
+    Optimizer/compact_literals.c
+    Optimizer/compact_vars.c
+    Optimizer/dce.c
+    Optimizer/dfa_pass.c
+    Optimizer/escape_analysis.c
+    Optimizer/nop_removal.c
+    Optimizer/optimize_func_calls.c
+    Optimizer/optimize_temp_vars_5.c
+    Optimizer/pass1.c
+    Optimizer/pass3.c
+    Optimizer/sccp.c
+    Optimizer/scdf.c
+    Optimizer/zend_call_graph.c
+    Optimizer/zend_cfg.c
+    Optimizer/zend_dfg.c
+    Optimizer/zend_dump.c
+    Optimizer/zend_func_info.c
+    Optimizer/zend_inference.c
+    Optimizer/zend_optimizer.c
+    Optimizer/zend_ssa.c
+    zend_alloc.c
+    zend_API.c
+    zend_ast.c
+    zend_atomic.c
+    zend_attributes.c
+    zend_builtin_functions.c
+    zend_call_stack.c
+    zend_closures.c
+    zend_compile.c
+    zend_constants.c
+    zend_cpuinfo.c
+    zend_default_classes.c
+    zend_dtrace.c
+    zend_enum.c
+    zend_exceptions.c
+    zend_execute_API.c
+    zend_execute.c
+    zend_extensions.c
+    zend_fibers.c
+    zend_float.c
+    zend_frameless_function.c
+    zend_gc.c
+    zend_gdb.c
+    zend_generators.c
+    zend_hash.c
+    zend_highlight.c
+    zend_hrtime.c
+    zend_inheritance.c
+    zend_ini_parser.c
+    zend_ini_scanner.c
+    zend_ini.c
+    zend_interfaces.c
+    zend_iterators.c
+    zend_language_parser.c
+    zend_language_scanner.c
+    zend_lazy_objects.c
+    zend_list.c
+    zend_llist.c
+    zend_max_execution_timer.c
+    zend_multibyte.c
+    zend_object_handlers.c
+    zend_objects_API.c
+    zend_objects.c
+    zend_observer.c
+    zend_opcode.c
+    zend_operators.c
+    zend_property_hooks.c
+    zend_ptr_stack.c
+    zend_signal.c
+    zend_smart_str.c
+    zend_sort.c
+    zend_stack.c
+    zend_stream.c
+    zend_string.c
+    zend_strtod.c
+    zend_system_id.c
+    zend_variables.c
+    zend_virtual_cwd.c
+    zend_vm_opcodes.c
+    zend_weakrefs.c
+    zend.c
+  ]),
+  [-DZEND_ENABLE_STATIC_TSRMLS_CACHE=1 $fiber_asm_cflag])
+
+PHP_ADD_MAKEFILE_FRAGMENT([$abs_srcdir/scripts/Makefile.frag],
+  [$abs_srcdir/scripts],
+  [scripts])
+PHP_ADD_MAKEFILE_FRAGMENT([$abs_srcdir/Zend/Makefile.frag],
+  [$abs_srcdir/Zend],
+  [Zend])
+
+AC_DEFINE([HAVE_BUILD_DEFS_H], [1],
+  [Define to 1 if PHP has the <main/build-defs.h> header file.])
+
+PHP_ADD_BUILD_DIR([
+  main
+  main/streams
+  scripts
+  scripts/man1
+  TSRM
+  Zend
+  Zend/asm
+  Zend/Optimizer
+])
+
+AC_CONFIG_FILES([
+  main/build-defs.h
+  scripts/man1/php-config.1
+  scripts/man1/phpize.1
+  scripts/php-config
+  scripts/phpize
+])
+
+AC_CONFIG_COMMANDS_PRE([PHP_PATCH_CONFIG_HEADERS([main/php_config.h.in])])
+
+AC_CONFIG_COMMANDS([Zend/zend_config.h], [
+cat >Zend/zend_config.h <<FEO
+#include <../main/php_config.h>
+FEO
+])
+
+AC_CONFIG_COMMANDS([main/internal_functions.c], [], [
+  AWK="$AWK" $SHELL $srcdir/build/genif.sh \
+    $srcdir/main/internal_functions.c.in \
+    "$EXT_STATIC" > main/internal_functions.c
+])
+
+AC_CONFIG_COMMANDS([main/internal_functions_cli.c], [], [
+  AWK="$AWK" $SHELL $srcdir/build/genif.sh \
+    $srcdir/main/internal_functions.c.in \
+    "$EXT_CLI_STATIC" > main/internal_functions_cli.c
+])
+
+AC_CONFIG_COMMANDS([default], [
+cat <<X
+
++--------------------------------------------------------------------+
+| License:                                                           |
+| This software is subject to the PHP License, available in this     |
+| distribution in the file LICENSE. By continuing this installation  |
+| process, you are bound by the terms of this license agreement.     |
+| If you do not agree with the terms of this license, you must abort |
+| the installation process at this point.                            |
++--------------------------------------------------------------------+
+
+Thank you for using PHP.
+
+X
+])
+AC_OUTPUT
diff '--color=auto' -Naur php-8.4.18/ext/bz2/bz2.c php-8.4.20RC1/ext/bz2/bz2.c
--- php-8.4.18/ext/bz2/bz2.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/bz2/bz2.c	2026-04-01 04:35:35.992171351 +0000
@@ -502,11 +502,7 @@
 	size_t source_len;
 	int error;
 	bool small = 0;
-#ifdef PHP_WIN32
-	unsigned __int64 size = 0;
-#else
-	unsigned long long size = 0;
-#endif
+	uint64_t size = 0;
 	bz_stream bzs;
 
 	if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "s|b", &source, &source_len, &small)) {
@@ -531,27 +527,22 @@
 	while ((error = BZ2_bzDecompress(&bzs)) == BZ_OK && bzs.avail_in > 0) {
 		/* compression is better then 2:1, need to allocate more memory */
 		bzs.avail_out = source_len;
-		size = (bzs.total_out_hi32 * (unsigned int) -1) + bzs.total_out_lo32;
-#ifndef ZEND_ENABLE_ZVAL_LONG64
+		size = (((uint64_t) bzs.total_out_hi32) << 32U) + bzs.total_out_lo32;
 		if (size > SIZE_MAX) {
 			/* no reason to continue if we're going to drop it anyway */
 			break;
 		}
-#endif
 		dest = zend_string_safe_realloc(dest, 1, bzs.avail_out+1, (size_t) size, 0);
 		bzs.next_out = ZSTR_VAL(dest) + size;
 	}
 
 	if (error == BZ_STREAM_END || error == BZ_OK) {
-		size = (bzs.total_out_hi32 * (unsigned int) -1) + bzs.total_out_lo32;
-#ifndef ZEND_ENABLE_ZVAL_LONG64
+		size = (((uint64_t) bzs.total_out_hi32) << 32U) + bzs.total_out_lo32;
 		if (UNEXPECTED(size > SIZE_MAX)) {
 			php_error_docref(NULL, E_WARNING, "Decompressed size too big, max is %zd", SIZE_MAX);
 			zend_string_efree(dest);
 			RETVAL_LONG(BZ_MEM_ERROR);
-		} else
-#endif
-		{
+		} else {
 			dest = zend_string_safe_realloc(dest, 1, (size_t)size, 1, 0);
 			ZSTR_LEN(dest) = (size_t)size;
 			ZSTR_VAL(dest)[(size_t)size] = '\0';
diff '--color=auto' -Naur php-8.4.18/ext/bz2/tests/gh20620.phpt php-8.4.20RC1/ext/bz2/tests/gh20620.phpt
--- php-8.4.18/ext/bz2/tests/gh20620.phpt	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/bz2/tests/gh20620.phpt	2026-04-01 04:35:35.992272473 +0000
@@ -4,6 +4,7 @@
 bz2
 --SKIPIF--
 <?php 
+if (!getenv('RUN_RESOURCE_HEAVY_TESTS')) die('skip resource-heavy test');
 if (PHP_INT_SIZE != 8) die('skip this test is for 64bit platforms only'); 
 if (getenv('SKIP_SLOW_TESTS')) die('skip slow tests excluded by request');
 ?>
diff '--color=auto' -Naur php-8.4.18/ext/bz2/tests/gh20807.phpt php-8.4.20RC1/ext/bz2/tests/gh20807.phpt
--- php-8.4.18/ext/bz2/tests/gh20807.phpt	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/ext/bz2/tests/gh20807.phpt	2026-04-01 04:35:35.992361431 +0000
@@ -0,0 +1,21 @@
+--TEST--
+Truncation of total output size causing erroneous size and data
+--EXTENSIONS--
+bz2
+--INI--
+memory_limit=-1
+--SKIPIF--
+<?php
+if (!getenv('RUN_RESOURCE_HEAVY_TESTS')) die('skip resource-heavy test');
+if (getenv("SKIP_SLOW_TESTS")) die('skip slow test');
+if (PHP_OS === 'FreeBSD') die('skip Worker does not handle OOM gracefully');
+if (PHP_OS_FAMILY === 'Darwin') die('skip Too slow');
+if (PHP_INT_SIZE !== 8) die('skip Only for 64-bit systems');
+if (getenv('SKIP_ASAN')) die('skip ASAN makes this test too slow');
+?>
+--FILE--
+<?php
+var_dump(sha1(bzdecompress(base64_decode("QlpoOTFBWSZTWei3pg8BX44IAMAAAAggADCATUZCoCWpCoCXMUFZJlNZ6LemDwFfjggAwAAACCAAMIBNRkKgJakKgJcxQVkmU1not6YPAV+OCADAAAAIIAAwgE1GQqAlqQqAlzFBWSZTWei3pg8BX44IAMAAAAggADCATUZCoCWpCoCXMUFZJlNZ6LemDwFfjggAwAAACCAAMIBNRkKgJakKgJcxQVkmU1not6YPAV+OCADAAAAIIAAwgE1GQqAlqQqAlzFBWSZTWei3pg8BX44IAMAAAAggADCATUZCoCWpCoCXMUFZJlNZ6LemDwFfjggAwAAACCAAMIBNRkKgJakKgJcxQVkmU1not6YPAV+OCADAAAAIIAAwgE1GQqAlqQqAlzFBWSZTWei3pg8BX44IAMAAAAggADCATUZCoCWpCoCXMUFZJlNZ6LemDwFfjggAwAAACCAAMIBNRkKgJakKgJcxQVkmU1not6YPAV+OCADAAAAIIAAwgE1GQqAlqQqAlzFBWSZTWei3pg8BX44IAMAAAAggADCATUZCoCWpCoCXMUFZJlNZ6LemDwFfjggAwAAACCAAMIBNRkKgJakKgJcxQVkmU1not6YPAV+OCADAAAAIIAAwgE1GQqAlqQqAlzFBWSZTWei3pg8BX44IAMAAAAggADCATUZCoCWpCoCXMUFZJlNZ6LemDwFfjggAwAAACCAAMIBNRkKgJakKgJcxQVkmU1not6YPAV+OCADAAAAIIAAwgE1GQqAlqQqAlzFBWSZTWei3pg8BX44IAMAAAAggADCATUZCoCWpCoCXMUFZJlNZ6LemDwFfjggAwAAACCAAMIBNRkKgJakKgJcxQVkmU1not6YPAV+OCADAAAAIIAAwgE1GQqAlqQqAlzFBWSZTWei3pg8BX44IAMAAAAggADCATUZCoCWpCoCXMUFZJlNZ6LemDwFfjggAwAAACCAAMIBNRkKgJakKgJcxQVkmU1kuvJCFAIpSiADgBAAIIABwM00E1SepopKSrpQIKdEKSTZKIArRSUlXCFJJ8xQVkmU1ntbvo0AV+OCACgAAAIIAAwgE1GQqAlqQqAlzFBWSZTWe1u+jQBX44IAKAAAAggADCATUZCoCWpCoCXMUFZJlNZ7W76NAFfjggAoAAACCAAMIBNRkKgJakKgJcxQVkmU1ntbvo0AV+OCACgAAAIIAAwgE1GQqAlqQqAlzFBWSZTWe1u+jQBX44IAKAAAAggADCATUZCoCWpCoCXMUFZJlNZ7W76NAFfjggAoAAACCAAMIBNRkKgJakKgJcxQVkmU1ntbvo0AV+OCACgAAAIIAAwgE1GQqAlqQqAlzFBWSZTWe1u+jQBX44IAKAAAAggADCATUZCoCWpCoCXMUFZJlNZ7W76NAFfjggAoAAACCAAMIBNRkKgJakKgJcxQVkmU1ntbvo0AV+OCACgAAAIIAAwgE1GQqAlqQqAlzFBWSZTWe1u+jQBX44IAKAAAAggADCATUZCoCWpCoCXMUFZJlNZ7W76NAFfjggAoAAACCAAMIBNRkKgJakKgJcxQVkmU1ntbvo0AV+OCACgAAAIIAAwgE1GQqAlqQqAlzFBWSZTWe1u+jQBX44IAKAAAAggADCATUZCoCWpCoCXMUFZJlNZ7W76NAFfjggAoAAACCAAMIBNRkKgJakKgJcxQVkmU1ntbvo0AV+OCACgAAAIIAAwgE1GQqAlqQqAlzFBWSZTWe1u+jQBX44IAKAAAAggADCATUZCoCWpCoCXMUFZJlNZ7W76NAFfjggAoAAACCAAMIBNRkKgJakKgJcxQVkmU1ntbvo0AV+OCACgAAAIIAAwgE1GQqAlqQqAlzFBWSZTWe1u+jQBX44IAKAAAAggADCATUZCoCWpCoCXMUFZJlNZ7W76NAFfjggAoAAACCAAMIBNRkKgJakKgJcxQVkmU1ntbvo0AV+OCACgAAAIIAAwgE1GQqAlqQqAlzFBWSZTWTNWeUMBFKWIALAEAAggAGoKUAUqPTiiRIYRVSqLAlSRtRUgViiRIehKkjzFBWSZTWeMFHnkBX44IAJAAAAggADCATUZCoCWpCoCXMUFZJlNZ4wUeeQFfjggAkAAACCAAMIBNRkKgJakKgJcxQVkmU1njBR55AV+OCACQAAAIIAAwgE1GQqAlqQqAlzFBWSZTWeMFHnkBX44IAJAAAAggADCATUZCoCWpCoCXMUFZJlNZ4wUeeQFfjggAkAAACCAAMIBNRkKgJakKgJcxQVkmU1njBR55AV+OCACQAAAIIAAwgE1GQqAlqQqAlzFBWSZTWeMFHnkBX44IAJAAAAggADCATUZCoCWpCoCXMUFZJlNZ4wUeeQFfjggAkAAACCAAMIBNRkKgJakKgJcxQVkmU1njBR55AV+OCACQAAAIIAAwgE1GQqAlqQqAlzFBWSZTWeMFHnkBX44IAJAAAAggADCATUZCoCWpCoCXMUFZJlNZ4wUeeQFfjggAkAAACCAAMIBNRkKgJakKgJcxQVkmU1njBR55AV+OCACQAAAIIAAwgE1GQqAlqQqAlzFBWSZTWeMFHnkBX44IAJAAAAggADCATUZCoCWpCoCXMUFZJlNZ4wUeeQFfjggAkAAACCAAMIBNRkKgJakKgJcxQVkmU1njBR55AV+OCACQAAAIIAAwgE1GQqAlqQqAlzFBWSZTWeMFHnkBX44IAJAAAAggADCATUZCoCWpCoCXMUFZJlNZ4wUeeQFfjggAkAAACCAAMIBNRkKgJakKgJcxQVkmU1njBR55AV+OCACQAAAIIAAwgE1GQqAlqQqAlzFBWSZTWeMFHnkBX44IAJAAAAggADCATUZCoCWpCoCXMUFZJlNZ4wUeeQFfjggAkAAACCAAMIBNRkKgJakKgJcxQVkmU1njBR55AV+OCACQAAAIIAAwgE1GQqAlqQqAlzFBWSZTWeMFHnkBX44IAJAAAAggADCATUZCoCWpCoCXMUFZJlNZ4wUeeQFfjggAkAAACCAAMIBNRkKgJakKgJcxQVkmU1mtxU0XAD9qCACYBAAIIABwM00ClJ6mklKq6qqFVOqEAjYUoClpJSquEQCPmKCskyms824hIQCvxwQARAAABBAAGEAmoyFQEtSFQEuYoKyTKazzbiEhAK/HBABEAAAEEAAYQCajIVAS1IVAS5igrJMprPNuISEAr8cEAEQAAAQQABhAJqMhUBLUhUBLmKCskyms824hIQCvxwQARAAABBAAGEAmoyFQEtSFQEuYoKyTKazzbiEhAK/HBABEAAAEEAAYQCajIVAS1IVAS5igrJMprPNuISEAr8cEAEQAAAQQABhAJqMhUBLUhUBLmKCskyms824hIQCvxwQARAAABBAAGEAmoyFQEtSFQEuYoKyTKazzbiEhAK/HBABEAAAEEAAYQCajIVAS1IVAS5igrJMprPNuISEAr8cEAEQAAAQQABhAJqMhUBLUhUBLmKCskyms824hIQCvxwQARAAABBAAGEAmoyFQEtSFQEuYoKyTKazzbiEhAK/HBABEAAAEEAAYQCajIVAS1IVAS5igrJMprPNuISEAr8cEAEQAAAQQABhAJqMhUBLUhUBLmKCskyms824hIQCvxwQARAAABBAAGEAmoyFQEtSFQEuYoKyTKazzbiEhAK/HBABEAAAEEAAYQCajIVAS1IVAS5igrJMprPNuISEAr8cEAEQAAAQQABhAJqMhUBLUhUBLmKCskyms824hIQCvxwQARAAABBAAGEAmoyFQEtSFQEuYoKyTKazzbiEhAK/HBABEAAAEEAAYQCajIVAS1IVAS5igrJMprPNuISEAr8cEAEQAAAQQABhAJqMhUBLUhUBLmKCskyms824hIQCvxwQARAAABBAAGEAmoyFQEtSFQEuYoKyTKazzbiEhAK/HBABEAAAEEAAYQCajIVAS1IVAS5igrJMprPNuISEAr8cEAEQAAAQQABhAJqMhUBLUhUBLmKCskyms824hIQCvxwQARAAABBAAGEAmoyFQEtSFQEuYoKyTKayOlbYVgGTehABGAgAEEAA4GaaCapPUxBFKcqFISuVSElbRQlVGIIpTpUhJXzFBWSZTWf/S1uMBX44IAIQAAAggADCATUZCoCWpCoCXMUFZJlNZ/9LW4wFfjggAhAAACCAAMIBNRkKgJakKgJcxQVkmU1n/0tbjAV+OCACEAAAIIAAwgE1GQqAlqQqAlzFBWSZTWf/S1uMBX44IAIQAAAggADCATUZCoCWpCoCXMUFZJlNZ/9LW4wFfjggAhAAACCAAMIBNRkKgJakKgJcxQVkmU1n/0tbjAV+OCACEAAAIIAAwgE1GQqAlqQqAlzFBWSZTWf/S1uMBX44IAIQAAAggADCATUZCoCWpCoCXMUFZJlNZ/9LW4wFfjggAhAAACCAAMIBNRkKgJakKgJcxQVkmU1n/0tbjAV+OCACEAAAIIAAwgE1GQqAlqQqAlzFBWSZTWf/S1uMBX44IAIQAAAggADCATUZCoCWpCoCXMUFZJlNZ/9LW4wFfjggAhAAACCAAMIBNRkKgJakKgJcxQVkmU1n/0tbjAV+OCACEAAAIIAAwgE1GQqAlqQqAlzFBWSZTWf/S1uMBX44IAIQAAAggADCATUZCoCWpCoCXMUFZJlNZ/9LW4wFfjggAhAAACCAAMIBNRkKgJakKgJcxQVkmU1n/0tbjAV+OCACEAAAIIAAwgE1GQqAlqQqAlzFBWSZTWf/S1uMBX44IAIQAAAggADCATUZCoCWpCoCXMUFZJlNZ/9LW4wFfjggAhAAACCAAMIBNRkKgJakKgJcxQVkmU1n/0tbjAV+OCACEAAAIIAAwgE1GQqAlqQqAlzFBWSZTWf/S1uMBX44IAIQAAAggADCATUZCoCWpCoCXMUFZJlNZ/9LW4wFfjggAhAAACCAAMIBNRkKgJakKgJcxQVkmU1n/0tbjAV+OCACEAAAIIAAwgE1GQqAlqQqAlzFBWSZTWf/S1uMBX44IAIQAAAggADCATUZCoCWpCoCXMUFZJlNZ9EMghAFUEAgAhgQACCAAUGaaBSk9TQQJJ1CgqqupVSmxKohoIEk4qqU+YoKyTKaz9BcVsAK/HBABBAAAEEAAYQCajIVAS1IVAS5igrJMprP0FxWwAr8cEAEEAAAQQABhAJqMhUBLUhUBLmKCskyms/QXFbACvxwQAQQAABBAAGEAmoyFQEtSFQEuYoKyTKaz9BcVsAK/HBABBAAAEEAAYQCajIVAS1IVAS5igrJMprP0FxWwAr8cEAEEAAAQQABhAJqMhUBLUhUBLmKCskyms/QXFbACvxwQAQQAABBAAGEAmoyFQEtSFQEuYoKyTKaz9BcVsAK/HBABBAAAEEAAYQCajIVAS1IVAS5igrJMprP0FxWwAr8cEAEEAAAQQABhAJqMhUBLUhUBLmKCskyms/QXFbACvxwQAQQAABBAAGEAmoyFQEtSFQEuYoKyTKaz9BcVsAK/HBABBAAAEEAAYQCajIVAS1IVAS5igrJMprP0FxWwAr8cEAEEAAAQQABhAJqMhUBLUhUBLmKCskyms/QXFbACvxwQAQQAABBAAGEAmoyFQEtSFQEuYoKyTKaz9BcVsAK/HBABBAAAEEAAYQCajIVAS1IVAS5igrJMprP0FxWwAr8cEAEEAAAQQABhAJqMhUBLUhUBLmKCskyms/QXFbACvxwQAQQAABBAAGEAmoyFQEtSFQEuYoKyTKaz9BcVsAK/HBABBAAAEEAAYQCajIVAS1IVAS5igrJMprP0FxWwAr8cEAEEAAAQQABhAJqMhUBLUhUBLmKCskyms/QXFbACvxwQAQQAABBAAGEAmoyFQEtSFQEuYoKyTKaz9BcVsAK/HBABBAAAEEAAYQCajIVAS1IVAS5igrJMprP0FxWwAr8cEAEEAAAQQABhAJqMhUBLUhUBLmKCskyms/QXFbACvxwQAQQAABBAAGEAmoyFQEtSFQEuYoKyTKaz9BcVsAK/HBABBAAAEEAAYQCajIVAS1IVAS5igrJMprP0FxWwAr8cEAEEAAAQQABhAJqMhUBLUhUBLmKCskymsiUnBUgA/akQAQYIABBAAOBmmgmqT1NJIgdAKgXShKqNlEqVJaSRA4oSqj5igrJMprPowN0qAr8cEAECAAAQQABhAJqMhUBLUhUBLmKCskyms+jA3SoCvxwQAQIAABBAAGEAmoyFQEtSFQEuYoKyTKaz6MDdKgK/HBABAgAAEEAAYQCajIVAS1IVAS5igrJMprPowN0qAr8cEAECAAAQQABhAJqMhUBLUhUBLmKCskyms+jA3SoCvxwQAQIAABBAAGEAmoyFQEtSFQEuYoKyTKaz6MDdKgK/HBABAgAAEEAAYQCajIVAS1IVAS5igrJMprPowN0qAr8cEAECAAAQQABhAJqMhUBLUhUBLmKCskyms+jA3SoCvxwQAQIAABBAAGEAmoyFQEtSFQEuYoKyTKaz6MDdKgK/HBABAgAAEEAAYQCajIVAS1IVAS5igrJMprPowN0qAr8cEAECAAAQQABhAJqMhUBLUhUBLmKCskyms+jA3SoCvxwQAQIAABBAAGEAmoyFQEtSFQEuYoKyTKaz6MDdKgK/HBABAgAAEEAAYQCajIVAS1IVAS5igrJMprPowN0qAr8cEAECAAAQQABhAJqMhUBLUhUBLmKCskyms+jA3SoCvxwQAQIAABBAAGEAmoyFQEtSFQEuYoKyTKaz6MDdKgK/HBABAgAAEEAAYQCajIVAS1IVAS5igrJMprPowN0qAr8cEAECAAAQQABhAJqMhUBLUhUBLmKCskyms+jA3SoCvxwQAQIAABBAAGEAmoyFQEtSFQEuYoKyTKaz6MDdKgK/HBABAgAAEEAAYQCajIVAS1IVAS5igrJMprPowN0qAr8cEAECAAAQQABhAJqMhUBLUhUBLmKCskyms+jA3SoCvxwQAQIAABBAAGEAmoyFQEtSFQEuYoKyTKaz6MDdKgK/HBABAgAAEEAAYQCajIVAS1IVAS5igrJMprPowN0qAr8cEAECAAAQQABhAJqMhUBLUhUBLmKCskyms4qxPEQCEk8QAQMIABBAAOBmmgUpPUwSIg4KpShcUUUm1RRQGCREHSiik+YoKyTKaz43JlXAK/HBABAQAAEEAAYQCajIVAS1IVAS5igrJMprPjcmVcAr8cEAEBAAAQQABhAJqMhUBLUhUBLmKCskyms+NyZVwCvxwQAQEAABBAAGEAmoyFQEtSFQEuYoKyTKaz43JlXAK/HBABAQAAEEAAYQCajIVAS1IVAS5igrJMprPjcmVcAr8cEAEBAAAQQABhAJqMhUBLUhUBLmKCskyms+NyZVwCvxwQAQEAABBAAGEAmoyFQEtSFQEuYoKyTKaz43JlXAK/HBABAQAAEEAAYQCajIVAS1IVAS5igrJMprPjcmVcAr8cEAEBAAAQQABhAJqMhUBLUhUBLmKCskyms+NyZVwCvxwQAQEAABBAAGEAmoyFQEtSFQEuYoKyTKaz43JlXAK/HBABAQAAEEAAYQCajIVAS1IVAS5igrJMprPjcmVcAr8cEAEBAAAQQABhAJqMhUBLUhUBLmKCskyms+NyZVwCvxwQAQEAABBAAGEAmoyFQEtSFQEuYoKyTKaz43JlXAK/HBABAQAAEEAAYQCajIVAS1IVAS5igrJMprPjcmVcAr8cEAEBAAAQQABhAJqMhUBLUhUBLmKCskyms+NyZVwCvxwQAQEAABBAAGEAmoyFQEtSFQEuYoKyTKaz43JlXAK/HBABAQAAEEAAYQCajIVAS1IVAS5igrJMprPjcmVcAr8cEAEBAAAQQABhAJqMhUBLUhUBLmKCskyms+NyZVwCvxwQAQEAABBAAGEAmoyFQEtSFQEuYoKyTKaz43JlXAK/HBABAQAAEEAAYQCajIVAS1IVAS5igrJMprPjcmVcAr8cEAEBAAAQQABhAJqMhUBLUhUBLmKCskyms+NyZVwCvxwQAQEAABBAAGEAmoyFQEtSFQEuYoKyTKaz43JlXAK/HBABAQAAEEAAYQCajIVAS1IVAS5igrJMprPjcmVcAr8cEAEBAAAQQABhAJqMhUBLUhUBLmKCskymswVrRDAAZ9gQAQEIABBAAGGYE1TTVECm1KIFPF3JFOFCQLW69vQ"))));
+?>
+--EXPECT--
+string(40) "d4b5e52ed34a774fa645f94369b0c61375436d30"
diff '--color=auto' -Naur php-8.4.18/ext/curl/interface.c php-8.4.20RC1/ext/curl/interface.c
--- php-8.4.18/ext/curl/interface.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/curl/interface.c	2026-04-01 04:35:35.992524208 +0000
@@ -583,7 +583,7 @@
 			return fwrite(data, size, nmemb, write_handler->fp);
 		case PHP_CURL_RETURN:
 			if (length > 0) {
-				smart_str_appendl(&write_handler->buf, data, (int) length);
+				smart_str_appendl(&write_handler->buf, data, length);
 			}
 			break;
 		case PHP_CURL_USER: {
@@ -621,6 +621,10 @@
 	zval argv[3];
 	zval retval;
 
+	if (!ZEND_FCC_INITIALIZED(ch->handlers.fnmatch)) {
+		return rval;
+	}
+
 	GC_ADDREF(&ch->std);
 	ZVAL_OBJ(&argv[0], &ch->std);
 	ZVAL_STRING(&argv[1], pattern);
@@ -652,6 +656,9 @@
 	fprintf(stderr, "curl_progress() called\n");
 	fprintf(stderr, "clientp = %x, dltotal = %f, dlnow = %f, ultotal = %f, ulnow = %f\n", clientp, dltotal, dlnow, ultotal, ulnow);
 #endif
+	if (!ZEND_FCC_INITIALIZED(ch->handlers.progress)) {
+		return rval;
+	}
 
 	zval args[5];
 	zval retval;
@@ -690,6 +697,9 @@
 	fprintf(stderr, "curl_xferinfo() called\n");
 	fprintf(stderr, "clientp = %x, dltotal = %ld, dlnow = %ld, ultotal = %ld, ulnow = %ld\n", clientp, dltotal, dlnow, ultotal, ulnow);
 #endif
+	if (!ZEND_FCC_INITIALIZED(ch->handlers.xferinfo)) {
+		return rval;
+	}
 
 	zval argv[5];
 	zval retval;
@@ -850,7 +860,7 @@
 			if (!Z_ISUNDEF(retval)) {
 				_php_curl_verify_handlers(ch, /* reporterror */ true);
 				if (Z_TYPE(retval) == IS_STRING) {
-					length = MIN((size * nmemb), Z_STRLEN(retval));
+					length = MIN(size * nmemb, Z_STRLEN(retval));
 					memcpy(data, Z_STRVAL(retval), length);
 				} else if (Z_TYPE(retval) == IS_LONG) {
 					length = Z_LVAL_P(&retval);
@@ -881,7 +891,7 @@
 			/* Handle special case write when we're returning the entire transfer
 			 */
 			if (ch->handlers.write->method == PHP_CURL_RETURN && length > 0) {
-				smart_str_appendl(&ch->handlers.write->buf, data, (int) length);
+				smart_str_appendl(&ch->handlers.write->buf, data, length);
 			} else {
 				PHPWRITE(data, length);
 			}
diff '--color=auto' -Naur php-8.4.18/ext/curl/tests/gh21023.phpt php-8.4.20RC1/ext/curl/tests/gh21023.phpt
--- php-8.4.18/ext/curl/tests/gh21023.phpt	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/ext/curl/tests/gh21023.phpt	2026-04-01 04:35:35.992737241 +0000
@@ -0,0 +1,27 @@
+--TEST--
+GH-21023 (crash with CURLOPT_XFERINFOFUNCTION set with an invalid callback)
+--EXTENSIONS--
+curl
+--FILE--
+<?php
+include 'server.inc';
+$host = curl_cli_server_start();
+$url = "{$host}/get.inc";
+$ch = curl_init($url);
+curl_setopt($ch, CURLOPT_NOPROGRESS, 0);
+curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+curl_setopt($ch, CURLOPT_XFERINFOFUNCTION, null);
+curl_exec($ch);
+$ch = curl_init($url);
+curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+curl_setopt($ch, CURLOPT_PROGRESSFUNCTION, null);
+curl_exec($ch);
+$ch = curl_init($url);
+curl_setopt($ch, CURLOPT_WILDCARDMATCH, 1);
+curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+curl_setopt($ch, CURLOPT_FNMATCH_FUNCTION, null);
+curl_exec($ch);
+echo "OK", PHP_EOL;
+?>
+--EXPECT--
+OK
diff '--color=auto' -Naur php-8.4.18/ext/date/lib/timezonedb.h php-8.4.20RC1/ext/date/lib/timezonedb.h
--- php-8.4.18/ext/date/lib/timezonedb.h	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/date/lib/timezonedb.h	2026-04-01 04:35:36.001936172 +0000
@@ -323,290 +323,290 @@
 	{ (char*) "Asia/Taipei"                       , 0x02DF83 },
 	{ (char*) "Asia/Tashkent"                     , 0x02E18E },
 	{ (char*) "Asia/Tbilisi"                      , 0x02E319 },
-	{ (char*) "Asia/Tehran"                       , 0x02E59A },
-	{ (char*) "Asia/Tel_Aviv"                     , 0x02E8D2 },
-	{ (char*) "Asia/Thimbu"                       , 0x02ED10 },
-	{ (char*) "Asia/Thimphu"                      , 0x02EDB6 },
-	{ (char*) "Asia/Tokyo"                        , 0x02EE5C },
-	{ (char*) "Asia/Tomsk"                        , 0x02EF3D },
-	{ (char*) "Asia/Ujung_Pandang"                , 0x02F248 },
-	{ (char*) "Asia/Ulaanbaatar"                  , 0x02F312 },
-	{ (char*) "Asia/Ulan_Bator"                   , 0x02F580 },
-	{ (char*) "Asia/Urumqi"                       , 0x02F7DE },
-	{ (char*) "Asia/Ust-Nera"                     , 0x02F87C },
-	{ (char*) "Asia/Vientiane"                    , 0x02FB9F },
-	{ (char*) "Asia/Vladivostok"                  , 0x02FC85 },
-	{ (char*) "Asia/Yakutsk"                      , 0x02FF8A },
-	{ (char*) "Asia/Yangon"                       , 0x03028E },
-	{ (char*) "Asia/Yekaterinburg"                , 0x030355 },
-	{ (char*) "Asia/Yerevan"                      , 0x030667 },
-	{ (char*) "Atlantic/Azores"                   , 0x030937 },
-	{ (char*) "Atlantic/Bermuda"                  , 0x030EC2 },
-	{ (char*) "Atlantic/Canary"                   , 0x0312CE },
-	{ (char*) "Atlantic/Cape_Verde"               , 0x0314C6 },
-	{ (char*) "Atlantic/Faeroe"                   , 0x031581 },
-	{ (char*) "Atlantic/Faroe"                    , 0x031746 },
-	{ (char*) "Atlantic/Jan_Mayen"                , 0x03190B },
-	{ (char*) "Atlantic/Madeira"                  , 0x031BD8 },
-	{ (char*) "Atlantic/Reykjavik"                , 0x03214F },
-	{ (char*) "Atlantic/South_Georgia"            , 0x03244C },
-	{ (char*) "Atlantic/St_Helena"                , 0x0324DC },
-	{ (char*) "Atlantic/Stanley"                  , 0x03257D },
-	{ (char*) "Australia/ACT"                     , 0x03289E },
-	{ (char*) "Australia/Adelaide"                , 0x032C32 },
-	{ (char*) "Australia/Brisbane"                , 0x032FE6 },
-	{ (char*) "Australia/Broken_Hill"             , 0x03312A },
-	{ (char*) "Australia/Canberra"                , 0x0334FF },
-	{ (char*) "Australia/Currie"                  , 0x033893 },
-	{ (char*) "Australia/Darwin"                  , 0x033C8A },
-	{ (char*) "Australia/Eucla"                   , 0x033D92 },
-	{ (char*) "Australia/Hobart"                  , 0x033EF1 },
-	{ (char*) "Australia/LHI"                     , 0x0342F0 },
-	{ (char*) "Australia/Lindeman"                , 0x0345B0 },
-	{ (char*) "Australia/Lord_Howe"               , 0x034720 },
-	{ (char*) "Australia/Melbourne"               , 0x0349F0 },
-	{ (char*) "Australia/North"                   , 0x034D8C },
-	{ (char*) "Australia/NSW"                     , 0x034E82 },
-	{ (char*) "Australia/Perth"                   , 0x035216 },
-	{ (char*) "Australia/Queensland"              , 0x035372 },
-	{ (char*) "Australia/South"                   , 0x03549F },
-	{ (char*) "Australia/Sydney"                  , 0x035844 },
-	{ (char*) "Australia/Tasmania"                , 0x035BF4 },
-	{ (char*) "Australia/Victoria"                , 0x035FEB },
-	{ (char*) "Australia/West"                    , 0x03637F },
-	{ (char*) "Australia/Yancowinna"              , 0x0364BD },
-	{ (char*) "Brazil/Acre"                       , 0x036876 },
-	{ (char*) "Brazil/DeNoronha"                  , 0x036A24 },
-	{ (char*) "Brazil/East"                       , 0x036C14 },
-	{ (char*) "Brazil/West"                       , 0x036FD8 },
-	{ (char*) "Canada/Atlantic"                   , 0x037180 },
-	{ (char*) "Canada/Central"                    , 0x037814 },
-	{ (char*) "Canada/Eastern"                    , 0x037D2E },
-	{ (char*) "Canada/Mountain"                   , 0x0383EF },
-	{ (char*) "Canada/Newfoundland"               , 0x0387C5 },
-	{ (char*) "Canada/Pacific"                    , 0x038F27 },
-	{ (char*) "Canada/Saskatchewan"               , 0x039465 },
-	{ (char*) "Canada/Yukon"                      , 0x0396EF },
-	{ (char*) "CET"                               , 0x039B00 },
-	{ (char*) "Chile/Continental"                 , 0x039F5B },
-	{ (char*) "Chile/EasterIsland"                , 0x03A4B1 },
-	{ (char*) "CST6CDT"                           , 0x03A953 },
-	{ (char*) "Cuba"                              , 0x03B039 },
-	{ (char*) "EET"                               , 0x03B4A2 },
-	{ (char*) "Egypt"                             , 0x03B758 },
-	{ (char*) "Eire"                              , 0x03BC81 },
-	{ (char*) "EST"                               , 0x03C265 },
-	{ (char*) "EST5EDT"                           , 0x03C306 },
-	{ (char*) "Etc/GMT"                           , 0x03C9E2 },
-	{ (char*) "Etc/GMT+0"                         , 0x03CA5D },
-	{ (char*) "Etc/GMT+1"                         , 0x03CAD8 },
-	{ (char*) "Etc/GMT+10"                        , 0x03CB55 },
-	{ (char*) "Etc/GMT+11"                        , 0x03CBD3 },
-	{ (char*) "Etc/GMT+12"                        , 0x03CC51 },
-	{ (char*) "Etc/GMT+2"                         , 0x03CCCF },
-	{ (char*) "Etc/GMT+3"                         , 0x03CD4C },
-	{ (char*) "Etc/GMT+4"                         , 0x03CDC9 },
-	{ (char*) "Etc/GMT+5"                         , 0x03CE46 },
-	{ (char*) "Etc/GMT+6"                         , 0x03CEC3 },
-	{ (char*) "Etc/GMT+7"                         , 0x03CF40 },
-	{ (char*) "Etc/GMT+8"                         , 0x03CFBD },
-	{ (char*) "Etc/GMT+9"                         , 0x03D03A },
-	{ (char*) "Etc/GMT-0"                         , 0x03D0B7 },
-	{ (char*) "Etc/GMT-1"                         , 0x03D132 },
-	{ (char*) "Etc/GMT-10"                        , 0x03D1B0 },
-	{ (char*) "Etc/GMT-11"                        , 0x03D22F },
-	{ (char*) "Etc/GMT-12"                        , 0x03D2AE },
-	{ (char*) "Etc/GMT-13"                        , 0x03D32D },
-	{ (char*) "Etc/GMT-14"                        , 0x03D3AC },
-	{ (char*) "Etc/GMT-2"                         , 0x03D42B },
-	{ (char*) "Etc/GMT-3"                         , 0x03D4A9 },
-	{ (char*) "Etc/GMT-4"                         , 0x03D527 },
-	{ (char*) "Etc/GMT-5"                         , 0x03D5A5 },
-	{ (char*) "Etc/GMT-6"                         , 0x03D623 },
-	{ (char*) "Etc/GMT-7"                         , 0x03D6A1 },
-	{ (char*) "Etc/GMT-8"                         , 0x03D71F },
-	{ (char*) "Etc/GMT-9"                         , 0x03D79D },
-	{ (char*) "Etc/GMT0"                          , 0x03D81B },
-	{ (char*) "Etc/Greenwich"                     , 0x03D896 },
-	{ (char*) "Etc/UCT"                           , 0x03D911 },
-	{ (char*) "Etc/Universal"                     , 0x03D98C },
-	{ (char*) "Etc/UTC"                           , 0x03DA07 },
-	{ (char*) "Etc/Zulu"                          , 0x03DA82 },
-	{ (char*) "Europe/Amsterdam"                  , 0x03DAFD },
-	{ (char*) "Europe/Andorra"                    , 0x03DF38 },
-	{ (char*) "Europe/Astrakhan"                  , 0x03E0C9 },
-	{ (char*) "Europe/Athens"                     , 0x03E3BD },
-	{ (char*) "Europe/Belfast"                    , 0x03E673 },
-	{ (char*) "Europe/Belgrade"                   , 0x03ECBE },
-	{ (char*) "Europe/Berlin"                     , 0x03EEA8 },
-	{ (char*) "Europe/Bratislava"                 , 0x03F184 },
-	{ (char*) "Europe/Brussels"                   , 0x03F463 },
-	{ (char*) "Europe/Bucharest"                  , 0x03F8BE },
-	{ (char*) "Europe/Budapest"                   , 0x03FB5F },
-	{ (char*) "Europe/Busingen"                   , 0x03FE69 },
-	{ (char*) "Europe/Chisinau"                   , 0x04006E },
-	{ (char*) "Europe/Copenhagen"                 , 0x04036D },
-	{ (char*) "Europe/Dublin"                     , 0x0405E8 },
-	{ (char*) "Europe/Gibraltar"                  , 0x040BCC },
-	{ (char*) "Europe/Guernsey"                   , 0x04109C },
-	{ (char*) "Europe/Helsinki"                   , 0x0416F3 },
-	{ (char*) "Europe/Isle_of_Man"                , 0x0418E0 },
-	{ (char*) "Europe/Istanbul"                   , 0x041F2B },
-	{ (char*) "Europe/Jersey"                     , 0x0423E7 },
-	{ (char*) "Europe/Kaliningrad"                , 0x042A3E },
-	{ (char*) "Europe/Kiev"                       , 0x042DE6 },
-	{ (char*) "Europe/Kirov"                      , 0x043020 },
-	{ (char*) "Europe/Kyiv"                       , 0x043319 },
-	{ (char*) "Europe/Lisbon"                     , 0x043562 },
-	{ (char*) "Europe/Ljubljana"                  , 0x043B38 },
-	{ (char*) "Europe/London"                     , 0x043D22 },
-	{ (char*) "Europe/Luxembourg"                 , 0x04436D },
-	{ (char*) "Europe/Madrid"                     , 0x0447B8 },
-	{ (char*) "Europe/Malta"                      , 0x044B55 },
-	{ (char*) "Europe/Mariehamn"                  , 0x044F01 },
-	{ (char*) "Europe/Minsk"                      , 0x0450EE },
-	{ (char*) "Europe/Monaco"                     , 0x045422 },
-	{ (char*) "Europe/Moscow"                     , 0x045888 },
-	{ (char*) "Europe/Nicosia"                    , 0x045C34 },
-	{ (char*) "Europe/Oslo"                       , 0x045E95 },
-	{ (char*) "Europe/Paris"                      , 0x046145 },
-	{ (char*) "Europe/Podgorica"                  , 0x0465A2 },
-	{ (char*) "Europe/Prague"                     , 0x04678C },
-	{ (char*) "Europe/Riga"                       , 0x046A6B },
-	{ (char*) "Europe/Rome"                       , 0x046D2D },
-	{ (char*) "Europe/Samara"                     , 0x0470EC },
-	{ (char*) "Europe/San_Marino"                 , 0x0473ED },
-	{ (char*) "Europe/Sarajevo"                   , 0x0477AC },
-	{ (char*) "Europe/Saratov"                    , 0x047996 },
-	{ (char*) "Europe/Simferopol"                 , 0x047C88 },
-	{ (char*) "Europe/Skopje"                     , 0x047FFB },
-	{ (char*) "Europe/Sofia"                      , 0x0481E5 },
-	{ (char*) "Europe/Stockholm"                  , 0x048441 },
-	{ (char*) "Europe/Tallinn"                    , 0x04863E },
-	{ (char*) "Europe/Tirane"                     , 0x0488ED },
-	{ (char*) "Europe/Tiraspol"                   , 0x048B55 },
-	{ (char*) "Europe/Ulyanovsk"                  , 0x048E54 },
-	{ (char*) "Europe/Uzhgorod"                   , 0x04916A },
-	{ (char*) "Europe/Vaduz"                      , 0x0493A4 },
-	{ (char*) "Europe/Vatican"                    , 0x04958E },
-	{ (char*) "Europe/Vienna"                     , 0x04994D },
-	{ (char*) "Europe/Vilnius"                    , 0x049BEB },
-	{ (char*) "Europe/Volgograd"                  , 0x049E9B },
-	{ (char*) "Europe/Warsaw"                     , 0x04A1AA },
-	{ (char*) "Europe/Zagreb"                     , 0x04A551 },
-	{ (char*) "Europe/Zaporozhye"                 , 0x04A73B },
-	{ (char*) "Europe/Zurich"                     , 0x04A975 },
-	{ (char*) "Factory"                           , 0x04AB72 },
-	{ (char*) "GB"                                , 0x04ABEF },
-	{ (char*) "GB-Eire"                           , 0x04B23A },
-	{ (char*) "GMT"                               , 0x04B885 },
-	{ (char*) "GMT+0"                             , 0x04B900 },
-	{ (char*) "GMT-0"                             , 0x04B97B },
-	{ (char*) "GMT0"                              , 0x04B9F6 },
-	{ (char*) "Greenwich"                         , 0x04BA71 },
-	{ (char*) "Hongkong"                          , 0x04BAEC },
-	{ (char*) "HST"                               , 0x04BDFF },
-	{ (char*) "Iceland"                           , 0x04BEE8 },
-	{ (char*) "Indian/Antananarivo"               , 0x04BF76 },
-	{ (char*) "Indian/Chagos"                     , 0x04C022 },
-	{ (char*) "Indian/Christmas"                  , 0x04C0C6 },
-	{ (char*) "Indian/Cocos"                      , 0x04C157 },
-	{ (char*) "Indian/Comoro"                     , 0x04C1EF },
-	{ (char*) "Indian/Kerguelen"                  , 0x04C27E },
-	{ (char*) "Indian/Mahe"                       , 0x04C30F },
-	{ (char*) "Indian/Maldives"                   , 0x04C3A0 },
-	{ (char*) "Indian/Mauritius"                  , 0x04C444 },
-	{ (char*) "Indian/Mayotte"                    , 0x04C503 },
-	{ (char*) "Indian/Reunion"                    , 0x04C592 },
-	{ (char*) "Iran"                              , 0x04C623 },
-	{ (char*) "Israel"                            , 0x04C95B },
-	{ (char*) "Jamaica"                           , 0x04CD99 },
-	{ (char*) "Japan"                             , 0x04CEF8 },
-	{ (char*) "Kwajalein"                         , 0x04CFD9 },
-	{ (char*) "Libya"                             , 0x04D0C0 },
-	{ (char*) "MET"                               , 0x04D27B },
-	{ (char*) "Mexico/BajaNorte"                  , 0x04D6D6 },
-	{ (char*) "Mexico/BajaSur"                    , 0x04DC39 },
-	{ (char*) "Mexico/General"                    , 0x04DEF7 },
-	{ (char*) "MST"                               , 0x04E208 },
-	{ (char*) "MST7MDT"                           , 0x04E304 },
-	{ (char*) "Navajo"                            , 0x04E722 },
-	{ (char*) "NZ"                                , 0x04EB40 },
-	{ (char*) "NZ-CHAT"                           , 0x04EF5F },
-	{ (char*) "Pacific/Apia"                      , 0x04F293 },
-	{ (char*) "Pacific/Auckland"                  , 0x04F436 },
-	{ (char*) "Pacific/Bougainville"              , 0x04F868 },
-	{ (char*) "Pacific/Chatham"                   , 0x04F949 },
-	{ (char*) "Pacific/Chuuk"                     , 0x04FC8C },
-	{ (char*) "Pacific/Easter"                    , 0x04FD6A },
-	{ (char*) "Pacific/Efate"                     , 0x050219 },
-	{ (char*) "Pacific/Enderbury"                 , 0x05037B },
-	{ (char*) "Pacific/Fakaofo"                   , 0x050433 },
-	{ (char*) "Pacific/Fiji"                      , 0x0504D8 },
-	{ (char*) "Pacific/Funafuti"                  , 0x050670 },
-	{ (char*) "Pacific/Galapagos"                 , 0x050702 },
-	{ (char*) "Pacific/Gambier"                   , 0x0507CE },
-	{ (char*) "Pacific/Guadalcanal"               , 0x05086D },
-	{ (char*) "Pacific/Guam"                      , 0x0508FF },
-	{ (char*) "Pacific/Honolulu"                  , 0x050A69 },
-	{ (char*) "Pacific/Johnston"                  , 0x050B58 },
-	{ (char*) "Pacific/Kanton"                    , 0x050C41 },
-	{ (char*) "Pacific/Kiritimati"                , 0x050D08 },
-	{ (char*) "Pacific/Kosrae"                    , 0x050DCE },
-	{ (char*) "Pacific/Kwajalein"                 , 0x050ED2 },
-	{ (char*) "Pacific/Majuro"                    , 0x050FC2 },
-	{ (char*) "Pacific/Marquesas"                 , 0x0510C0 },
-	{ (char*) "Pacific/Midway"                    , 0x051168 },
-	{ (char*) "Pacific/Nauru"                     , 0x05122B },
-	{ (char*) "Pacific/Niue"                      , 0x0512EE },
-	{ (char*) "Pacific/Norfolk"                   , 0x051394 },
-	{ (char*) "Pacific/Noumea"                    , 0x05148D },
-	{ (char*) "Pacific/Pago_Pago"                 , 0x05155F },
-	{ (char*) "Pacific/Palau"                     , 0x0515FD },
-	{ (char*) "Pacific/Pitcairn"                  , 0x05169D },
-	{ (char*) "Pacific/Pohnpei"                   , 0x051742 },
-	{ (char*) "Pacific/Ponape"                    , 0x051832 },
-	{ (char*) "Pacific/Port_Moresby"              , 0x0518C4 },
-	{ (char*) "Pacific/Rarotonga"                 , 0x051982 },
-	{ (char*) "Pacific/Saipan"                    , 0x051B24 },
-	{ (char*) "Pacific/Samoa"                     , 0x051C85 },
-	{ (char*) "Pacific/Tahiti"                    , 0x051D23 },
-	{ (char*) "Pacific/Tarawa"                    , 0x051DC3 },
-	{ (char*) "Pacific/Tongatapu"                 , 0x051E64 },
-	{ (char*) "Pacific/Truk"                      , 0x051F5D },
-	{ (char*) "Pacific/Wake"                      , 0x052003 },
-	{ (char*) "Pacific/Wallis"                    , 0x0520A0 },
-	{ (char*) "Pacific/Yap"                       , 0x052132 },
-	{ (char*) "Poland"                            , 0x0521D8 },
-	{ (char*) "Portugal"                          , 0x05257F },
-	{ (char*) "PRC"                               , 0x052B42 },
-	{ (char*) "PST8PDT"                           , 0x052CD7 },
-	{ (char*) "ROC"                               , 0x0531F1 },
-	{ (char*) "ROK"                               , 0x0533FC },
-	{ (char*) "Singapore"                         , 0x0535A7 },
-	{ (char*) "Turkey"                            , 0x0536B3 },
-	{ (char*) "UCT"                               , 0x053B6F },
-	{ (char*) "Universal"                         , 0x053BEA },
-	{ (char*) "US/Alaska"                         , 0x053C65 },
-	{ (char*) "US/Aleutian"                       , 0x054042 },
-	{ (char*) "US/Arizona"                        , 0x054417 },
-	{ (char*) "US/Central"                        , 0x054513 },
-	{ (char*) "US/East-Indiana"                   , 0x054BF9 },
-	{ (char*) "US/Eastern"                        , 0x054E18 },
-	{ (char*) "US/Hawaii"                         , 0x0554F4 },
-	{ (char*) "US/Indiana-Starke"                 , 0x0555DD },
-	{ (char*) "US/Michigan"                       , 0x0559E1 },
-	{ (char*) "US/Mountain"                       , 0x055D70 },
-	{ (char*) "US/Pacific"                        , 0x05618E },
-	{ (char*) "US/Samoa"                          , 0x0566A8 },
-	{ (char*) "UTC"                               , 0x056746 },
-	{ (char*) "W-SU"                              , 0x0567C1 },
-	{ (char*) "WET"                               , 0x056B59 },
-	{ (char*) "Zulu"                              , 0x05711C },
+	{ (char*) "Asia/Tehran"                       , 0x02E591 },
+	{ (char*) "Asia/Tel_Aviv"                     , 0x02E8C9 },
+	{ (char*) "Asia/Thimbu"                       , 0x02ED07 },
+	{ (char*) "Asia/Thimphu"                      , 0x02EDAD },
+	{ (char*) "Asia/Tokyo"                        , 0x02EE53 },
+	{ (char*) "Asia/Tomsk"                        , 0x02EF34 },
+	{ (char*) "Asia/Ujung_Pandang"                , 0x02F23F },
+	{ (char*) "Asia/Ulaanbaatar"                  , 0x02F309 },
+	{ (char*) "Asia/Ulan_Bator"                   , 0x02F577 },
+	{ (char*) "Asia/Urumqi"                       , 0x02F7D5 },
+	{ (char*) "Asia/Ust-Nera"                     , 0x02F873 },
+	{ (char*) "Asia/Vientiane"                    , 0x02FB96 },
+	{ (char*) "Asia/Vladivostok"                  , 0x02FC7C },
+	{ (char*) "Asia/Yakutsk"                      , 0x02FF81 },
+	{ (char*) "Asia/Yangon"                       , 0x030285 },
+	{ (char*) "Asia/Yekaterinburg"                , 0x03034C },
+	{ (char*) "Asia/Yerevan"                      , 0x03065E },
+	{ (char*) "Atlantic/Azores"                   , 0x03092E },
+	{ (char*) "Atlantic/Bermuda"                  , 0x030EB9 },
+	{ (char*) "Atlantic/Canary"                   , 0x0312C5 },
+	{ (char*) "Atlantic/Cape_Verde"               , 0x0314BD },
+	{ (char*) "Atlantic/Faeroe"                   , 0x031578 },
+	{ (char*) "Atlantic/Faroe"                    , 0x03173D },
+	{ (char*) "Atlantic/Jan_Mayen"                , 0x031902 },
+	{ (char*) "Atlantic/Madeira"                  , 0x031BCF },
+	{ (char*) "Atlantic/Reykjavik"                , 0x032146 },
+	{ (char*) "Atlantic/South_Georgia"            , 0x032443 },
+	{ (char*) "Atlantic/St_Helena"                , 0x0324D3 },
+	{ (char*) "Atlantic/Stanley"                  , 0x032574 },
+	{ (char*) "Australia/ACT"                     , 0x032895 },
+	{ (char*) "Australia/Adelaide"                , 0x032C29 },
+	{ (char*) "Australia/Brisbane"                , 0x032FDD },
+	{ (char*) "Australia/Broken_Hill"             , 0x033121 },
+	{ (char*) "Australia/Canberra"                , 0x0334F6 },
+	{ (char*) "Australia/Currie"                  , 0x03388A },
+	{ (char*) "Australia/Darwin"                  , 0x033C81 },
+	{ (char*) "Australia/Eucla"                   , 0x033D89 },
+	{ (char*) "Australia/Hobart"                  , 0x033EE8 },
+	{ (char*) "Australia/LHI"                     , 0x0342E7 },
+	{ (char*) "Australia/Lindeman"                , 0x0345A7 },
+	{ (char*) "Australia/Lord_Howe"               , 0x034717 },
+	{ (char*) "Australia/Melbourne"               , 0x0349E7 },
+	{ (char*) "Australia/North"                   , 0x034D83 },
+	{ (char*) "Australia/NSW"                     , 0x034E79 },
+	{ (char*) "Australia/Perth"                   , 0x03520D },
+	{ (char*) "Australia/Queensland"              , 0x035369 },
+	{ (char*) "Australia/South"                   , 0x035496 },
+	{ (char*) "Australia/Sydney"                  , 0x03583B },
+	{ (char*) "Australia/Tasmania"                , 0x035BEB },
+	{ (char*) "Australia/Victoria"                , 0x035FE2 },
+	{ (char*) "Australia/West"                    , 0x036376 },
+	{ (char*) "Australia/Yancowinna"              , 0x0364B4 },
+	{ (char*) "Brazil/Acre"                       , 0x03686D },
+	{ (char*) "Brazil/DeNoronha"                  , 0x036A1B },
+	{ (char*) "Brazil/East"                       , 0x036C0B },
+	{ (char*) "Brazil/West"                       , 0x036FCF },
+	{ (char*) "Canada/Atlantic"                   , 0x037177 },
+	{ (char*) "Canada/Central"                    , 0x03780B },
+	{ (char*) "Canada/Eastern"                    , 0x037D25 },
+	{ (char*) "Canada/Mountain"                   , 0x0383E6 },
+	{ (char*) "Canada/Newfoundland"               , 0x0387BC },
+	{ (char*) "Canada/Pacific"                    , 0x038F1E },
+	{ (char*) "Canada/Saskatchewan"               , 0x03945C },
+	{ (char*) "Canada/Yukon"                      , 0x0396E6 },
+	{ (char*) "CET"                               , 0x039AF7 },
+	{ (char*) "Chile/Continental"                 , 0x039F52 },
+	{ (char*) "Chile/EasterIsland"                , 0x03A4A8 },
+	{ (char*) "CST6CDT"                           , 0x03A94A },
+	{ (char*) "Cuba"                              , 0x03B030 },
+	{ (char*) "EET"                               , 0x03B499 },
+	{ (char*) "Egypt"                             , 0x03B74F },
+	{ (char*) "Eire"                              , 0x03BC78 },
+	{ (char*) "EST"                               , 0x03C25C },
+	{ (char*) "EST5EDT"                           , 0x03C2FD },
+	{ (char*) "Etc/GMT"                           , 0x03C9D9 },
+	{ (char*) "Etc/GMT+0"                         , 0x03CA54 },
+	{ (char*) "Etc/GMT+1"                         , 0x03CACF },
+	{ (char*) "Etc/GMT+10"                        , 0x03CB4C },
+	{ (char*) "Etc/GMT+11"                        , 0x03CBCA },
+	{ (char*) "Etc/GMT+12"                        , 0x03CC48 },
+	{ (char*) "Etc/GMT+2"                         , 0x03CCC6 },
+	{ (char*) "Etc/GMT+3"                         , 0x03CD43 },
+	{ (char*) "Etc/GMT+4"                         , 0x03CDC0 },
+	{ (char*) "Etc/GMT+5"                         , 0x03CE3D },
+	{ (char*) "Etc/GMT+6"                         , 0x03CEBA },
+	{ (char*) "Etc/GMT+7"                         , 0x03CF37 },
+	{ (char*) "Etc/GMT+8"                         , 0x03CFB4 },
+	{ (char*) "Etc/GMT+9"                         , 0x03D031 },
+	{ (char*) "Etc/GMT-0"                         , 0x03D0AE },
+	{ (char*) "Etc/GMT-1"                         , 0x03D129 },
+	{ (char*) "Etc/GMT-10"                        , 0x03D1A7 },
+	{ (char*) "Etc/GMT-11"                        , 0x03D226 },
+	{ (char*) "Etc/GMT-12"                        , 0x03D2A5 },
+	{ (char*) "Etc/GMT-13"                        , 0x03D324 },
+	{ (char*) "Etc/GMT-14"                        , 0x03D3A3 },
+	{ (char*) "Etc/GMT-2"                         , 0x03D422 },
+	{ (char*) "Etc/GMT-3"                         , 0x03D4A0 },
+	{ (char*) "Etc/GMT-4"                         , 0x03D51E },
+	{ (char*) "Etc/GMT-5"                         , 0x03D59C },
+	{ (char*) "Etc/GMT-6"                         , 0x03D61A },
+	{ (char*) "Etc/GMT-7"                         , 0x03D698 },
+	{ (char*) "Etc/GMT-8"                         , 0x03D716 },
+	{ (char*) "Etc/GMT-9"                         , 0x03D794 },
+	{ (char*) "Etc/GMT0"                          , 0x03D812 },
+	{ (char*) "Etc/Greenwich"                     , 0x03D88D },
+	{ (char*) "Etc/UCT"                           , 0x03D908 },
+	{ (char*) "Etc/Universal"                     , 0x03D983 },
+	{ (char*) "Etc/UTC"                           , 0x03D9FE },
+	{ (char*) "Etc/Zulu"                          , 0x03DA79 },
+	{ (char*) "Europe/Amsterdam"                  , 0x03DAF4 },
+	{ (char*) "Europe/Andorra"                    , 0x03DF2F },
+	{ (char*) "Europe/Astrakhan"                  , 0x03E0C0 },
+	{ (char*) "Europe/Athens"                     , 0x03E3B4 },
+	{ (char*) "Europe/Belfast"                    , 0x03E66A },
+	{ (char*) "Europe/Belgrade"                   , 0x03ECB5 },
+	{ (char*) "Europe/Berlin"                     , 0x03EE9F },
+	{ (char*) "Europe/Bratislava"                 , 0x03F17B },
+	{ (char*) "Europe/Brussels"                   , 0x03F45A },
+	{ (char*) "Europe/Bucharest"                  , 0x03F8B5 },
+	{ (char*) "Europe/Budapest"                   , 0x03FB56 },
+	{ (char*) "Europe/Busingen"                   , 0x03FE60 },
+	{ (char*) "Europe/Chisinau"                   , 0x040065 },
+	{ (char*) "Europe/Copenhagen"                 , 0x040528 },
+	{ (char*) "Europe/Dublin"                     , 0x0407A3 },
+	{ (char*) "Europe/Gibraltar"                  , 0x040D87 },
+	{ (char*) "Europe/Guernsey"                   , 0x041257 },
+	{ (char*) "Europe/Helsinki"                   , 0x0418AE },
+	{ (char*) "Europe/Isle_of_Man"                , 0x041A9B },
+	{ (char*) "Europe/Istanbul"                   , 0x0420E6 },
+	{ (char*) "Europe/Jersey"                     , 0x0425A2 },
+	{ (char*) "Europe/Kaliningrad"                , 0x042BF9 },
+	{ (char*) "Europe/Kiev"                       , 0x042FA1 },
+	{ (char*) "Europe/Kirov"                      , 0x0431DB },
+	{ (char*) "Europe/Kyiv"                       , 0x0434D4 },
+	{ (char*) "Europe/Lisbon"                     , 0x04371D },
+	{ (char*) "Europe/Ljubljana"                  , 0x043CF3 },
+	{ (char*) "Europe/London"                     , 0x043EDD },
+	{ (char*) "Europe/Luxembourg"                 , 0x044528 },
+	{ (char*) "Europe/Madrid"                     , 0x044973 },
+	{ (char*) "Europe/Malta"                      , 0x044D10 },
+	{ (char*) "Europe/Mariehamn"                  , 0x0450BC },
+	{ (char*) "Europe/Minsk"                      , 0x0452A9 },
+	{ (char*) "Europe/Monaco"                     , 0x0455DD },
+	{ (char*) "Europe/Moscow"                     , 0x045A43 },
+	{ (char*) "Europe/Nicosia"                    , 0x045DEF },
+	{ (char*) "Europe/Oslo"                       , 0x046050 },
+	{ (char*) "Europe/Paris"                      , 0x046300 },
+	{ (char*) "Europe/Podgorica"                  , 0x04675D },
+	{ (char*) "Europe/Prague"                     , 0x046947 },
+	{ (char*) "Europe/Riga"                       , 0x046C26 },
+	{ (char*) "Europe/Rome"                       , 0x046EE8 },
+	{ (char*) "Europe/Samara"                     , 0x0472A7 },
+	{ (char*) "Europe/San_Marino"                 , 0x0475A8 },
+	{ (char*) "Europe/Sarajevo"                   , 0x047967 },
+	{ (char*) "Europe/Saratov"                    , 0x047B51 },
+	{ (char*) "Europe/Simferopol"                 , 0x047E43 },
+	{ (char*) "Europe/Skopje"                     , 0x0481B6 },
+	{ (char*) "Europe/Sofia"                      , 0x0483A0 },
+	{ (char*) "Europe/Stockholm"                  , 0x0485FC },
+	{ (char*) "Europe/Tallinn"                    , 0x0487F9 },
+	{ (char*) "Europe/Tirane"                     , 0x048AA8 },
+	{ (char*) "Europe/Tiraspol"                   , 0x048D10 },
+	{ (char*) "Europe/Ulyanovsk"                  , 0x0491D3 },
+	{ (char*) "Europe/Uzhgorod"                   , 0x0494E9 },
+	{ (char*) "Europe/Vaduz"                      , 0x049723 },
+	{ (char*) "Europe/Vatican"                    , 0x04990D },
+	{ (char*) "Europe/Vienna"                     , 0x049CCC },
+	{ (char*) "Europe/Vilnius"                    , 0x049F6A },
+	{ (char*) "Europe/Volgograd"                  , 0x04A21A },
+	{ (char*) "Europe/Warsaw"                     , 0x04A529 },
+	{ (char*) "Europe/Zagreb"                     , 0x04A8D0 },
+	{ (char*) "Europe/Zaporozhye"                 , 0x04AABA },
+	{ (char*) "Europe/Zurich"                     , 0x04ACF4 },
+	{ (char*) "Factory"                           , 0x04AEF1 },
+	{ (char*) "GB"                                , 0x04AF6E },
+	{ (char*) "GB-Eire"                           , 0x04B5B9 },
+	{ (char*) "GMT"                               , 0x04BC04 },
+	{ (char*) "GMT+0"                             , 0x04BC7F },
+	{ (char*) "GMT-0"                             , 0x04BCFA },
+	{ (char*) "GMT0"                              , 0x04BD75 },
+	{ (char*) "Greenwich"                         , 0x04BDF0 },
+	{ (char*) "Hongkong"                          , 0x04BE6B },
+	{ (char*) "HST"                               , 0x04C17E },
+	{ (char*) "Iceland"                           , 0x04C267 },
+	{ (char*) "Indian/Antananarivo"               , 0x04C2F5 },
+	{ (char*) "Indian/Chagos"                     , 0x04C3A1 },
+	{ (char*) "Indian/Christmas"                  , 0x04C445 },
+	{ (char*) "Indian/Cocos"                      , 0x04C4D6 },
+	{ (char*) "Indian/Comoro"                     , 0x04C56E },
+	{ (char*) "Indian/Kerguelen"                  , 0x04C5FD },
+	{ (char*) "Indian/Mahe"                       , 0x04C68E },
+	{ (char*) "Indian/Maldives"                   , 0x04C71F },
+	{ (char*) "Indian/Mauritius"                  , 0x04C7C3 },
+	{ (char*) "Indian/Mayotte"                    , 0x04C882 },
+	{ (char*) "Indian/Reunion"                    , 0x04C911 },
+	{ (char*) "Iran"                              , 0x04C9A2 },
+	{ (char*) "Israel"                            , 0x04CCDA },
+	{ (char*) "Jamaica"                           , 0x04D118 },
+	{ (char*) "Japan"                             , 0x04D277 },
+	{ (char*) "Kwajalein"                         , 0x04D358 },
+	{ (char*) "Libya"                             , 0x04D43F },
+	{ (char*) "MET"                               , 0x04D5FA },
+	{ (char*) "Mexico/BajaNorte"                  , 0x04DA55 },
+	{ (char*) "Mexico/BajaSur"                    , 0x04DFB8 },
+	{ (char*) "Mexico/General"                    , 0x04E276 },
+	{ (char*) "MST"                               , 0x04E587 },
+	{ (char*) "MST7MDT"                           , 0x04E683 },
+	{ (char*) "Navajo"                            , 0x04EAA1 },
+	{ (char*) "NZ"                                , 0x04EEBF },
+	{ (char*) "NZ-CHAT"                           , 0x04F2DE },
+	{ (char*) "Pacific/Apia"                      , 0x04F612 },
+	{ (char*) "Pacific/Auckland"                  , 0x04F7B5 },
+	{ (char*) "Pacific/Bougainville"              , 0x04FBE7 },
+	{ (char*) "Pacific/Chatham"                   , 0x04FCC8 },
+	{ (char*) "Pacific/Chuuk"                     , 0x05000B },
+	{ (char*) "Pacific/Easter"                    , 0x0500E9 },
+	{ (char*) "Pacific/Efate"                     , 0x050598 },
+	{ (char*) "Pacific/Enderbury"                 , 0x0506FA },
+	{ (char*) "Pacific/Fakaofo"                   , 0x0507B2 },
+	{ (char*) "Pacific/Fiji"                      , 0x050857 },
+	{ (char*) "Pacific/Funafuti"                  , 0x0509EF },
+	{ (char*) "Pacific/Galapagos"                 , 0x050A81 },
+	{ (char*) "Pacific/Gambier"                   , 0x050B4D },
+	{ (char*) "Pacific/Guadalcanal"               , 0x050BEC },
+	{ (char*) "Pacific/Guam"                      , 0x050C7E },
+	{ (char*) "Pacific/Honolulu"                  , 0x050DE8 },
+	{ (char*) "Pacific/Johnston"                  , 0x050ED7 },
+	{ (char*) "Pacific/Kanton"                    , 0x050FC0 },
+	{ (char*) "Pacific/Kiritimati"                , 0x051087 },
+	{ (char*) "Pacific/Kosrae"                    , 0x05114D },
+	{ (char*) "Pacific/Kwajalein"                 , 0x051251 },
+	{ (char*) "Pacific/Majuro"                    , 0x051341 },
+	{ (char*) "Pacific/Marquesas"                 , 0x05143F },
+	{ (char*) "Pacific/Midway"                    , 0x0514E7 },
+	{ (char*) "Pacific/Nauru"                     , 0x0515AA },
+	{ (char*) "Pacific/Niue"                      , 0x05166D },
+	{ (char*) "Pacific/Norfolk"                   , 0x051713 },
+	{ (char*) "Pacific/Noumea"                    , 0x05180C },
+	{ (char*) "Pacific/Pago_Pago"                 , 0x0518DE },
+	{ (char*) "Pacific/Palau"                     , 0x05197C },
+	{ (char*) "Pacific/Pitcairn"                  , 0x051A1C },
+	{ (char*) "Pacific/Pohnpei"                   , 0x051AC1 },
+	{ (char*) "Pacific/Ponape"                    , 0x051BB1 },
+	{ (char*) "Pacific/Port_Moresby"              , 0x051C43 },
+	{ (char*) "Pacific/Rarotonga"                 , 0x051D01 },
+	{ (char*) "Pacific/Saipan"                    , 0x051EA3 },
+	{ (char*) "Pacific/Samoa"                     , 0x052004 },
+	{ (char*) "Pacific/Tahiti"                    , 0x0520A2 },
+	{ (char*) "Pacific/Tarawa"                    , 0x052142 },
+	{ (char*) "Pacific/Tongatapu"                 , 0x0521E3 },
+	{ (char*) "Pacific/Truk"                      , 0x0522DC },
+	{ (char*) "Pacific/Wake"                      , 0x052382 },
+	{ (char*) "Pacific/Wallis"                    , 0x05241F },
+	{ (char*) "Pacific/Yap"                       , 0x0524B1 },
+	{ (char*) "Poland"                            , 0x052557 },
+	{ (char*) "Portugal"                          , 0x0528FE },
+	{ (char*) "PRC"                               , 0x052EC1 },
+	{ (char*) "PST8PDT"                           , 0x053056 },
+	{ (char*) "ROC"                               , 0x053570 },
+	{ (char*) "ROK"                               , 0x05377B },
+	{ (char*) "Singapore"                         , 0x053926 },
+	{ (char*) "Turkey"                            , 0x053A32 },
+	{ (char*) "UCT"                               , 0x053EEE },
+	{ (char*) "Universal"                         , 0x053F69 },
+	{ (char*) "US/Alaska"                         , 0x053FE4 },
+	{ (char*) "US/Aleutian"                       , 0x0543C1 },
+	{ (char*) "US/Arizona"                        , 0x054796 },
+	{ (char*) "US/Central"                        , 0x054892 },
+	{ (char*) "US/East-Indiana"                   , 0x054F78 },
+	{ (char*) "US/Eastern"                        , 0x055197 },
+	{ (char*) "US/Hawaii"                         , 0x055873 },
+	{ (char*) "US/Indiana-Starke"                 , 0x05595C },
+	{ (char*) "US/Michigan"                       , 0x055D60 },
+	{ (char*) "US/Mountain"                       , 0x0560EF },
+	{ (char*) "US/Pacific"                        , 0x05650D },
+	{ (char*) "US/Samoa"                          , 0x056A27 },
+	{ (char*) "UTC"                               , 0x056AC5 },
+	{ (char*) "W-SU"                              , 0x056B40 },
+	{ (char*) "WET"                               , 0x056ED8 },
+	{ (char*) "Zulu"                              , 0x05749B },
 };
 
 
-const unsigned char timelib_timezone_db_data_builtin[356759] = {
+const unsigned char timelib_timezone_db_data_builtin[357654] = {
 
 /* Africa/Abidjan */
 0x50, 0x48, 0x50, 0x32, 0x01, 0x43, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -13242,7 +13242,7 @@
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x54, 0x5A, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x15, 0xFF,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x15, 0xFF,
 0xFF, 0xFF, 0xFF, 0x56, 0xB6, 0xBA, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xAA, 0x19, 0x9A, 0x01, 0xFF,
 0xFF, 0xFF, 0xFF, 0xE7, 0xDA, 0x0C, 0x50, 0x00, 0x00, 0x00, 0x00, 0x15, 0x27, 0x99, 0xC0, 0x00,
 0x00, 0x00, 0x00, 0x16, 0x18, 0xCE, 0x30, 0x00, 0x00, 0x00, 0x00, 0x17, 0x08, 0xCD, 0x40, 0x00,
@@ -13260,24 +13260,23 @@
 0x00, 0x00, 0x00, 0x2C, 0xA4, 0xA3, 0x40, 0x00, 0x00, 0x00, 0x00, 0x2D, 0x94, 0xA2, 0x50, 0x00,
 0x00, 0x00, 0x00, 0x2E, 0x84, 0x85, 0x40, 0x00, 0x00, 0x00, 0x00, 0x2F, 0x74, 0x76, 0x40, 0x00,
 0x00, 0x00, 0x00, 0x30, 0x64, 0x59, 0x30, 0x00, 0x00, 0x00, 0x00, 0x31, 0x5D, 0x92, 0xC0, 0x00,
-0x00, 0x00, 0x00, 0x33, 0x3D, 0x66, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x34, 0x52, 0x41, 0xB0, 0x00,
-0x00, 0x00, 0x00, 0x35, 0x1D, 0x56, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x36, 0x32, 0x23, 0xB0, 0x00,
-0x00, 0x00, 0x00, 0x36, 0xFD, 0x38, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x38, 0x1B, 0x40, 0x30, 0x00,
-0x00, 0x00, 0x00, 0x38, 0xDD, 0x1A, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x39, 0xFB, 0x22, 0x30, 0x00,
-0x00, 0x00, 0x00, 0x3A, 0xBC, 0xFC, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x3B, 0xDB, 0x04, 0x30, 0x00,
-0x00, 0x00, 0x00, 0x3C, 0xA6, 0x19, 0x40, 0x00, 0x00, 0x00, 0x00, 0x3D, 0xBA, 0xE6, 0x30, 0x00,
-0x00, 0x00, 0x00, 0x3E, 0x85, 0xFB, 0x40, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x9A, 0xC8, 0x30, 0x00,
-0x00, 0x00, 0x00, 0x40, 0x65, 0xDD, 0x40, 0x00, 0x00, 0x00, 0x00, 0x40, 0xDD, 0xC7, 0xB0, 0x00,
-0x00, 0x00, 0x00, 0x41, 0x84, 0x1C, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x42, 0x45, 0xE9, 0x70, 0x01,
-0x02, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04,
-0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x04, 0x03, 0x04,
-0x03, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03,
-0x05, 0x02, 0x04, 0x00, 0x00, 0x29, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x29, 0xFF, 0x00, 0x04, 0x00,
-0x00, 0x2A, 0x30, 0x00, 0x09, 0x00, 0x00, 0x46, 0x50, 0x01, 0x0D, 0x00, 0x00, 0x38, 0x40, 0x00,
-0x11, 0x00, 0x00, 0x38, 0x40, 0x01, 0x11, 0x4C, 0x4D, 0x54, 0x00, 0x54, 0x42, 0x4D, 0x54, 0x00,
-0x2B, 0x30, 0x33, 0x00, 0x2B, 0x30, 0x35, 0x00, 0x2B, 0x30, 0x34, 0x00, 0x0A, 0x3C, 0x2B, 0x30,
-0x34, 0x3E, 0x2D, 0x34, 0x0A, 0x00, 0xC8, 0xFB, 0xD2, 0x01, 0x57, 0x0B, 0x02, 0x00, 0x00, 0x00,
-0x00, 
+0x00, 0x00, 0x00, 0x34, 0x52, 0x41, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x35, 0x1D, 0x56, 0xC0, 0x00,
+0x00, 0x00, 0x00, 0x36, 0x32, 0x23, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x36, 0xFD, 0x38, 0xC0, 0x00,
+0x00, 0x00, 0x00, 0x38, 0x1B, 0x40, 0x30, 0x00, 0x00, 0x00, 0x00, 0x38, 0xDD, 0x1A, 0xC0, 0x00,
+0x00, 0x00, 0x00, 0x39, 0xFB, 0x22, 0x30, 0x00, 0x00, 0x00, 0x00, 0x3A, 0xBC, 0xFC, 0xC0, 0x00,
+0x00, 0x00, 0x00, 0x3B, 0xDB, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x3C, 0xA6, 0x19, 0x40, 0x00,
+0x00, 0x00, 0x00, 0x3D, 0xBA, 0xE6, 0x30, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x85, 0xFB, 0x40, 0x00,
+0x00, 0x00, 0x00, 0x3F, 0x9A, 0xC8, 0x30, 0x00, 0x00, 0x00, 0x00, 0x40, 0x65, 0xDD, 0x40, 0x00,
+0x00, 0x00, 0x00, 0x40, 0xDD, 0xC7, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x41, 0x84, 0x1C, 0xF0, 0x00,
+0x00, 0x00, 0x00, 0x42, 0x45, 0xE9, 0x70, 0x01, 0x02, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04,
+0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x05, 0x02,
+0x05, 0x02, 0x05, 0x02, 0x05, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04,
+0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x05, 0x02, 0x04, 0x00, 0x00, 0x29, 0xFF, 0x00, 0x00,
+0x00, 0x00, 0x29, 0xFF, 0x00, 0x04, 0x00, 0x00, 0x2A, 0x30, 0x00, 0x09, 0x00, 0x00, 0x46, 0x50,
+0x01, 0x0D, 0x00, 0x00, 0x38, 0x40, 0x00, 0x11, 0x00, 0x00, 0x38, 0x40, 0x01, 0x11, 0x4C, 0x4D,
+0x54, 0x00, 0x54, 0x42, 0x4D, 0x54, 0x00, 0x2B, 0x30, 0x33, 0x00, 0x2B, 0x30, 0x35, 0x00, 0x2B,
+0x30, 0x34, 0x00, 0x0A, 0x3C, 0x2B, 0x30, 0x34, 0x3E, 0x2D, 0x34, 0x0A, 0x00, 0xC8, 0xFB, 0xD2,
+0x01, 0x57, 0x0B, 0x02, 0x00, 0x00, 0x00, 0x00, 
 
 /* Asia/Tehran */
 0x50, 0x48, 0x50, 0x32, 0x01, 0x49, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -18107,7 +18106,7 @@
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x54, 0x5A, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x26, 0xFF,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6E, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x26, 0xFF,
 0xFF, 0xFF, 0xFF, 0x56, 0xB6, 0xC8, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0x9E, 0x6B, 0x9F, 0x0C, 0xFF,
 0xFF, 0xFF, 0xFF, 0xB7, 0xB0, 0xD2, 0x08, 0xFF, 0xFF, 0xFF, 0xFF, 0xB9, 0x3E, 0xF3, 0x60, 0xFF,
 0xFF, 0xFF, 0xFF, 0xB9, 0xEF, 0x9C, 0x60, 0xFF, 0xFF, 0xFF, 0xFF, 0xBA, 0xDF, 0x8D, 0x60, 0xFF,
@@ -18137,19 +18136,48 @@
 0x00, 0x00, 0x00, 0x2C, 0xA4, 0xB1, 0x50, 0x00, 0x00, 0x00, 0x00, 0x2D, 0x94, 0xB0, 0x60, 0x00,
 0x00, 0x00, 0x00, 0x2E, 0x84, 0x93, 0x50, 0x00, 0x00, 0x00, 0x00, 0x2F, 0x74, 0x92, 0x60, 0x00,
 0x00, 0x00, 0x00, 0x30, 0x64, 0x75, 0x50, 0x00, 0x00, 0x00, 0x00, 0x31, 0x5D, 0xAE, 0xE0, 0x00,
-0x00, 0x00, 0x00, 0x32, 0x72, 0x7B, 0xD0, 0x00, 0x00, 0x00, 0x00, 0x32, 0xC9, 0x8C, 0xE0, 0x01,
+0x00, 0x00, 0x00, 0x32, 0x72, 0x7B, 0xD0, 0x00, 0x00, 0x00, 0x00, 0x33, 0x3D, 0xAD, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x34, 0x52, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, 0x1D, 0x8F, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x36, 0x32, 0x6A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0xFD, 0x71, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x38, 0x1B, 0x86, 0x80, 0x00, 0x00, 0x00, 0x00, 0x38, 0xDD, 0x53, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x39, 0xFB, 0x68, 0x80, 0x00, 0x00, 0x00, 0x00, 0x3A, 0xBD, 0x35, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x3B, 0xDB, 0x4A, 0x80, 0x00, 0x00, 0x00, 0x00, 0x3C, 0xA6, 0x51, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x3D, 0xBB, 0x2C, 0x80, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x86, 0x33, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x3F, 0x9B, 0x0E, 0x80, 0x00, 0x00, 0x00, 0x00, 0x40, 0x66, 0x15, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x41, 0x84, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x45, 0xF7, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x43, 0x64, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x25, 0xD9, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x45, 0x43, 0xEF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x05, 0xBB, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x47, 0x23, 0xD1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0xEE, 0xD8, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x49, 0x03, 0xB3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0xCE, 0xBA, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x4A, 0xE3, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4B, 0xAE, 0x9C, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x4C, 0xCC, 0xB1, 0x80, 0x00, 0x00, 0x00, 0x00, 0x4D, 0x8E, 0x7E, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x4E, 0xAC, 0x93, 0x80, 0x00, 0x00, 0x00, 0x00, 0x4F, 0x6E, 0x60, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x50, 0x8C, 0x75, 0x80, 0x00, 0x00, 0x00, 0x00, 0x51, 0x57, 0x7C, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x52, 0x6C, 0x57, 0x80, 0x00, 0x00, 0x00, 0x00, 0x53, 0x37, 0x5E, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x54, 0x4C, 0x39, 0x80, 0x00, 0x00, 0x00, 0x00, 0x55, 0x17, 0x40, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x56, 0x2C, 0x1B, 0x80, 0x00, 0x00, 0x00, 0x00, 0x56, 0xF7, 0x22, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x58, 0x15, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0xD7, 0x04, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x59, 0xF5, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5A, 0xB6, 0xE6, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x5B, 0xD4, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5C, 0xA0, 0x03, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x5D, 0xB4, 0xDE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5E, 0x7F, 0xE5, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x5F, 0x94, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x5F, 0xC7, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x61, 0x7D, 0xDC, 0x80, 0x00, 0x00, 0x00, 0x00, 0x61, 0xCF, 0x7D, 0x60, 0x01,
 0x02, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04,
 0x03, 0x04, 0x03, 0x06, 0x05, 0x06, 0x05, 0x06, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07,
 0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x03, 0x04, 0x03, 0x04,
-0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x04, 0x00, 0x00, 0x1B, 0x08, 0x00,
-0x00, 0x00, 0x00, 0x1A, 0xF4, 0x00, 0x04, 0x00, 0x00, 0x18, 0x78, 0x00, 0x08, 0x00, 0x00, 0x2A,
-0x30, 0x01, 0x0C, 0x00, 0x00, 0x1C, 0x20, 0x00, 0x11, 0x00, 0x00, 0x0E, 0x10, 0x00, 0x15, 0x00,
-0x00, 0x1C, 0x20, 0x01, 0x19, 0x00, 0x00, 0x38, 0x40, 0x01, 0x1E, 0x00, 0x00, 0x2A, 0x30, 0x00,
-0x22, 0x4C, 0x4D, 0x54, 0x00, 0x43, 0x4D, 0x54, 0x00, 0x42, 0x4D, 0x54, 0x00, 0x45, 0x45, 0x53,
-0x54, 0x00, 0x45, 0x45, 0x54, 0x00, 0x43, 0x45, 0x54, 0x00, 0x43, 0x45, 0x53, 0x54, 0x00, 0x4D,
-0x53, 0x44, 0x00, 0x4D, 0x53, 0x4B, 0x00, 0x0A, 0x45, 0x45, 0x54, 0x2D, 0x32, 0x45, 0x45, 0x53,
-0x54, 0x2C, 0x4D, 0x33, 0x2E, 0x35, 0x2E, 0x30, 0x2C, 0x4D, 0x31, 0x30, 0x2E, 0x35, 0x2E, 0x30,
-0x2F, 0x33, 0x0A, 0x00, 0xD1, 0x0B, 0xA0, 0x01, 0x3E, 0xA7, 0x85, 0x00, 0x00, 0x00, 0x00, 
+0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04,
+0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04,
+0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04,
+0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x04, 0x00, 0x00, 0x1B,
+0x08, 0x00, 0x00, 0x00, 0x00, 0x1A, 0xF4, 0x00, 0x04, 0x00, 0x00, 0x18, 0x78, 0x00, 0x08, 0x00,
+0x00, 0x2A, 0x30, 0x01, 0x0C, 0x00, 0x00, 0x1C, 0x20, 0x00, 0x11, 0x00, 0x00, 0x0E, 0x10, 0x00,
+0x15, 0x00, 0x00, 0x1C, 0x20, 0x01, 0x19, 0x00, 0x00, 0x38, 0x40, 0x01, 0x1E, 0x00, 0x00, 0x2A,
+0x30, 0x00, 0x22, 0x4C, 0x4D, 0x54, 0x00, 0x43, 0x4D, 0x54, 0x00, 0x42, 0x4D, 0x54, 0x00, 0x45,
+0x45, 0x53, 0x54, 0x00, 0x45, 0x45, 0x54, 0x00, 0x43, 0x45, 0x54, 0x00, 0x43, 0x45, 0x53, 0x54,
+0x00, 0x4D, 0x53, 0x44, 0x00, 0x4D, 0x53, 0x4B, 0x00, 0x0A, 0x45, 0x45, 0x54, 0x2D, 0x32, 0x45,
+0x45, 0x53, 0x54, 0x2C, 0x4D, 0x33, 0x2E, 0x35, 0x2E, 0x30, 0x2F, 0x33, 0x2C, 0x4D, 0x31, 0x30,
+0x2E, 0x35, 0x2E, 0x30, 0x2F, 0x34, 0x0A, 0x00, 0xD1, 0x0B, 0xA0, 0x01, 0x3E, 0xA7, 0x85, 0x00,
+0x00, 0x00, 0x00, 
 
 /* Europe/Copenhagen */
 0x50, 0x48, 0x50, 0x32, 0x01, 0x44, 0x4B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -20427,7 +20455,7 @@
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x54, 0x5A, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x26, 0xFF,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6E, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x26, 0xFF,
 0xFF, 0xFF, 0xFF, 0x56, 0xB6, 0xC8, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0x9E, 0x6B, 0x9F, 0x0C, 0xFF,
 0xFF, 0xFF, 0xFF, 0xB7, 0xB0, 0xD2, 0x08, 0xFF, 0xFF, 0xFF, 0xFF, 0xB9, 0x3E, 0xF3, 0x60, 0xFF,
 0xFF, 0xFF, 0xFF, 0xB9, 0xEF, 0x9C, 0x60, 0xFF, 0xFF, 0xFF, 0xFF, 0xBA, 0xDF, 0x8D, 0x60, 0xFF,
@@ -20457,19 +20485,48 @@
 0x00, 0x00, 0x00, 0x2C, 0xA4, 0xB1, 0x50, 0x00, 0x00, 0x00, 0x00, 0x2D, 0x94, 0xB0, 0x60, 0x00,
 0x00, 0x00, 0x00, 0x2E, 0x84, 0x93, 0x50, 0x00, 0x00, 0x00, 0x00, 0x2F, 0x74, 0x92, 0x60, 0x00,
 0x00, 0x00, 0x00, 0x30, 0x64, 0x75, 0x50, 0x00, 0x00, 0x00, 0x00, 0x31, 0x5D, 0xAE, 0xE0, 0x00,
-0x00, 0x00, 0x00, 0x32, 0x72, 0x7B, 0xD0, 0x00, 0x00, 0x00, 0x00, 0x32, 0xC9, 0x8C, 0xE0, 0x01,
+0x00, 0x00, 0x00, 0x32, 0x72, 0x7B, 0xD0, 0x00, 0x00, 0x00, 0x00, 0x33, 0x3D, 0xAD, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x34, 0x52, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, 0x1D, 0x8F, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x36, 0x32, 0x6A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0xFD, 0x71, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x38, 0x1B, 0x86, 0x80, 0x00, 0x00, 0x00, 0x00, 0x38, 0xDD, 0x53, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x39, 0xFB, 0x68, 0x80, 0x00, 0x00, 0x00, 0x00, 0x3A, 0xBD, 0x35, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x3B, 0xDB, 0x4A, 0x80, 0x00, 0x00, 0x00, 0x00, 0x3C, 0xA6, 0x51, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x3D, 0xBB, 0x2C, 0x80, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x86, 0x33, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x3F, 0x9B, 0x0E, 0x80, 0x00, 0x00, 0x00, 0x00, 0x40, 0x66, 0x15, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x41, 0x84, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x45, 0xF7, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x43, 0x64, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x25, 0xD9, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x45, 0x43, 0xEF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x05, 0xBB, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x47, 0x23, 0xD1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0xEE, 0xD8, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x49, 0x03, 0xB3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0xCE, 0xBA, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x4A, 0xE3, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4B, 0xAE, 0x9C, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x4C, 0xCC, 0xB1, 0x80, 0x00, 0x00, 0x00, 0x00, 0x4D, 0x8E, 0x7E, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x4E, 0xAC, 0x93, 0x80, 0x00, 0x00, 0x00, 0x00, 0x4F, 0x6E, 0x60, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x50, 0x8C, 0x75, 0x80, 0x00, 0x00, 0x00, 0x00, 0x51, 0x57, 0x7C, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x52, 0x6C, 0x57, 0x80, 0x00, 0x00, 0x00, 0x00, 0x53, 0x37, 0x5E, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x54, 0x4C, 0x39, 0x80, 0x00, 0x00, 0x00, 0x00, 0x55, 0x17, 0x40, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x56, 0x2C, 0x1B, 0x80, 0x00, 0x00, 0x00, 0x00, 0x56, 0xF7, 0x22, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x58, 0x15, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0xD7, 0x04, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x59, 0xF5, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5A, 0xB6, 0xE6, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x5B, 0xD4, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5C, 0xA0, 0x03, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x5D, 0xB4, 0xDE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5E, 0x7F, 0xE5, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x5F, 0x94, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x5F, 0xC7, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x61, 0x7D, 0xDC, 0x80, 0x00, 0x00, 0x00, 0x00, 0x61, 0xCF, 0x7D, 0x60, 0x01,
 0x02, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04,
 0x03, 0x04, 0x03, 0x06, 0x05, 0x06, 0x05, 0x06, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07,
 0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x08, 0x07, 0x03, 0x04, 0x03, 0x04,
-0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x04, 0x00, 0x00, 0x1B, 0x08, 0x00,
-0x00, 0x00, 0x00, 0x1A, 0xF4, 0x00, 0x04, 0x00, 0x00, 0x18, 0x78, 0x00, 0x08, 0x00, 0x00, 0x2A,
-0x30, 0x01, 0x0C, 0x00, 0x00, 0x1C, 0x20, 0x00, 0x11, 0x00, 0x00, 0x0E, 0x10, 0x00, 0x15, 0x00,
-0x00, 0x1C, 0x20, 0x01, 0x19, 0x00, 0x00, 0x38, 0x40, 0x01, 0x1E, 0x00, 0x00, 0x2A, 0x30, 0x00,
-0x22, 0x4C, 0x4D, 0x54, 0x00, 0x43, 0x4D, 0x54, 0x00, 0x42, 0x4D, 0x54, 0x00, 0x45, 0x45, 0x53,
-0x54, 0x00, 0x45, 0x45, 0x54, 0x00, 0x43, 0x45, 0x54, 0x00, 0x43, 0x45, 0x53, 0x54, 0x00, 0x4D,
-0x53, 0x44, 0x00, 0x4D, 0x53, 0x4B, 0x00, 0x0A, 0x45, 0x45, 0x54, 0x2D, 0x32, 0x45, 0x45, 0x53,
-0x54, 0x2C, 0x4D, 0x33, 0x2E, 0x35, 0x2E, 0x30, 0x2C, 0x4D, 0x31, 0x30, 0x2E, 0x35, 0x2E, 0x30,
-0x2F, 0x33, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04,
+0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04,
+0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04,
+0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x04, 0x00, 0x00, 0x1B,
+0x08, 0x00, 0x00, 0x00, 0x00, 0x1A, 0xF4, 0x00, 0x04, 0x00, 0x00, 0x18, 0x78, 0x00, 0x08, 0x00,
+0x00, 0x2A, 0x30, 0x01, 0x0C, 0x00, 0x00, 0x1C, 0x20, 0x00, 0x11, 0x00, 0x00, 0x0E, 0x10, 0x00,
+0x15, 0x00, 0x00, 0x1C, 0x20, 0x01, 0x19, 0x00, 0x00, 0x38, 0x40, 0x01, 0x1E, 0x00, 0x00, 0x2A,
+0x30, 0x00, 0x22, 0x4C, 0x4D, 0x54, 0x00, 0x43, 0x4D, 0x54, 0x00, 0x42, 0x4D, 0x54, 0x00, 0x45,
+0x45, 0x53, 0x54, 0x00, 0x45, 0x45, 0x54, 0x00, 0x43, 0x45, 0x54, 0x00, 0x43, 0x45, 0x53, 0x54,
+0x00, 0x4D, 0x53, 0x44, 0x00, 0x4D, 0x53, 0x4B, 0x00, 0x0A, 0x45, 0x45, 0x54, 0x2D, 0x32, 0x45,
+0x45, 0x53, 0x54, 0x2C, 0x4D, 0x33, 0x2E, 0x35, 0x2E, 0x30, 0x2F, 0x33, 0x2C, 0x4D, 0x31, 0x30,
+0x2E, 0x35, 0x2E, 0x30, 0x2F, 0x34, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 
 
 /* Europe/Ulyanovsk */
 0x50, 0x48, 0x50, 0x32, 0x01, 0x52, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -24720,290 +24777,290 @@
 	{ (char*) "Asia/Taipei"                       , 0x053BCB },
 	{ (char*) "Asia/Tashkent"                     , 0x053ED0 },
 	{ (char*) "Asia/Tbilisi"                      , 0x05412E },
-	{ (char*) "Asia/Tehran"                       , 0x054537 },
-	{ (char*) "Asia/Tel_Aviv"                     , 0x054A23 },
-	{ (char*) "Asia/Thimbu"                       , 0x055383 },
-	{ (char*) "Asia/Thimphu"                      , 0x05544C },
-	{ (char*) "Asia/Tokyo"                        , 0x055515 },
-	{ (char*) "Asia/Tomsk"                        , 0x055656 },
-	{ (char*) "Asia/Ujung_Pandang"                , 0x055B27 },
-	{ (char*) "Asia/Ulaanbaatar"                  , 0x055C31 },
-	{ (char*) "Asia/Ulan_Bator"                   , 0x055FBA },
-	{ (char*) "Asia/Urumqi"                       , 0x056333 },
-	{ (char*) "Asia/Ust-Nera"                     , 0x0563E3 },
-	{ (char*) "Asia/Vientiane"                    , 0x0568D9 },
-	{ (char*) "Asia/Vladivostok"                  , 0x056A1A },
-	{ (char*) "Asia/Yakutsk"                      , 0x056EE3 },
-	{ (char*) "Asia/Yangon"                       , 0x0573AB },
-	{ (char*) "Asia/Yekaterinburg"                , 0x0574B5 },
-	{ (char*) "Asia/Yerevan"                      , 0x05799C },
-	{ (char*) "Atlantic/Azores"                   , 0x057E19 },
-	{ (char*) "Atlantic/Bermuda"                  , 0x058B9D },
-	{ (char*) "Atlantic/Canary"                   , 0x059505 },
-	{ (char*) "Atlantic/Cape_Verde"               , 0x059C88 },
-	{ (char*) "Atlantic/Faeroe"                   , 0x059D94 },
-	{ (char*) "Atlantic/Faroe"                    , 0x05A4B7 },
-	{ (char*) "Atlantic/Jan_Mayen"                , 0x05ABDA },
-	{ (char*) "Atlantic/Madeira"                  , 0x05B4E0 },
-	{ (char*) "Atlantic/Reykjavik"                , 0x05C22C },
-	{ (char*) "Atlantic/South_Georgia"            , 0x05C6C2 },
-	{ (char*) "Atlantic/St_Helena"                , 0x05C764 },
-	{ (char*) "Atlantic/Stanley"                  , 0x05C826 },
-	{ (char*) "Australia/ACT"                     , 0x05CCE2 },
-	{ (char*) "Australia/Adelaide"                , 0x05D57C },
-	{ (char*) "Australia/Brisbane"                , 0x05DE37 },
-	{ (char*) "Australia/Broken_Hill"             , 0x05DFFD },
-	{ (char*) "Australia/Canberra"                , 0x05E8DA },
-	{ (char*) "Australia/Currie"                  , 0x05F174 },
-	{ (char*) "Australia/Darwin"                  , 0x05FAB6 },
-	{ (char*) "Australia/Eucla"                   , 0x05FC19 },
-	{ (char*) "Australia/Hobart"                  , 0x05FE06 },
-	{ (char*) "Australia/LHI"                     , 0x060750 },
-	{ (char*) "Australia/Lindeman"                , 0x060E92 },
-	{ (char*) "Australia/Lord_Howe"               , 0x061098 },
-	{ (char*) "Australia/Melbourne"               , 0x0617EA },
-	{ (char*) "Australia/North"                   , 0x06208C },
-	{ (char*) "Australia/NSW"                     , 0x0621DD },
-	{ (char*) "Australia/Perth"                   , 0x062A77 },
-	{ (char*) "Australia/Queensland"              , 0x062C5F },
-	{ (char*) "Australia/South"                   , 0x062E0E },
-	{ (char*) "Australia/Sydney"                  , 0x0636BA },
-	{ (char*) "Australia/Tasmania"                , 0x063F70 },
-	{ (char*) "Australia/Victoria"                , 0x0648B2 },
-	{ (char*) "Australia/West"                    , 0x06514C },
-	{ (char*) "Australia/Yancowinna"              , 0x065316 },
-	{ (char*) "Brazil/Acre"                       , 0x065BD7 },
-	{ (char*) "Brazil/DeNoronha"                  , 0x065E49 },
-	{ (char*) "Brazil/East"                       , 0x066113 },
-	{ (char*) "Brazil/West"                       , 0x0666B5 },
-	{ (char*) "Canada/Atlantic"                   , 0x06690F },
-	{ (char*) "Canada/Central"                    , 0x06767B },
-	{ (char*) "Canada/Eastern"                    , 0x0681BB },
-	{ (char*) "Canada/Mountain"                   , 0x068F6D },
-	{ (char*) "Canada/Newfoundland"               , 0x069895 },
-	{ (char*) "Canada/Pacific"                    , 0x06A6E8 },
-	{ (char*) "Canada/Saskatchewan"               , 0x06B240 },
-	{ (char*) "Canada/Yukon"                      , 0x06B620 },
-	{ (char*) "CET"                               , 0x06BC7A },
-	{ (char*) "Chile/Continental"                 , 0x06C7FB },
-	{ (char*) "Chile/EasterIsland"                , 0x06D1DA },
-	{ (char*) "CST6CDT"                           , 0x06DA91 },
-	{ (char*) "Cuba"                              , 0x06E8A5 },
-	{ (char*) "EET"                               , 0x06F221 },
-	{ (char*) "Egypt"                             , 0x06FB03 },
-	{ (char*) "Eire"                              , 0x07046E },
-	{ (char*) "EST"                               , 0x07121E },
-	{ (char*) "EST5EDT"                           , 0x0712E0 },
-	{ (char*) "Etc/GMT"                           , 0x0720CC },
-	{ (char*) "Etc/GMT+0"                         , 0x07214A },
-	{ (char*) "Etc/GMT+1"                         , 0x0721C8 },
-	{ (char*) "Etc/GMT+10"                        , 0x072248 },
-	{ (char*) "Etc/GMT+11"                        , 0x0722C9 },
-	{ (char*) "Etc/GMT+12"                        , 0x07234A },
-	{ (char*) "Etc/GMT+2"                         , 0x0723CB },
-	{ (char*) "Etc/GMT+3"                         , 0x07244B },
-	{ (char*) "Etc/GMT+4"                         , 0x0724CB },
-	{ (char*) "Etc/GMT+5"                         , 0x07254B },
-	{ (char*) "Etc/GMT+6"                         , 0x0725CB },
-	{ (char*) "Etc/GMT+7"                         , 0x07264B },
-	{ (char*) "Etc/GMT+8"                         , 0x0726CB },
-	{ (char*) "Etc/GMT+9"                         , 0x07274B },
-	{ (char*) "Etc/GMT-0"                         , 0x0727CB },
-	{ (char*) "Etc/GMT-1"                         , 0x072849 },
-	{ (char*) "Etc/GMT-10"                        , 0x0728CA },
-	{ (char*) "Etc/GMT-11"                        , 0x07294C },
-	{ (char*) "Etc/GMT-12"                        , 0x0729CE },
-	{ (char*) "Etc/GMT-13"                        , 0x072A50 },
-	{ (char*) "Etc/GMT-14"                        , 0x072AD2 },
-	{ (char*) "Etc/GMT-2"                         , 0x072B54 },
-	{ (char*) "Etc/GMT-3"                         , 0x072BD5 },
-	{ (char*) "Etc/GMT-4"                         , 0x072C56 },
-	{ (char*) "Etc/GMT-5"                         , 0x072CD7 },
-	{ (char*) "Etc/GMT-6"                         , 0x072D58 },
-	{ (char*) "Etc/GMT-7"                         , 0x072DD9 },
-	{ (char*) "Etc/GMT-8"                         , 0x072E5A },
-	{ (char*) "Etc/GMT-9"                         , 0x072EDB },
-	{ (char*) "Etc/GMT0"                          , 0x072F5C },
-	{ (char*) "Etc/Greenwich"                     , 0x072FDA },
-	{ (char*) "Etc/UCT"                           , 0x073058 },
-	{ (char*) "Etc/Universal"                     , 0x0730D6 },
-	{ (char*) "Etc/UTC"                           , 0x073154 },
-	{ (char*) "Etc/Zulu"                          , 0x0731D2 },
-	{ (char*) "Europe/Amsterdam"                  , 0x073250 },
-	{ (char*) "Europe/Andorra"                    , 0x073DBA },
-	{ (char*) "Europe/Astrakhan"                  , 0x074494 },
-	{ (char*) "Europe/Athens"                     , 0x074931 },
-	{ (char*) "Europe/Belfast"                    , 0x075213 },
-	{ (char*) "Europe/Belgrade"                   , 0x07606F },
-	{ (char*) "Europe/Berlin"                     , 0x0767FB },
-	{ (char*) "Europe/Bratislava"                 , 0x077110 },
-	{ (char*) "Europe/Brussels"                   , 0x077A19 },
-	{ (char*) "Europe/Bucharest"                  , 0x07859A },
-	{ (char*) "Europe/Budapest"                   , 0x078E2E },
-	{ (char*) "Europe/Busingen"                   , 0x07977A },
-	{ (char*) "Europe/Chisinau"                   , 0x079F03 },
-	{ (char*) "Europe/Copenhagen"                 , 0x07A865 },
-	{ (char*) "Europe/Dublin"                     , 0x07B0CA },
-	{ (char*) "Europe/Gibraltar"                  , 0x07BE7A },
-	{ (char*) "Europe/Guernsey"                   , 0x07CA82 },
-	{ (char*) "Europe/Helsinki"                   , 0x07D922 },
-	{ (char*) "Europe/Isle_of_Man"                , 0x07E09A },
-	{ (char*) "Europe/Istanbul"                   , 0x07EEE6 },
-	{ (char*) "Europe/Jersey"                     , 0x07F67F },
-	{ (char*) "Europe/Kaliningrad"                , 0x08051F },
-	{ (char*) "Europe/Kiev"                       , 0x080B14 },
-	{ (char*) "Europe/Kirov"                      , 0x081368 },
-	{ (char*) "Europe/Kyiv"                       , 0x081823 },
-	{ (char*) "Europe/Lisbon"                     , 0x082086 },
-	{ (char*) "Europe/Ljubljana"                  , 0x082E6C },
-	{ (char*) "Europe/London"                     , 0x0835F8 },
-	{ (char*) "Europe/Luxembourg"                 , 0x084454 },
-	{ (char*) "Europe/Madrid"                     , 0x084FE2 },
-	{ (char*) "Europe/Malta"                      , 0x085A34 },
-	{ (char*) "Europe/Mariehamn"                  , 0x08647C },
-	{ (char*) "Europe/Minsk"                      , 0x086BF4 },
-	{ (char*) "Europe/Monaco"                     , 0x08711B },
-	{ (char*) "Europe/Moscow"                     , 0x087CA7 },
-	{ (char*) "Europe/Nicosia"                    , 0x0882C6 },
-	{ (char*) "Europe/Oslo"                       , 0x088AA4 },
-	{ (char*) "Europe/Paris"                      , 0x089364 },
-	{ (char*) "Europe/Podgorica"                  , 0x089F02 },
-	{ (char*) "Europe/Prague"                     , 0x08A68E },
-	{ (char*) "Europe/Riga"                       , 0x08AF97 },
-	{ (char*) "Europe/Rome"                       , 0x08B839 },
-	{ (char*) "Europe/Samara"                     , 0x08C296 },
-	{ (char*) "Europe/San_Marino"                 , 0x08C76C },
-	{ (char*) "Europe/Sarajevo"                   , 0x08D1C9 },
-	{ (char*) "Europe/Saratov"                    , 0x08D955 },
-	{ (char*) "Europe/Simferopol"                 , 0x08DE02 },
-	{ (char*) "Europe/Skopje"                     , 0x08E3D1 },
-	{ (char*) "Europe/Sofia"                      , 0x08EB5D },
-	{ (char*) "Europe/Stockholm"                  , 0x08F386 },
-	{ (char*) "Europe/Tallinn"                    , 0x08FB07 },
-	{ (char*) "Europe/Tirane"                     , 0x090377 },
-	{ (char*) "Europe/Tiraspol"                   , 0x090BA7 },
-	{ (char*) "Europe/Ulyanovsk"                  , 0x091509 },
-	{ (char*) "Europe/Uzhgorod"                   , 0x091A0C },
-	{ (char*) "Europe/Vaduz"                      , 0x092260 },
-	{ (char*) "Europe/Vatican"                    , 0x0929CC },
-	{ (char*) "Europe/Vienna"                     , 0x093429 },
-	{ (char*) "Europe/Vilnius"                    , 0x093CCD },
-	{ (char*) "Europe/Volgograd"                  , 0x09454B },
-	{ (char*) "Europe/Warsaw"                     , 0x094A12 },
-	{ (char*) "Europe/Zagreb"                     , 0x09547C },
-	{ (char*) "Europe/Zaporozhye"                 , 0x095C08 },
-	{ (char*) "Europe/Zurich"                     , 0x09645C },
-	{ (char*) "Factory"                           , 0x096BDD },
-	{ (char*) "GB"                                , 0x096C5D },
-	{ (char*) "GB-Eire"                           , 0x097AB9 },
-	{ (char*) "GMT"                               , 0x098915 },
-	{ (char*) "GMT+0"                             , 0x098993 },
-	{ (char*) "GMT-0"                             , 0x098A11 },
-	{ (char*) "GMT0"                              , 0x098A8F },
-	{ (char*) "Greenwich"                         , 0x098B0D },
-	{ (char*) "Hongkong"                          , 0x098B8B },
-	{ (char*) "HST"                               , 0x099068 },
-	{ (char*) "Iceland"                           , 0x0991BD },
-	{ (char*) "Indian/Antananarivo"               , 0x09925D },
-	{ (char*) "Indian/Chagos"                     , 0x099344 },
-	{ (char*) "Indian/Christmas"                  , 0x099409 },
-	{ (char*) "Indian/Cocos"                      , 0x0994AC },
-	{ (char*) "Indian/Comoro"                     , 0x099558 },
-	{ (char*) "Indian/Kerguelen"                  , 0x0995F9 },
-	{ (char*) "Indian/Mahe"                       , 0x09969C },
-	{ (char*) "Indian/Maldives"                   , 0x09973F },
-	{ (char*) "Indian/Mauritius"                  , 0x099804 },
-	{ (char*) "Indian/Mayotte"                    , 0x0998F3 },
-	{ (char*) "Indian/Reunion"                    , 0x099994 },
-	{ (char*) "Iran"                              , 0x099A37 },
-	{ (char*) "Israel"                            , 0x099F23 },
-	{ (char*) "Jamaica"                           , 0x09A883 },
-	{ (char*) "Japan"                             , 0x09AA71 },
-	{ (char*) "Kwajalein"                         , 0x09ABB2 },
-	{ (char*) "Libya"                             , 0x09ACEC },
-	{ (char*) "MET"                               , 0x09AF69 },
-	{ (char*) "Mexico/BajaNorte"                  , 0x09BAEA },
-	{ (char*) "Mexico/BajaSur"                    , 0x09C650 },
-	{ (char*) "Mexico/General"                    , 0x09CA80 },
-	{ (char*) "MST"                               , 0x09CF52 },
-	{ (char*) "MST7MDT"                           , 0x09D0C6 },
-	{ (char*) "Navajo"                            , 0x09DA6E },
-	{ (char*) "NZ"                                , 0x09E416 },
-	{ (char*) "NZ-CHAT"                           , 0x09EDA7 },
-	{ (char*) "Pacific/Apia"                      , 0x09F5B9 },
-	{ (char*) "Pacific/Auckland"                  , 0x09F81B },
-	{ (char*) "Pacific/Bougainville"              , 0x0A01BF },
-	{ (char*) "Pacific/Chatham"                   , 0x0A02D5 },
-	{ (char*) "Pacific/Chuuk"                     , 0x0A0AF6 },
-	{ (char*) "Pacific/Easter"                    , 0x0A0C10 },
-	{ (char*) "Pacific/Efate"                     , 0x0A14D4 },
-	{ (char*) "Pacific/Enderbury"                 , 0x0A16EC },
-	{ (char*) "Pacific/Fakaofo"                   , 0x0A17D4 },
-	{ (char*) "Pacific/Fiji"                      , 0x0A189A },
-	{ (char*) "Pacific/Funafuti"                  , 0x0A1ADA },
-	{ (char*) "Pacific/Galapagos"                 , 0x0A1B7E },
-	{ (char*) "Pacific/Gambier"                   , 0x0A1C7B },
-	{ (char*) "Pacific/Guadalcanal"               , 0x0A1D2C },
-	{ (char*) "Pacific/Guam"                      , 0x0A1DD0 },
-	{ (char*) "Pacific/Honolulu"                  , 0x0A1FCA },
-	{ (char*) "Pacific/Johnston"                  , 0x0A2125 },
-	{ (char*) "Pacific/Kanton"                    , 0x0A227A },
-	{ (char*) "Pacific/Kiritimati"                , 0x0A2371 },
-	{ (char*) "Pacific/Kosrae"                    , 0x0A2469 },
-	{ (char*) "Pacific/Kwajalein"                 , 0x0A25CC },
-	{ (char*) "Pacific/Majuro"                    , 0x0A270F },
-	{ (char*) "Pacific/Marquesas"                 , 0x0A285B },
-	{ (char*) "Pacific/Midway"                    , 0x0A2917 },
-	{ (char*) "Pacific/Nauru"                     , 0x0A2A0A },
-	{ (char*) "Pacific/Niue"                      , 0x0A2B04 },
-	{ (char*) "Pacific/Norfolk"                   , 0x0A2BCD },
-	{ (char*) "Pacific/Noumea"                    , 0x0A2F3B },
-	{ (char*) "Pacific/Pago_Pago"                 , 0x0A3069 },
-	{ (char*) "Pacific/Palau"                     , 0x0A3124 },
-	{ (char*) "Pacific/Pitcairn"                  , 0x0A31D6 },
-	{ (char*) "Pacific/Pohnpei"                   , 0x0A329E },
-	{ (char*) "Pacific/Ponape"                    , 0x0A33D9 },
-	{ (char*) "Pacific/Port_Moresby"              , 0x0A347D },
-	{ (char*) "Pacific/Rarotonga"                 , 0x0A354D },
-	{ (char*) "Pacific/Saipan"                    , 0x0A37A6 },
-	{ (char*) "Pacific/Samoa"                     , 0x0A3992 },
-	{ (char*) "Pacific/Tahiti"                    , 0x0A3A4D },
-	{ (char*) "Pacific/Tarawa"                    , 0x0A3AFF },
-	{ (char*) "Pacific/Tongatapu"                 , 0x0A3BB2 },
-	{ (char*) "Pacific/Truk"                      , 0x0A3D24 },
-	{ (char*) "Pacific/Wake"                      , 0x0A3DDC },
-	{ (char*) "Pacific/Wallis"                    , 0x0A3E8B },
-	{ (char*) "Pacific/Yap"                       , 0x0A3F2F },
-	{ (char*) "Poland"                            , 0x0A3FE7 },
-	{ (char*) "Portugal"                          , 0x0A4A51 },
-	{ (char*) "PRC"                               , 0x0A5824 },
-	{ (char*) "PST8PDT"                           , 0x0A5A61 },
-	{ (char*) "ROC"                               , 0x0A6591 },
-	{ (char*) "ROK"                               , 0x0A6896 },
-	{ (char*) "Singapore"                         , 0x0A6B0B },
-	{ (char*) "Turkey"                            , 0x0A6CA8 },
-	{ (char*) "UCT"                               , 0x0A7441 },
-	{ (char*) "Universal"                         , 0x0A74BF },
-	{ (char*) "US/Alaska"                         , 0x0A753D },
-	{ (char*) "US/Aleutian"                       , 0x0A7E8C },
-	{ (char*) "US/Arizona"                        , 0x0A87CC },
-	{ (char*) "US/Central"                        , 0x0A8940 },
-	{ (char*) "US/East-Indiana"                   , 0x0A9754 },
-	{ (char*) "US/Eastern"                        , 0x0A9DF2 },
-	{ (char*) "US/Hawaii"                         , 0x0AABDE },
-	{ (char*) "US/Indiana-Starke"                 , 0x0AAD33 },
-	{ (char*) "US/Michigan"                       , 0x0AB6CB },
-	{ (char*) "US/Mountain"                       , 0x0ABF8D },
-	{ (char*) "US/Pacific"                        , 0x0AC935 },
-	{ (char*) "US/Samoa"                          , 0x0AD465 },
-	{ (char*) "UTC"                               , 0x0AD520 },
-	{ (char*) "W-SU"                              , 0x0AD59E },
-	{ (char*) "WET"                               , 0x0ADBA9 },
-	{ (char*) "Zulu"                              , 0x0AE97C },
+	{ (char*) "Asia/Tehran"                       , 0x054529 },
+	{ (char*) "Asia/Tel_Aviv"                     , 0x054A15 },
+	{ (char*) "Asia/Thimbu"                       , 0x055375 },
+	{ (char*) "Asia/Thimphu"                      , 0x05543E },
+	{ (char*) "Asia/Tokyo"                        , 0x055507 },
+	{ (char*) "Asia/Tomsk"                        , 0x055648 },
+	{ (char*) "Asia/Ujung_Pandang"                , 0x055B19 },
+	{ (char*) "Asia/Ulaanbaatar"                  , 0x055C23 },
+	{ (char*) "Asia/Ulan_Bator"                   , 0x055FAC },
+	{ (char*) "Asia/Urumqi"                       , 0x056325 },
+	{ (char*) "Asia/Ust-Nera"                     , 0x0563D5 },
+	{ (char*) "Asia/Vientiane"                    , 0x0568CB },
+	{ (char*) "Asia/Vladivostok"                  , 0x056A0C },
+	{ (char*) "Asia/Yakutsk"                      , 0x056ED5 },
+	{ (char*) "Asia/Yangon"                       , 0x05739D },
+	{ (char*) "Asia/Yekaterinburg"                , 0x0574A7 },
+	{ (char*) "Asia/Yerevan"                      , 0x05798E },
+	{ (char*) "Atlantic/Azores"                   , 0x057E0B },
+	{ (char*) "Atlantic/Bermuda"                  , 0x058B8F },
+	{ (char*) "Atlantic/Canary"                   , 0x0594F7 },
+	{ (char*) "Atlantic/Cape_Verde"               , 0x059C7A },
+	{ (char*) "Atlantic/Faeroe"                   , 0x059D86 },
+	{ (char*) "Atlantic/Faroe"                    , 0x05A4A9 },
+	{ (char*) "Atlantic/Jan_Mayen"                , 0x05ABCC },
+	{ (char*) "Atlantic/Madeira"                  , 0x05B4D2 },
+	{ (char*) "Atlantic/Reykjavik"                , 0x05C21E },
+	{ (char*) "Atlantic/South_Georgia"            , 0x05C6B4 },
+	{ (char*) "Atlantic/St_Helena"                , 0x05C756 },
+	{ (char*) "Atlantic/Stanley"                  , 0x05C818 },
+	{ (char*) "Australia/ACT"                     , 0x05CCD4 },
+	{ (char*) "Australia/Adelaide"                , 0x05D56E },
+	{ (char*) "Australia/Brisbane"                , 0x05DE29 },
+	{ (char*) "Australia/Broken_Hill"             , 0x05DFEF },
+	{ (char*) "Australia/Canberra"                , 0x05E8CC },
+	{ (char*) "Australia/Currie"                  , 0x05F166 },
+	{ (char*) "Australia/Darwin"                  , 0x05FAA8 },
+	{ (char*) "Australia/Eucla"                   , 0x05FC0B },
+	{ (char*) "Australia/Hobart"                  , 0x05FDF8 },
+	{ (char*) "Australia/LHI"                     , 0x060742 },
+	{ (char*) "Australia/Lindeman"                , 0x060E84 },
+	{ (char*) "Australia/Lord_Howe"               , 0x06108A },
+	{ (char*) "Australia/Melbourne"               , 0x0617DC },
+	{ (char*) "Australia/North"                   , 0x06207E },
+	{ (char*) "Australia/NSW"                     , 0x0621CF },
+	{ (char*) "Australia/Perth"                   , 0x062A69 },
+	{ (char*) "Australia/Queensland"              , 0x062C51 },
+	{ (char*) "Australia/South"                   , 0x062E00 },
+	{ (char*) "Australia/Sydney"                  , 0x0636AC },
+	{ (char*) "Australia/Tasmania"                , 0x063F62 },
+	{ (char*) "Australia/Victoria"                , 0x0648A4 },
+	{ (char*) "Australia/West"                    , 0x06513E },
+	{ (char*) "Australia/Yancowinna"              , 0x065308 },
+	{ (char*) "Brazil/Acre"                       , 0x065BC9 },
+	{ (char*) "Brazil/DeNoronha"                  , 0x065E3B },
+	{ (char*) "Brazil/East"                       , 0x066105 },
+	{ (char*) "Brazil/West"                       , 0x0666A7 },
+	{ (char*) "Canada/Atlantic"                   , 0x066901 },
+	{ (char*) "Canada/Central"                    , 0x06766D },
+	{ (char*) "Canada/Eastern"                    , 0x0681AD },
+	{ (char*) "Canada/Mountain"                   , 0x068F5F },
+	{ (char*) "Canada/Newfoundland"               , 0x069887 },
+	{ (char*) "Canada/Pacific"                    , 0x06A6DA },
+	{ (char*) "Canada/Saskatchewan"               , 0x06B232 },
+	{ (char*) "Canada/Yukon"                      , 0x06B612 },
+	{ (char*) "CET"                               , 0x06BC6C },
+	{ (char*) "Chile/Continental"                 , 0x06C7ED },
+	{ (char*) "Chile/EasterIsland"                , 0x06D1CC },
+	{ (char*) "CST6CDT"                           , 0x06DA83 },
+	{ (char*) "Cuba"                              , 0x06E897 },
+	{ (char*) "EET"                               , 0x06F213 },
+	{ (char*) "Egypt"                             , 0x06FAF5 },
+	{ (char*) "Eire"                              , 0x070460 },
+	{ (char*) "EST"                               , 0x071210 },
+	{ (char*) "EST5EDT"                           , 0x0712D2 },
+	{ (char*) "Etc/GMT"                           , 0x0720BE },
+	{ (char*) "Etc/GMT+0"                         , 0x07213C },
+	{ (char*) "Etc/GMT+1"                         , 0x0721BA },
+	{ (char*) "Etc/GMT+10"                        , 0x07223A },
+	{ (char*) "Etc/GMT+11"                        , 0x0722BB },
+	{ (char*) "Etc/GMT+12"                        , 0x07233C },
+	{ (char*) "Etc/GMT+2"                         , 0x0723BD },
+	{ (char*) "Etc/GMT+3"                         , 0x07243D },
+	{ (char*) "Etc/GMT+4"                         , 0x0724BD },
+	{ (char*) "Etc/GMT+5"                         , 0x07253D },
+	{ (char*) "Etc/GMT+6"                         , 0x0725BD },
+	{ (char*) "Etc/GMT+7"                         , 0x07263D },
+	{ (char*) "Etc/GMT+8"                         , 0x0726BD },
+	{ (char*) "Etc/GMT+9"                         , 0x07273D },
+	{ (char*) "Etc/GMT-0"                         , 0x0727BD },
+	{ (char*) "Etc/GMT-1"                         , 0x07283B },
+	{ (char*) "Etc/GMT-10"                        , 0x0728BC },
+	{ (char*) "Etc/GMT-11"                        , 0x07293E },
+	{ (char*) "Etc/GMT-12"                        , 0x0729C0 },
+	{ (char*) "Etc/GMT-13"                        , 0x072A42 },
+	{ (char*) "Etc/GMT-14"                        , 0x072AC4 },
+	{ (char*) "Etc/GMT-2"                         , 0x072B46 },
+	{ (char*) "Etc/GMT-3"                         , 0x072BC7 },
+	{ (char*) "Etc/GMT-4"                         , 0x072C48 },
+	{ (char*) "Etc/GMT-5"                         , 0x072CC9 },
+	{ (char*) "Etc/GMT-6"                         , 0x072D4A },
+	{ (char*) "Etc/GMT-7"                         , 0x072DCB },
+	{ (char*) "Etc/GMT-8"                         , 0x072E4C },
+	{ (char*) "Etc/GMT-9"                         , 0x072ECD },
+	{ (char*) "Etc/GMT0"                          , 0x072F4E },
+	{ (char*) "Etc/Greenwich"                     , 0x072FCC },
+	{ (char*) "Etc/UCT"                           , 0x07304A },
+	{ (char*) "Etc/Universal"                     , 0x0730C8 },
+	{ (char*) "Etc/UTC"                           , 0x073146 },
+	{ (char*) "Etc/Zulu"                          , 0x0731C4 },
+	{ (char*) "Europe/Amsterdam"                  , 0x073242 },
+	{ (char*) "Europe/Andorra"                    , 0x073DAC },
+	{ (char*) "Europe/Astrakhan"                  , 0x074486 },
+	{ (char*) "Europe/Athens"                     , 0x074923 },
+	{ (char*) "Europe/Belfast"                    , 0x075205 },
+	{ (char*) "Europe/Belgrade"                   , 0x076061 },
+	{ (char*) "Europe/Berlin"                     , 0x0767ED },
+	{ (char*) "Europe/Bratislava"                 , 0x077102 },
+	{ (char*) "Europe/Brussels"                   , 0x077A0B },
+	{ (char*) "Europe/Bucharest"                  , 0x07858C },
+	{ (char*) "Europe/Budapest"                   , 0x078E20 },
+	{ (char*) "Europe/Busingen"                   , 0x07976C },
+	{ (char*) "Europe/Chisinau"                   , 0x079EF5 },
+	{ (char*) "Europe/Copenhagen"                 , 0x07A879 },
+	{ (char*) "Europe/Dublin"                     , 0x07B0DE },
+	{ (char*) "Europe/Gibraltar"                  , 0x07BE8E },
+	{ (char*) "Europe/Guernsey"                   , 0x07CA96 },
+	{ (char*) "Europe/Helsinki"                   , 0x07D936 },
+	{ (char*) "Europe/Isle_of_Man"                , 0x07E0AE },
+	{ (char*) "Europe/Istanbul"                   , 0x07EEFA },
+	{ (char*) "Europe/Jersey"                     , 0x07F693 },
+	{ (char*) "Europe/Kaliningrad"                , 0x080533 },
+	{ (char*) "Europe/Kiev"                       , 0x080B28 },
+	{ (char*) "Europe/Kirov"                      , 0x08137C },
+	{ (char*) "Europe/Kyiv"                       , 0x081837 },
+	{ (char*) "Europe/Lisbon"                     , 0x08209A },
+	{ (char*) "Europe/Ljubljana"                  , 0x082E80 },
+	{ (char*) "Europe/London"                     , 0x08360C },
+	{ (char*) "Europe/Luxembourg"                 , 0x084468 },
+	{ (char*) "Europe/Madrid"                     , 0x084FF6 },
+	{ (char*) "Europe/Malta"                      , 0x085A48 },
+	{ (char*) "Europe/Mariehamn"                  , 0x086490 },
+	{ (char*) "Europe/Minsk"                      , 0x086C08 },
+	{ (char*) "Europe/Monaco"                     , 0x08712F },
+	{ (char*) "Europe/Moscow"                     , 0x087CBB },
+	{ (char*) "Europe/Nicosia"                    , 0x0882DA },
+	{ (char*) "Europe/Oslo"                       , 0x088AB8 },
+	{ (char*) "Europe/Paris"                      , 0x089378 },
+	{ (char*) "Europe/Podgorica"                  , 0x089F16 },
+	{ (char*) "Europe/Prague"                     , 0x08A6A2 },
+	{ (char*) "Europe/Riga"                       , 0x08AFAB },
+	{ (char*) "Europe/Rome"                       , 0x08B84D },
+	{ (char*) "Europe/Samara"                     , 0x08C2AA },
+	{ (char*) "Europe/San_Marino"                 , 0x08C780 },
+	{ (char*) "Europe/Sarajevo"                   , 0x08D1DD },
+	{ (char*) "Europe/Saratov"                    , 0x08D969 },
+	{ (char*) "Europe/Simferopol"                 , 0x08DE16 },
+	{ (char*) "Europe/Skopje"                     , 0x08E3E5 },
+	{ (char*) "Europe/Sofia"                      , 0x08EB71 },
+	{ (char*) "Europe/Stockholm"                  , 0x08F39A },
+	{ (char*) "Europe/Tallinn"                    , 0x08FB1B },
+	{ (char*) "Europe/Tirane"                     , 0x09038B },
+	{ (char*) "Europe/Tiraspol"                   , 0x090BBB },
+	{ (char*) "Europe/Ulyanovsk"                  , 0x09153F },
+	{ (char*) "Europe/Uzhgorod"                   , 0x091A42 },
+	{ (char*) "Europe/Vaduz"                      , 0x092296 },
+	{ (char*) "Europe/Vatican"                    , 0x092A02 },
+	{ (char*) "Europe/Vienna"                     , 0x09345F },
+	{ (char*) "Europe/Vilnius"                    , 0x093D03 },
+	{ (char*) "Europe/Volgograd"                  , 0x094581 },
+	{ (char*) "Europe/Warsaw"                     , 0x094A48 },
+	{ (char*) "Europe/Zagreb"                     , 0x0954B2 },
+	{ (char*) "Europe/Zaporozhye"                 , 0x095C3E },
+	{ (char*) "Europe/Zurich"                     , 0x096492 },
+	{ (char*) "Factory"                           , 0x096C13 },
+	{ (char*) "GB"                                , 0x096C93 },
+	{ (char*) "GB-Eire"                           , 0x097AEF },
+	{ (char*) "GMT"                               , 0x09894B },
+	{ (char*) "GMT+0"                             , 0x0989C9 },
+	{ (char*) "GMT-0"                             , 0x098A47 },
+	{ (char*) "GMT0"                              , 0x098AC5 },
+	{ (char*) "Greenwich"                         , 0x098B43 },
+	{ (char*) "Hongkong"                          , 0x098BC1 },
+	{ (char*) "HST"                               , 0x09909E },
+	{ (char*) "Iceland"                           , 0x0991F3 },
+	{ (char*) "Indian/Antananarivo"               , 0x099293 },
+	{ (char*) "Indian/Chagos"                     , 0x09937A },
+	{ (char*) "Indian/Christmas"                  , 0x09943F },
+	{ (char*) "Indian/Cocos"                      , 0x0994E2 },
+	{ (char*) "Indian/Comoro"                     , 0x09958E },
+	{ (char*) "Indian/Kerguelen"                  , 0x09962F },
+	{ (char*) "Indian/Mahe"                       , 0x0996D2 },
+	{ (char*) "Indian/Maldives"                   , 0x099775 },
+	{ (char*) "Indian/Mauritius"                  , 0x09983A },
+	{ (char*) "Indian/Mayotte"                    , 0x099929 },
+	{ (char*) "Indian/Reunion"                    , 0x0999CA },
+	{ (char*) "Iran"                              , 0x099A6D },
+	{ (char*) "Israel"                            , 0x099F59 },
+	{ (char*) "Jamaica"                           , 0x09A8B9 },
+	{ (char*) "Japan"                             , 0x09AAA7 },
+	{ (char*) "Kwajalein"                         , 0x09ABE8 },
+	{ (char*) "Libya"                             , 0x09AD22 },
+	{ (char*) "MET"                               , 0x09AF9F },
+	{ (char*) "Mexico/BajaNorte"                  , 0x09BB20 },
+	{ (char*) "Mexico/BajaSur"                    , 0x09C686 },
+	{ (char*) "Mexico/General"                    , 0x09CAB6 },
+	{ (char*) "MST"                               , 0x09CF88 },
+	{ (char*) "MST7MDT"                           , 0x09D0FC },
+	{ (char*) "Navajo"                            , 0x09DAA4 },
+	{ (char*) "NZ"                                , 0x09E44C },
+	{ (char*) "NZ-CHAT"                           , 0x09EDDD },
+	{ (char*) "Pacific/Apia"                      , 0x09F5EF },
+	{ (char*) "Pacific/Auckland"                  , 0x09F851 },
+	{ (char*) "Pacific/Bougainville"              , 0x0A01F5 },
+	{ (char*) "Pacific/Chatham"                   , 0x0A030B },
+	{ (char*) "Pacific/Chuuk"                     , 0x0A0B2C },
+	{ (char*) "Pacific/Easter"                    , 0x0A0C46 },
+	{ (char*) "Pacific/Efate"                     , 0x0A150A },
+	{ (char*) "Pacific/Enderbury"                 , 0x0A1722 },
+	{ (char*) "Pacific/Fakaofo"                   , 0x0A180A },
+	{ (char*) "Pacific/Fiji"                      , 0x0A18D0 },
+	{ (char*) "Pacific/Funafuti"                  , 0x0A1B10 },
+	{ (char*) "Pacific/Galapagos"                 , 0x0A1BB4 },
+	{ (char*) "Pacific/Gambier"                   , 0x0A1CB1 },
+	{ (char*) "Pacific/Guadalcanal"               , 0x0A1D62 },
+	{ (char*) "Pacific/Guam"                      , 0x0A1E06 },
+	{ (char*) "Pacific/Honolulu"                  , 0x0A2000 },
+	{ (char*) "Pacific/Johnston"                  , 0x0A215B },
+	{ (char*) "Pacific/Kanton"                    , 0x0A22B0 },
+	{ (char*) "Pacific/Kiritimati"                , 0x0A23A7 },
+	{ (char*) "Pacific/Kosrae"                    , 0x0A249F },
+	{ (char*) "Pacific/Kwajalein"                 , 0x0A2602 },
+	{ (char*) "Pacific/Majuro"                    , 0x0A2745 },
+	{ (char*) "Pacific/Marquesas"                 , 0x0A2891 },
+	{ (char*) "Pacific/Midway"                    , 0x0A294D },
+	{ (char*) "Pacific/Nauru"                     , 0x0A2A40 },
+	{ (char*) "Pacific/Niue"                      , 0x0A2B3A },
+	{ (char*) "Pacific/Norfolk"                   , 0x0A2C03 },
+	{ (char*) "Pacific/Noumea"                    , 0x0A2F71 },
+	{ (char*) "Pacific/Pago_Pago"                 , 0x0A309F },
+	{ (char*) "Pacific/Palau"                     , 0x0A315A },
+	{ (char*) "Pacific/Pitcairn"                  , 0x0A320C },
+	{ (char*) "Pacific/Pohnpei"                   , 0x0A32D4 },
+	{ (char*) "Pacific/Ponape"                    , 0x0A340F },
+	{ (char*) "Pacific/Port_Moresby"              , 0x0A34B3 },
+	{ (char*) "Pacific/Rarotonga"                 , 0x0A3583 },
+	{ (char*) "Pacific/Saipan"                    , 0x0A37DC },
+	{ (char*) "Pacific/Samoa"                     , 0x0A39C8 },
+	{ (char*) "Pacific/Tahiti"                    , 0x0A3A83 },
+	{ (char*) "Pacific/Tarawa"                    , 0x0A3B35 },
+	{ (char*) "Pacific/Tongatapu"                 , 0x0A3BE8 },
+	{ (char*) "Pacific/Truk"                      , 0x0A3D5A },
+	{ (char*) "Pacific/Wake"                      , 0x0A3E12 },
+	{ (char*) "Pacific/Wallis"                    , 0x0A3EC1 },
+	{ (char*) "Pacific/Yap"                       , 0x0A3F65 },
+	{ (char*) "Poland"                            , 0x0A401D },
+	{ (char*) "Portugal"                          , 0x0A4A87 },
+	{ (char*) "PRC"                               , 0x0A585A },
+	{ (char*) "PST8PDT"                           , 0x0A5A97 },
+	{ (char*) "ROC"                               , 0x0A65C7 },
+	{ (char*) "ROK"                               , 0x0A68CC },
+	{ (char*) "Singapore"                         , 0x0A6B41 },
+	{ (char*) "Turkey"                            , 0x0A6CDE },
+	{ (char*) "UCT"                               , 0x0A7477 },
+	{ (char*) "Universal"                         , 0x0A74F5 },
+	{ (char*) "US/Alaska"                         , 0x0A7573 },
+	{ (char*) "US/Aleutian"                       , 0x0A7EC2 },
+	{ (char*) "US/Arizona"                        , 0x0A8802 },
+	{ (char*) "US/Central"                        , 0x0A8976 },
+	{ (char*) "US/East-Indiana"                   , 0x0A978A },
+	{ (char*) "US/Eastern"                        , 0x0A9E28 },
+	{ (char*) "US/Hawaii"                         , 0x0AAC14 },
+	{ (char*) "US/Indiana-Starke"                 , 0x0AAD69 },
+	{ (char*) "US/Michigan"                       , 0x0AB701 },
+	{ (char*) "US/Mountain"                       , 0x0ABFC3 },
+	{ (char*) "US/Pacific"                        , 0x0AC96B },
+	{ (char*) "US/Samoa"                          , 0x0AD49B },
+	{ (char*) "UTC"                               , 0x0AD556 },
+	{ (char*) "W-SU"                              , 0x0AD5D4 },
+	{ (char*) "WET"                               , 0x0ADBDF },
+	{ (char*) "Zulu"                              , 0x0AE9B2 },
 };
 
 
-const unsigned char timelib_timezone_db_data_builtin[715258] = {
+const unsigned char timelib_timezone_db_data_builtin[715312] = {
 
 /* Africa/Abidjan */
 0x50, 0x48, 0x50, 0x32, 0x01, 0x43, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -47351,7 +47408,7 @@
 /* Asia/Tbilisi */
 0x50, 0x48, 0x50, 0x32, 0x01, 0x47, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x15, 0x80, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x15, 0x80, 0x00, 0x00, 0x00,
 0xAA, 0x19, 0x9A, 0x01, 0xE7, 0xDA, 0x0C, 0x50, 0x15, 0x27, 0x99, 0xC0, 0x16, 0x18, 0xCE, 0x30,
 0x17, 0x08, 0xCD, 0x40, 0x17, 0xFA, 0x01, 0xB0, 0x18, 0xEA, 0x00, 0xC0, 0x19, 0xDB, 0x35, 0x30,
 0x1A, 0xCC, 0x85, 0xC0, 0x1B, 0xBC, 0x92, 0xE0, 0x1C, 0xAC, 0x83, 0xE0, 0x1D, 0x9C, 0x74, 0xE0,
@@ -47360,60 +47417,59 @@
 0x26, 0x0B, 0xED, 0xE0, 0x27, 0x05, 0x19, 0x60, 0x27, 0xF5, 0x0A, 0x60, 0x28, 0xE5, 0x09, 0x70,
 0x29, 0xD4, 0xDE, 0x50, 0x2A, 0xC4, 0xC1, 0x40, 0x2B, 0xB4, 0xC0, 0x50, 0x2C, 0xA4, 0xA3, 0x40,
 0x2D, 0x94, 0xA2, 0x50, 0x2E, 0x84, 0x85, 0x40, 0x2F, 0x74, 0x76, 0x40, 0x30, 0x64, 0x59, 0x30,
-0x31, 0x5D, 0x92, 0xC0, 0x33, 0x3D, 0x66, 0xB0, 0x34, 0x52, 0x41, 0xB0, 0x35, 0x1D, 0x56, 0xC0,
-0x36, 0x32, 0x23, 0xB0, 0x36, 0xFD, 0x38, 0xC0, 0x38, 0x1B, 0x40, 0x30, 0x38, 0xDD, 0x1A, 0xC0,
-0x39, 0xFB, 0x22, 0x30, 0x3A, 0xBC, 0xFC, 0xC0, 0x3B, 0xDB, 0x04, 0x30, 0x3C, 0xA6, 0x19, 0x40,
-0x3D, 0xBA, 0xE6, 0x30, 0x3E, 0x85, 0xFB, 0x40, 0x3F, 0x9A, 0xC8, 0x30, 0x40, 0x65, 0xDD, 0x40,
-0x40, 0xDD, 0xC7, 0xB0, 0x41, 0x84, 0x1C, 0xF0, 0x42, 0x45, 0xE9, 0x70, 0x01, 0x02, 0x04, 0x03,
-0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06,
-0x05, 0x06, 0x05, 0x07, 0x08, 0x09, 0x02, 0x09, 0x02, 0x09, 0x04, 0x03, 0x04, 0x03, 0x03, 0x04,
-0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x09, 0x08, 0x04,
-0x00, 0x00, 0x29, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x29, 0xFF, 0x00, 0x04, 0x00, 0x00, 0x2A, 0x30,
-0x00, 0x09, 0x00, 0x00, 0x46, 0x50, 0x01, 0x0D, 0x00, 0x00, 0x38, 0x40, 0x00, 0x11, 0x00, 0x00,
-0x38, 0x40, 0x00, 0x11, 0x00, 0x00, 0x46, 0x50, 0x01, 0x0D, 0x00, 0x00, 0x38, 0x40, 0x01, 0x11,
-0x00, 0x00, 0x2A, 0x30, 0x00, 0x09, 0x00, 0x00, 0x38, 0x40, 0x01, 0x11, 0x00, 0x00, 0x38, 0x40,
-0x00, 0x11, 0x4C, 0x4D, 0x54, 0x00, 0x54, 0x42, 0x4D, 0x54, 0x00, 0x2B, 0x30, 0x33, 0x00, 0x2B,
-0x30, 0x35, 0x00, 0x2B, 0x30, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
-0x00, 0x00, 0x54, 0x5A, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x15, 0xFF, 0xFF,
-0xFF, 0xFF, 0x56, 0xB6, 0xBA, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xAA, 0x19, 0x9A, 0x01, 0xFF, 0xFF,
-0xFF, 0xFF, 0xE7, 0xDA, 0x0C, 0x50, 0x00, 0x00, 0x00, 0x00, 0x15, 0x27, 0x99, 0xC0, 0x00, 0x00,
-0x00, 0x00, 0x16, 0x18, 0xCE, 0x30, 0x00, 0x00, 0x00, 0x00, 0x17, 0x08, 0xCD, 0x40, 0x00, 0x00,
-0x00, 0x00, 0x17, 0xFA, 0x01, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x18, 0xEA, 0x00, 0xC0, 0x00, 0x00,
-0x00, 0x00, 0x19, 0xDB, 0x35, 0x30, 0x00, 0x00, 0x00, 0x00, 0x1A, 0xCC, 0x85, 0xC0, 0x00, 0x00,
-0x00, 0x00, 0x1B, 0xBC, 0x92, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x1C, 0xAC, 0x83, 0xE0, 0x00, 0x00,
-0x00, 0x00, 0x1D, 0x9C, 0x74, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x8C, 0x65, 0xE0, 0x00, 0x00,
-0x00, 0x00, 0x1F, 0x7C, 0x56, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x20, 0x6C, 0x47, 0xE0, 0x00, 0x00,
-0x00, 0x00, 0x21, 0x5C, 0x38, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x22, 0x4C, 0x29, 0xE0, 0x00, 0x00,
-0x00, 0x00, 0x23, 0x3C, 0x1A, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x24, 0x2C, 0x0B, 0xE0, 0x00, 0x00,
-0x00, 0x00, 0x25, 0x1B, 0xFC, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x26, 0x0B, 0xED, 0xE0, 0x00, 0x00,
-0x00, 0x00, 0x27, 0x05, 0x19, 0x60, 0x00, 0x00, 0x00, 0x00, 0x27, 0xF5, 0x0A, 0x60, 0x00, 0x00,
-0x00, 0x00, 0x28, 0xE5, 0x09, 0x70, 0x00, 0x00, 0x00, 0x00, 0x29, 0xD4, 0xDE, 0x50, 0x00, 0x00,
-0x00, 0x00, 0x2A, 0xC4, 0xC1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x2B, 0xB4, 0xC0, 0x50, 0x00, 0x00,
-0x00, 0x00, 0x2C, 0xA4, 0xA3, 0x40, 0x00, 0x00, 0x00, 0x00, 0x2D, 0x94, 0xA2, 0x50, 0x00, 0x00,
-0x00, 0x00, 0x2E, 0x84, 0x85, 0x40, 0x00, 0x00, 0x00, 0x00, 0x2F, 0x74, 0x76, 0x40, 0x00, 0x00,
-0x00, 0x00, 0x30, 0x64, 0x59, 0x30, 0x00, 0x00, 0x00, 0x00, 0x31, 0x5D, 0x92, 0xC0, 0x00, 0x00,
-0x00, 0x00, 0x33, 0x3D, 0x66, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x34, 0x52, 0x41, 0xB0, 0x00, 0x00,
-0x00, 0x00, 0x35, 0x1D, 0x56, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x36, 0x32, 0x23, 0xB0, 0x00, 0x00,
-0x00, 0x00, 0x36, 0xFD, 0x38, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x38, 0x1B, 0x40, 0x30, 0x00, 0x00,
-0x00, 0x00, 0x38, 0xDD, 0x1A, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x39, 0xFB, 0x22, 0x30, 0x00, 0x00,
-0x00, 0x00, 0x3A, 0xBC, 0xFC, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x3B, 0xDB, 0x04, 0x30, 0x00, 0x00,
-0x00, 0x00, 0x3C, 0xA6, 0x19, 0x40, 0x00, 0x00, 0x00, 0x00, 0x3D, 0xBA, 0xE6, 0x30, 0x00, 0x00,
-0x00, 0x00, 0x3E, 0x85, 0xFB, 0x40, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x9A, 0xC8, 0x30, 0x00, 0x00,
-0x00, 0x00, 0x40, 0x65, 0xDD, 0x40, 0x00, 0x00, 0x00, 0x00, 0x40, 0xDD, 0xC7, 0xB0, 0x00, 0x00,
-0x00, 0x00, 0x41, 0x84, 0x1C, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x42, 0x45, 0xE9, 0x70, 0x01, 0x02,
-0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06,
-0x05, 0x06, 0x05, 0x06, 0x05, 0x07, 0x08, 0x09, 0x02, 0x09, 0x02, 0x09, 0x04, 0x03, 0x04, 0x03,
-0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x09,
-0x08, 0x04, 0x00, 0x00, 0x29, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x29, 0xFF, 0x00, 0x04, 0x00, 0x00,
-0x2A, 0x30, 0x00, 0x09, 0x00, 0x00, 0x46, 0x50, 0x01, 0x0D, 0x00, 0x00, 0x38, 0x40, 0x00, 0x11,
-0x00, 0x00, 0x38, 0x40, 0x00, 0x11, 0x00, 0x00, 0x46, 0x50, 0x01, 0x0D, 0x00, 0x00, 0x38, 0x40,
-0x01, 0x11, 0x00, 0x00, 0x2A, 0x30, 0x00, 0x09, 0x00, 0x00, 0x38, 0x40, 0x01, 0x11, 0x00, 0x00,
-0x38, 0x40, 0x00, 0x11, 0x4C, 0x4D, 0x54, 0x00, 0x54, 0x42, 0x4D, 0x54, 0x00, 0x2B, 0x30, 0x33,
-0x00, 0x2B, 0x30, 0x35, 0x00, 0x2B, 0x30, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
-0x01, 0x01, 0x00, 0x00, 0x0A, 0x3C, 0x2B, 0x30, 0x34, 0x3E, 0x2D, 0x34, 0x0A, 0x00, 0xC8, 0xFB,
-0xD2, 0x01, 0x57, 0x0B, 0x02, 0x00, 0x00, 0x00, 0x00, 
+0x31, 0x5D, 0x92, 0xC0, 0x34, 0x52, 0x41, 0xB0, 0x35, 0x1D, 0x56, 0xC0, 0x36, 0x32, 0x23, 0xB0,
+0x36, 0xFD, 0x38, 0xC0, 0x38, 0x1B, 0x40, 0x30, 0x38, 0xDD, 0x1A, 0xC0, 0x39, 0xFB, 0x22, 0x30,
+0x3A, 0xBC, 0xFC, 0xC0, 0x3B, 0xDB, 0x04, 0x30, 0x3C, 0xA6, 0x19, 0x40, 0x3D, 0xBA, 0xE6, 0x30,
+0x3E, 0x85, 0xFB, 0x40, 0x3F, 0x9A, 0xC8, 0x30, 0x40, 0x65, 0xDD, 0x40, 0x40, 0xDD, 0xC7, 0xB0,
+0x41, 0x84, 0x1C, 0xF0, 0x42, 0x45, 0xE9, 0x70, 0x01, 0x02, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03,
+0x04, 0x03, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x07,
+0x08, 0x09, 0x02, 0x09, 0x02, 0x09, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03,
+0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x09, 0x08, 0x04, 0x00, 0x00, 0x29, 0xFF, 0x00,
+0x00, 0x00, 0x00, 0x29, 0xFF, 0x00, 0x04, 0x00, 0x00, 0x2A, 0x30, 0x00, 0x09, 0x00, 0x00, 0x46,
+0x50, 0x01, 0x0D, 0x00, 0x00, 0x38, 0x40, 0x00, 0x11, 0x00, 0x00, 0x38, 0x40, 0x00, 0x11, 0x00,
+0x00, 0x46, 0x50, 0x01, 0x0D, 0x00, 0x00, 0x38, 0x40, 0x01, 0x11, 0x00, 0x00, 0x2A, 0x30, 0x00,
+0x09, 0x00, 0x00, 0x38, 0x40, 0x01, 0x11, 0x00, 0x00, 0x38, 0x40, 0x00, 0x11, 0x4C, 0x4D, 0x54,
+0x00, 0x54, 0x42, 0x4D, 0x54, 0x00, 0x2B, 0x30, 0x33, 0x00, 0x2B, 0x30, 0x35, 0x00, 0x2B, 0x30,
+0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x54, 0x5A, 0x69,
+0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x33, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x15, 0xFF, 0xFF, 0xFF, 0xFF, 0x56, 0xB6, 0xBA,
+0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xAA, 0x19, 0x9A, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xDA, 0x0C,
+0x50, 0x00, 0x00, 0x00, 0x00, 0x15, 0x27, 0x99, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x16, 0x18, 0xCE,
+0x30, 0x00, 0x00, 0x00, 0x00, 0x17, 0x08, 0xCD, 0x40, 0x00, 0x00, 0x00, 0x00, 0x17, 0xFA, 0x01,
+0xB0, 0x00, 0x00, 0x00, 0x00, 0x18, 0xEA, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x19, 0xDB, 0x35,
+0x30, 0x00, 0x00, 0x00, 0x00, 0x1A, 0xCC, 0x85, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x1B, 0xBC, 0x92,
+0xE0, 0x00, 0x00, 0x00, 0x00, 0x1C, 0xAC, 0x83, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x1D, 0x9C, 0x74,
+0xE0, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x8C, 0x65, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x7C, 0x56,
+0xE0, 0x00, 0x00, 0x00, 0x00, 0x20, 0x6C, 0x47, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x21, 0x5C, 0x38,
+0xE0, 0x00, 0x00, 0x00, 0x00, 0x22, 0x4C, 0x29, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x23, 0x3C, 0x1A,
+0xE0, 0x00, 0x00, 0x00, 0x00, 0x24, 0x2C, 0x0B, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x25, 0x1B, 0xFC,
+0xE0, 0x00, 0x00, 0x00, 0x00, 0x26, 0x0B, 0xED, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x27, 0x05, 0x19,
+0x60, 0x00, 0x00, 0x00, 0x00, 0x27, 0xF5, 0x0A, 0x60, 0x00, 0x00, 0x00, 0x00, 0x28, 0xE5, 0x09,
+0x70, 0x00, 0x00, 0x00, 0x00, 0x29, 0xD4, 0xDE, 0x50, 0x00, 0x00, 0x00, 0x00, 0x2A, 0xC4, 0xC1,
+0x40, 0x00, 0x00, 0x00, 0x00, 0x2B, 0xB4, 0xC0, 0x50, 0x00, 0x00, 0x00, 0x00, 0x2C, 0xA4, 0xA3,
+0x40, 0x00, 0x00, 0x00, 0x00, 0x2D, 0x94, 0xA2, 0x50, 0x00, 0x00, 0x00, 0x00, 0x2E, 0x84, 0x85,
+0x40, 0x00, 0x00, 0x00, 0x00, 0x2F, 0x74, 0x76, 0x40, 0x00, 0x00, 0x00, 0x00, 0x30, 0x64, 0x59,
+0x30, 0x00, 0x00, 0x00, 0x00, 0x31, 0x5D, 0x92, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x34, 0x52, 0x41,
+0xB0, 0x00, 0x00, 0x00, 0x00, 0x35, 0x1D, 0x56, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x36, 0x32, 0x23,
+0xB0, 0x00, 0x00, 0x00, 0x00, 0x36, 0xFD, 0x38, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x38, 0x1B, 0x40,
+0x30, 0x00, 0x00, 0x00, 0x00, 0x38, 0xDD, 0x1A, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x39, 0xFB, 0x22,
+0x30, 0x00, 0x00, 0x00, 0x00, 0x3A, 0xBC, 0xFC, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x3B, 0xDB, 0x04,
+0x30, 0x00, 0x00, 0x00, 0x00, 0x3C, 0xA6, 0x19, 0x40, 0x00, 0x00, 0x00, 0x00, 0x3D, 0xBA, 0xE6,
+0x30, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x85, 0xFB, 0x40, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x9A, 0xC8,
+0x30, 0x00, 0x00, 0x00, 0x00, 0x40, 0x65, 0xDD, 0x40, 0x00, 0x00, 0x00, 0x00, 0x40, 0xDD, 0xC7,
+0xB0, 0x00, 0x00, 0x00, 0x00, 0x41, 0x84, 0x1C, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x42, 0x45, 0xE9,
+0x70, 0x01, 0x02, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x05, 0x06, 0x05, 0x06, 0x05,
+0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x07, 0x08, 0x09, 0x02, 0x09, 0x02, 0x09, 0x04,
+0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04,
+0x03, 0x09, 0x08, 0x04, 0x00, 0x00, 0x29, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x29, 0xFF, 0x00, 0x04,
+0x00, 0x00, 0x2A, 0x30, 0x00, 0x09, 0x00, 0x00, 0x46, 0x50, 0x01, 0x0D, 0x00, 0x00, 0x38, 0x40,
+0x00, 0x11, 0x00, 0x00, 0x38, 0x40, 0x00, 0x11, 0x00, 0x00, 0x46, 0x50, 0x01, 0x0D, 0x00, 0x00,
+0x38, 0x40, 0x01, 0x11, 0x00, 0x00, 0x2A, 0x30, 0x00, 0x09, 0x00, 0x00, 0x38, 0x40, 0x01, 0x11,
+0x00, 0x00, 0x38, 0x40, 0x00, 0x11, 0x4C, 0x4D, 0x54, 0x00, 0x54, 0x42, 0x4D, 0x54, 0x00, 0x2B,
+0x30, 0x33, 0x00, 0x2B, 0x30, 0x35, 0x00, 0x2B, 0x30, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x0A, 0x3C, 0x2B, 0x30, 0x34, 0x3E, 0x2D, 0x34, 0x0A, 0x00,
+0xC8, 0xFB, 0xD2, 0x01, 0x57, 0x0B, 0x02, 0x00, 0x00, 0x00, 0x00, 
 
 /* Asia/Tehran */
 0x50, 0x48, 0x50, 0x32, 0x01, 0x49, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -57363,7 +57419,7 @@
 
 /* Europe/Chisinau */
 0x50, 0x48, 0x50, 0x32, 0x01, 0x4D, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x8D, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x26, 0x80, 0x00, 0x00, 0x00,
 0x9E, 0x6B, 0x9F, 0x0C, 0xB7, 0xB0, 0xD2, 0x08, 0xB9, 0x3E, 0xF3, 0x60, 0xB9, 0xEF, 0x9C, 0x60,
 0xBA, 0xDF, 0x8D, 0x60, 0xBB, 0xCF, 0x7E, 0x60, 0xBC, 0xC8, 0xA9, 0xE0, 0xBD, 0xB8, 0x9A, 0xE0,
@@ -57392,23 +57448,23 @@
 0x56, 0xF7, 0x22, 0x80, 0x58, 0x15, 0x38, 0x00, 0x58, 0xD7, 0x04, 0x80, 0x59, 0xF5, 0x1A, 0x00,
 0x5A, 0xB6, 0xE6, 0x80, 0x5B, 0xD4, 0xFC, 0x00, 0x5C, 0xA0, 0x03, 0x00, 0x5D, 0xB4, 0xDE, 0x00,
 0x5E, 0x7F, 0xE5, 0x00, 0x5F, 0x94, 0xC0, 0x00, 0x60, 0x5F, 0xC7, 0x00, 0x61, 0x7D, 0xDC, 0x80,
-0x62, 0x3F, 0xA9, 0x00, 0x63, 0x5D, 0xBE, 0x80, 0x64, 0x1F, 0x8B, 0x00, 0x65, 0x3D, 0xA0, 0x80,
-0x66, 0x08, 0xA7, 0x80, 0x67, 0x1D, 0x82, 0x80, 0x67, 0xE8, 0x89, 0x80, 0x68, 0xFD, 0x64, 0x80,
-0x69, 0xC8, 0x6B, 0x80, 0x6A, 0xDD, 0x46, 0x80, 0x6B, 0xA8, 0x4D, 0x80, 0x6C, 0xC6, 0x63, 0x00,
-0x6D, 0x88, 0x2F, 0x80, 0x6E, 0xA6, 0x45, 0x00, 0x6F, 0x68, 0x11, 0x80, 0x70, 0x86, 0x27, 0x00,
-0x71, 0x51, 0x2E, 0x00, 0x72, 0x66, 0x09, 0x00, 0x73, 0x31, 0x10, 0x00, 0x74, 0x45, 0xEB, 0x00,
-0x75, 0x10, 0xF2, 0x00, 0x76, 0x2F, 0x07, 0x80, 0x76, 0xF0, 0xD4, 0x00, 0x78, 0x0E, 0xE9, 0x80,
-0x78, 0xD0, 0xB6, 0x00, 0x79, 0xEE, 0xCB, 0x80, 0x7A, 0xB0, 0x98, 0x00, 0x7B, 0xCE, 0xAD, 0x80,
-0x7C, 0x99, 0xB4, 0x80, 0x7D, 0xAE, 0x8F, 0x80, 0x7E, 0x79, 0x96, 0x80, 0x7F, 0x8E, 0x71, 0x80,
+0x62, 0x3F, 0xB7, 0x10, 0x63, 0x5D, 0xCC, 0x90, 0x64, 0x1F, 0x99, 0x10, 0x65, 0x3D, 0xAE, 0x90,
+0x66, 0x08, 0xB5, 0x90, 0x67, 0x1D, 0x90, 0x90, 0x67, 0xE8, 0x97, 0x90, 0x68, 0xFD, 0x72, 0x90,
+0x69, 0xC8, 0x79, 0x90, 0x6A, 0xDD, 0x54, 0x90, 0x6B, 0xA8, 0x5B, 0x90, 0x6C, 0xC6, 0x71, 0x10,
+0x6D, 0x88, 0x3D, 0x90, 0x6E, 0xA6, 0x53, 0x10, 0x6F, 0x68, 0x1F, 0x90, 0x70, 0x86, 0x35, 0x10,
+0x71, 0x51, 0x3C, 0x10, 0x72, 0x66, 0x17, 0x10, 0x73, 0x31, 0x1E, 0x10, 0x74, 0x45, 0xF9, 0x10,
+0x75, 0x11, 0x00, 0x10, 0x76, 0x2F, 0x15, 0x90, 0x76, 0xF0, 0xE2, 0x10, 0x78, 0x0E, 0xF7, 0x90,
+0x78, 0xD0, 0xC4, 0x10, 0x79, 0xEE, 0xD9, 0x90, 0x7A, 0xB0, 0xA6, 0x10, 0x7B, 0xCE, 0xBB, 0x90,
+0x7C, 0x99, 0xC2, 0x90, 0x7D, 0xAE, 0x9D, 0x90, 0x7E, 0x79, 0xA4, 0x90, 0x7F, 0x8E, 0x7F, 0x90,
 0x01, 0x02, 0x05, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03,
 0x04, 0x03, 0x04, 0x06, 0x09, 0x07, 0x08, 0x07, 0x08, 0x0B, 0x0A, 0x0B, 0x0A, 0x0B, 0x0A, 0x0B,
 0x0A, 0x0C, 0x0D, 0x0C, 0x0D, 0x0C, 0x0D, 0x0C, 0x0D, 0x0C, 0x0D, 0x0C, 0x0D, 0x06, 0x04, 0x03,
 0x04, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06,
 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06,
 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06,
-0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06,
-0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06,
-0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x00, 0x00, 0x1B,
+0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x0E, 0x0F, 0x0E,
+0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E,
+0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x00, 0x00, 0x1B,
 0x08, 0x00, 0x00, 0x00, 0x00, 0x1A, 0xF4, 0x00, 0x04, 0x00, 0x00, 0x18, 0x78, 0x00, 0x08, 0x00,
 0x00, 0x2A, 0x30, 0x01, 0x0C, 0x00, 0x00, 0x1C, 0x20, 0x00, 0x11, 0x00, 0x00, 0x1C, 0x20, 0x00,
 0x11, 0x00, 0x00, 0x2A, 0x30, 0x01, 0x0C, 0x00, 0x00, 0x0E, 0x10, 0x00, 0x15, 0x00, 0x00, 0x1C,
@@ -57418,8 +57474,9 @@
 0x00, 0x43, 0x4D, 0x54, 0x00, 0x42, 0x4D, 0x54, 0x00, 0x45, 0x45, 0x53, 0x54, 0x00, 0x45, 0x45,
 0x54, 0x00, 0x43, 0x45, 0x54, 0x00, 0x43, 0x45, 0x53, 0x54, 0x00, 0x4D, 0x53, 0x44, 0x00, 0x4D,
 0x53, 0x4B, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01,
-0x01, 0x00, 0x00, 0x54, 0x5A, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
+0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x01, 0x01, 0x54, 0x5A, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00,
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8D, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x26, 0xFF,
 0xFF, 0xFF, 0xFF, 0x56, 0xB6, 0xC8, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0x9E, 0x6B, 0x9F, 0x0C, 0xFF,
 0xFF, 0xFF, 0xFF, 0xB7, 0xB0, 0xD2, 0x08, 0xFF, 0xFF, 0xFF, 0xFF, 0xB9, 0x3E, 0xF3, 0x60, 0xFF,
@@ -57475,32 +57532,32 @@
 0x00, 0x00, 0x00, 0x5B, 0xD4, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5C, 0xA0, 0x03, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x5D, 0xB4, 0xDE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5E, 0x7F, 0xE5, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x5F, 0x94, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x5F, 0xC7, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x61, 0x7D, 0xDC, 0x80, 0x00, 0x00, 0x00, 0x00, 0x62, 0x3F, 0xA9, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x63, 0x5D, 0xBE, 0x80, 0x00, 0x00, 0x00, 0x00, 0x64, 0x1F, 0x8B, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x65, 0x3D, 0xA0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x66, 0x08, 0xA7, 0x80, 0x00,
-0x00, 0x00, 0x00, 0x67, 0x1D, 0x82, 0x80, 0x00, 0x00, 0x00, 0x00, 0x67, 0xE8, 0x89, 0x80, 0x00,
-0x00, 0x00, 0x00, 0x68, 0xFD, 0x64, 0x80, 0x00, 0x00, 0x00, 0x00, 0x69, 0xC8, 0x6B, 0x80, 0x00,
-0x00, 0x00, 0x00, 0x6A, 0xDD, 0x46, 0x80, 0x00, 0x00, 0x00, 0x00, 0x6B, 0xA8, 0x4D, 0x80, 0x00,
-0x00, 0x00, 0x00, 0x6C, 0xC6, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6D, 0x88, 0x2F, 0x80, 0x00,
-0x00, 0x00, 0x00, 0x6E, 0xA6, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6F, 0x68, 0x11, 0x80, 0x00,
-0x00, 0x00, 0x00, 0x70, 0x86, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x71, 0x51, 0x2E, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x72, 0x66, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x31, 0x10, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x74, 0x45, 0xEB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0x10, 0xF2, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x76, 0x2F, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x76, 0xF0, 0xD4, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x78, 0x0E, 0xE9, 0x80, 0x00, 0x00, 0x00, 0x00, 0x78, 0xD0, 0xB6, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x79, 0xEE, 0xCB, 0x80, 0x00, 0x00, 0x00, 0x00, 0x7A, 0xB0, 0x98, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x7B, 0xCE, 0xAD, 0x80, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x99, 0xB4, 0x80, 0x00,
-0x00, 0x00, 0x00, 0x7D, 0xAE, 0x8F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x79, 0x96, 0x80, 0x00,
-0x00, 0x00, 0x00, 0x7F, 0x8E, 0x71, 0x80, 0x01, 0x02, 0x05, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04,
+0x00, 0x00, 0x00, 0x61, 0x7D, 0xDC, 0x80, 0x00, 0x00, 0x00, 0x00, 0x62, 0x3F, 0xB7, 0x10, 0x00,
+0x00, 0x00, 0x00, 0x63, 0x5D, 0xCC, 0x90, 0x00, 0x00, 0x00, 0x00, 0x64, 0x1F, 0x99, 0x10, 0x00,
+0x00, 0x00, 0x00, 0x65, 0x3D, 0xAE, 0x90, 0x00, 0x00, 0x00, 0x00, 0x66, 0x08, 0xB5, 0x90, 0x00,
+0x00, 0x00, 0x00, 0x67, 0x1D, 0x90, 0x90, 0x00, 0x00, 0x00, 0x00, 0x67, 0xE8, 0x97, 0x90, 0x00,
+0x00, 0x00, 0x00, 0x68, 0xFD, 0x72, 0x90, 0x00, 0x00, 0x00, 0x00, 0x69, 0xC8, 0x79, 0x90, 0x00,
+0x00, 0x00, 0x00, 0x6A, 0xDD, 0x54, 0x90, 0x00, 0x00, 0x00, 0x00, 0x6B, 0xA8, 0x5B, 0x90, 0x00,
+0x00, 0x00, 0x00, 0x6C, 0xC6, 0x71, 0x10, 0x00, 0x00, 0x00, 0x00, 0x6D, 0x88, 0x3D, 0x90, 0x00,
+0x00, 0x00, 0x00, 0x6E, 0xA6, 0x53, 0x10, 0x00, 0x00, 0x00, 0x00, 0x6F, 0x68, 0x1F, 0x90, 0x00,
+0x00, 0x00, 0x00, 0x70, 0x86, 0x35, 0x10, 0x00, 0x00, 0x00, 0x00, 0x71, 0x51, 0x3C, 0x10, 0x00,
+0x00, 0x00, 0x00, 0x72, 0x66, 0x17, 0x10, 0x00, 0x00, 0x00, 0x00, 0x73, 0x31, 0x1E, 0x10, 0x00,
+0x00, 0x00, 0x00, 0x74, 0x45, 0xF9, 0x10, 0x00, 0x00, 0x00, 0x00, 0x75, 0x11, 0x00, 0x10, 0x00,
+0x00, 0x00, 0x00, 0x76, 0x2F, 0x15, 0x90, 0x00, 0x00, 0x00, 0x00, 0x76, 0xF0, 0xE2, 0x10, 0x00,
+0x00, 0x00, 0x00, 0x78, 0x0E, 0xF7, 0x90, 0x00, 0x00, 0x00, 0x00, 0x78, 0xD0, 0xC4, 0x10, 0x00,
+0x00, 0x00, 0x00, 0x79, 0xEE, 0xD9, 0x90, 0x00, 0x00, 0x00, 0x00, 0x7A, 0xB0, 0xA6, 0x10, 0x00,
+0x00, 0x00, 0x00, 0x7B, 0xCE, 0xBB, 0x90, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x99, 0xC2, 0x90, 0x00,
+0x00, 0x00, 0x00, 0x7D, 0xAE, 0x9D, 0x90, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x79, 0xA4, 0x90, 0x00,
+0x00, 0x00, 0x00, 0x7F, 0x8E, 0x7F, 0x90, 0x01, 0x02, 0x05, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04,
 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x06, 0x09, 0x07, 0x08, 0x07, 0x08,
 0x0B, 0x0A, 0x0B, 0x0A, 0x0B, 0x0A, 0x0B, 0x0A, 0x0C, 0x0D, 0x0C, 0x0D, 0x0C, 0x0D, 0x0C, 0x0D,
 0x0C, 0x0D, 0x0C, 0x0D, 0x06, 0x04, 0x03, 0x04, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05,
 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05,
 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05,
 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05,
-0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05,
-0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05,
-0x06, 0x05, 0x06, 0x05, 0x00, 0x00, 0x1B, 0x08, 0x00, 0x00, 0x00, 0x00, 0x1A, 0xF4, 0x00, 0x04,
+0x06, 0x05, 0x06, 0x05, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F,
+0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F,
+0x0E, 0x0F, 0x0E, 0x0F, 0x00, 0x00, 0x1B, 0x08, 0x00, 0x00, 0x00, 0x00, 0x1A, 0xF4, 0x00, 0x04,
 0x00, 0x00, 0x18, 0x78, 0x00, 0x08, 0x00, 0x00, 0x2A, 0x30, 0x01, 0x0C, 0x00, 0x00, 0x1C, 0x20,
 0x00, 0x11, 0x00, 0x00, 0x1C, 0x20, 0x00, 0x11, 0x00, 0x00, 0x2A, 0x30, 0x01, 0x0C, 0x00, 0x00,
 0x0E, 0x10, 0x00, 0x15, 0x00, 0x00, 0x1C, 0x20, 0x01, 0x19, 0x00, 0x00, 0x1C, 0x20, 0x01, 0x19,
@@ -57509,10 +57566,11 @@
 0x1C, 0x20, 0x00, 0x11, 0x4C, 0x4D, 0x54, 0x00, 0x43, 0x4D, 0x54, 0x00, 0x42, 0x4D, 0x54, 0x00,
 0x45, 0x45, 0x53, 0x54, 0x00, 0x45, 0x45, 0x54, 0x00, 0x43, 0x45, 0x54, 0x00, 0x43, 0x45, 0x53,
 0x54, 0x00, 0x4D, 0x53, 0x44, 0x00, 0x4D, 0x53, 0x4B, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00,
-0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x0A, 0x45, 0x45, 0x54, 0x2D, 0x32,
-0x45, 0x45, 0x53, 0x54, 0x2C, 0x4D, 0x33, 0x2E, 0x35, 0x2E, 0x30, 0x2C, 0x4D, 0x31, 0x30, 0x2E,
-0x35, 0x2E, 0x30, 0x2F, 0x33, 0x0A, 0x00, 0xD1, 0x0B, 0xA0, 0x01, 0x3E, 0xA7, 0x85, 0x00, 0x00,
-0x00, 0x00, 
+0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x0A, 0x45, 0x45, 0x54, 0x2D, 0x32,
+0x45, 0x45, 0x53, 0x54, 0x2C, 0x4D, 0x33, 0x2E, 0x35, 0x2E, 0x30, 0x2F, 0x33, 0x2C, 0x4D, 0x31,
+0x30, 0x2E, 0x35, 0x2E, 0x30, 0x2F, 0x34, 0x0A, 0x00, 0xD1, 0x0B, 0xA0, 0x01, 0x3E, 0xA7, 0x85,
+0x00, 0x00, 0x00, 0x00, 
 
 /* Europe/Copenhagen */
 0x50, 0x48, 0x50, 0x32, 0x01, 0x44, 0x4B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -63298,7 +63356,7 @@
 
 /* Europe/Tiraspol */
 0x50, 0x48, 0x50, 0x32, 0x00, 0x3F, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x8D, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x26, 0x80, 0x00, 0x00, 0x00,
 0x9E, 0x6B, 0x9F, 0x0C, 0xB7, 0xB0, 0xD2, 0x08, 0xB9, 0x3E, 0xF3, 0x60, 0xB9, 0xEF, 0x9C, 0x60,
 0xBA, 0xDF, 0x8D, 0x60, 0xBB, 0xCF, 0x7E, 0x60, 0xBC, 0xC8, 0xA9, 0xE0, 0xBD, 0xB8, 0x9A, 0xE0,
@@ -63327,23 +63385,23 @@
 0x56, 0xF7, 0x22, 0x80, 0x58, 0x15, 0x38, 0x00, 0x58, 0xD7, 0x04, 0x80, 0x59, 0xF5, 0x1A, 0x00,
 0x5A, 0xB6, 0xE6, 0x80, 0x5B, 0xD4, 0xFC, 0x00, 0x5C, 0xA0, 0x03, 0x00, 0x5D, 0xB4, 0xDE, 0x00,
 0x5E, 0x7F, 0xE5, 0x00, 0x5F, 0x94, 0xC0, 0x00, 0x60, 0x5F, 0xC7, 0x00, 0x61, 0x7D, 0xDC, 0x80,
-0x62, 0x3F, 0xA9, 0x00, 0x63, 0x5D, 0xBE, 0x80, 0x64, 0x1F, 0x8B, 0x00, 0x65, 0x3D, 0xA0, 0x80,
-0x66, 0x08, 0xA7, 0x80, 0x67, 0x1D, 0x82, 0x80, 0x67, 0xE8, 0x89, 0x80, 0x68, 0xFD, 0x64, 0x80,
-0x69, 0xC8, 0x6B, 0x80, 0x6A, 0xDD, 0x46, 0x80, 0x6B, 0xA8, 0x4D, 0x80, 0x6C, 0xC6, 0x63, 0x00,
-0x6D, 0x88, 0x2F, 0x80, 0x6E, 0xA6, 0x45, 0x00, 0x6F, 0x68, 0x11, 0x80, 0x70, 0x86, 0x27, 0x00,
-0x71, 0x51, 0x2E, 0x00, 0x72, 0x66, 0x09, 0x00, 0x73, 0x31, 0x10, 0x00, 0x74, 0x45, 0xEB, 0x00,
-0x75, 0x10, 0xF2, 0x00, 0x76, 0x2F, 0x07, 0x80, 0x76, 0xF0, 0xD4, 0x00, 0x78, 0x0E, 0xE9, 0x80,
-0x78, 0xD0, 0xB6, 0x00, 0x79, 0xEE, 0xCB, 0x80, 0x7A, 0xB0, 0x98, 0x00, 0x7B, 0xCE, 0xAD, 0x80,
-0x7C, 0x99, 0xB4, 0x80, 0x7D, 0xAE, 0x8F, 0x80, 0x7E, 0x79, 0x96, 0x80, 0x7F, 0x8E, 0x71, 0x80,
+0x62, 0x3F, 0xB7, 0x10, 0x63, 0x5D, 0xCC, 0x90, 0x64, 0x1F, 0x99, 0x10, 0x65, 0x3D, 0xAE, 0x90,
+0x66, 0x08, 0xB5, 0x90, 0x67, 0x1D, 0x90, 0x90, 0x67, 0xE8, 0x97, 0x90, 0x68, 0xFD, 0x72, 0x90,
+0x69, 0xC8, 0x79, 0x90, 0x6A, 0xDD, 0x54, 0x90, 0x6B, 0xA8, 0x5B, 0x90, 0x6C, 0xC6, 0x71, 0x10,
+0x6D, 0x88, 0x3D, 0x90, 0x6E, 0xA6, 0x53, 0x10, 0x6F, 0x68, 0x1F, 0x90, 0x70, 0x86, 0x35, 0x10,
+0x71, 0x51, 0x3C, 0x10, 0x72, 0x66, 0x17, 0x10, 0x73, 0x31, 0x1E, 0x10, 0x74, 0x45, 0xF9, 0x10,
+0x75, 0x11, 0x00, 0x10, 0x76, 0x2F, 0x15, 0x90, 0x76, 0xF0, 0xE2, 0x10, 0x78, 0x0E, 0xF7, 0x90,
+0x78, 0xD0, 0xC4, 0x10, 0x79, 0xEE, 0xD9, 0x90, 0x7A, 0xB0, 0xA6, 0x10, 0x7B, 0xCE, 0xBB, 0x90,
+0x7C, 0x99, 0xC2, 0x90, 0x7D, 0xAE, 0x9D, 0x90, 0x7E, 0x79, 0xA4, 0x90, 0x7F, 0x8E, 0x7F, 0x90,
 0x01, 0x02, 0x05, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03,
 0x04, 0x03, 0x04, 0x06, 0x09, 0x07, 0x08, 0x07, 0x08, 0x0B, 0x0A, 0x0B, 0x0A, 0x0B, 0x0A, 0x0B,
 0x0A, 0x0C, 0x0D, 0x0C, 0x0D, 0x0C, 0x0D, 0x0C, 0x0D, 0x0C, 0x0D, 0x0C, 0x0D, 0x06, 0x04, 0x03,
 0x04, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06,
 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06,
 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06,
-0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06,
-0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06,
-0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x00, 0x00, 0x1B,
+0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x0E, 0x0F, 0x0E,
+0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E,
+0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x00, 0x00, 0x1B,
 0x08, 0x00, 0x00, 0x00, 0x00, 0x1A, 0xF4, 0x00, 0x04, 0x00, 0x00, 0x18, 0x78, 0x00, 0x08, 0x00,
 0x00, 0x2A, 0x30, 0x01, 0x0C, 0x00, 0x00, 0x1C, 0x20, 0x00, 0x11, 0x00, 0x00, 0x1C, 0x20, 0x00,
 0x11, 0x00, 0x00, 0x2A, 0x30, 0x01, 0x0C, 0x00, 0x00, 0x0E, 0x10, 0x00, 0x15, 0x00, 0x00, 0x1C,
@@ -63353,8 +63411,9 @@
 0x00, 0x43, 0x4D, 0x54, 0x00, 0x42, 0x4D, 0x54, 0x00, 0x45, 0x45, 0x53, 0x54, 0x00, 0x45, 0x45,
 0x54, 0x00, 0x43, 0x45, 0x54, 0x00, 0x43, 0x45, 0x53, 0x54, 0x00, 0x4D, 0x53, 0x44, 0x00, 0x4D,
 0x53, 0x4B, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01,
-0x01, 0x00, 0x00, 0x54, 0x5A, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
+0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x01, 0x01, 0x54, 0x5A, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00,
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8D, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x26, 0xFF,
 0xFF, 0xFF, 0xFF, 0x56, 0xB6, 0xC8, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0x9E, 0x6B, 0x9F, 0x0C, 0xFF,
 0xFF, 0xFF, 0xFF, 0xB7, 0xB0, 0xD2, 0x08, 0xFF, 0xFF, 0xFF, 0xFF, 0xB9, 0x3E, 0xF3, 0x60, 0xFF,
@@ -63410,32 +63469,32 @@
 0x00, 0x00, 0x00, 0x5B, 0xD4, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5C, 0xA0, 0x03, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x5D, 0xB4, 0xDE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5E, 0x7F, 0xE5, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x5F, 0x94, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x5F, 0xC7, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x61, 0x7D, 0xDC, 0x80, 0x00, 0x00, 0x00, 0x00, 0x62, 0x3F, 0xA9, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x63, 0x5D, 0xBE, 0x80, 0x00, 0x00, 0x00, 0x00, 0x64, 0x1F, 0x8B, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x65, 0x3D, 0xA0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x66, 0x08, 0xA7, 0x80, 0x00,
-0x00, 0x00, 0x00, 0x67, 0x1D, 0x82, 0x80, 0x00, 0x00, 0x00, 0x00, 0x67, 0xE8, 0x89, 0x80, 0x00,
-0x00, 0x00, 0x00, 0x68, 0xFD, 0x64, 0x80, 0x00, 0x00, 0x00, 0x00, 0x69, 0xC8, 0x6B, 0x80, 0x00,
-0x00, 0x00, 0x00, 0x6A, 0xDD, 0x46, 0x80, 0x00, 0x00, 0x00, 0x00, 0x6B, 0xA8, 0x4D, 0x80, 0x00,
-0x00, 0x00, 0x00, 0x6C, 0xC6, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6D, 0x88, 0x2F, 0x80, 0x00,
-0x00, 0x00, 0x00, 0x6E, 0xA6, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6F, 0x68, 0x11, 0x80, 0x00,
-0x00, 0x00, 0x00, 0x70, 0x86, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x71, 0x51, 0x2E, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x72, 0x66, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x31, 0x10, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x74, 0x45, 0xEB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0x10, 0xF2, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x76, 0x2F, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x76, 0xF0, 0xD4, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x78, 0x0E, 0xE9, 0x80, 0x00, 0x00, 0x00, 0x00, 0x78, 0xD0, 0xB6, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x79, 0xEE, 0xCB, 0x80, 0x00, 0x00, 0x00, 0x00, 0x7A, 0xB0, 0x98, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x7B, 0xCE, 0xAD, 0x80, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x99, 0xB4, 0x80, 0x00,
-0x00, 0x00, 0x00, 0x7D, 0xAE, 0x8F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x79, 0x96, 0x80, 0x00,
-0x00, 0x00, 0x00, 0x7F, 0x8E, 0x71, 0x80, 0x01, 0x02, 0x05, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04,
+0x00, 0x00, 0x00, 0x61, 0x7D, 0xDC, 0x80, 0x00, 0x00, 0x00, 0x00, 0x62, 0x3F, 0xB7, 0x10, 0x00,
+0x00, 0x00, 0x00, 0x63, 0x5D, 0xCC, 0x90, 0x00, 0x00, 0x00, 0x00, 0x64, 0x1F, 0x99, 0x10, 0x00,
+0x00, 0x00, 0x00, 0x65, 0x3D, 0xAE, 0x90, 0x00, 0x00, 0x00, 0x00, 0x66, 0x08, 0xB5, 0x90, 0x00,
+0x00, 0x00, 0x00, 0x67, 0x1D, 0x90, 0x90, 0x00, 0x00, 0x00, 0x00, 0x67, 0xE8, 0x97, 0x90, 0x00,
+0x00, 0x00, 0x00, 0x68, 0xFD, 0x72, 0x90, 0x00, 0x00, 0x00, 0x00, 0x69, 0xC8, 0x79, 0x90, 0x00,
+0x00, 0x00, 0x00, 0x6A, 0xDD, 0x54, 0x90, 0x00, 0x00, 0x00, 0x00, 0x6B, 0xA8, 0x5B, 0x90, 0x00,
+0x00, 0x00, 0x00, 0x6C, 0xC6, 0x71, 0x10, 0x00, 0x00, 0x00, 0x00, 0x6D, 0x88, 0x3D, 0x90, 0x00,
+0x00, 0x00, 0x00, 0x6E, 0xA6, 0x53, 0x10, 0x00, 0x00, 0x00, 0x00, 0x6F, 0x68, 0x1F, 0x90, 0x00,
+0x00, 0x00, 0x00, 0x70, 0x86, 0x35, 0x10, 0x00, 0x00, 0x00, 0x00, 0x71, 0x51, 0x3C, 0x10, 0x00,
+0x00, 0x00, 0x00, 0x72, 0x66, 0x17, 0x10, 0x00, 0x00, 0x00, 0x00, 0x73, 0x31, 0x1E, 0x10, 0x00,
+0x00, 0x00, 0x00, 0x74, 0x45, 0xF9, 0x10, 0x00, 0x00, 0x00, 0x00, 0x75, 0x11, 0x00, 0x10, 0x00,
+0x00, 0x00, 0x00, 0x76, 0x2F, 0x15, 0x90, 0x00, 0x00, 0x00, 0x00, 0x76, 0xF0, 0xE2, 0x10, 0x00,
+0x00, 0x00, 0x00, 0x78, 0x0E, 0xF7, 0x90, 0x00, 0x00, 0x00, 0x00, 0x78, 0xD0, 0xC4, 0x10, 0x00,
+0x00, 0x00, 0x00, 0x79, 0xEE, 0xD9, 0x90, 0x00, 0x00, 0x00, 0x00, 0x7A, 0xB0, 0xA6, 0x10, 0x00,
+0x00, 0x00, 0x00, 0x7B, 0xCE, 0xBB, 0x90, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x99, 0xC2, 0x90, 0x00,
+0x00, 0x00, 0x00, 0x7D, 0xAE, 0x9D, 0x90, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x79, 0xA4, 0x90, 0x00,
+0x00, 0x00, 0x00, 0x7F, 0x8E, 0x7F, 0x90, 0x01, 0x02, 0x05, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04,
 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x06, 0x09, 0x07, 0x08, 0x07, 0x08,
 0x0B, 0x0A, 0x0B, 0x0A, 0x0B, 0x0A, 0x0B, 0x0A, 0x0C, 0x0D, 0x0C, 0x0D, 0x0C, 0x0D, 0x0C, 0x0D,
 0x0C, 0x0D, 0x0C, 0x0D, 0x06, 0x04, 0x03, 0x04, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05,
 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05,
 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05,
 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05,
-0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05,
-0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05,
-0x06, 0x05, 0x06, 0x05, 0x00, 0x00, 0x1B, 0x08, 0x00, 0x00, 0x00, 0x00, 0x1A, 0xF4, 0x00, 0x04,
+0x06, 0x05, 0x06, 0x05, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F,
+0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F,
+0x0E, 0x0F, 0x0E, 0x0F, 0x00, 0x00, 0x1B, 0x08, 0x00, 0x00, 0x00, 0x00, 0x1A, 0xF4, 0x00, 0x04,
 0x00, 0x00, 0x18, 0x78, 0x00, 0x08, 0x00, 0x00, 0x2A, 0x30, 0x01, 0x0C, 0x00, 0x00, 0x1C, 0x20,
 0x00, 0x11, 0x00, 0x00, 0x1C, 0x20, 0x00, 0x11, 0x00, 0x00, 0x2A, 0x30, 0x01, 0x0C, 0x00, 0x00,
 0x0E, 0x10, 0x00, 0x15, 0x00, 0x00, 0x1C, 0x20, 0x01, 0x19, 0x00, 0x00, 0x1C, 0x20, 0x01, 0x19,
@@ -63444,10 +63503,11 @@
 0x1C, 0x20, 0x00, 0x11, 0x4C, 0x4D, 0x54, 0x00, 0x43, 0x4D, 0x54, 0x00, 0x42, 0x4D, 0x54, 0x00,
 0x45, 0x45, 0x53, 0x54, 0x00, 0x45, 0x45, 0x54, 0x00, 0x43, 0x45, 0x54, 0x00, 0x43, 0x45, 0x53,
 0x54, 0x00, 0x4D, 0x53, 0x44, 0x00, 0x4D, 0x53, 0x4B, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00,
-0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x0A, 0x45, 0x45, 0x54, 0x2D, 0x32,
-0x45, 0x45, 0x53, 0x54, 0x2C, 0x4D, 0x33, 0x2E, 0x35, 0x2E, 0x30, 0x2C, 0x4D, 0x31, 0x30, 0x2E,
-0x35, 0x2E, 0x30, 0x2F, 0x33, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 
+0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x0A, 0x45, 0x45, 0x54, 0x2D, 0x32,
+0x45, 0x45, 0x53, 0x54, 0x2C, 0x4D, 0x33, 0x2E, 0x35, 0x2E, 0x30, 0x2F, 0x33, 0x2C, 0x4D, 0x31,
+0x30, 0x2E, 0x35, 0x2E, 0x30, 0x2F, 0x34, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 
 
 /* Europe/Ulyanovsk */
 0x50, 0x48, 0x50, 0x32, 0x01, 0x52, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -71255,4 +71315,4 @@
 };
 #endif
 
-const timelib_tzdb timezonedb_builtin = { "2025.3", 598, timezonedb_idx_builtin, timelib_timezone_db_data_builtin };
+const timelib_tzdb timezonedb_builtin = { "2026.1", 598, timezonedb_idx_builtin, timelib_timezone_db_data_builtin };
diff '--color=auto' -Naur php-8.4.18/ext/date/php_date.c php-8.4.20RC1/ext/date/php_date.c
--- php-8.4.18/ext/date/php_date.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/date/php_date.c	2026-04-01 04:35:36.003142962 +0000
@@ -795,13 +795,24 @@
 							  case TIMELIB_ZONETYPE_ABBR:
 								  length = slprintf(buffer, sizeof(buffer), "%s", offset->abbr);
 								  break;
-							  case TIMELIB_ZONETYPE_OFFSET:
-								  length = slprintf(buffer, sizeof(buffer), "%c%02d:%02d",
-												((offset->offset < 0) ? '-' : '+'),
-												abs(offset->offset / 3600),
-												abs((offset->offset % 3600) / 60)
-										   );
+							  case TIMELIB_ZONETYPE_OFFSET: {
+								  int seconds = offset->offset % 60;
+								  if (seconds == 0) {
+								      length = slprintf(buffer, sizeof(buffer), "%c%02d:%02d",
+								      				((offset->offset < 0) ? '-' : '+'),
+								      				abs(offset->offset / 3600),
+								      				abs((offset->offset % 3600) / 60)
+								      		   );
+								  } else {
+								      length = slprintf(buffer, sizeof(buffer), "%c%02d:%02d:%02d",
+								      				((offset->offset < 0) ? '-' : '+'),
+								      				abs(offset->offset / 3600),
+								      				abs((offset->offset % 3600) / 60),
+													abs(seconds)
+								      		   );
+								  }
 								  break;
+							  }
 						  }
 					  }
 					  break;
@@ -1930,6 +1941,32 @@
 	return zend_std_get_properties(object);
 } /* }}} */
 
+static zend_string *date_create_tz_offset_str(timelib_sll offset)
+{
+	int seconds = offset % 60;
+	size_t size;
+	const char *format;
+
+	if (seconds == 0) {
+		size = sizeof("+05:00");
+		format = "%c%02d:%02d";
+	} else {
+		size = sizeof("+05:00:01");
+		format = "%c%02d:%02d:%02d";
+	}
+
+	zend_string *tmpstr = zend_string_alloc(size - 1, 0);
+
+	/* Note: if seconds == 0, the seconds argument will be excessive and therefore ignored. */
+	ZSTR_LEN(tmpstr) = snprintf(ZSTR_VAL(tmpstr), size, format,
+		offset < 0 ? '-' : '+',
+		abs((int)(offset / 3600)),
+		abs((int)(offset % 3600) / 60),
+		abs(seconds));
+
+	return tmpstr;
+}
+
 static void date_object_to_hash(php_date_obj *dateobj, HashTable *props)
 {
 	zval zv;
@@ -1947,17 +1984,8 @@
 			case TIMELIB_ZONETYPE_ID:
 				ZVAL_STRING(&zv, dateobj->time->tz_info->name);
 				break;
-			case TIMELIB_ZONETYPE_OFFSET: {
-				zend_string *tmpstr = zend_string_alloc(sizeof("UTC+05:00")-1, 0);
-				int utc_offset = dateobj->time->z;
-
-				ZSTR_LEN(tmpstr) = snprintf(ZSTR_VAL(tmpstr), sizeof("+05:00"), "%c%02d:%02d",
-					utc_offset < 0 ? '-' : '+',
-					abs(utc_offset / 3600),
-					abs(((utc_offset % 3600) / 60)));
-
-				ZVAL_NEW_STR(&zv, tmpstr);
-				}
+			case TIMELIB_ZONETYPE_OFFSET:
+				ZVAL_NEW_STR(&zv, date_create_tz_offset_str(dateobj->time->z));
 				break;
 			case TIMELIB_ZONETYPE_ABBR:
 				ZVAL_STRING(&zv, dateobj->time->tz_abbr);
@@ -2069,29 +2097,8 @@
 		case TIMELIB_ZONETYPE_ID:
 			ZVAL_STRING(zv, tzobj->tzi.tz->name);
 			break;
-		case TIMELIB_ZONETYPE_OFFSET: {
-			timelib_sll utc_offset = tzobj->tzi.utc_offset;
-			int seconds = utc_offset % 60;
-			size_t size;
-			const char *format;
-			if (seconds == 0) {
-				size = sizeof("+05:00");
-				format = "%c%02d:%02d";
-			} else {
-				size = sizeof("+05:00:01");
-				format = "%c%02d:%02d:%02d";
-			}
-			zend_string *tmpstr = zend_string_alloc(size - 1, 0);
-
-			/* Note: if seconds == 0, the seconds argument will be excessive and therefore ignored. */
-			ZSTR_LEN(tmpstr) = snprintf(ZSTR_VAL(tmpstr), size, format,
-				utc_offset < 0 ? '-' : '+',
-				abs((int)(utc_offset / 3600)),
-				abs((int)(utc_offset % 3600) / 60),
-				abs(seconds));
-
-			ZVAL_NEW_STR(zv, tmpstr);
-			}
+		case TIMELIB_ZONETYPE_OFFSET:
+			ZVAL_NEW_STR(zv, date_create_tz_offset_str(tzobj->tzi.utc_offset));
 			break;
 		case TIMELIB_ZONETYPE_ABBR:
 			ZVAL_STRING(zv, tzobj->tzi.z.abbr);
@@ -5811,7 +5818,7 @@
 			php_date_obj *date_obj;
 			date_obj = Z_PHPDATE_P(ht_entry);
 
-			if (!date_obj->time) {
+			if (!date_obj->time || !period_obj->start_ce) {
 				return 0;
 			}
 
@@ -5832,7 +5839,7 @@
 			php_date_obj *date_obj;
 			date_obj = Z_PHPDATE_P(ht_entry);
 
-			if (!date_obj->time) {
+			if (!date_obj->time || !period_obj->start_ce) {
 				return 0;
 			}
 
diff '--color=auto' -Naur php-8.4.18/ext/date/tests/bug81565.phpt php-8.4.20RC1/ext/date/tests/bug81565.phpt
--- php-8.4.18/ext/date/tests/bug81565.phpt	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/date/tests/bug81565.phpt	2026-04-01 04:35:36.003518993 +0000
@@ -15,6 +15,6 @@
 \DateTime::__set_state(array(
    'date' => '0021-08-21 00:00:00.000000',
    'timezone_type' => 1,
-   'timezone' => '+00:49',
+   'timezone' => '+00:49:56',
 ))
 +01:45:30
diff '--color=auto' -Naur php-8.4.18/ext/date/tests/gh20764.phpt php-8.4.20RC1/ext/date/tests/gh20764.phpt
--- php-8.4.18/ext/date/tests/gh20764.phpt	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/ext/date/tests/gh20764.phpt	2026-04-01 04:35:36.003623931 +0000
@@ -0,0 +1,53 @@
+--TEST--
+GH-20764 (Timezone offset with seconds loses precision)
+--FILE--
+<?php
+
+$timezones = [
+    '+03:00:30',
+    '-03:00:30',
+];
+
+foreach ($timezones as $timezone) {
+  echo "--- Testing timezone $timezone ---\n";
+  $tz = new DateTimeZone($timezone);
+  $dt = new DateTimeImmutable('2025-04-01', $tz);
+  var_dump($dt->format('e'));
+  var_dump($dt);
+  var_dump(unserialize(serialize($dt))->getTimezone());
+}
+
+?>
+--EXPECTF--
+--- Testing timezone +03:00:30 ---
+string(9) "+03:00:30"
+object(DateTimeImmutable)#%d (3) {
+  ["date"]=>
+  string(26) "2025-04-01 00:00:00.000000"
+  ["timezone_type"]=>
+  int(1)
+  ["timezone"]=>
+  string(9) "+03:00:30"
+}
+object(DateTimeZone)#%d (2) {
+  ["timezone_type"]=>
+  int(1)
+  ["timezone"]=>
+  string(9) "+03:00:30"
+}
+--- Testing timezone -03:00:30 ---
+string(9) "-03:00:30"
+object(DateTimeImmutable)#%d (3) {
+  ["date"]=>
+  string(26) "2025-04-01 00:00:00.000000"
+  ["timezone_type"]=>
+  int(1)
+  ["timezone"]=>
+  string(9) "-03:00:30"
+}
+object(DateTimeZone)#%d (2) {
+  ["timezone_type"]=>
+  int(1)
+  ["timezone"]=>
+  string(9) "-03:00:30"
+}
diff '--color=auto' -Naur php-8.4.18/ext/date/tests/gh20936.phpt php-8.4.20RC1/ext/date/tests/gh20936.phpt
--- php-8.4.18/ext/date/tests/gh20936.phpt	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/ext/date/tests/gh20936.phpt	2026-04-01 04:35:36.003702640 +0000
@@ -0,0 +1,14 @@
+--TEST--
+GH-20936 (DatePeriod::__set_state() cannot handle null start)
+--FILE--
+<?php
+$end = new DateTime('2022-07-16', new DateTimeZone('UTC'));
+$interval = new DateInterval('P2D');
+try {
+    DatePeriod::__set_state(['start' => null, 'end' => $end, 'current' => null, 'interval' => $interval, 'recurrences' => 2, 'include_start_date' => false, 'include_end_date' => true]);
+} catch (Throwable $e) {
+    echo $e::class, ": ", $e->getMessage(), "\n";
+}
+?>
+--EXPECT--
+Error: Invalid serialization data for DatePeriod object
diff '--color=auto' -Naur php-8.4.18/ext/dom/documenttype.c php-8.4.20RC1/ext/dom/documenttype.c
--- php-8.4.18/ext/dom/documenttype.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/dom/documenttype.c	2026-04-01 04:35:36.003837464 +0000
@@ -47,7 +47,7 @@
 {
 	DOM_PROP_NODE(xmlDtdPtr, dtdptr, obj);
 
-	php_dom_create_iterator(retval, DOM_DTD_NAMEDNODEMAP, php_dom_follow_spec_intern(obj));
+	php_dom_create_iterator(retval, DOM_DTD_NAMEDNODEMAP, instanceof_function(obj->std.ce, dom_modern_documenttype_class_entry));
 
 	xmlHashTable *entityht = (xmlHashTable *) dtdptr->entities;
 
@@ -68,7 +68,7 @@
 {
 	DOM_PROP_NODE(xmlDtdPtr, dtdptr, obj);
 
-	php_dom_create_iterator(retval, DOM_DTD_NAMEDNODEMAP, php_dom_follow_spec_intern(obj));
+	php_dom_create_iterator(retval, DOM_DTD_NAMEDNODEMAP, instanceof_function(obj->std.ce, dom_modern_documenttype_class_entry));
 
 	xmlHashTable *notationht = (xmlHashTable *) dtdptr->notations;
 
diff '--color=auto' -Naur php-8.4.18/ext/dom/dom_properties.h php-8.4.20RC1/ext/dom/dom_properties.h
--- php-8.4.18/ext/dom/dom_properties.h	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/dom/dom_properties.h	2026-04-01 04:35:36.003939257 +0000
@@ -102,6 +102,7 @@
 zend_result dom_entity_reference_child_read(dom_object *obj, zval *retval);
 zend_result dom_entity_reference_text_content_read(dom_object *obj, zval *retval);
 zend_result dom_entity_reference_child_nodes_read(dom_object *obj, zval *retval);
+zend_result dom_modern_entity_reference_child_nodes_read(dom_object *obj, zval *retval);
 
 /* namednodemap properties */
 zend_result dom_namednodemap_length_read(dom_object *obj, zval *retval);
@@ -119,6 +120,7 @@
 zend_result dom_node_parent_node_read(dom_object *obj, zval *retval);
 zend_result dom_node_parent_element_read(dom_object *obj, zval *retval);
 zend_result dom_node_child_nodes_read(dom_object *obj, zval *retval);
+zend_result dom_modern_node_child_nodes_read(dom_object *obj, zval *retval);
 zend_result dom_node_first_child_read(dom_object *obj, zval *retval);
 zend_result dom_node_last_child_read(dom_object *obj, zval *retval);
 zend_result dom_node_previous_sibling_read(dom_object *obj, zval *retval);
@@ -134,6 +136,7 @@
 zend_result dom_node_prefix_write(dom_object *obj, zval *newval);
 zend_result dom_node_local_name_read(dom_object *obj, zval *retval);
 zend_result dom_node_base_uri_read(dom_object *obj, zval *retval);
+zend_result dom_modern_node_base_uri_read(dom_object *obj, zval *retval);
 zend_result dom_node_text_content_read(dom_object *obj, zval *retval);
 zend_result dom_node_text_content_write(dom_object *obj, zval *newval);
 
diff '--color=auto' -Naur php-8.4.18/ext/dom/entityreference.c php-8.4.20RC1/ext/dom/entityreference.c
--- php-8.4.18/ext/dom/entityreference.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/dom/entityreference.c	2026-04-01 04:35:36.004038935 +0000
@@ -106,4 +106,12 @@
 	return dom_node_child_nodes_read(obj, retval);
 }
 
+zend_result dom_modern_entity_reference_child_nodes_read(dom_object *obj, zval *retval)
+{
+	DOM_PROP_NODE(xmlNodePtr, nodep, obj);
+
+	dom_entity_reference_fetch_and_sync_declaration(nodep);
+	return dom_modern_node_child_nodes_read(obj, retval);
+}
+
 #endif
diff '--color=auto' -Naur php-8.4.18/ext/dom/html5_parser.c php-8.4.20RC1/ext/dom/html5_parser.c
--- php-8.4.18/ext/dom/html5_parser.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/dom/html5_parser.c	2026-04-01 04:35:36.004124116 +0000
@@ -117,6 +117,7 @@
 	php_dom_libxml_ns_mapper *ns_mapper = php_dom_ns_mapper_from_private(private_data);
     xmlNsPtr html_ns = php_dom_libxml_ns_mapper_ensure_html_ns(ns_mapper);
     xmlNsPtr xlink_ns = NULL;
+    xmlNsPtr xml_ns = NULL;
     xmlNsPtr prefixed_xmlns_ns = NULL;
 
     lexbor_array_obj_t work_list;
@@ -256,6 +257,12 @@
                         xlink_ns->_private = (void *) php_dom_ns_is_xlink_magic_token;
                     }
                     lxml_attr->ns = xlink_ns;
+                } else if (attr->node.ns == LXB_NS_XML) {
+                    if (xml_ns == NULL) {
+                        xml_ns = php_dom_libxml_ns_mapper_get_ns_raw_strings_nullsafe(ns_mapper, "xml", DOM_XML_NS_URI);
+                        xml_ns->_private = (void *) php_dom_ns_is_xml_magic_token;
+                    }
+                    lxml_attr->ns = xml_ns;
                 }
 
                 if (last_added_attr == NULL) {
diff '--color=auto' -Naur php-8.4.18/ext/dom/node.c php-8.4.20RC1/ext/dom/node.c
--- php-8.4.18/ext/dom/node.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/dom/node.c	2026-04-01 04:35:36.004292043 +0000
@@ -287,7 +287,18 @@
 {
 	DOM_PROP_NODE(xmlNodePtr, nodep, obj);
 
-	php_dom_create_iterator(retval, DOM_NODELIST, php_dom_follow_spec_intern(obj));
+	php_dom_create_iterator(retval, DOM_NODELIST, false);
+	dom_object *intern = Z_DOMOBJ_P(retval);
+	dom_namednode_iter(obj, XML_ELEMENT_NODE, intern, NULL, NULL, 0, NULL, 0);
+
+	return SUCCESS;
+}
+
+zend_result dom_modern_node_child_nodes_read(dom_object *obj, zval *retval)
+{
+	DOM_PROP_NODE(xmlNodePtr, nodep, obj);
+
+	php_dom_create_iterator(retval, DOM_NODELIST, true);
 	dom_object *intern = Z_DOMOBJ_P(retval);
 	dom_namednode_iter(obj, XML_ELEMENT_NODE, intern, NULL, NULL, 0, NULL, 0);
 
@@ -659,14 +670,25 @@
 		ZVAL_STRING(retval, (const char *) baseuri);
 		xmlFree(baseuri);
 	} else {
-		if (php_dom_follow_spec_intern(obj)) {
-			if (nodep->doc->URL) {
-				ZVAL_STRING(retval, (const char *) nodep->doc->URL);
-			} else {
-				ZVAL_STRING(retval, "about:blank");
-			}
+		ZVAL_NULL(retval);
+	}
+
+	return SUCCESS;
+}
+
+zend_result dom_modern_node_base_uri_read(dom_object *obj, zval *retval)
+{
+	DOM_PROP_NODE(xmlNodePtr, nodep, obj);
+
+	xmlChar *baseuri = xmlNodeGetBase(nodep->doc, nodep);
+	if (baseuri) {
+		ZVAL_STRING(retval, (const char *) baseuri);
+		xmlFree(baseuri);
+	} else {
+		if (nodep->doc && nodep->doc->URL) {
+			ZVAL_STRING(retval, (const char *) nodep->doc->URL);
 		} else {
-			ZVAL_NULL(retval);
+			ZVAL_STRING(retval, "about:blank");
 		}
 	}
 
diff '--color=auto' -Naur php-8.4.18/ext/dom/php_dom.c php-8.4.20RC1/ext/dom/php_dom.c
--- php-8.4.18/ext/dom/php_dom.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/dom/php_dom.c	2026-04-01 04:35:36.004564107 +0000
@@ -892,12 +892,12 @@
 	zend_hash_init(&dom_modern_node_prop_handlers, 0, NULL, NULL, true);
 	DOM_REGISTER_PROP_HANDLER(&dom_modern_node_prop_handlers, "nodeType", dom_node_node_type_read, NULL);
 	DOM_REGISTER_PROP_HANDLER(&dom_modern_node_prop_handlers, "nodeName", dom_node_node_name_read, NULL);
-	DOM_REGISTER_PROP_HANDLER(&dom_modern_node_prop_handlers, "baseURI", dom_node_base_uri_read, NULL);
+	DOM_REGISTER_PROP_HANDLER(&dom_modern_node_prop_handlers, "baseURI", dom_modern_node_base_uri_read, NULL);
 	DOM_REGISTER_PROP_HANDLER(&dom_modern_node_prop_handlers, "isConnected", dom_node_is_connected_read, NULL);
 	DOM_REGISTER_PROP_HANDLER(&dom_modern_node_prop_handlers, "ownerDocument", dom_node_owner_document_read, NULL);
 	DOM_REGISTER_PROP_HANDLER(&dom_modern_node_prop_handlers, "parentNode", dom_node_parent_node_read, NULL);
 	DOM_REGISTER_PROP_HANDLER(&dom_modern_node_prop_handlers, "parentElement", dom_node_parent_element_read, NULL);
-	DOM_REGISTER_PROP_HANDLER(&dom_modern_node_prop_handlers, "childNodes", dom_node_child_nodes_read, NULL);
+	DOM_REGISTER_PROP_HANDLER(&dom_modern_node_prop_handlers, "childNodes", dom_modern_node_child_nodes_read, NULL);
 	DOM_REGISTER_PROP_HANDLER(&dom_modern_node_prop_handlers, "firstChild", dom_node_first_child_read, NULL);
 	DOM_REGISTER_PROP_HANDLER(&dom_modern_node_prop_handlers, "lastChild", dom_node_last_child_read, NULL);
 	DOM_REGISTER_PROP_HANDLER(&dom_modern_node_prop_handlers, "previousSibling", dom_node_previous_sibling_read, NULL);
@@ -1294,7 +1294,7 @@
 	DOM_OVERWRITE_PROP_HANDLER(&dom_modern_entity_reference_prop_handlers, "firstChild", dom_entity_reference_child_read, NULL);
 	DOM_OVERWRITE_PROP_HANDLER(&dom_modern_entity_reference_prop_handlers, "lastChild", dom_entity_reference_child_read, NULL);
 	DOM_OVERWRITE_PROP_HANDLER(&dom_modern_entity_reference_prop_handlers, "textContent", dom_entity_reference_text_content_read, NULL);
-	DOM_OVERWRITE_PROP_HANDLER(&dom_modern_entity_reference_prop_handlers, "childNodes", dom_entity_reference_child_nodes_read, NULL);
+	DOM_OVERWRITE_PROP_HANDLER(&dom_modern_entity_reference_prop_handlers, "childNodes", dom_modern_entity_reference_child_nodes_read, NULL);
 	zend_hash_add_new_ptr(&classes, dom_modern_entityreference_class_entry->name, &dom_modern_entity_reference_prop_handlers);
 
 	dom_processinginstruction_class_entry = register_class_DOMProcessingInstruction(dom_node_class_entry);
diff '--color=auto' -Naur php-8.4.18/ext/dom/tests/modern/common/gh21077.phpt php-8.4.20RC1/ext/dom/tests/modern/common/gh21077.phpt
--- php-8.4.18/ext/dom/tests/modern/common/gh21077.phpt	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/ext/dom/tests/modern/common/gh21077.phpt	2026-04-01 04:35:36.004787860 +0000
@@ -0,0 +1,28 @@
+--TEST--
+GH-21077 (Accessing Dom\Node::baseURI can throw TypeError)
+--EXTENSIONS--
+dom
+--CREDITS--
+mbeccati
+--FILE--
+<?php
+
+$implementation = new Dom\Implementation();
+$node = $implementation->createDocumentType('html', 'publicId', 'systemId');
+
+var_dump($node->baseURI);
+
+$dom = Dom\XMLDocument::createEmpty();
+$dom->append($node = $dom->importNode($node));
+
+var_dump($dom->saveXML());
+
+var_dump($node->baseURI);
+
+?>
+--EXPECT--
+string(11) "about:blank"
+string(84) "<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "publicId" "systemId">
+"
+string(11) "about:blank"
diff '--color=auto' -Naur php-8.4.18/ext/dom/tests/modern/common/gh21097.phpt php-8.4.20RC1/ext/dom/tests/modern/common/gh21097.phpt
--- php-8.4.18/ext/dom/tests/modern/common/gh21097.phpt	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/ext/dom/tests/modern/common/gh21097.phpt	2026-04-01 04:35:36.004853194 +0000
@@ -0,0 +1,49 @@
+--TEST--
+GH-21097 (Accessing Dom\Node properties can can throw TypeError(s))
+--EXTENSIONS--
+dom
+--CREDITS--
+mbeccati
+--FILE--
+<?php
+
+$implementation = new \Dom\Implementation();
+$node = $implementation->createDocumentType('html', 'publicId', 'systemId');
+
+$r = new \ReflectionClass($node);
+foreach ($r->getProperties(\ReflectionProperty::IS_PUBLIC) as $p) {
+    echo $p->getName(), ": ";
+    var_dump($node->{$p->getName()});
+}
+
+?>
+--EXPECT--
+nodeType: int(10)
+nodeName: string(4) "html"
+baseURI: string(11) "about:blank"
+isConnected: bool(false)
+ownerDocument: NULL
+parentNode: NULL
+parentElement: NULL
+childNodes: object(Dom\NodeList)#24 (1) {
+  ["length"]=>
+  int(0)
+}
+firstChild: NULL
+lastChild: NULL
+previousSibling: NULL
+nextSibling: NULL
+nodeValue: NULL
+textContent: string(0) ""
+name: string(4) "html"
+entities: object(Dom\DtdNamedNodeMap)#24 (1) {
+  ["length"]=>
+  int(0)
+}
+notations: object(Dom\DtdNamedNodeMap)#24 (1) {
+  ["length"]=>
+  int(0)
+}
+publicId: string(8) "publicId"
+systemId: string(8) "systemId"
+internalSubset: NULL
diff '--color=auto' -Naur php-8.4.18/ext/dom/tests/modern/html/parser/gh21486.phpt php-8.4.20RC1/ext/dom/tests/modern/html/parser/gh21486.phpt
--- php-8.4.18/ext/dom/tests/modern/html/parser/gh21486.phpt	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/ext/dom/tests/modern/html/parser/gh21486.phpt	2026-04-01 04:35:36.004970495 +0000
@@ -0,0 +1,18 @@
+--TEST--
+GH-21486 (Dom\HTMLDocument parser mangles xml:space and xml:lang attributes)
+--EXTENSIONS--
+dom
+--CREDITS--
+JKingweb
+--FILE--
+<?php
+$d = @\Dom\HTMLDocument::createFromString("<div></div>");
+$e = $d->getElementsByTagName("div")[0];
+$e->innerHTML = '<svg xml:space="default" xlink:href="about:blank" xmlns:foo="barspace"></svg>';
+$svg = $d->querySelector("svg");
+echo $e->innerHTML."\n";
+echo $svg->attributes[0]->localName." ".var_export($svg->attributes[0]->namespaceURI, true)."\n";
+?>
+--EXPECT--
+<svg xml:space="default" xlink:href="about:blank" xmlns:foo="barspace"></svg>
+space 'http://www.w3.org/XML/1998/namespace'
diff '--color=auto' -Naur php-8.4.18/ext/dom/tests/modern/spec/Document_implementation_createDocumentType.phpt php-8.4.20RC1/ext/dom/tests/modern/spec/Document_implementation_createDocumentType.phpt
--- php-8.4.18/ext/dom/tests/modern/spec/Document_implementation_createDocumentType.phpt	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/dom/tests/modern/spec/Document_implementation_createDocumentType.phpt	2026-04-01 04:35:36.005080072 +0000
@@ -43,7 +43,7 @@
   ["nodeName"]=>
   string(5) "qname"
   ["baseURI"]=>
-  NULL
+  string(11) "about:blank"
   ["isConnected"]=>
   bool(false)
   ["parentNode"]=>
@@ -86,7 +86,7 @@
   ["nodeName"]=>
   string(5) "qname"
   ["baseURI"]=>
-  NULL
+  string(11) "about:blank"
   ["isConnected"]=>
   bool(false)
   ["parentNode"]=>
@@ -129,7 +129,7 @@
   ["nodeName"]=>
   string(5) "qname"
   ["baseURI"]=>
-  NULL
+  string(11) "about:blank"
   ["isConnected"]=>
   bool(false)
   ["parentNode"]=>
@@ -172,7 +172,7 @@
   ["nodeName"]=>
   string(5) "qname"
   ["baseURI"]=>
-  NULL
+  string(11) "about:blank"
   ["isConnected"]=>
   bool(false)
   ["parentNode"]=>
diff '--color=auto' -Naur php-8.4.18/ext/dom/tests/modern/xml/DTDNamedNodeMap.phpt php-8.4.20RC1/ext/dom/tests/modern/xml/DTDNamedNodeMap.phpt
--- php-8.4.18/ext/dom/tests/modern/xml/DTDNamedNodeMap.phpt	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/dom/tests/modern/xml/DTDNamedNodeMap.phpt	2026-04-01 04:35:36.005163149 +0000
@@ -148,7 +148,7 @@
   ["nodeName"]=>
   string(3) "GIF"
   ["baseURI"]=>
-  NULL
+  string(11) "about:blank"
   ["isConnected"]=>
   bool(false)
   ["parentNode"]=>
diff '--color=auto' -Naur php-8.4.18/ext/dom/tests/parentnode_childnode_too_long_text.phpt php-8.4.20RC1/ext/dom/tests/parentnode_childnode_too_long_text.phpt
--- php-8.4.18/ext/dom/tests/parentnode_childnode_too_long_text.phpt	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/dom/tests/parentnode_childnode_too_long_text.phpt	2026-04-01 04:35:36.005236287 +0000
@@ -6,6 +6,7 @@
 memory_limit=-1
 --SKIPIF--
 <?php
+if (!getenv('RUN_RESOURCE_HEAVY_TESTS')) die('skip resource-heavy test');
 if (PHP_INT_SIZE !== 8) die('skip Only for 64-bit');
 if (getenv('SKIP_SLOW_TESTS')) die('skip slow test');
 // Copied from file_get_contents_file_put_contents_5gb.phpt
diff '--color=auto' -Naur php-8.4.18/ext/ffi/ffi.c php-8.4.20RC1/ext/ffi/ffi.c
--- php-8.4.18/ext/ffi/ffi.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/ffi/ffi.c	2026-04-01 04:35:36.005521797 +0000
@@ -1257,10 +1257,8 @@
 			type = ZEND_FFI_TYPE(type->pointer.type);
 		}
 		if (UNEXPECTED(type->kind != ZEND_FFI_TYPE_STRUCT)) {
-			if (UNEXPECTED(type->kind != ZEND_FFI_TYPE_STRUCT)) {
-				zend_throw_error(zend_ffi_exception_ce, "Attempt to read field '%s' of non C struct/union", ZSTR_VAL(field_name));
-				return &EG(uninitialized_zval);
-			}
+			zend_throw_error(zend_ffi_exception_ce, "Attempt to read field '%s' of non C struct/union", ZSTR_VAL(field_name));
+			return &EG(uninitialized_zval);
 		}
 
 		field = zend_hash_find_ptr(&type->record.fields, field_name);
@@ -1334,10 +1332,8 @@
 			type = ZEND_FFI_TYPE(type->pointer.type);
 		}
 		if (UNEXPECTED(type->kind != ZEND_FFI_TYPE_STRUCT)) {
-			if (UNEXPECTED(type->kind != ZEND_FFI_TYPE_STRUCT)) {
-				zend_throw_error(zend_ffi_exception_ce, "Attempt to assign field '%s' of non C struct/union", ZSTR_VAL(field_name));
-				return value;
-			}
+			zend_throw_error(zend_ffi_exception_ce, "Attempt to assign field '%s' of non C struct/union", ZSTR_VAL(field_name));
+			return value;
 		}
 
 		field = zend_hash_find_ptr(&type->record.fields, field_name);
@@ -3069,17 +3065,7 @@
 		FFI_G(default_type_attr) = ZEND_FFI_ATTR_STORED;
 
 		if (zend_ffi_parse_decl(ZSTR_VAL(code), ZSTR_LEN(code)) == FAILURE) {
-			if (FFI_G(symbols)) {
-				zend_hash_destroy(FFI_G(symbols));
-				efree(FFI_G(symbols));
-				FFI_G(symbols) = NULL;
-			}
-			if (FFI_G(tags)) {
-				zend_hash_destroy(FFI_G(tags));
-				efree(FFI_G(tags));
-				FFI_G(tags) = NULL;
-			}
-			RETURN_THROWS();
+			goto cleanup;
 		}
 
 		if (FFI_G(symbols)) {
@@ -3091,7 +3077,7 @@
 					addr = DL_FETCH_SYMBOL(handle, ZSTR_VAL(name));
 					if (!addr) {
 						zend_throw_error(zend_ffi_exception_ce, "Failed resolving C variable '%s'", ZSTR_VAL(name));
-						RETURN_THROWS();
+						goto cleanup;
 					}
 					sym->addr = addr;
 				} else if (sym->kind == ZEND_FFI_SYM_FUNC) {
@@ -3101,7 +3087,7 @@
 					zend_string_release(mangled_name);
 					if (!addr) {
 						zend_throw_error(zend_ffi_exception_ce, "Failed resolving C function '%s'", ZSTR_VAL(name));
-						RETURN_THROWS();
+						goto cleanup;
 					}
 					sym->addr = addr;
 				}
@@ -3118,6 +3104,22 @@
 	FFI_G(tags) = NULL;
 
 	RETURN_OBJ(&ffi->std);
+
+cleanup:
+	if (lib && handle) {
+		DL_UNLOAD(handle);
+	}
+	if (FFI_G(symbols)) {
+		zend_hash_destroy(FFI_G(symbols));
+		efree(FFI_G(symbols));
+		FFI_G(symbols) = NULL;
+	}
+	if (FFI_G(tags)) {
+		zend_hash_destroy(FFI_G(tags));
+		efree(FFI_G(tags));
+		FFI_G(tags) = NULL;
+	}
+	RETURN_THROWS();
 }
 /* }}} */
 
diff '--color=auto' -Naur php-8.4.18/ext/ffi/tests/gh14286_2.phpt php-8.4.20RC1/ext/ffi/tests/gh14286_2.phpt
--- php-8.4.18/ext/ffi/tests/gh14286_2.phpt	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/ffi/tests/gh14286_2.phpt	2026-04-01 04:35:36.005895463 +0000
@@ -2,10 +2,6 @@
 GH-14286 (ffi enum type (when enum has no name) make memory leak)
 --EXTENSIONS--
 ffi
---SKIPIF--
-<?php
-if (PHP_DEBUG || getenv('SKIP_ASAN')) die("xfail: FFI cleanup after parser error is not implemented");
-?>
 --INI--
 ffi.enable=1
 --FILE--
diff '--color=auto' -Naur php-8.4.18/ext/ffi/tests/gh18629_cdef_resolve_func.phpt php-8.4.20RC1/ext/ffi/tests/gh18629_cdef_resolve_func.phpt
--- php-8.4.18/ext/ffi/tests/gh18629_cdef_resolve_func.phpt	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/ext/ffi/tests/gh18629_cdef_resolve_func.phpt	2026-04-01 04:35:36.005985062 +0000
@@ -0,0 +1,16 @@
+--TEST--
+GH-18629 (FFI::cdef() leaks on function resolution failure)
+--EXTENSIONS--
+ffi
+--INI--
+ffi.enable=1
+--FILE--
+<?php
+try {
+	$ffi = FFI::cdef("void nonexistent_ffi_test_func(void);");
+} catch (\FFI\Exception $e) {
+	echo $e->getMessage() . "\n";
+}
+?>
+--EXPECT--
+Failed resolving C function 'nonexistent_ffi_test_func'
diff '--color=auto' -Naur php-8.4.18/ext/ffi/tests/gh18629_read_field_non_struct.phpt php-8.4.20RC1/ext/ffi/tests/gh18629_read_field_non_struct.phpt
--- php-8.4.18/ext/ffi/tests/gh18629_read_field_non_struct.phpt	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/ext/ffi/tests/gh18629_read_field_non_struct.phpt	2026-04-01 04:35:36.006051738 +0000
@@ -0,0 +1,17 @@
+--TEST--
+GH-18629 (Read field of non C struct/union)
+--EXTENSIONS--
+ffi
+--INI--
+ffi.enable=1
+--FILE--
+<?php
+$x = FFI::cdef()->new("int*");
+try {
+	$y = $x->foo;
+} catch (\FFI\Exception $e) {
+	echo $e->getMessage() . "\n";
+}
+?>
+--EXPECT--
+Attempt to read field 'foo' of non C struct/union
diff '--color=auto' -Naur php-8.4.18/ext/filter/logical_filters.c php-8.4.20RC1/ext/filter/logical_filters.c
--- php-8.4.18/ext/filter/logical_filters.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/filter/logical_filters.c	2026-04-01 04:35:36.006187675 +0000
@@ -723,7 +723,7 @@
 }
 /* }}} */
 
-static int _php_filter_validate_ipv4(char *str, size_t str_len, int *ip) /* {{{ */
+static int _php_filter_validate_ipv4(const char *str, size_t str_len, int *ip) /* {{{ */
 {
 	const char *end = str + str_len;
 	int num, m;
@@ -764,7 +764,7 @@
 	int blocks = 0;
 	unsigned int num, n;
 	int i;
-	char *ipv4;
+	const char *ipv4;
 	const char *end;
 	int ip4elm[4];
 	const char *s = str;
diff '--color=auto' -Naur php-8.4.18/ext/gd/libgd/gd_jpeg.c php-8.4.20RC1/ext/gd/libgd/gd_jpeg.c
--- php-8.4.18/ext/gd/libgd/gd_jpeg.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/gd/libgd/gd_jpeg.c	2026-04-01 04:35:36.006338480 +0000
@@ -125,6 +125,10 @@
 			return "9 compatible";
 			break;
 
+		case 100:
+			return "10 compatible";
+			break;
+
 		default:
 			return "unknown";
 	}
diff '--color=auto' -Naur php-8.4.18/ext/gd/tests/bug77270.phpt php-8.4.20RC1/ext/gd/tests/bug77270.phpt
--- php-8.4.18/ext/gd/tests/bug77270.phpt	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/gd/tests/bug77270.phpt	2026-04-01 04:35:36.006463797 +0000
@@ -1,7 +1,5 @@
 --TEST--
 Bug #77270 (imagecolormatch Out Of Bounds Write on Heap)
---INI--
-memory_limit=-1
 --EXTENSIONS--
 gd
 --SKIPIF--
diff '--color=auto' -Naur php-8.4.18/ext/gd/tests/bug77272.phpt php-8.4.20RC1/ext/gd/tests/bug77272.phpt
--- php-8.4.18/ext/gd/tests/bug77272.phpt	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/gd/tests/bug77272.phpt	2026-04-01 04:35:36.006530563 +0000
@@ -6,6 +6,7 @@
 gd
 --SKIPIF--
 <?php
+if (!getenv('RUN_RESOURCE_HEAVY_TESTS')) die('skip resource-heavy test');
 if (!GD_BUNDLED && version_compare(GD_VERSION, '2.2.5', '<=')) die('skip upstream fix not yet released');
 if (getenv("SKIP_SLOW_TESTS")) die("skip slow test");
 if (substr(PHP_OS, 0, 3) == 'WIN' && PHP_INT_SIZE === 4) die("skip not for Windows x86");
diff '--color=auto' -Naur php-8.4.18/ext/gd/tests/bug77479.phpt php-8.4.20RC1/ext/gd/tests/bug77479.phpt
--- php-8.4.18/ext/gd/tests/bug77479.phpt	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/gd/tests/bug77479.phpt	2026-04-01 04:35:36.006613860 +0000
@@ -4,6 +4,7 @@
 gd
 --SKIPIF--
 <?php
+if (!getenv('RUN_RESOURCE_HEAVY_TESTS')) die('skip resource-heavy test');
 if (getenv("SKIP_SLOW_TESTS")) die("skip slow test");
 ?>
 --INI--
diff '--color=auto' -Naur php-8.4.18/ext/gd/tests/gh16322.phpt php-8.4.20RC1/ext/gd/tests/gh16322.phpt
--- php-8.4.18/ext/gd/tests/gh16322.phpt	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/gd/tests/gh16322.phpt	2026-04-01 04:35:36.006683772 +0000
@@ -2,8 +2,6 @@
 GH-16322 (imageaffine overflow/underflow on affine matrix)
 --EXTENSIONS--
 gd
---INI--
-memory_limit=-1
 --FILE--
 <?php
 $matrix = [INF, 1, 1, 1, 1, 1];
diff '--color=auto' -Naur php-8.4.18/ext/iconv/iconv.c php-8.4.20RC1/ext/iconv/iconv.c
--- php-8.4.18/ext/iconv/iconv.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/iconv/iconv.c	2026-04-01 04:35:36.006821392 +0000
@@ -320,7 +320,7 @@
 
 		if (mimetype != NULL && (!(output_context->op & PHP_OUTPUT_HANDLER_CLEAN) || ((output_context->op & PHP_OUTPUT_HANDLER_START) && !(output_context->op & PHP_OUTPUT_HANDLER_FINAL)))) {
 			size_t len;
-			char *p = strstr(get_output_encoding(), "//");
+			const char *p = strstr(get_output_encoding(), "//");
 
 			if (p) {
 				len = spprintf(&content_type, 0, "Content-Type:%.*s; charset=%.*s", mimetype_len ? mimetype_len : (int) strlen(mimetype), mimetype, (int) (p - get_output_encoding()), get_output_encoding());
@@ -2577,7 +2577,7 @@
 {
 	php_stream_filter *retval = NULL;
 	php_iconv_stream_filter *inst;
-	char *from_charset = NULL, *to_charset = NULL;
+	const char *from_charset = NULL, *to_charset = NULL;
 	size_t from_charset_len, to_charset_len;
 
 	if ((from_charset = strchr(name, '.')) == NULL) {
diff '--color=auto' -Naur php-8.4.18/ext/ldap/tests/GHSA-g665-fm4p-vhff-1.phpt php-8.4.20RC1/ext/ldap/tests/GHSA-g665-fm4p-vhff-1.phpt
--- php-8.4.18/ext/ldap/tests/GHSA-g665-fm4p-vhff-1.phpt	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/ldap/tests/GHSA-g665-fm4p-vhff-1.phpt	2026-04-01 04:35:36.007008837 +0000
@@ -6,6 +6,7 @@
 memory_limit=-1
 --SKIPIF--
 <?php
+if (!getenv('RUN_RESOURCE_HEAVY_TESTS')) die('skip resource-heavy test');
 if (PHP_INT_SIZE !== 4) die("skip only for 32-bit");
 if (getenv("SKIP_SLOW_TESTS")) die("skip slow test");
 ?>
diff '--color=auto' -Naur php-8.4.18/ext/ldap/tests/GHSA-g665-fm4p-vhff-2.phpt php-8.4.20RC1/ext/ldap/tests/GHSA-g665-fm4p-vhff-2.phpt
--- php-8.4.18/ext/ldap/tests/GHSA-g665-fm4p-vhff-2.phpt	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/ldap/tests/GHSA-g665-fm4p-vhff-2.phpt	2026-04-01 04:35:36.007070102 +0000
@@ -6,6 +6,7 @@
 memory_limit=-1
 --SKIPIF--
 <?php
+if (!getenv('RUN_RESOURCE_HEAVY_TESTS')) die('skip resource-heavy test');
 if (PHP_INT_SIZE !== 4) die("skip only for 32-bit");
 if (getenv("SKIP_SLOW_TESTS")) die("skip slow test");
 ?>
diff '--color=auto' -Naur php-8.4.18/ext/mbstring/mbstring.c php-8.4.20RC1/ext/mbstring/mbstring.c
--- php-8.4.18/ext/mbstring/mbstring.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/mbstring/mbstring.c	2026-04-01 04:35:36.007301119 +0000
@@ -3376,8 +3376,9 @@
 		return *elist;
 	}
 
-	/* Allocate on stack; when we return, this array is automatically freed */
-	struct candidate *array = alloca(elist_size * sizeof(struct candidate));
+	/* Allocate on stack or heap */
+	ALLOCA_FLAG(use_heap)
+	struct candidate *array = do_alloca(elist_size * sizeof(struct candidate), use_heap);
 	elist_size = init_candidate_array(array, elist_size, elist, strings, str_lengths, n, strict, order_significant);
 
 	while (n--) {
@@ -3385,6 +3386,7 @@
 		elist_size = count_demerits(array, elist_size, strict);
 		if (elist_size == 0) {
 			/* All candidates were eliminated */
+			free_alloca(array, use_heap);
 			return NULL;
 		}
 	}
@@ -3396,7 +3398,10 @@
 			best = i;
 		}
 	}
-	return array[best].enc;
+
+	const mbfl_encoding *result = array[best].enc;
+	free_alloca(array, use_heap);
+	return result;
 }
 
 /* When doing 'strict' detection, any string which is invalid in the candidate encoding
diff '--color=auto' -Naur php-8.4.18/ext/mbstring/tests/gh20836_stack_limit.phpt php-8.4.20RC1/ext/mbstring/tests/gh20836_stack_limit.phpt
--- php-8.4.18/ext/mbstring/tests/gh20836_stack_limit.phpt	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/mbstring/tests/gh20836_stack_limit.phpt	2026-04-01 04:35:36.007676358 +0000
@@ -12,7 +12,7 @@
 }
 ?>
 --INI--
-zend.max_allowed_stack_size=128K
+zend.max_allowed_stack_size=256K
 --FILE--
 <?php
 
diff '--color=auto' -Naur php-8.4.18/ext/mbstring/tests/gh21223.phpt php-8.4.20RC1/ext/mbstring/tests/gh21223.phpt
--- php-8.4.18/ext/mbstring/tests/gh21223.phpt	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/ext/mbstring/tests/gh21223.phpt	2026-04-01 04:35:36.007744567 +0000
@@ -0,0 +1,19 @@
+--TEST--
+GH-21223 (Stack overflow in mb_guess_encoding called via mb_detect_encoding)
+--EXTENSIONS--
+mbstring
+--FILE--
+<?php
+$str = "hello";
+
+$list = [];
+for ($i = 0; $i < 500000; $i++) {
+    $list[] = "UTF-8";
+}
+
+var_dump(mb_detect_encoding($str, $list, false));
+echo "Done";
+?>
+--EXPECT--
+string(5) "UTF-8"
+Done
diff '--color=auto' -Naur php-8.4.18/ext/opcache/jit/ir/ir_aarch64.dasc php-8.4.20RC1/ext/opcache/jit/ir/ir_aarch64.dasc
--- php-8.4.18/ext/opcache/jit/ir/ir_aarch64.dasc	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/opcache/jit/ir/ir_aarch64.dasc	2026-04-01 04:35:36.008443898 +0000
@@ -60,7 +60,7 @@
 #define ADR_IMM         (1<<20)        // signed imm21
 #define ADRP_IMM        (1LL<<32)      // signed imm21 * 4096
 
-static bool aarch64_may_use_b(ir_code_buffer *code_buffer, const void *addr)
+static bool aarch64_may_use_b(const ir_code_buffer *code_buffer, const void *addr)
 {
 	if (code_buffer) {
 		if (addr >= code_buffer->start && (char*)addr < (char*)code_buffer->end) {
@@ -824,6 +824,34 @@
 	}
 }
 
+static bool all_usages_are_fusable(ir_ctx *ctx, ir_ref ref)
+{
+	ir_insn *insn = &ctx->ir_base[ref];
+
+	if (insn->op >= IR_EQ && insn->op <= IR_UNORDERED) {
+		ir_use_list *use_list = &ctx->use_lists[ref];
+		ir_ref n = use_list->count;
+
+		if (n > 0) {
+			ir_ref *p = ctx->use_edges + use_list->refs;
+
+			do {
+				insn = &ctx->ir_base[*p];
+				if (insn->op != IR_IF
+				 && insn->op != IR_GUARD
+				 && insn->op != IR_GUARD_NOT) {
+					return 0;
+				}
+				p++;
+				n--;
+			} while (n);
+			return 1;
+		}
+	}
+	return 0;
+}
+
+
 static uint32_t ir_match_insn(ir_ctx *ctx, ir_ref ref)
 {
 	ir_insn *op2_insn;
@@ -1145,7 +1173,7 @@
 				return IR_RETURN_FP;
 			}
 		case IR_IF:
-			if (!IR_IS_CONST_REF(insn->op2) && ctx->use_lists[insn->op2].count == 1) {
+			if (!IR_IS_CONST_REF(insn->op2) && (ctx->use_lists[insn->op2].count == 1 || all_usages_are_fusable(ctx, insn->op2))) {
 				op2_insn = &ctx->ir_base[insn->op2];
 				if (op2_insn->op >= IR_EQ && op2_insn->op <= IR_UNORDERED) {
 					if (IR_IS_TYPE_INT(ctx->ir_base[op2_insn->op1].type)) {
@@ -1168,13 +1196,13 @@
 			}
 		case IR_GUARD:
 		case IR_GUARD_NOT:
-			if (!IR_IS_CONST_REF(insn->op2) && ctx->use_lists[insn->op2].count == 1) {
+			if (!IR_IS_CONST_REF(insn->op2) && (ctx->use_lists[insn->op2].count == 1 || all_usages_are_fusable(ctx, insn->op2))) {
 				op2_insn = &ctx->ir_base[insn->op2];
-				if (op2_insn->op >= IR_EQ && op2_insn->op <= IR_UNORDERED
+				if (op2_insn->op >= IR_EQ && op2_insn->op <= IR_UNORDERED) {
 					// TODO: register allocator may clobber operands of CMP before they are used in the GUARD_CMP
-				 && (insn->op2 == ref - 1 ||
-				     (insn->op2 == ctx->prev_ref[ref] - 1
-				   && ctx->ir_base[ctx->prev_ref[ref]].op == IR_SNAPSHOT))) {
+//???				 && (insn->op2 == ref - 1 ||
+//???				     (insn->op2 == ctx->prev_ref[ref] - 1
+//???				   && ctx->ir_base[ctx->prev_ref[ref]].op == IR_SNAPSHOT))) {
 					if (IR_IS_TYPE_INT(ctx->ir_base[op2_insn->op1].type)) {
 						ctx->rules[insn->op2] = IR_FUSED | IR_CMP_INT;
 						return IR_GUARD_CMP_INT;
@@ -3084,7 +3112,7 @@
 	}
 }
 
-static ir_op ir_emit_cmp_fp_common(ir_ctx *ctx, ir_ref cmp_ref, ir_insn *cmp_insn)
+static ir_op ir_emit_cmp_fp_common(ir_ctx *ctx, ir_ref root, ir_ref cmp_ref, ir_insn *cmp_insn)
 {
 	ir_backend_data *data = ctx->data;
 	dasm_State **Dst = &data->dasm_state;
@@ -3093,16 +3121,12 @@
 	ir_ref op1, op2;
 	ir_reg op1_reg, op2_reg;
 
-	if (op == IR_LT || op == IR_LE) {
-		/* swap operands to avoid P flag check */
-		op ^= 3;
-		op1 = cmp_insn->op2;
-		op2 = cmp_insn->op1;
-		op1_reg = ctx->regs[cmp_ref][2];
-		op2_reg = ctx->regs[cmp_ref][1];
+	op1 = cmp_insn->op1;
+	op2 = cmp_insn->op2;
+	if (UNEXPECTED(ctx->rules[cmp_ref] & IR_FUSED_REG)) {
+		op1_reg = ir_get_fused_reg(ctx, root, cmp_ref * sizeof(ir_ref) + 1);
+		op2_reg = ir_get_fused_reg(ctx, root, cmp_ref * sizeof(ir_ref) + 2);
 	} else {
-		op1 = cmp_insn->op1;
-		op2 = cmp_insn->op2;
 		op1_reg = ctx->regs[cmp_ref][1];
 		op2_reg = ctx->regs[cmp_ref][2];
 	}
@@ -3131,7 +3155,7 @@
 {
 	ir_backend_data *data = ctx->data;
 	dasm_State **Dst = &data->dasm_state;
-	ir_op op = ir_emit_cmp_fp_common(ctx, def, insn);
+	ir_op op = ir_emit_cmp_fp_common(ctx, def, def, insn);
 	ir_reg def_reg = IR_REG_NUM(ctx->regs[def][0]);
 //???	ir_reg tmp_reg = ctx->regs[def][3]; // TODO: take into account vs flag
 
@@ -3348,8 +3372,15 @@
 	ir_type type = ctx->ir_base[cmp_insn->op1].type;
 	ir_ref op1 = cmp_insn->op1;
 	ir_ref op2 = cmp_insn->op2;
-	ir_reg op1_reg = ctx->regs[insn->op2][1];
-	ir_reg op2_reg = ctx->regs[insn->op2][2];
+	ir_reg op1_reg, op2_reg;
+
+	if (UNEXPECTED(ctx->rules[insn->op2] & IR_FUSED_REG)) {
+		op1_reg = ir_get_fused_reg(ctx, def, insn->op2 * sizeof(ir_ref) + 1);
+		op2_reg = ir_get_fused_reg(ctx, def, insn->op2 * sizeof(ir_ref) + 2);
+	} else {
+		op1_reg = ctx->regs[insn->op2][1];
+		op2_reg = ctx->regs[insn->op2][2];
+	}
 
 	if (op1_reg != IR_REG_NONE && IR_REG_SPILLED(op1_reg)) {
 		op1_reg = IR_REG_NUM(op1_reg);
@@ -3390,7 +3421,7 @@
 
 static void ir_emit_cmp_and_branch_fp(ir_ctx *ctx, uint32_t b, ir_ref def, ir_insn *insn, uint32_t next_block)
 {
-	ir_op op = ir_emit_cmp_fp_common(ctx, insn->op2, &ctx->ir_base[insn->op2]);
+	ir_op op = ir_emit_cmp_fp_common(ctx, def, insn->op2, &ctx->ir_base[insn->op2]);
 	ir_emit_jcc(ctx, b, def, insn, next_block, op, 0);
 }
 
@@ -3459,14 +3490,14 @@
 			op3_reg = op2_reg;
 		}
 	}
-	if (op3 != op2 && IR_REG_SPILLED(op3_reg)) {
+	if (IR_REG_SPILLED(op3_reg)) {
 		op3_reg = IR_REG_NUM(op3_reg);
 		ir_emit_load(ctx, type, op3_reg, op3);
-		if (op1 == op2) {
+		if (op1 == op3) {
 			op1_reg = op3_reg;
 		}
 	}
-	if (op1 != op2 && op1 != op3 && IR_REG_SPILLED(op1_reg)) {
+	if (IR_REG_SPILLED(op1_reg)) {
 		op1_reg = IR_REG_NUM(op1_reg);
 		ir_emit_load(ctx, op1_type, op1_reg, op1);
 	}
@@ -5682,9 +5713,16 @@
 	ir_type type = ctx->ir_base[cmp_insn->op1].type;
 	ir_ref op1 = cmp_insn->op1;
 	ir_ref op2 = cmp_insn->op2;
-	ir_reg op1_reg = ctx->regs[insn->op2][1];
-	ir_reg op2_reg = ctx->regs[insn->op2][2];
 	void *addr;
+	ir_reg op1_reg, op2_reg;
+
+	if (UNEXPECTED(ctx->rules[insn->op2] & IR_FUSED_REG)) {
+		op1_reg = ir_get_fused_reg(ctx, def, insn->op2 * sizeof(ir_ref) + 1);
+		op2_reg = ir_get_fused_reg(ctx, def, insn->op2 * sizeof(ir_ref) + 2);
+	} else {
+		op1_reg = ctx->regs[insn->op2][1];
+		op2_reg = ctx->regs[insn->op2][2];
+	}
 
 	if (op1_reg != IR_REG_NONE && IR_REG_SPILLED(op1_reg)) {
 		op1_reg = IR_REG_NUM(op1_reg);
@@ -5738,7 +5776,7 @@
 
 static void ir_emit_guard_cmp_fp(ir_ctx *ctx, uint32_t b, ir_ref def, ir_insn *insn)
 {
-	ir_op op = ir_emit_cmp_fp_common(ctx, insn->op2, &ctx->ir_base[insn->op2]);
+	ir_op op = ir_emit_cmp_fp_common(ctx, def, insn->op2, &ctx->ir_base[insn->op2]);
 	void *addr = ir_jmp_addr(ctx, insn, &ctx->ir_base[insn->op3]);
 
 	if (insn->op == IR_GUARD) {
@@ -7143,7 +7181,7 @@
 	return n;
 }
 
-bool ir_needs_thunk(ir_code_buffer *code_buffer, void *addr)
+bool ir_needs_thunk(const ir_code_buffer *code_buffer, void *addr)
 {
 	return !aarch64_may_use_b(code_buffer, addr);
 }
diff '--color=auto' -Naur php-8.4.18/ext/opcache/jit/ir/ir.c php-8.4.20RC1/ext/opcache/jit/ir/ir.c
--- php-8.4.18/ext/opcache/jit/ir/ir.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/opcache/jit/ir/ir.c	2026-04-01 04:35:36.007920439 +0000
@@ -858,7 +858,7 @@
 static ir_ref _ir_fold_cse(ir_ctx *ctx, uint32_t opt, ir_ref op1, ir_ref op2, ir_ref op3)
 {
 	ir_ref ref = ctx->prev_insn_chain[opt & IR_OPT_OP_MASK];
-	ir_insn *insn;
+	const ir_insn *insn;
 
 	if (ref) {
 		ir_ref limit = ctx->fold_cse_limit;
@@ -954,7 +954,8 @@
  * ANY and UNUSED ops are represented by 0
  */
 
-ir_ref ir_folding(ir_ctx *ctx, uint32_t opt, ir_ref op1, ir_ref op2, ir_ref op3, ir_insn *op1_insn, ir_insn *op2_insn, ir_insn *op3_insn)
+ir_ref ir_folding(ir_ctx *ctx, uint32_t opt, ir_ref op1, ir_ref op2, ir_ref op3,
+                  const ir_insn *op1_insn, const ir_insn *op2_insn, const ir_insn *op3_insn)
 {
 	uint8_t op;
 	ir_ref ref;
@@ -1136,9 +1137,9 @@
 	ir_insn_set_op(insn, n, val);
 }
 
-ir_ref ir_get_op(ir_ctx *ctx, ir_ref ref, int32_t n)
+ir_ref ir_get_op(const ir_ctx *ctx, ir_ref ref, int32_t n)
 {
-	ir_insn *insn = &ctx->ir_base[ref];
+	const ir_insn *insn = &ctx->ir_base[ref];
 
 #ifdef IR_DEBUG
 	if (n > 3) {
@@ -1419,13 +1420,21 @@
 		if (old_size < new_size) {
 			/* Reallocate the whole edges buffer (this is inefficient) */
 			ctx->use_edges = ir_mem_realloc(ctx->use_edges, new_size);
+			if (n == ctx->use_edges_count) {
+				ctx->use_edges[n] = ref;
+				use_list->count++;
+				ctx->use_edges_count++;
+				return 1;
+			}
 		} else if (n == ctx->use_edges_count) {
 			ctx->use_edges[n] = ref;
 			use_list->count++;
 			ctx->use_edges_count++;
 			return 0;
 		}
-		memcpy(ctx->use_edges + ctx->use_edges_count, ctx->use_edges + use_list->refs, use_list->count * sizeof(ir_ref));
+		if (use_list->count) {
+			memcpy(ctx->use_edges + ctx->use_edges_count, ctx->use_edges + use_list->refs, use_list->count * sizeof(ir_ref));
+		}
 		use_list->refs = ctx->use_edges_count;
 		ctx->use_edges[use_list->refs + use_list->count] = ref;
 		use_list->count++;
@@ -2025,7 +2034,7 @@
 
 ir_alias ir_check_partial_aliasing(const ir_ctx *ctx, ir_ref addr1, ir_ref addr2, ir_type type1, ir_type type2)
 {
-	ir_insn *insn1, *insn2;
+	const ir_insn *insn1, *insn2;
 	ir_ref base1, base2, off1, off2;
 
 	/* this must be already check */
@@ -2117,9 +2126,9 @@
 	return IR_MAY_ALIAS;
 }
 
-IR_ALWAYS_INLINE ir_ref ir_find_aliasing_load_i(ir_ctx *ctx, ir_ref ref, ir_type type, ir_ref addr, ir_ref limit)
+IR_ALWAYS_INLINE ir_ref ir_find_aliasing_load_i(const ir_ctx *ctx, ir_ref ref, ir_type type, ir_ref addr, ir_ref limit)
 {
-	ir_insn *insn;
+	const ir_insn *insn;
 	uint32_t modified_regset = 0;
 
 	while (ref > limit) {
@@ -2159,7 +2168,7 @@
 		} else if (insn->op == IR_RSTORE) {
 			modified_regset |= (1 << insn->op3);
 		} else if (insn->op == IR_CALL) {
-			ir_insn *func = &ctx->ir_base[insn->op2];
+			const ir_insn *func = &ctx->ir_base[insn->op2];
 			ir_ref func_proto;
 			const ir_proto_t *proto;
 
@@ -2186,14 +2195,14 @@
 	return IR_UNUSED;
 }
 
-ir_ref ir_find_aliasing_load(ir_ctx *ctx, ir_ref ref, ir_type type, ir_ref addr)
+ir_ref ir_find_aliasing_load(const ir_ctx *ctx, ir_ref ref, ir_type type, ir_ref addr)
 {
 	return ir_find_aliasing_load_i(ctx, ref, type, addr, (addr > 0 && addr < ref) ? addr : 1);
 }
 
-IR_ALWAYS_INLINE ir_ref ir_find_aliasing_vload_i(ir_ctx *ctx, ir_ref ref, ir_type type, ir_ref var)
+IR_ALWAYS_INLINE ir_ref ir_find_aliasing_vload_i(const ir_ctx *ctx, ir_ref ref, ir_type type, ir_ref var)
 {
-	ir_insn *insn;
+	const ir_insn *insn;
 
 	while (ref > var) {
 		insn = &ctx->ir_base[ref];
@@ -2224,7 +2233,7 @@
 				}
 			}
 		} else if (insn->op == IR_CALL) {
-			ir_insn *func = &ctx->ir_base[insn->op2];
+			const ir_insn *func = &ctx->ir_base[insn->op2];
 			ir_ref func_proto;
 			const ir_proto_t *proto;
 
@@ -2251,7 +2260,7 @@
 	return IR_UNUSED;
 }
 
-ir_ref ir_find_aliasing_vload(ir_ctx *ctx, ir_ref ref, ir_type type, ir_ref var)
+ir_ref ir_find_aliasing_vload(const ir_ctx *ctx, ir_ref ref, ir_type type, ir_ref var)
 {
 	return ir_find_aliasing_vload_i(ctx, ref, type, var);
 }
@@ -2547,12 +2556,12 @@
 	}
 }
 
-static ir_ref _ir_fold_condition(ir_ctx *ctx, ir_ref ref)
+static ir_ref _ir_fold_condition(const ir_ctx *ctx, ir_ref ref)
 {
-	ir_insn *insn = &ctx->ir_base[ref];
+	const ir_insn *insn = &ctx->ir_base[ref];
 
 	if (insn->op == IR_NE && IR_IS_CONST_REF(insn->op2)) {
-		ir_insn *op2_insn = &ctx->ir_base[insn->op2];
+		const ir_insn *op2_insn = &ctx->ir_base[insn->op2];
 
 		if (IR_IS_TYPE_INT(op2_insn->type) && op2_insn->val.u64 == 0) {
 			ref = insn->op1;
@@ -2565,7 +2574,7 @@
 		ref = insn->op1;
 		insn = &ctx->ir_base[ref];
 	} else if (insn->op == IR_EQ && insn->op2 == IR_NULL) {
-		ir_insn *op1_insn = &ctx->ir_base[insn->op1];
+		const ir_insn *op1_insn = &ctx->ir_base[insn->op1];
 		if (op1_insn->op == IR_ALLOCA || op1_insn->op == IR_VADDR) {
 			return IR_FALSE;
 		}
@@ -2577,10 +2586,10 @@
 	return ref;
 }
 
-IR_ALWAYS_INLINE ir_ref ir_check_dominating_predicates_i(ir_ctx *ctx, ir_ref ref, ir_ref condition, ir_ref limit)
+IR_ALWAYS_INLINE ir_ref ir_check_dominating_predicates_i(const ir_ctx *ctx, ir_ref ref, ir_ref condition, ir_ref limit)
 {
-	ir_insn *prev = NULL;
-	ir_insn *insn;
+	const ir_insn *prev = NULL;
+	const ir_insn *insn;
 
 	while (ref > limit) {
 		insn = &ctx->ir_base[ref];
@@ -2610,7 +2619,7 @@
 	return condition;
 }
 
-ir_ref ir_check_dominating_predicates(ir_ctx *ctx, ir_ref ref, ir_ref condition)
+ir_ref ir_check_dominating_predicates(const ir_ctx *ctx, ir_ref ref, ir_ref condition)
 {
 	IR_ASSERT(!IR_IS_CONST_REF(condition));
 	return ir_check_dominating_predicates_i(ctx, ref, condition, (condition < ref) ? condition : 1);
@@ -2751,7 +2760,7 @@
 
 		/* count inputs count */
 		do {
-			ir_insn *insn = &ctx->ir_base[ref];
+			const ir_insn *insn = &ctx->ir_base[ref];
 
 			IR_ASSERT(insn->op == IR_END);
 			ref = insn->op2;
@@ -2781,8 +2790,10 @@
 
 ir_ref _ir_PHI_LIST(ir_ctx *ctx, ir_ref list)
 {
-	ir_insn *merge, *end;
-	ir_ref phi, *ops, i;
+	const ir_insn *merge;
+	const ir_ref *ops;
+	ir_insn *end;
+	ir_ref phi, i;
 	ir_type type;
 
 	if (list == IR_UNUSED) {
@@ -3246,7 +3257,8 @@
 	if (EXPECTED(ctx->flags & IR_OPT_FOLDING)) {
 		ref = ir_find_aliasing_vload_i(ctx, ctx->control, type, var);
 		if (ref) {
-			ir_insn *insn = &ctx->ir_base[ref];
+			const ir_insn *insn = &ctx->ir_base[ref];
+
 			if (insn->type == type) {
 				return ref;
 			} else if (ir_type_size[insn->type] == ir_type_size[type]) {
@@ -3312,7 +3324,8 @@
 		}
 		ref = ir_find_aliasing_load_i(ctx, ctx->control, type, addr, (addr > 0) ? addr : 1);
 		if (ref) {
-			ir_insn *insn = &ctx->ir_base[ref];
+			const ir_insn *insn = &ctx->ir_base[ref];
+
 			if (insn->type == type) {
 				return ref;
 			} else if (ir_type_size[insn->type] == ir_type_size[type]) {
diff '--color=auto' -Naur php-8.4.18/ext/opcache/jit/ir/ir_cfg.c php-8.4.20RC1/ext/opcache/jit/ir/ir_cfg.c
--- php-8.4.18/ext/opcache/jit/ir/ir_cfg.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/opcache/jit/ir/ir_cfg.c	2026-04-01 04:35:36.008870324 +0000
@@ -5,6 +5,10 @@
  * Authors: Dmitry Stogov <dmitry@php.net>
  */
 
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE
+#endif
+
 #include "ir.h"
 #include "ir_private.h"
 
@@ -77,12 +81,86 @@
 	}
 }
 
+static void ir_remove_phis_inputs(ir_ctx *ctx, ir_use_list *use_list, int new_inputs_count, ir_bitset life_inputs)
+{
+	ir_ref i, j, n, k, *p, *q, use;
+	ir_insn *use_insn;
+
+	if (new_inputs_count == 1) {
+		for (k = use_list->count, p = q = &ctx->use_edges[use_list->refs]; k > 0; p++, k--) {
+			use = *p;
+			use_insn = &ctx->ir_base[use];
+			if (use_insn->op == IR_PHI) {
+				/* Convert PHI to COPY */
+				n = use_insn->inputs_count;
+				i = 2;
+				for (j = 2; j <= n; j++) {
+					ir_ref input = ir_insn_op(use_insn, j);
+
+					if (ir_bitset_in(life_inputs, j - 1)) {
+						use_insn->op1 = ir_insn_op(use_insn, j);
+					} else if (input > 0) {
+						ir_use_list_remove_one(ctx, input, use);
+					}
+				}
+				use_insn->op = IR_COPY;
+				use_insn->inputs_count = 1;
+				for (j = 2; j <= n; j++) {
+					ir_insn_set_op(use_insn, j, IR_UNUSED);
+				}
+				continue;
+			}
+
+			/*compact use list */
+			if (p != q){
+				*q = use;
+			}
+			q++;
+		}
+
+		if (p != q) {
+			use_list->count -= (p - q);
+			do {
+				*q = IR_UNUSED; /* clenu-op the removed tail */
+				q++;
+			} while (p != q);
+		}
+	} else {
+		for (k = use_list->count, p = &ctx->use_edges[use_list->refs]; k > 0; p++, k--) {
+			use = *p;
+			use_insn = &ctx->ir_base[use];
+			if (use_insn->op == IR_PHI) {
+				n = use_insn->inputs_count;
+				i = 2;
+				for (j = 2; j <= n; j++) {
+					ir_ref input = ir_insn_op(use_insn, j);
+
+					if (ir_bitset_in(life_inputs, j - 1)) {
+						IR_ASSERT(input);
+						if (i != j) {
+							ir_insn_set_op(use_insn, i, input);
+						}
+						i++;
+					} else if (input > 0) {
+						ir_use_list_remove_one(ctx, input, use);
+					}
+				}
+				use_insn->inputs_count = i - 1;
+				for (j = i; j <= n; j++) {
+					ir_insn_set_op(use_insn, j, IR_UNUSED);
+				}
+			}
+		}
+	}
+}
+
 static uint32_t IR_NEVER_INLINE ir_cfg_remove_dead_inputs(ir_ctx *ctx, uint32_t *_blocks, ir_block *blocks, uint32_t bb_count)
 {
 	uint32_t b, count = 0;
 	ir_block *bb = blocks + 1;
 	ir_insn *insn;
 	ir_ref i, j, n, *ops, input;
+	ir_bitset life_inputs = NULL;
 
 	for (b = 1; b <= bb_count; b++, bb++) {
 		bb->successors = count;
@@ -96,12 +174,27 @@
 			for (i = 1, j = 1; i <= n; i++) {
 				input = ops[i];
 				if (_blocks[input]) {
+					if (life_inputs) {
+						ir_bitset_incl(life_inputs, i);
+					}
 					if (i != j) {
 						ops[j] = ops[i];
 					}
 					j++;
-				} else if (input > 0) {
-					ir_use_list_remove_one(ctx, input, bb->start);
+				} else {
+					if (ctx->use_lists[bb->start].count > 1) {
+						/* Some inputs of this MERGE are deleted and we have to update the depended PHIs */
+						if (!life_inputs) {
+							int k;
+							life_inputs = ir_bitset_malloc(n + 1);
+							for (k = 1; k < i; k++) {
+								ir_bitset_incl(life_inputs, k);
+							}
+						}
+					}
+					IR_ASSERT(input > 0);
+					IR_ASSERT(ctx->use_lists[input].count == 1 && ctx->use_edges[ctx->use_lists[input].refs] == bb->start);
+					CLEAR_USES(input);
 				}
 			}
 			j--;
@@ -115,6 +208,11 @@
 				for (;j <= n; j++) {
 					ops[j] = IR_UNUSED;
 				}
+				if (life_inputs) {
+					ir_remove_phis_inputs(ctx, &ctx->use_lists[bb->start], insn->inputs_count, life_inputs);
+					ir_mem_free(life_inputs);
+					life_inputs = NULL;
+				}
 			}
 		}
 		count += bb->predecessors_count;
@@ -375,8 +473,7 @@
 
 static void ir_remove_merge_input(ir_ctx *ctx, ir_ref merge, ir_ref from)
 {
-	ir_ref i, j, n, k, *p, *q, use;
-	ir_insn *use_insn;
+	ir_ref i, j, n;
 	ir_use_list *use_list;
 	ir_bitset life_inputs;
 	ir_insn *insn = &ctx->ir_base[merge];
@@ -402,82 +499,17 @@
 	}
 	if (i == 1) {
 		insn->op = IR_BEGIN;
-		insn->inputs_count = 1;
-		use_list = &ctx->use_lists[merge];
-		if (use_list->count > 1) {
-			n++;
-			for (k = use_list->count, p = q = &ctx->use_edges[use_list->refs]; k > 0; p++, k--) {
-				use = *p;
-				use_insn = &ctx->ir_base[use];
-				if (use_insn->op == IR_PHI) {
-					/* Convert PHI to COPY */
-					i = 2;
-					for (j = 2; j <= n; j++) {
-						ir_ref input = ir_insn_op(use_insn, j);
-
-						if (ir_bitset_in(life_inputs, j - 1)) {
-							use_insn->op1 = ir_insn_op(use_insn, j);
-						} else if (input > 0) {
-							ir_use_list_remove_one(ctx, input, use);
-						}
-					}
-					use_insn->op = IR_COPY;
-					use_insn->inputs_count = 1;
-					for (j = 2; j <= n; j++) {
-						ir_insn_set_op(use_insn, j, IR_UNUSED);
-					}
-					continue;
-				}
-
-				/*compact use list */
-				if (p != q){
-					*q = use;
-				}
-				q++;
-			}
-
-			if (p != q) {
-				use_list->count -= (p - q);
-				do {
-					*q = IR_UNUSED; /* clenu-op the removed tail */
-					q++;
-				} while (p != q);
-			}
-		}
-	} else {
-		insn->inputs_count = i;
+	}
+	insn->inputs_count = i;
 
-		use_list = &ctx->use_lists[merge];
-		if (use_list->count > 1) {
-			n++;
-			for (k = use_list->count, p = &ctx->use_edges[use_list->refs]; k > 0; p++, k--) {
-				use = *p;
-				use_insn = &ctx->ir_base[use];
-				if (use_insn->op == IR_PHI) {
-					i = 2;
-					for (j = 2; j <= n; j++) {
-						ir_ref input = ir_insn_op(use_insn, j);
-
-						if (ir_bitset_in(life_inputs, j - 1)) {
-							IR_ASSERT(input);
-							if (i != j) {
-								ir_insn_set_op(use_insn, i, input);
-							}
-							i++;
-						} else if (input > 0) {
-							ir_use_list_remove_one(ctx, input, use);
-						}
-					}
-					use_insn->inputs_count = i - 1;
-					for (j = i; j <= n; j++) {
-						ir_insn_set_op(use_insn, j, IR_UNUSED);
-					}
-				}
-			}
-		}
+	use_list = &ctx->use_lists[merge];
+	if (use_list->count > 1) {
+		ir_remove_phis_inputs(ctx, use_list, i, life_inputs);
 	}
+
 	ir_mem_free(life_inputs);
-	ir_use_list_remove_all(ctx, from, merge);
+	IR_ASSERT(ctx->use_lists[from].count == 1 && ctx->use_edges[ctx->use_lists[from].refs] == merge);
+	CLEAR_USES(from);
 }
 
 /* CFG constructed after SCCP pass doesn't have unreachable BBs, otherwise they should be removed */
@@ -582,59 +614,64 @@
 	return 1;
 }
 
-static void compute_postnum(const ir_ctx *ctx, uint32_t *cur, uint32_t b)
-{
-	uint32_t i, *p;
-	ir_block *bb = &ctx->cfg_blocks[b];
-
-	if (bb->postnum != 0) {
-		return;
-	}
-
-	if (bb->successors_count) {
-		bb->postnum = -1; /* Marker for "currently visiting" */
-		p = ctx->cfg_edges + bb->successors;
-		i = bb->successors_count;
-		do {
-			compute_postnum(ctx, cur, *p);
-			p++;
-		} while (--i);
-	}
-	bb->postnum = (*cur)++;
-}
-
 /* Computes dominator tree using algorithm from "A Simple, Fast Dominance Algorithm" by
  * Cooper, Harvey and Kennedy. */
 static IR_NEVER_INLINE int ir_build_dominators_tree_slow(ir_ctx *ctx)
 {
-	uint32_t blocks_count, b, postnum;
+	uint32_t blocks_count, b, postnum, i;
 	ir_block *blocks, *bb;
 	uint32_t *edges;
+	uint32_t *rpo = ir_mem_malloc((ctx->cfg_blocks_count + 1) * sizeof(uint32_t));
 	bool changed;
 
 	blocks = ctx->cfg_blocks;
 	edges  = ctx->cfg_edges;
 	blocks_count = ctx->cfg_blocks_count;
 
-	/* Clear the dominators tree */
-	for (b = 0, bb = &blocks[0]; b <= blocks_count; b++, bb++) {
-		bb->idom = 0;
-		bb->dom_depth = 0;
-		bb->dom_child = 0;
-		bb->dom_next_child = 0;
-	}
-
 	ctx->flags2 &= ~IR_NO_LOOPS;
 
 	postnum = 1;
-	compute_postnum(ctx, &postnum, 1);
+	ir_worklist work;
+	ir_worklist_init(&work, ctx->cfg_blocks_count + 1);
+	ir_worklist_push(&work, 1);
+	IR_ASSERT(blocks[1].next_succ == 0);
+	while (ir_worklist_len(&work)) {
+next:
+		b = ir_worklist_peek(&work);
+		bb = &blocks[b];
+		uint32_t n = bb->successors_count - bb->next_succ;
+		if (n) {
+			uint32_t *p = edges + bb->successors + bb->next_succ;
+			for (; n > 0; p++, n--) {
+				uint32_t succ = *p;
+				if (ir_worklist_push(&work, succ)) {
+					bb->next_succ = bb->successors_count - n + 1;
+					IR_ASSERT(blocks[succ].next_succ == 0);
+					goto next;
+				}
+			}
+		}
+
+		/* Start from bb->idom calculated by the fast dominators algorithm */
+		// bb->idom = 0;
+		bb->next_succ = 0;
+		rpo[postnum] = b;
+		bb->postnum = postnum++;
+		ir_worklist_pop(&work);
+	}
+	ir_worklist_free(&work);
+
+	IR_ASSERT(rpo[blocks_count] == 1);
 
 	/* Find immediate dominators by iterative fixed-point algorithm */
 	blocks[1].idom = 1;
 	do {
 		changed = 0;
+
 		/* Iterating in Reverse Post Order */
-		for (b = 2, bb = &blocks[2]; b <= blocks_count; b++, bb++) {
+		for (i = blocks_count - 1; i > 0; i--) {
+			b = rpo[i];
+			bb = &blocks[b];
 			IR_ASSERT(!(bb->flags & IR_BB_UNREACHABLE));
 			IR_ASSERT(bb->predecessors_count > 0);
 			if (bb->predecessors_count == 1) {
@@ -687,6 +724,8 @@
 		}
 	} while (changed);
 
+	ir_mem_free(rpo);
+
 	/* Build dominators tree */
 	blocks[1].idom = 0;
 	blocks[1].dom_depth = 0;
@@ -740,7 +779,7 @@
 	blocks[1].idom = 1;
 	blocks[1].dom_depth = 0;
 
-	/* Iterating in Reverse Post Order */
+	/* Iterating in Reverse Post Order (relay on existing BB order and fall-back to slow algorithm) */
 	for (b = 2, bb = &blocks[2]; b <= blocks_count; b++, bb++) {
 		IR_ASSERT(!(bb->flags & IR_BB_UNREACHABLE));
 		IR_ASSERT(bb->predecessors_count > 0);
@@ -752,8 +791,8 @@
 		if (UNEXPECTED(idom >= b)) {
 			/* In rare cases, LOOP_BEGIN.op1 may be a back-edge. Skip back-edges. */
 			ctx->flags2 &= ~IR_NO_LOOPS;
-//			IR_ASSERT(k > 1 && "Wrong blocks order: BB is before its single predecessor");
 			if (UNEXPECTED(k <= 1)) {
+				// IR_ASSERT(k > 1 && "Wrong blocks order: BB is before its single predecessor");
 slow_case:
 				ir_list_free(&worklist);
 				return ir_build_dominators_tree_slow(ctx);
@@ -767,6 +806,7 @@
 					break;
 				}
 				if (UNEXPECTED(k == 0)) {
+					// IR_ASSERT(0 && "Wrong blocks order: BB is before all its predecessors");
 					goto slow_case;
 				}
 				ir_list_push(&worklist, idom);
@@ -799,13 +839,6 @@
 		bb->dom_depth = idom_bb->dom_depth + 1;
 	}
 
-	/* Construct children lists sorted by block number */
-	for (b = blocks_count, bb = &blocks[b]; b >= 2; b--, bb--) {
-		ir_block *idom_bb = &blocks[bb->idom];
-		bb->dom_next_child = idom_bb->dom_child;
-		idom_bb->dom_child = b;
-	}
-
 	blocks[1].idom = 0;
 
 	if (ir_list_len(&worklist) != 0) {
@@ -843,10 +876,18 @@
 
 		if (UNEXPECTED(!complete)) {
 			ir_list_free(&worklist);
+			// TODO: this algorithm may be incorrect. Prove and/or switch to ir_build_dominators_tree_slow() ???
 			return ir_build_dominators_tree_iterative(ctx);
 		}
 	}
 
+	/* Construct children lists sorted by block number */
+	for (b = blocks_count, bb = &blocks[b]; b >= 2; b--, bb--) {
+		ir_block *idom_bb = &blocks[bb->idom];
+		bb->dom_next_child = idom_bb->dom_child;
+		idom_bb->dom_child = b;
+	}
+
 	ir_list_free(&worklist);
 
 	return 1;
@@ -867,8 +908,6 @@
 	/* Clear the dominators tree, but keep already found dominators */
 	for (b = 0, bb = &blocks[0]; b <= blocks_count; b++, bb++) {
 		bb->dom_depth = 0;
-		bb->dom_child = 0;
-		bb->dom_next_child = 0;
 	}
 
 	/* Find immediate dominators by iterative fixed-point algorithm */
@@ -886,20 +925,20 @@
 			if (blocks[idom].idom == 0) {
 				while (1) {
 					k--;
+					if (UNEXPECTED(k == 0)) break;
 					p++;
 					idom = *p;
 					if (blocks[idom].idom > 0) {
 						break;
 					}
-					IR_ASSERT(k > 0);
 				}
+				if (UNEXPECTED(k == 0)) continue;
 			}
 			IR_ASSERT(k != 0);
 			while (--k > 0) {
 				uint32_t pred_b = *(++p);
 
 				if (blocks[pred_b].idom > 0) {
-					IR_ASSERT(blocks[pred_b].idom > 0);
 					while (idom != pred_b) {
 						while (pred_b > idom) {
 							pred_b = blocks[pred_b].idom;
@@ -949,10 +988,107 @@
 	return b1 == b2;
 }
 
+/* Identify loops. See Sreedhar et al, "Identifying Loops Using DJ Graphs" and
+ * G. Ramalingam "Identifying Loops In Almost Linear Time". */
+
+#define ENTRY_TIME(b) times[(b) * 2]
+#define EXIT_TIME(b)  times[(b) * 2 + 1]
+
+static IR_NEVER_INLINE void ir_collect_irreducible_loops(ir_ctx *ctx, uint32_t *times, ir_worklist *work, ir_list *list)
+{
+	ir_block *blocks = ctx->cfg_blocks;
+	uint32_t *edges = ctx->cfg_edges;
+
+	IR_ASSERT(ir_list_len(list) != 0);
+	if (ir_list_len(list) > 1) {
+		/* Sort list to process irreducible loops in DFS order (insertion sort) */
+		ir_ref *a = list->a.refs;
+		uint32_t n = ir_list_len(list);
+		uint32_t i = 1;
+		while (i < n) {
+			uint32_t j = i;
+			while (j > 0 && ENTRY_TIME(a[j-1]) > ENTRY_TIME(a[j])) {
+				ir_ref tmp = a[j];
+				a[j] = a[j-1];
+				a[j-1] = tmp;
+				j--;
+			}
+			i++;
+		}
+	}
+	while (ir_list_len(list)) {
+		uint32_t hdr = ir_list_pop(list);
+		ir_block *bb = &blocks[hdr];
+
+		IR_ASSERT(bb->flags & IR_BB_IRREDUCIBLE_LOOP);
+		IR_ASSERT(!bb->loop_depth);
+		if (!bb->loop_depth) {
+			/* process irreducible loop */
+
+			bb->flags |= IR_BB_LOOP_HEADER;
+			bb->loop_depth = 1;
+			if (ctx->ir_base[bb->start].op == IR_MERGE) {
+				ctx->ir_base[bb->start].op = IR_LOOP_BEGIN;
+			}
+
+			/* find the closing edge(s) of the irreucible loop */
+			IR_ASSERT(bb->predecessors_count > 1);
+			IR_ASSERT(ir_worklist_len(work) == 0);
+			ir_bitset_clear(work->visited, ir_bitset_len(ir_worklist_capasity(work)));
+			ir_bitset_incl(work->visited, hdr);
+
+			uint32_t *p = &edges[bb->predecessors];
+			uint32_t n = bb->predecessors_count;
+			do {
+				uint32_t pred = *p;
+				if (ENTRY_TIME(pred) > ENTRY_TIME(hdr) && EXIT_TIME(pred) < EXIT_TIME(hdr)) {
+					ir_worklist_push(work, pred);
+				}
+				p++;
+			} while (--n);
+
+			/* collect members of the irreducible loop */
+			while (ir_worklist_len(work)) {
+				uint32_t b = ir_worklist_pop(work);
+
+				bb = &blocks[b];
+				if (!bb->loop_header) {
+					bb->loop_header = hdr;
+				}
+
+				uint32_t *p = &edges[bb->predecessors];
+				uint32_t n = bb->predecessors_count;
+
+				for (; n > 0; p++, n--) {
+					uint32_t pred = *p;
+					if (!ir_bitset_in(work->visited, pred)) {
+						if (blocks[pred].loop_header) {
+							if (blocks[pred].loop_header == b) continue;
+							do {
+								pred = blocks[pred].loop_header;
+							} while (blocks[pred].loop_header > 0);
+						}
+						if (ENTRY_TIME(pred) > ENTRY_TIME(hdr) && EXIT_TIME(pred) < EXIT_TIME(hdr)) {
+							/* "pred" is a descendant of "hdr" */
+								ir_worklist_push(work, pred);
+						} else if (bb->predecessors_count > 1) {
+							/* another entry to the irreducible loop */
+							bb->flags |= IR_BB_IRREDUCIBLE_LOOP;
+							if (ctx->ir_base[bb->start].op == IR_MERGE) {
+								ctx->ir_base[bb->start].op = IR_LOOP_BEGIN;
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+}
+
 int ir_find_loops(ir_ctx *ctx)
 {
-	uint32_t b, j, n, count;
-	uint32_t *entry_times, *exit_times, *sorted_blocks, time = 1;
+	uint32_t b, j, n;
+	uint32_t *times, *sorted_blocks, time = 1;
 	ir_block *blocks = ctx->cfg_blocks;
 	uint32_t *edges = ctx->cfg_edges;
 	ir_worklist work;
@@ -961,52 +1097,44 @@
 		return 1;
 	}
 
-	/* We don't materialize the DJ spanning tree explicitly, as we are only interested in ancestor
-	 * queries. These are implemented by checking entry/exit times of the DFS search. */
+	/* Compute entry/exit times for the CFG DFS spanning tree to perform ancestor and back-edge queries. */
 	ir_worklist_init(&work, ctx->cfg_blocks_count + 1);
-	entry_times = ir_mem_malloc((ctx->cfg_blocks_count + 1) * 3 * sizeof(uint32_t));
-	exit_times = entry_times + ctx->cfg_blocks_count + 1;
-	sorted_blocks = exit_times + ctx->cfg_blocks_count + 1;
-
-	memset(entry_times, 0, (ctx->cfg_blocks_count + 1) * sizeof(uint32_t));
+	times = ir_mem_malloc((ctx->cfg_blocks_count + 1) * 3 * sizeof(uint32_t));
+	sorted_blocks = times + (ctx->cfg_blocks_count + 1) * 2;
 
+	ir_bitset visited = ir_bitset_malloc(ctx->cfg_blocks_count + 1);
 	ir_worklist_push(&work, 1);
 	while (ir_worklist_len(&work)) {
-		ir_block *bb;
-		int child;
-
 next:
 		b = ir_worklist_peek(&work);
-		if (!entry_times[b]) {
-			entry_times[b] = time++;
-		}
+		ir_block *bb = &blocks[b];
 
-		/* Visit blocks immediately dominated by "b". */
-		bb = &blocks[b];
-		for (child = bb->dom_child; child > 0; child = blocks[child].dom_next_child) {
-			if (ir_worklist_push(&work, child)) {
-				goto next;
-			}
+		if (!ir_bitset_in(visited, b)) {
+			ir_bitset_incl(visited, b);
+			ENTRY_TIME(b) = time++;
 		}
 
-		/* Visit join edges. */
-		if (bb->successors_count) {
-			uint32_t *p = edges + bb->successors;
-			for (j = 0; j < bb->successors_count; j++, p++) {
+		uint32_t n = bb->successors_count - bb->next_succ;
+		if (n) {
+			uint32_t *p = edges + bb->successors + bb->next_succ;
+			for (; n > 0; p++, n--) {
 				uint32_t succ = *p;
-
-				if (blocks[succ].idom == b) {
-					continue;
-				} else if (ir_worklist_push(&work, succ)) {
+				if (ir_worklist_push(&work, succ)) {
+					bb->next_succ = bb->successors_count - n + 1;
+					IR_ASSERT(blocks[succ].next_succ == 0);
 					goto next;
 				}
 			}
 		}
-		exit_times[b] = time++;
+
+		bb->next_succ = 0;
+		EXIT_TIME(b) = time++;
 		ir_worklist_pop(&work);
 	}
+	ir_mem_free(visited);
 
 	/* Sort blocks by level, which is the opposite order in which we want to process them */
+	/* (Breadth First Search using "sorted_blocks" as a queue) */
 	sorted_blocks[1] = 1;
 	j = 1;
 	n = 2;
@@ -1020,127 +1148,62 @@
 			}
 		}
 	}
-	count = n;
+	IR_ASSERT(n == ctx->cfg_blocks_count + 1);
 
-	/* Identify loops. See Sreedhar et al, "Identifying Loops Using DJ Graphs". */
+#if IR_DEBUG
 	uint32_t prev_dom_depth = blocks[sorted_blocks[n - 1]].dom_depth;
-	uint32_t prev_irreducible = 0;
+#endif
+	uint32_t irreducible_depth = 0;
+	ir_list irreducible_list = {0};
+
 	while (n > 1) {
 		b = sorted_blocks[--n];
 		ir_block *bb = &blocks[b];
 
 		IR_ASSERT(bb->dom_depth <= prev_dom_depth);
-		if (UNEXPECTED(prev_irreducible) && bb->dom_depth != prev_dom_depth) {
-			/* process delyed irreducible loops */
-			do {
-				b = sorted_blocks[prev_irreducible];
-				bb = &blocks[b];
-				if ((bb->flags & IR_BB_IRREDUCIBLE_LOOP) && !bb->loop_depth) {
-					/* process irreducible loop */
-					uint32_t hdr = b;
-
-					bb->loop_depth = 1;
-					if (ctx->ir_base[bb->start].op == IR_MERGE) {
-						ctx->ir_base[bb->start].op = IR_LOOP_BEGIN;
-					}
 
-					/* find the closing edge(s) of the irreucible loop */
-					IR_ASSERT(bb->predecessors_count > 1);
-					uint32_t *p = &edges[bb->predecessors];
-					j = bb->predecessors_count;
-					do {
-						uint32_t pred = *p;
-
-						if (entry_times[pred] > entry_times[b] && exit_times[pred] < exit_times[b]) {
-							if (!ir_worklist_len(&work)) {
-								ir_bitset_clear(work.visited, ir_bitset_len(ir_worklist_capasity(&work)));
-							}
-							blocks[pred].loop_header = 0; /* support for merged loops */
-							ir_worklist_push(&work, pred);
-						}
-						p++;
-					} while (--j);
-					if (ir_worklist_len(&work) == 0) continue;
-
-					/* collect members of the irreducible loop */
-					while (ir_worklist_len(&work)) {
-						b = ir_worklist_pop(&work);
-						if (b != hdr) {
-							ir_block *bb = &blocks[b];
-							bb->loop_header = hdr;
-							if (bb->predecessors_count) {
-								uint32_t *p = &edges[bb->predecessors];
-								uint32_t n = bb->predecessors_count;
-								do {
-									uint32_t pred = *p;
-									while (blocks[pred].loop_header > 0) {
-										pred = blocks[pred].loop_header;
-									}
-									if (pred != hdr) {
-										if (entry_times[pred] > entry_times[hdr] && exit_times[pred] < exit_times[hdr]) {
-											/* "pred" is a descendant of "hdr" */
-											ir_worklist_push(&work, pred);
-										} else {
-											/* another entry to the irreducible loop */
-											bb->flags |= IR_BB_IRREDUCIBLE_LOOP;
-											if (ctx->ir_base[bb->start].op == IR_MERGE) {
-												ctx->ir_base[bb->start].op = IR_LOOP_BEGIN;
-											}
-										}
-									}
-									p++;
-								} while (--n);
-							}
-						}
-					}
-				}
-			} while (--prev_irreducible != n);
-			prev_irreducible = 0;
-			b = sorted_blocks[n];
-			bb = &blocks[b];
+		if (UNEXPECTED(bb->dom_depth < irreducible_depth)) {
+			ir_collect_irreducible_loops(ctx, times, &work, &irreducible_list);
+			irreducible_depth = 0;
 		}
 
 		if (bb->predecessors_count > 1) {
 			bool irreducible = 0;
+			uint32_t b_entry_time = ENTRY_TIME(b);
+			uint32_t b_exit_time = EXIT_TIME(b);
 			uint32_t *p = &edges[bb->predecessors];
 
-			j = bb->predecessors_count;
-			do {
+			for (j = bb->predecessors_count; j > 0; p++, j--) {
 				uint32_t pred = *p;
 
-				/* A join edge is one for which the predecessor does not
-				   immediately dominate the successor.  */
-				if (bb->idom != pred) {
-					/* In a loop back-edge (back-join edge), the successor dominates
-					   the predecessor.  */
+				/* Check back-edges */
+				if (ENTRY_TIME(pred) >= b_entry_time && EXIT_TIME(pred) <= b_exit_time) {
 					if (ir_dominates(blocks, b, pred)) {
+						/* In a loop back-edge (back-join edge), the successor dominates
+						   the predecessor.  */
 						if (!ir_worklist_len(&work)) {
 							ir_bitset_clear(work.visited, ir_bitset_len(ir_worklist_capasity(&work)));
 						}
-						blocks[pred].loop_header = 0; /* support for merged loops */
 						ir_worklist_push(&work, pred);
 					} else {
-						/* Otherwise it's a cross-join edge.  See if it's a branch
-						   to an ancestor on the DJ spanning tree.  */
-						if (entry_times[pred] > entry_times[b] && exit_times[pred] < exit_times[b]) {
-							irreducible = 1;
-							break;
-						}
+						/* Otherwise it's a back-edge of irreducible loop. */
+						irreducible = 1;
+						break;
 					}
 				}
-				p++;
-			} while (--j);
+			}
 
 			if (UNEXPECTED(irreducible)) {
-				bb->flags |= IR_BB_LOOP_HEADER | IR_BB_IRREDUCIBLE_LOOP;
+				bb->flags |= IR_BB_IRREDUCIBLE_LOOP;
 				ctx->flags2 |= IR_CFG_HAS_LOOPS | IR_IRREDUCIBLE_CFG;
-				/* Remember the position of the first irreducible loop to process all the irreducible loops
-				 * after the reducible loops with the same dominator tree depth
+				/* Delay processing of all irreducible loops
+				 * after all reducible loops with the same dominator tree depth
 				 */
-				if (!prev_irreducible) {
-					prev_irreducible = n;
-					prev_dom_depth = bb->dom_depth;
+				irreducible_depth = bb->dom_depth;
+				if (!ir_list_capasity(&irreducible_list)) {
+					ir_list_init(&irreducible_list, 16);
 				}
+				ir_list_push(&irreducible_list, b);
 				ir_list_clear(&work.l);
 			} else if (ir_worklist_len(&work)) {
 				/* collect members of the reducible loop */
@@ -1152,35 +1215,48 @@
 				if (ctx->ir_base[bb->start].op == IR_MERGE) {
 					ctx->ir_base[bb->start].op = IR_LOOP_BEGIN;
 				}
+				ir_bitset_incl(work.visited, hdr);
 				while (ir_worklist_len(&work)) {
 					b = ir_worklist_pop(&work);
 					if (b != hdr) {
 						ir_block *bb = &blocks[b];
-						bb->loop_header = hdr;
-						if (bb->predecessors_count) {
-							uint32_t *p = &edges[bb->predecessors];
-							uint32_t n = bb->predecessors_count;
-							do {
-								uint32_t pred = *p;
-								while (blocks[pred].loop_header > 0) {
-									pred = blocks[pred].loop_header;
-								}
-								if (pred != hdr) {
+
+						if (!bb->loop_header) {
+							bb->loop_header = hdr;
+						}
+
+						uint32_t *p = &edges[bb->predecessors];
+						uint32_t n = bb->predecessors_count;
+						for (; n > 0; p++, n--) {
+							uint32_t pred = *p;
+							if (!ir_bitset_in(work.visited, pred)) {
+								if (blocks[pred].loop_header) {
+									if (blocks[pred].loop_header == b) continue;
+									do {
+										pred = blocks[pred].loop_header;
+									} while (blocks[pred].loop_header > 0);
 									ir_worklist_push(&work, pred);
+								} else {
+									ir_bitset_incl(work.visited, pred);
+									ir_list_push_unchecked(&work.l, pred);
 								}
-								p++;
-							} while (--n);
+							}
 						}
 					}
 				}
 			}
 		}
 	}
-	IR_ASSERT(!prev_irreducible);
+
+	IR_ASSERT(!irreducible_depth);
+	if (ir_list_capasity(&irreducible_list)) {
+		ir_list_free(&irreducible_list);
+	}
 
 	if (ctx->flags2 & IR_CFG_HAS_LOOPS) {
-		for (n = 1; n < count; n++) {
-			b = sorted_blocks[n];
+		n = ctx->cfg_blocks_count + 1;
+		for (j = 1; j < n; j++) {
+			b = sorted_blocks[j];
 			ir_block *bb = &blocks[b];
 			if (bb->loop_header > 0) {
 				ir_block *loop = &blocks[bb->loop_header];
@@ -1211,7 +1287,7 @@
 		}
 	}
 
-	ir_mem_free(entry_times);
+	ir_mem_free(times);
 	ir_worklist_free(&work);
 
 	return 1;
@@ -1411,6 +1487,19 @@
 		}
 	}
 }
+
+static bool ir_is_merged_loop_back_edge(ir_ctx *ctx, uint32_t hdr, uint32_t b)
+{
+	if (ctx->cfg_blocks[hdr].flags & IR_BB_LOOP_HEADER) {
+		uint32_t loop_depth = ctx->cfg_blocks[hdr].loop_depth;
+
+		while (ctx->cfg_blocks[b].loop_depth > loop_depth) {
+			b = ctx->cfg_blocks[b].loop_header;
+		}
+		return b == hdr;
+	}
+	return 0;
+}
 #endif
 
 static int ir_schedule_blocks_bottom_up(ir_ctx *ctx)
@@ -1467,7 +1556,8 @@
 					}
 				} else if (b != predecessor && ctx->cfg_blocks[predecessor].loop_header != b) {
 					/* not a loop back-edge */
-					IR_ASSERT(b == predecessor || ctx->cfg_blocks[predecessor].loop_header == b);
+					IR_ASSERT(b == predecessor || ctx->cfg_blocks[predecessor].loop_header == b ||
+						ir_is_merged_loop_back_edge(ctx, b, predecessor));
 				}
 			}
 		}
diff '--color=auto' -Naur php-8.4.18/ext/opcache/jit/ir/ir_dump.c php-8.4.20RC1/ext/opcache/jit/ir/ir_dump.c
--- php-8.4.18/ext/opcache/jit/ir/ir_dump.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/opcache/jit/ir/ir_dump.c	2026-04-01 04:35:36.009148690 +0000
@@ -60,7 +60,7 @@
 	}
 }
 
-void ir_dump_dot(const ir_ctx *ctx, const char *name, FILE *f)
+void ir_dump_dot(const ir_ctx *ctx, const char *name, const char *comments, FILE *f)
 {
 	int DATA_WEIGHT    = 0;
 	int CONTROL_WEIGHT = 5;
@@ -70,6 +70,13 @@
 	uint32_t flags;
 
 	fprintf(f, "digraph %s {\n", name);
+	fprintf(f, "\tlabelloc=t;\n");
+	fprintf(f, "\tlabel=\"");
+	ir_print_func_proto(ctx, name, 0, f);
+	if (comments) {
+		fprintf(f, " # %s", comments);
+	}
+	fprintf(f, "\"\n");
 	fprintf(f, "\trankdir=TB;\n");
 	for (i = 1 - ctx->consts_count, insn = ctx->ir_base + i; i < IR_UNUSED; i++, insn++) {
 		fprintf(f, "\tc%d [label=\"C%d: CONST %s(", -i, -i, ir_type_name[insn->type]);
diff '--color=auto' -Naur php-8.4.18/ext/opcache/jit/ir/ir_emit.c php-8.4.20RC1/ext/opcache/jit/ir/ir_emit.c
--- php-8.4.18/ext/opcache/jit/ir/ir_emit.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/opcache/jit/ir/ir_emit.c	2026-04-01 04:35:36.009261042 +0000
@@ -5,6 +5,10 @@
  * Authors: Dmitry Stogov <dmitry@php.net>
  */
 
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE
+#endif
+
 #include "ir.h"
 
 #if defined(IR_TARGET_X86) || defined(IR_TARGET_X64)
@@ -971,7 +975,7 @@
 	return 1;
 }
 
-int32_t ir_get_spill_slot_offset(ir_ctx *ctx, ir_ref ref)
+int32_t ir_get_spill_slot_offset(const ir_ctx *ctx, ir_ref ref)
 {
 	int32_t offset;
 
diff '--color=auto' -Naur php-8.4.18/ext/opcache/jit/ir/ir_fold.h php-8.4.20RC1/ext/opcache/jit/ir/ir_fold.h
--- php-8.4.18/ext/opcache/jit/ir/ir_fold.h	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/opcache/jit/ir/ir_fold.h	2026-04-01 04:35:36.009413630 +0000
@@ -3439,5 +3439,84 @@
 	if (op2 == op3) {
 		IR_FOLD_COPY(op2);
 	}
+
+	if (op1_insn->type == IR_BOOL) {
+		if (op2 == IR_TRUE) {
+			if (op3 == IR_FALSE) {
+				/* a ? true : false => a */
+				IR_FOLD_COPY(op1);
+			} else {
+				/* a ? true : b => a | b */
+				opt = IR_OPT(IR_OR, IR_BOOL);
+				op2 = op3;
+				op3 = IR_UNUSED;
+				IR_FOLD_RESTART;
+			}
+		} else if (op3 == IR_FALSE) {
+			/* a ? b : false => a & b */
+			opt = IR_OPT(IR_AND, IR_BOOL);
+			op3 = IR_UNUSED;
+			IR_FOLD_RESTART;
+		} else if (op2 == IR_FALSE) {
+			if (op3 == IR_TRUE) {
+				/* a ? flase : true => !a */
+				opt = IR_OPT(IR_NOT, IR_BOOL);
+				op2 = IR_UNUSED;
+				op3 = IR_UNUSED;
+				IR_FOLD_RESTART;
+			}
+		} else if (IR_IS_TYPE_INT(IR_OPT_TYPE(opt))
+		 && IR_IS_CONST_REF(op2)
+		 && IR_IS_CONST_REF(op3)
+		 && op2_insn->val.u64 == 1
+		 && op3_insn->val.u64 == 0) {
+			if (ir_type_size[IR_OPT_TYPE(opt)] > 1) {
+				/* a ? 1 : 0 => ZEXT(a) */
+				opt = IR_OPT(IR_ZEXT, IR_OPT_TYPE(opt));
+			} else {
+				/* a ? 1 : 0 => BITCAST(a) */
+				opt = IR_OPT(IR_BITCAST, IR_OPT_TYPE(opt));
+			}
+			op2 = IR_UNUSED;
+			op3 = IR_UNUSED;
+			IR_FOLD_RESTART;
+	   }
+	} else if (IR_IS_TYPE_INT(op1_insn->type)) {
+		if (op2 == IR_TRUE) {
+			if (op3 == IR_FALSE) {
+				opt = IR_OPT(IR_NE, IR_BOOL);
+				val.u64 = 0;
+				op2 = ir_const(ctx, val, op1_insn->type);
+				op3 = IR_UNUSED;
+				IR_FOLD_RESTART;
+			}
+		} else if (op2 == IR_FALSE) {
+			if (op3 == IR_TRUE) {
+				opt = IR_OPT(IR_EQ, IR_BOOL);
+				val.u64 = 0;
+				op2 = ir_const(ctx, val, op1_insn->type);
+				op3 = IR_UNUSED;
+				IR_FOLD_RESTART;
+			}
+		}
+	}
+
+	if (op1_insn->op == IR_NE) {
+		if (IR_IS_CONST_REF(op1_insn->op2)
+		 && IR_IS_TYPE_INT(ctx->ir_base[op1_insn->op2].type)
+		 && ctx->ir_base[op1_insn->op2].val.u64 == 0) {
+			op1 = op1_insn->op1;
+			IR_FOLD_RESTART;
+		}
+	} else if (op1_insn->op == IR_EQ) {
+		if (IR_IS_CONST_REF(op1_insn->op2)
+		 && IR_IS_TYPE_INT(ctx->ir_base[op1_insn->op2].type)
+		 && ctx->ir_base[op1_insn->op2].val.u64 == 0) {
+			op1 = op1_insn->op1;
+			SWAP_REFS(op2, op3);
+			IR_FOLD_RESTART;
+		}
+	}
+
 	IR_FOLD_NEXT;
 }
diff '--color=auto' -Naur php-8.4.18/ext/opcache/jit/ir/ir_gcm.c php-8.4.20RC1/ext/opcache/jit/ir/ir_gcm.c
--- php-8.4.18/ext/opcache/jit/ir/ir_gcm.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/opcache/jit/ir/ir_gcm.c	2026-04-01 04:35:36.009619069 +0000
@@ -262,7 +262,7 @@
 #endif
 
 	/* 1.2. Iteratively check the predecessors of already found TOTALLY_USEFUL blocks and
-	 *      add them into TOTALLY_USEFUL set if all of their sucessors are already there.
+	 *      add them into TOTALLY_USEFUL set if all of their successors are already there.
 	 */
 	IR_SPARSE_SET_FOREACH(&data->totally_useful, i) {
 		_push_predecessors(ctx, &ctx->cfg_blocks[i], data);
@@ -788,7 +788,7 @@
 
 IR_ALWAYS_INLINE bool ir_is_good_bb_order(ir_ctx *ctx, uint32_t b, ir_block *bb, ir_ref start)
 {
-	ir_insn	*insn = &ctx->ir_base[start];
+	ir_insn *insn = &ctx->ir_base[start];
 	uint32_t n = insn->inputs_count;
 	ir_ref *p = insn->ops + 1;
 
@@ -842,6 +842,7 @@
 	xlat = ir_mem_malloc(count * sizeof(uint32_t));
 	ir_worklist_init(&worklist, count);
 	ir_worklist_push(&worklist, 1);
+	/* Schedule blocks bottom-up. Place block only after all its successurs (except back-edges) are placed. */
 	while (ir_worklist_len(&worklist) != 0) {
 next:
 		b = ir_worklist_peek(&worklist);
@@ -849,7 +850,14 @@
 		n = bb->successors_count;
 		if (n == 1) {
 			succ = ctx->cfg_edges[bb->successors];
-			if (ir_worklist_push(&worklist, succ)) {
+			if (ir_bitset_in(worklist.visited, succ)) {
+				/* already processed */
+			} else if ((ctx->cfg_blocks[succ].flags & IR_BB_IRREDUCIBLE_LOOP)
+					&& ((ctx->cfg_blocks[b].flags & IR_BB_LOOP_HEADER) ?
+						(ctx->cfg_blocks[succ].loop_header != b) :
+						(ctx->cfg_blocks[succ].loop_header != ctx->cfg_blocks[b].loop_header))) {
+				/* "side" entry of irreducible loop (ignore) */
+			} else if (ir_worklist_push(&worklist, succ)) {
 				goto next;
 			}
 		} else if (n > 1) {
@@ -862,12 +870,11 @@
 				succ = *q;
 				if (ir_bitset_in(worklist.visited, succ)) {
 					/* already processed */
-				} else if ((ctx->cfg_blocks[succ].flags & IR_BB_LOOP_HEADER)
-				  && (succ == b || ctx->cfg_blocks[b].loop_header == succ)) {
-					/* back-edge of reducible loop */
 				} else if ((ctx->cfg_blocks[succ].flags & IR_BB_IRREDUCIBLE_LOOP)
-				  && (ctx->cfg_blocks[succ].loop_header == ctx->cfg_blocks[b].loop_header)) {
-					/* closing edge of irreducible loop */
+						&& ((ctx->cfg_blocks[b].flags & IR_BB_LOOP_HEADER) ?
+							(ctx->cfg_blocks[succ].loop_header != b) :
+							(ctx->cfg_blocks[succ].loop_header != ctx->cfg_blocks[b].loop_header))) {
+					/* "side" entry of irreducible loop (ignore) */
 				} else if (!best) {
 					best = succ;
 					best_loop_depth = ctx->cfg_blocks[best].loop_depth;
@@ -883,6 +890,8 @@
 				goto next;
 			}
 		}
+
+		/* All successors of "b" are placed. Now we can place "b" itself. */
 		ir_worklist_pop(&worklist);
 		count--;
 		new_blocks[count] = *bb;
@@ -924,25 +933,120 @@
 	ctx->cfg_blocks = new_blocks;
 }
 
+#if IR_DEBUG
+static void ir_schedule_print_list(const ir_ctx *ctx, uint32_t b, const ir_ref *_next,
+                                   ir_ref start, ir_ref end, const char *label)
+{
+	ir_ref ref;
+
+	fprintf(stderr, "  %s [%d", label, start);
+	ref = _next[start];
+	while (ref != end) {
+		fprintf(stderr, ",%d", ref);
+		ref = _next[ref];
+	}
+	fprintf(stderr, ",%d]\n", ref);
+}
+#endif
+
+/* Simple Stable Topological Sort */
+static void ir_schedule_topsort(const ir_ctx *ctx, uint32_t b, const ir_block *bb,
+                                ir_ref *_xlat, ir_ref *_next, ir_ref *_prev,
+                                ir_ref ref, ir_ref end,
+                                ir_ref *insns_count, ir_ref *consts_count)
+{
+	ir_ref i = ref;
+	const ir_insn *insn;
+
+	if (bb->successors_count > 1) {
+		ir_ref input, j = bb->end;
+		ir_insn *end = &ctx->ir_base[j];
+
+		if (end->op == IR_IF) {
+			/* Move condition closer to IF */
+			input = end->op2;
+			if (input > 0
+			 && ctx->cfg_map[input] == b
+			 && !_xlat[input]
+			 && _prev[j] != input
+			 && (!(ir_op_flags[ctx->ir_base[input].op] & IR_OP_FLAG_CONTROL) || end->op1 == input)) {
+				if (input == i) {
+					i = _next[i];
+					insn = &ctx->ir_base[i];
+				}
+				/* remove "input" */
+				_prev[_next[input]] = _prev[input];
+				_next[_prev[input]] = _next[input];
+				/* insert before "j" */
+				_prev[input] = _prev[j];
+				_next[input] = j;
+				_next[_prev[j]] = input;
+				_prev[j] = input;
+			}
+		}
+	}
+
+	while (i != end) {
+		ir_ref n, j, input;
+		const ir_ref *p;
+
+restart:
+		IR_ASSERT(ctx->cfg_map[i] == b);
+		insn = &ctx->ir_base[i];
+		n = insn->inputs_count;
+		for (j = n, p = insn->ops + 1; j > 0; p++, j--) {
+			input = *p;
+			if (!_xlat[input]) {
+				/* input is not scheduled yet */
+				if (input > 0) {
+					if (ctx->cfg_map[input] == b) {
+						/* "input" should be before "i" to satisfy dependency */
+#ifdef IR_DEBUG
+						if (ctx->flags & IR_DEBUG_SCHEDULE) {
+							fprintf(stderr, "Wrong dependency %d:%d -> %d\n", b, input, i);
+						}
+#endif
+						/* remove "input" */
+						_prev[_next[input]] = _prev[input];
+						_next[_prev[input]] = _next[input];
+						/* insert before "i" */
+						_prev[input] = _prev[i];
+						_next[input] = i;
+						_next[_prev[i]] = input;
+						_prev[i] = input;
+						/* restart from "input" */
+						i = input;
+						goto restart;
+					}
+				} else if (input < IR_TRUE) {
+					*consts_count += ir_count_constant(_xlat, input);
+				}
+			}
+		}
+
+		_xlat[i] = *insns_count;
+		*insns_count += ir_insn_inputs_to_len(n);
+		IR_ASSERT(_next[i] != IR_UNUSED);
+		i = _next[i];
+	}
+}
+
 int ir_schedule(ir_ctx *ctx)
 {
-	ir_ctx new_ctx;
 	ir_ref i, j, k, n, *p, *q, ref, new_ref, prev_ref, insns_count, consts_count, use_edges_count;
 	ir_ref *_xlat;
 	ir_ref *edges;
 	ir_ref prev_b_end;
 	uint32_t b;
-	uint32_t *_blocks = ctx->cfg_map;
 	ir_ref *_next = ir_mem_malloc(ctx->insns_count * sizeof(ir_ref));
 	ir_ref *_prev = ir_mem_malloc(ctx->insns_count * sizeof(ir_ref));
 	ir_block *bb;
-	ir_insn *insn, *new_insn;
+	ir_insn *insn, *new_insn, *base;
 	ir_use_list *lists, *use_list, *new_list;
 	bool bad_bb_order = 0;
 
-
 	/* Create a double-linked list of nodes ordered by BB, respecting BB->start and BB->end */
-	IR_ASSERT(_blocks[1] == 1);
+	IR_ASSERT(ctx->cfg_map[1] == 1);
 
 	/* link BB boundaries */
 	_prev[1] = 0;
@@ -950,30 +1054,34 @@
 	_next[1] = prev_b_end;
 	_prev[prev_b_end] = 1;
 	for (b = 2, bb = ctx->cfg_blocks + 2; b <= ctx->cfg_blocks_count; b++, bb++) {
-		_next[prev_b_end] = bb->start;
-		_prev[bb->start] = prev_b_end;
-		_next[bb->start] = bb->end;
-		_prev[bb->end] = bb->start;
-		prev_b_end = bb->end;
-		if (!ir_is_good_bb_order(ctx, b, bb, bb->start)) {
+		ir_ref start = bb->start;
+		ir_ref end = bb->end;
+		_next[prev_b_end] = start;
+		_prev[start] = prev_b_end;
+		_next[start] = end;
+		_prev[end] = start;
+		prev_b_end = end;
+		if (!ir_is_good_bb_order(ctx, b, bb, start)) {
 			bad_bb_order = 1;
 		}
 	}
 	_next[prev_b_end] = 0;
 
 	/* insert intermediate BB nodes */
-	for (i = 2, j = 1; i < ctx->insns_count; i++) {
-		b = _blocks[i];
+	use_edges_count = ctx->use_lists[1].count;
+	for (i = 2, use_list = &ctx->use_lists[i]; i < ctx->insns_count; use_list++, i++) {
+		b = ctx->cfg_map[i];
 		if (!b) continue;
+		use_edges_count += use_list->count;
 		bb = &ctx->cfg_blocks[b];
 		if (i != bb->start && i != bb->end) {
 			/* insert before "end" */
-			ir_ref n = bb->end;
-			ir_ref p = _prev[n];
-			_prev[i] = p;
-			_next[i] = n;
-			_next[p] = i;
-			_prev[n] = i;
+			ir_ref next = bb->end;
+			ir_ref prev = _prev[next];
+			_prev[i] = prev;
+			_next[i] = next;
+			_next[prev] = i;
+			_prev[next] = i;
 		}
 	}
 
@@ -981,15 +1089,6 @@
 		ir_fix_bb_order(ctx, _prev, _next);
 	}
 
-#ifdef IR_DEBUG
-	if (ctx->flags & IR_DEBUG_SCHEDULE) {
-		fprintf(stderr, "Before Schedule\n");
-		for (i = 1; i != 0; i = _next[i]) {
-			fprintf(stderr, "%d -> %d\n", i, _blocks[i]);
-		}
-	}
-#endif
-
 	_xlat = ir_mem_calloc((ctx->consts_count + ctx->insns_count), sizeof(ir_ref));
 	_xlat += ctx->consts_count;
 	_xlat[IR_TRUE] = IR_TRUE;
@@ -999,10 +1098,17 @@
 	insns_count = 1;
 	consts_count = -(IR_TRUE - 1);
 
-	/* Topological sort according dependencies inside each basic block */
+	/* Schedule instructions inside each BB (now just topological sort according to dependencies) */
 	for (b = 1, bb = ctx->cfg_blocks + 1; b <= ctx->cfg_blocks_count; b++, bb++) {
 		ir_ref start;
 
+#ifdef IR_DEBUG
+		if (ctx->flags & IR_DEBUG_SCHEDULE) {
+			fprintf(stderr, "BB%d\n", b);
+			ir_schedule_print_list(ctx, b, _next, bb->start, bb->end, "INITIAL");
+		}
+#endif
+
 		IR_ASSERT(!(bb->flags & IR_BB_UNREACHABLE));
 		/* Schedule BB start */
 		start = i = bb->start;
@@ -1062,8 +1168,8 @@
 				for (p = &ctx->use_edges[use_list->refs]; count > 0; p++, count--) {
 					ir_ref use = *p;
 					ir_insn *use_insn = &ctx->ir_base[use];
-					if (!_xlat[use] && (_blocks[use] || use_insn->op == IR_PARAM)) {
-						IR_ASSERT(_blocks[use] == b || use_insn->op == IR_PARAM);
+					if (!_xlat[use] && ctx->cfg_map[use]) {
+						IR_ASSERT(ctx->cfg_map[use] == b);
 						if (use_insn->op == IR_PARAM
 						 || use_insn->op == IR_VAR
 						 || use_insn->op == IR_PI
@@ -1100,76 +1206,20 @@
 				insn = &ctx->ir_base[i];
 			}
 		}
-		if (bb->successors_count > 1) {
-			ir_ref input, j = bb->end;
-			ir_insn *end = &ctx->ir_base[j];
-
-			if (end->op == IR_IF) {
-				/* Move condition closer to IF */
-				input = end->op2;
-				if (input > 0
-				 && _blocks[input] == b
-				 && !_xlat[input]
-				 && _prev[j] != input
-				 && (!(ir_op_flags[ctx->ir_base[input].op] & IR_OP_FLAG_CONTROL) || end->op1 == input)) {
-					if (input == i) {
-						i = _next[i];
-						insn = &ctx->ir_base[i];
-					}
-					/* remove "input" */
-					_prev[_next[input]] = _prev[input];
-					_next[_prev[input]] = _next[input];
-					/* insert before "j" */
-					_prev[input] = _prev[j];
-					_next[input] = j;
-					_next[_prev[j]] = input;
-					_prev[j] = input;
-				}
-			}
+
+		if (i != bb->end) {
+			ir_schedule_topsort(ctx, b, bb, _xlat, _next, _prev, i, bb->end, &insns_count, &consts_count);
 		}
-		while (i != bb->end) {
-			ir_ref n, j, *p, input;
 
-restart:
-			IR_ASSERT(_blocks[i] == b);
-			n = insn->inputs_count;
-			for (j = n, p = insn->ops + 1; j > 0; p++, j--) {
-				input = *p;
-				if (!_xlat[input]) {
-					/* input is not scheduled yet */
-					if (input > 0) {
-						if (_blocks[input] == b) {
-							/* "input" should be before "i" to satisfy dependency */
 #ifdef IR_DEBUG
-							if (ctx->flags & IR_DEBUG_SCHEDULE) {
-								fprintf(stderr, "Wrong dependency %d:%d -> %d\n", b, input, i);
-							}
-#endif
-							/* remove "input" */
-							_prev[_next[input]] = _prev[input];
-							_next[_prev[input]] = _next[input];
-							/* insert before "i" */
-							_prev[input] = _prev[i];
-							_next[input] = i;
-							_next[_prev[i]] = input;
-							_prev[i] = input;
-							/* restart from "input" */
-							i = input;
-							insn = &ctx->ir_base[i];
-							goto restart;
-						}
-					} else if (input < IR_TRUE) {
-						consts_count += ir_count_constant(_xlat, input);
-					}
-				}
-			}
-			_xlat[i] = insns_count;
-			insns_count += ir_insn_inputs_to_len(n);
-			IR_ASSERT(_next[i] != IR_UNUSED);
-			i = _next[i];
-			insn = &ctx->ir_base[i];
+		if (ctx->flags & IR_DEBUG_SCHEDULE) {
+			ir_schedule_print_list(ctx, b, _next, start, bb->end, "  FINAL");
 		}
+#endif
+
 		/* Schedule BB end */
+		i = bb->end;
+		insn = &ctx->ir_base[i];
 		_xlat[i] = bb->end = insns_count;
 		insns_count++;
 		if (IR_INPUT_EDGES_COUNT(ir_op_flags[insn->op]) == 2) {
@@ -1179,15 +1229,6 @@
 		}
 	}
 
-#ifdef IR_DEBUG
-	if (ctx->flags & IR_DEBUG_SCHEDULE) {
-		fprintf(stderr, "After Schedule\n");
-		for (i = 1; i != 0; i = _next[i]) {
-			fprintf(stderr, "%d -> %d (%d)\n", i, _blocks[i], _xlat[i]);
-		}
-	}
-#endif
-
 #if 1
 	/* Check if scheduling didn't make any modifications */
 	if (consts_count == ctx->consts_count && insns_count == ctx->insns_count) {
@@ -1215,113 +1256,55 @@
 
 	ir_mem_free(_prev);
 
-	ir_init(&new_ctx, ctx->flags, consts_count, insns_count);
-	new_ctx.insns_count = insns_count;
-	new_ctx.flags2 = ctx->flags2;
-	new_ctx.ret_type = ctx->ret_type;
-	new_ctx.value_params = ctx->value_params;
-	new_ctx.mflags = ctx->mflags;
-	new_ctx.spill_base = ctx->spill_base;
-	new_ctx.fixed_stack_red_zone = ctx->fixed_stack_red_zone;
-	new_ctx.fixed_stack_frame_size = ctx->fixed_stack_frame_size;
-	new_ctx.fixed_call_stack_size = ctx->fixed_call_stack_size;
-	new_ctx.fixed_regset = ctx->fixed_regset;
-	new_ctx.fixed_save_regset = ctx->fixed_save_regset;
-	new_ctx.entries_count = ctx->entries_count;
-#if defined(IR_TARGET_AARCH64)
-	new_ctx.deoptimization_exits = ctx->deoptimization_exits;
-	new_ctx.get_exit_addr = ctx->get_exit_addr;
-	new_ctx.get_veneer = ctx->get_veneer;
-	new_ctx.set_veneer = ctx->set_veneer;
-#endif
-	new_ctx.loader = ctx->loader;
+	uint32_t *map = ir_mem_calloc(insns_count, sizeof(uint32_t));
+	_prev = ir_mem_malloc(insns_count * sizeof(ir_ref));
+	lists = ir_mem_malloc(insns_count * sizeof(ir_use_list));
+	ir_ref *use_edges = edges = ir_mem_malloc(use_edges_count * sizeof(ir_ref));
+	base = ir_mem_malloc((consts_count + insns_count) * sizeof(ir_insn));
+	base += consts_count;
 
 	/* Copy constants */
-	if (consts_count == ctx->consts_count) {
-		new_ctx.consts_count = consts_count;
-		ref = 1 - consts_count;
-		insn = &ctx->ir_base[ref];
-		new_insn = &new_ctx.ir_base[ref];
-
-		memcpy(new_insn, insn, sizeof(ir_insn) * (IR_TRUE - ref));
-		if (ctx->strtab.data) {
-			while (ref != IR_TRUE) {
-				if (new_insn->op == IR_FUNC_ADDR) {
-					if (new_insn->proto) {
-						size_t len;
-						const char *proto = ir_get_strl(ctx, new_insn->proto, &len);
-						new_insn->proto = ir_strl(&new_ctx, proto, len);
-					}
-				} else if (new_insn->op == IR_FUNC) {
-					size_t len;
-					const char *name = ir_get_strl(ctx, new_insn->val.name, &len);
-					new_insn->val.u64 = ir_strl(&new_ctx, name, len);
-					if (new_insn->proto) {
-						const char *proto = ir_get_strl(ctx, new_insn->proto, &len);
-						new_insn->proto = ir_strl(&new_ctx, proto, len);
-					}
-				} else if (new_insn->op == IR_SYM || new_insn->op == IR_STR || new_insn->op == IR_LABEL) {
-					size_t len;
-					const char *str = ir_get_strl(ctx, new_insn->val.name, &len);
-					new_insn->val.u64 = ir_strl(&new_ctx, str, len);
-				}
-				new_insn++;
-				ref++;
-			}
+	if (ctx->consts_count == consts_count) {
+		memcpy(base - consts_count + 1, ctx->ir_base - consts_count + 1, sizeof(ir_insn) * consts_count);
+		for (j = -consts_count + 1; j < IR_TRUE; j++) {
+			_xlat[j] = j;
 		}
 	} else {
-		new_ref = -new_ctx.consts_count;
-		new_insn = &new_ctx.ir_base[new_ref];
-		for (ref = IR_TRUE - 1, insn = &ctx->ir_base[ref]; ref > -ctx->consts_count; insn--, ref--) {
-			if (!_xlat[ref]) {
-				continue;
-			}
-			new_insn->optx = insn->optx;
-			new_insn->prev_const = 0;
-			if (insn->op == IR_FUNC_ADDR) {
-				new_insn->val.u64 = insn->val.u64;
-				if (insn->proto) {
-					size_t len;
-					const char *proto = ir_get_strl(ctx, insn->proto, &len);
-					new_insn->proto = ir_strl(&new_ctx, proto, len);
-				} else {
-					new_insn->proto = 0;
-				}
-			} else if (insn->op == IR_FUNC) {
-				size_t len;
-				const char *name = ir_get_strl(ctx, insn->val.name, &len);
-				new_insn->val.u64 = ir_strl(&new_ctx, name, len);
-				if (insn->proto) {
-					const char *proto = ir_get_strl(ctx, insn->proto, &len);
-					new_insn->proto = ir_strl(&new_ctx, proto, len);
-				} else {
-					new_insn->proto = 0;
-				}
-			} else if (insn->op == IR_SYM || insn->op == IR_STR || insn->op == IR_LABEL) {
-				size_t len;
-				const char *str = ir_get_strl(ctx, insn->val.name, &len);
-				new_insn->val.u64 = ir_strl(&new_ctx, str, len);
-			} else {
-				new_insn->val.u64 = insn->val.u64;
-			}
-			_xlat[ref] = new_ref;
-			new_ref--;
-			new_insn--;
-		}
-		new_ctx.consts_count = -new_ref;
-	}
+		ir_insn *src = ctx->ir_base - ctx->consts_count + 1;
+		ir_insn *dst = base - consts_count + 1;
 
-	new_ctx.cfg_map = ir_mem_calloc(ctx->insns_count, sizeof(uint32_t));
-	new_ctx.prev_ref = _prev = ir_mem_malloc(insns_count * sizeof(ir_ref));
-	new_ctx.use_lists = lists = ir_mem_malloc(insns_count * sizeof(ir_use_list));
-	new_ctx.use_edges = edges = ir_mem_malloc(ctx->use_edges_count * sizeof(ir_ref));
+		i = -ctx->consts_count + 1;
+		j = -consts_count + 1;
+		while (i < IR_TRUE) {
+			if (_xlat[i]) {
+				*dst = *src;
+				dst->prev_const = 0;
+				_xlat[i] = j;
+				dst++;
+				j++;
+			}
+			src++;
+			i++;
+		}
+		IR_ASSERT(j == IR_TRUE);
+		base[IR_TRUE].optx = IR_OPT(IR_C_BOOL, IR_BOOL);
+		base[IR_TRUE].val.u64 = 1;
+		base[IR_FALSE].optx = IR_OPT(IR_C_BOOL, IR_BOOL);
+		base[IR_FALSE].val.u64 = 0;
+		base[IR_NULL].optx = IR_OPT(IR_C_ADDR, IR_ADDR);
+		base[IR_NULL].val.u64 = 0;
+		MAKE_NOP(&base[IR_UNUSED]);
+	}
 
 	/* Copy instructions, use lists and use edges */
+#ifdef IR_DEBUG
+	ir_ref orig_use_edges_count = use_edges_count;
+#endif
 	prev_ref = 0;
 	use_edges_count = 0;
 	for (i = 1; i != 0; i = _next[i]) {
 		new_ref = _xlat[i];
-		new_ctx.cfg_map[new_ref] = _blocks[i];
+		map[new_ref] = ctx->cfg_map[i];
 		_prev[new_ref] = prev_ref;
 		prev_ref = new_ref;
 
@@ -1330,7 +1313,7 @@
 		k = 0;
 		if (n == 1) {
 			ref = ctx->use_edges[use_list->refs];
-			if (_xlat[ref]) {
+			if (EXPECTED(_xlat[ref])) {
 				*edges = _xlat[ref];
 				edges++;
 				k = 1;
@@ -1339,7 +1322,7 @@
 			p = &ctx->use_edges[use_list->refs];
 			while (n--) {
 				ref = *p;
-				if (_xlat[ref]) {
+				if (EXPECTED(_xlat[ref])) {
 					*edges = _xlat[ref];
 					edges++;
 					k++;
@@ -1353,7 +1336,7 @@
 		new_list->count = k;
 
 		insn = &ctx->ir_base[i];
-		new_insn = &new_ctx.ir_base[new_ref];
+		new_insn = &base[new_ref];
 
 		new_insn->optx = insn->optx;
 		n = new_insn->inputs_count;
@@ -1365,11 +1348,7 @@
 				break;
 			case 1:
 				new_insn->op1 = _xlat[insn->op1];
-				if (new_insn->op == IR_PARAM || new_insn->op == IR_VAR || new_insn->op == IR_PROTO) {
-					size_t len;
-					const char *str = ir_get_strl(ctx, insn->op2, &len);
-					new_insn->op2 = ir_strl(&new_ctx, str, len);
-				} else if (new_insn->op == IR_BEGIN && insn->op2) {
+				if (new_insn->op == IR_BEGIN && insn->op2) {
 					new_insn->op2 = _xlat[insn->op2];
 				} else {
 					new_insn->op2 = insn->op2;
@@ -1428,12 +1407,12 @@
 	}
 
 	/* Update list of terminators (IR_OPND_CONTROL_REF) */
-	insn = &new_ctx.ir_base[1];
+	insn = &base[1];
 	ref = insn->op1;
 	if (ref) {
 		insn->op1 = ref = _xlat[ref];
 		while (1) {
-			insn = &new_ctx.ir_base[ref];
+			insn = &base[ref];
 			ref = insn->op3;
 			if (!ref) {
 				break;
@@ -1442,36 +1421,33 @@
 		}
 	}
 
-	IR_ASSERT(ctx->use_edges_count >= use_edges_count);
-	new_ctx.use_edges_count = use_edges_count;
-	new_ctx.use_edges = ir_mem_realloc(new_ctx.use_edges, use_edges_count * sizeof(ir_ref));
-
 	if (ctx->binding) {
 		ir_xlat_binding(ctx, _xlat);
-		new_ctx.binding = ctx->binding;
-		ctx->binding = NULL;
 	}
 
 	_xlat -= ctx->consts_count;
 	ir_mem_free(_xlat);
+	ir_mem_free(_next);
 
-	new_ctx.cfg_blocks_count = ctx->cfg_blocks_count;
-	new_ctx.cfg_edges_count = ctx->cfg_edges_count;
-	new_ctx.cfg_blocks = ctx->cfg_blocks;
-	new_ctx.cfg_edges = ctx->cfg_edges;
-	ctx->cfg_blocks = NULL;
-	ctx->cfg_edges = NULL;
-	ctx->value_params = NULL;
-	ir_code_buffer *saved_code_buffer = ctx->code_buffer;
-
-	ir_free(ctx);
-	IR_ASSERT(new_ctx.consts_count == new_ctx.consts_limit);
-	IR_ASSERT(new_ctx.insns_count == new_ctx.insns_limit);
-	memcpy(ctx, &new_ctx, sizeof(ir_ctx));
-	ctx->code_buffer = saved_code_buffer;
-	ctx->flags2 |= IR_LINEAR;
+	/* Switch to new IR buffer */
+	ir_mem_free(ctx->ir_base - ctx->consts_limit);
+	ctx->ir_base = base;
+	ctx->insns_count = ctx->insns_limit = insns_count;
+	ctx->consts_count = ctx->consts_limit = consts_count;
+
+	ir_mem_free(ctx->use_lists);
+	ir_mem_free(ctx->use_edges);
+	IR_ASSERT(orig_use_edges_count >= use_edges_count);
+	ctx->use_lists = lists;
+	ctx->use_edges = use_edges;
+	ctx->use_edges_count = use_edges_count;
 
-	ir_mem_free(_next);
+	ir_mem_free(ctx->cfg_map);
+	ctx->cfg_map = map;
+
+	ctx->prev_ref = _prev;
+
+	ctx->flags2 |= IR_LINEAR;
 
 	return 1;
 }
diff '--color=auto' -Naur php-8.4.18/ext/opcache/jit/ir/ir_gdb.c php-8.4.20RC1/ext/opcache/jit/ir/ir_gdb.c
--- php-8.4.18/ext/opcache/jit/ir/ir_gdb.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/opcache/jit/ir/ir_gdb.c	2026-04-01 04:35:36.009855365 +0000
@@ -7,6 +7,10 @@
  * Based on Mike Pall's implementation of GDB interface for LuaJIT.
  */
 
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE
+#endif
+
 #include <stddef.h>
 #include <stdlib.h>
 #include <unistd.h>
@@ -517,6 +521,8 @@
 static bool ir_gdb_register_code(const void *object, size_t size)
 {
 	ir_gdbjit_code_entry *entry;
+	ir_elf_header *elf_header;
+	ir_elf_sectheader *elf_section, *elf_section_end;
 
 	entry = malloc(sizeof(ir_gdbjit_code_entry) + size);
 	if (entry == NULL) {
@@ -528,6 +534,17 @@
 
 	memcpy((char *)entry->symfile_addr, object, size);
 
+	elf_header = (ir_elf_header*)entry->symfile_addr;
+	elf_section = (ir_elf_sectheader*)(entry->symfile_addr + elf_header->shofs);
+	elf_section_end = (ir_elf_sectheader*)((char*)elf_section + (elf_header->shentsize * elf_header->shnum));
+
+	while (elf_section < elf_section_end) {
+		if ((elf_section->flags & ELFSECT_FLAGS_ALLOC) && elf_section->addr == 0) {
+			elf_section->addr = (uintptr_t)(entry->symfile_addr + elf_section->ofs);
+		}
+		elf_section = (ir_elf_sectheader*)((char*)elf_section + elf_header->shentsize);
+	}
+
 	entry->prev_entry = NULL;
 	entry->next_entry = __jit_debug_descriptor.first_entry;
 
diff '--color=auto' -Naur php-8.4.18/ext/opcache/jit/ir/ir.h php-8.4.20RC1/ext/opcache/jit/ir/ir.h
--- php-8.4.18/ext/opcache/jit/ir/ir.h	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/opcache/jit/ir/ir.h	2026-04-01 04:35:36.008176533 +0000
@@ -569,8 +569,6 @@
 #define IR_OPT_CFG             (1<<21) /* merge BBs, by remove END->BEGIN nodes during CFG construction */
 #define IR_OPT_MEM2SSA         (1<<22)
 #define IR_OPT_CODEGEN         (1<<23)
-#define IR_GEN_NATIVE          (1<<24)
-#define IR_GEN_CODE            (1<<25)
 
 /* debug related */
 #ifdef IR_DEBUG
@@ -771,7 +769,7 @@
 
 ir_ref ir_emit_N(ir_ctx *ctx, uint32_t opt, int32_t count);
 void   ir_set_op(ir_ctx *ctx, ir_ref ref, int32_t n, ir_ref val);
-ir_ref ir_get_op(ir_ctx *ctx, ir_ref ref, int32_t n);
+ir_ref ir_get_op(const ir_ctx *ctx, ir_ref ref, int32_t n);
 
 IR_ALWAYS_INLINE void ir_set_op1(ir_ctx *ctx, ir_ref ref, ir_ref val)
 {
@@ -865,13 +863,13 @@
 int ir_regs_number(void);
 bool ir_reg_is_int(int32_t reg);
 const char *ir_reg_name(int8_t reg, ir_type type);
-int32_t ir_get_spill_slot_offset(ir_ctx *ctx, ir_ref ref);
+int32_t ir_get_spill_slot_offset(const ir_ctx *ctx, ir_ref ref);
 
 /* Target CPU instruction selection and code generation (see ir_x86.c) */
 int ir_match(ir_ctx *ctx);
 void *ir_emit_code(ir_ctx *ctx, size_t *size);
 
-bool ir_needs_thunk(ir_code_buffer *code_buffer, void *addr);
+bool ir_needs_thunk(const ir_code_buffer *code_buffer, void *addr);
 void *ir_emit_thunk(ir_code_buffer *code_buffer, void *addr, size_t *size_ptr);
 void ir_fix_thunk(void *thunk_entry, void *addr);
 
@@ -947,13 +945,14 @@
 #define IR_SAVE_REGS       (1<<4) /* add info about selected registers */
 #define IR_SAVE_SAFE_NAMES (1<<5) /* add '@' prefix to symbol names */
 
+void ir_print_func_proto(const ir_ctx *ctx, const char *name, bool prefix, FILE *f);
 void ir_print_proto(const ir_ctx *ctx, ir_ref proto, FILE *f);
 void ir_print_proto_ex(uint8_t flags, ir_type ret_type, uint32_t params_count, const uint8_t *param_types, FILE *f);
 void ir_save(const ir_ctx *ctx, uint32_t save_flags, FILE *f);
 
 /* IR debug dump API (implementation in ir_dump.c) */
 void ir_dump(const ir_ctx *ctx, FILE *f);
-void ir_dump_dot(const ir_ctx *ctx, const char *name, FILE *f);
+void ir_dump_dot(const ir_ctx *ctx, const char *name, const char *comments, FILE *f);
 void ir_dump_use_lists(const ir_ctx *ctx, FILE *f);
 void ir_dump_cfg(ir_ctx *ctx, FILE *f);
 void ir_dump_cfg_map(const ir_ctx *ctx, FILE *f);
diff '--color=auto' -Naur php-8.4.18/ext/opcache/jit/ir/ir_perf.c php-8.4.20RC1/ext/opcache/jit/ir/ir_perf.c
--- php-8.4.18/ext/opcache/jit/ir/ir_perf.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/opcache/jit/ir/ir_perf.c	2026-04-01 04:35:36.009948752 +0000
@@ -14,6 +14,10 @@
  * perf report -i perf.data.jitted
  */
 
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE
+#endif
+
 #include <stdio.h>
 #include <unistd.h>
 #include <time.h>
@@ -26,7 +30,7 @@
 
 #if defined(__linux__)
 #include <sys/syscall.h>
-#elif defined(__darwin__)
+#elif defined(__APPLE__)
 # include <pthread.h>
 #elif defined(__FreeBSD__)
 # include <sys/thr.h>
@@ -211,7 +215,7 @@
 		uint32_t thread_id = 0;
 #if defined(__linux__)
 		thread_id = syscall(SYS_gettid);
-#elif defined(__darwin__)
+#elif defined(__APPLE__)
 		uint64_t thread_id_u64;
 		pthread_threadid_np(NULL, &thread_id_u64);
 		thread_id = (uint32_t) thread_id_u64;
diff '--color=auto' -Naur php-8.4.18/ext/opcache/jit/ir/ir_private.h php-8.4.20RC1/ext/opcache/jit/ir/ir_private.h
--- php-8.4.18/ext/opcache/jit/ir/ir_private.h	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/opcache/jit/ir/ir_private.h	2026-04-01 04:35:36.010041096 +0000
@@ -908,7 +908,7 @@
 	return 0;
 }
 
-IR_ALWAYS_INLINE bool ir_ref_is_true(ir_ctx *ctx, ir_ref ref)
+IR_ALWAYS_INLINE bool ir_ref_is_true(const ir_ctx *ctx, ir_ref ref)
 {
 	if (ref == IR_TRUE) {
 		return 1;
@@ -1096,6 +1096,7 @@
 void ir_update_op(ir_ctx *ctx, ir_ref ref, uint32_t idx, ir_ref new_val);
 
 /*** Iterative Optimization ***/
+void ir_iter_add_uses(ir_ctx *ctx, ir_ref ref, ir_bitqueue *worklist);
 void ir_iter_replace(ir_ctx *ctx, ir_ref ref, ir_ref new_ref, ir_bitqueue *worklist);
 void ir_iter_update_op(ir_ctx *ctx, ir_ref ref, uint32_t idx, ir_ref new_val, ir_bitqueue *worklist);
 void ir_iter_opt(ir_ctx *ctx, ir_bitqueue *worklist);
@@ -1144,12 +1145,15 @@
 	};
 	union {
 		uint32_t dom_depth;      /* depth from the root of the dominators tree */
-		uint32_t postnum;        /* used temporary during tree constructon     */
+		uint32_t postnum;        /* used temporary for iterative Post Ordering */
 	};
 	uint32_t     dom_child;      /* first dominated blocks                     */
 	uint32_t     dom_next_child; /* next dominated block (linked list)         */
 	uint32_t     loop_header;
-	uint32_t     loop_depth;
+	union {
+		uint32_t loop_depth;
+		uint32_t next_succ;      /* used temporary for iterative Post Ordering */
+	};
 };
 
 void ir_build_prev_refs(ir_ctx *ctx);
@@ -1179,16 +1183,17 @@
 	IR_FOLD_DO_CONST
 } ir_fold_action;
 
-ir_ref ir_folding(ir_ctx *ctx, uint32_t opt, ir_ref op1, ir_ref op2, ir_ref op3, ir_insn *op1_insn, ir_insn *op2_insn, ir_insn *op3_insn);
+ir_ref ir_folding(ir_ctx *ctx, uint32_t opt, ir_ref op1, ir_ref op2, ir_ref op3,
+                  const ir_insn *op1_insn, const ir_insn *op2_insn, const ir_insn *op3_insn);
 
 /*** Alias Analyzes (see ir.c) ***/
-ir_ref ir_find_aliasing_load(ir_ctx *ctx, ir_ref ref, ir_type type, ir_ref addr);
-ir_ref ir_find_aliasing_vload(ir_ctx *ctx, ir_ref ref, ir_type type, ir_ref var);
+ir_ref ir_find_aliasing_load(const ir_ctx *ctx, ir_ref ref, ir_type type, ir_ref addr);
+ir_ref ir_find_aliasing_vload(const ir_ctx *ctx, ir_ref ref, ir_type type, ir_ref var);
 ir_ref ir_find_aliasing_store(ir_ctx *ctx, ir_ref ref, ir_ref addr, ir_ref val);
 ir_ref ir_find_aliasing_vstore(ir_ctx *ctx, ir_ref ref, ir_ref addr, ir_ref val);
 
 /*** Predicates (see ir.c) ***/
-ir_ref ir_check_dominating_predicates(ir_ctx *ctx, ir_ref ref, ir_ref condition);
+ir_ref ir_check_dominating_predicates(const ir_ctx *ctx, ir_ref ref, ir_ref condition);
 
 /*** IR Live Info ***/
 typedef ir_ref                   ir_live_pos;
@@ -1468,9 +1473,7 @@
 void ir_fix_stack_frame(ir_ctx *ctx);
 
 /* Utility */
-ir_type ir_get_return_type(ir_ctx *ctx);
 const ir_proto_t *ir_call_proto(const ir_ctx *ctx, const ir_insn *insn);
-void ir_print_call_conv(uint32_t flags, FILE *f);
 
 //#define IR_BITSET_LIVENESS
 
diff '--color=auto' -Naur php-8.4.18/ext/opcache/jit/ir/ir_ra.c php-8.4.20RC1/ext/opcache/jit/ir/ir_ra.c
--- php-8.4.18/ext/opcache/jit/ir/ir_ra.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/opcache/jit/ir/ir_ra.c	2026-04-01 04:35:36.010241264 +0000
@@ -3761,14 +3761,13 @@
 {
 	char key[10];
 
-	IR_ASSERT(reg != IR_REG_NONE);
 	if (!ctx->fused_regs) {
 		ctx->fused_regs = ir_mem_malloc(sizeof(ir_strtab));
 		ir_strtab_init(ctx->fused_regs, 8, 128);
 	}
 	memcpy(key, &root, sizeof(ir_ref));
 	memcpy(key + 4, &ref_and_op, sizeof(ir_ref));
-	ir_strtab_lookup(ctx->fused_regs, key, 8, 0x10000000 | reg);
+	ir_strtab_lookup(ctx->fused_regs, key, 8, 0x10000000 | (uint8_t)reg);
 }
 
 static void assign_regs(ir_ctx *ctx)
@@ -3874,93 +3873,88 @@
 										}
 										prev_use_ref = ref;
 									}
-								} else if ((!prev_use_ref || ctx->cfg_map[prev_use_ref] != ctx->cfg_map[ref])
-								 && needs_spill_reload(ctx, ival, ctx->cfg_map[ref], available)) {
-									if (!(use_pos->flags & IR_USE_MUST_BE_IN_REG)
-									 && use_pos->hint != reg
-//									 && ctx->ir_base[ref].op != IR_CALL
-//									 && ctx->ir_base[ref].op != IR_TAILCALL) {
-									 && ctx->ir_base[ref].op != IR_SNAPSHOT
-									 && !needs_spill_load(ctx, ival, use_pos)) {
-										/* fuse spill load (valid only when register is not reused) */
-										reg = IR_REG_NONE;
-										if (use_pos->next
-										 && use_pos->op_num == 1
-										 && use_pos->next->pos == use_pos->pos
-										 && !(use_pos->next->flags & IR_USE_MUST_BE_IN_REG)) {
-											/* Support for R2 = BINOP(R1, R1) */
-											if (use_pos->hint_ref < 0) {
-												ref = -use_pos->hint_ref;
+								} else {
+									if ((!prev_use_ref || ctx->cfg_map[prev_use_ref] != ctx->cfg_map[ref])
+									 && needs_spill_reload(ctx, ival, ctx->cfg_map[ref], available)) {
+										if (!(use_pos->flags & IR_USE_MUST_BE_IN_REG)
+										 && use_pos->hint != reg
+//										 && ctx->ir_base[ref].op != IR_CALL
+//										 && ctx->ir_base[ref].op != IR_TAILCALL) {
+										 && ctx->ir_base[ref].op != IR_SNAPSHOT
+										 && !needs_spill_load(ctx, ival, use_pos)) {
+											/* fuse spill load (valid only when register is not reused) */
+											reg = IR_REG_NONE;
+											if (use_pos->next
+											 && use_pos->op_num == 1
+											 && use_pos->next->pos == use_pos->pos
+											 && !(use_pos->next->flags & IR_USE_MUST_BE_IN_REG)) {
+												/* Support for R2 = BINOP(R1, R1) */
+												if (use_pos->hint_ref < 0) {
+													ref = -use_pos->hint_ref;
+												}
+												ir_set_alocated_reg(ctx, ref, use_pos->op_num, reg);
+												use_pos = use_pos->next;
 											}
-											ir_set_alocated_reg(ctx, ref, use_pos->op_num, reg);
-											use_pos = use_pos->next;
-										}
-									} else {
-										if (top_ival->flags & IR_LIVE_INTERVAL_SPILL_SPECIAL) {
-											reg |= IR_REG_SPILL_SPECIAL;
 										} else {
-											reg |= IR_REG_SPILL_LOAD;
-										}
-										if (ctx->ir_base[ref].op != IR_SNAPSHOT && !(use_pos->flags & IR_PHI_USE)) {
-											uint32_t use_b = ctx->cfg_map[ref];
+											if (top_ival->flags & IR_LIVE_INTERVAL_SPILL_SPECIAL) {
+												reg |= IR_REG_SPILL_SPECIAL;
+											} else {
+												reg |= IR_REG_SPILL_LOAD;
+											}
+											if (ctx->ir_base[ref].op != IR_SNAPSHOT && !(use_pos->flags & IR_PHI_USE)) {
+												uint32_t use_b = ctx->cfg_map[ref];
 
-											if (ir_ival_covers(ival, IR_SAVE_LIVE_POS_FROM_REF(ctx->cfg_blocks[use_b].end))) {
-												ir_bitset_incl(available, use_b);
+												if (ir_ival_covers(ival, IR_SAVE_LIVE_POS_FROM_REF(ctx->cfg_blocks[use_b].end))) {
+													ir_bitset_incl(available, use_b);
+												}
+												prev_use_ref = ref;
 											}
-											prev_use_ref = ref;
 										}
+									} else {
+										/* reuse register without spill load */
 									}
-									if (use_pos->hint_ref < 0
-									 && (old_reg = ir_get_alocated_reg(ctx, -use_pos->hint_ref, use_pos->op_num)) != IR_REG_NONE) {
-										if (top_ival->flags & IR_LIVE_INTERVAL_SPILL_SPECIAL) {
-											reg |= IR_REG_SPILL_SPECIAL;
+
+									if (use_pos->hint_ref < 0) {
+										if (use_pos->flags & IR_PHI_USE) {
+											IR_ASSERT(use_pos->hint_ref < 0);
+											IR_ASSERT(ctx->vregs[-use_pos->hint_ref]);
+											IR_ASSERT(ctx->live_intervals[ctx->vregs[-use_pos->hint_ref]]);
+											if (ctx->live_intervals[ctx->vregs[-use_pos->hint_ref]]->flags & IR_LIVE_INTERVAL_SPILLED) {
+												/* Spilled PHI var is passed through memory */
+												reg = IR_REG_NONE;
+											}
 										} else {
-											reg |= IR_REG_SPILL_LOAD;
-										}
-										if (reg != old_reg) {
 											IR_ASSERT(ctx->rules[-use_pos->hint_ref] & IR_FUSED);
-											ctx->rules[-use_pos->hint_ref] |= IR_FUSED_REG;
-											ir_set_fused_reg(ctx, ref, -use_pos->hint_ref * sizeof(ir_ref) + use_pos->op_num, reg);
-											use_pos = use_pos->next;
-											continue;
+											old_reg = ir_get_alocated_reg(ctx, -use_pos->hint_ref, use_pos->op_num);
+											if ((old_reg != IR_REG_NONE && reg != old_reg) || reg == IR_REG_NONE) {
+												ctx->rules[-use_pos->hint_ref] |= IR_FUSED_REG;
+												ir_set_fused_reg(ctx, ref, -use_pos->hint_ref * sizeof(ir_ref) + use_pos->op_num, reg);
+												use_pos = use_pos->next;
+												continue;
+											}
 										}
+										ref = -use_pos->hint_ref;
 									}
-								} else if (use_pos->flags & IR_PHI_USE) {
-									IR_ASSERT(use_pos->hint_ref < 0);
-									IR_ASSERT(ctx->vregs[-use_pos->hint_ref]);
-									IR_ASSERT(ctx->live_intervals[ctx->vregs[-use_pos->hint_ref]]);
-									if (ctx->live_intervals[ctx->vregs[-use_pos->hint_ref]]->flags & IR_LIVE_INTERVAL_SPILLED) {
-										/* Spilled PHI var is passed through memory */
-										reg = IR_REG_NONE;
-									}
-								} else if (use_pos->hint_ref < 0
-										&& (old_reg = ir_get_alocated_reg(ctx, -use_pos->hint_ref, use_pos->op_num)) != IR_REG_NONE) {
-									if (reg != old_reg) {
-										IR_ASSERT(ctx->rules[-use_pos->hint_ref] & IR_FUSED);
-										ctx->rules[-use_pos->hint_ref] |= IR_FUSED_REG;
-										ir_set_fused_reg(ctx, ref, -use_pos->hint_ref * sizeof(ir_ref) + use_pos->op_num, reg);
-										use_pos = use_pos->next;
-										continue;
-									}
-								} else {
-									/* reuse register without spill load */
-								}
-								if (use_pos->hint_ref < 0) {
-									ref = -use_pos->hint_ref;
 								}
+
 								ir_set_alocated_reg(ctx, ref, use_pos->op_num, reg);
 
 								use_pos = use_pos->next;
 							}
-						} else if (!(top_ival->flags & IR_LIVE_INTERVAL_SPILL_SPECIAL)) {
+						} else {
 							use_pos = ival->use_pos;
 							while (use_pos) {
 								ref = IR_LIVE_POS_TO_REF(use_pos->pos);
-								if (ctx->ir_base[ref].op == IR_SNAPSHOT) {
+								if (ctx->ir_base[ref].op == IR_SNAPSHOT
+								 && !(top_ival->flags & IR_LIVE_INTERVAL_SPILL_SPECIAL)) {
 									IR_ASSERT(use_pos->hint_ref >= 0);
 									/* A reference to a CPU spill slot */
 									reg = IR_REG_SPILL_STORE | IR_REG_STACK_POINTER;
 									ir_set_alocated_reg(ctx, ref, use_pos->op_num, reg);
+								} else if (use_pos->hint_ref < 0 && !(use_pos->flags & IR_PHI_USE)) {
+									IR_ASSERT(ctx->rules[-use_pos->hint_ref] & IR_FUSED);
+									ctx->rules[-use_pos->hint_ref] |= IR_FUSED_REG;
+									ir_set_fused_reg(ctx, ref, -use_pos->hint_ref * sizeof(ir_ref) + use_pos->op_num, IR_REG_NONE);
 								}
 								use_pos = use_pos->next;
 							}
diff '--color=auto' -Naur php-8.4.18/ext/opcache/jit/ir/ir_save.c php-8.4.20RC1/ext/opcache/jit/ir/ir_save.c
--- php-8.4.18/ext/opcache/jit/ir/ir_save.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/opcache/jit/ir/ir_save.c	2026-04-01 04:35:36.010501847 +0000
@@ -18,7 +18,7 @@
 	}
 }
 
-void ir_print_call_conv(uint32_t flags, FILE *f)
+static void ir_print_call_conv(uint32_t flags, FILE *f)
 {
 	switch (flags & IR_CALL_CONV_MASK) {
 		case IR_CC_BUILTIN:
@@ -74,6 +74,38 @@
 		fprintf(f, " __pure");
 	}
 }
+
+void ir_print_func_proto(const ir_ctx *ctx, const char *name, bool prefix, FILE *f)
+{
+	if (ctx->flags & IR_STATIC) {
+		fprintf(f, "static ");
+	}
+	fprintf(f, "func %s%s(",
+		prefix ? "@" : "",
+		name);
+	if (ctx->ir_base[2].op == IR_PARAM) {
+		ir_insn *insn = &ctx->ir_base[2];
+
+		fprintf(f, "%s", ir_type_cname[insn->type]);
+		insn++;
+		while (insn->op == IR_PARAM) {
+			fprintf(f, ", %s", ir_type_cname[insn->type]);
+			insn++;;
+		}
+		if (ctx->flags & IR_VARARG_FUNC) {
+			fprintf(f, ", ...");
+		}
+	} else if (ctx->flags & IR_VARARG_FUNC) {
+		fprintf(f, "...");
+	}
+	fprintf(f, "): %s", ir_type_cname[ctx->ret_type != (ir_type)-1 ? ctx->ret_type : IR_VOID]);
+	ir_print_call_conv(ctx->flags, f);
+	if (ctx->flags & IR_CONST_FUNC) {
+		fprintf(f, " __const");
+	} else if (ctx->flags & IR_PURE_FUNC) {
+		fprintf(f, " __pure");
+	}
+}
 
 static void ir_save_dessa_moves(const ir_ctx *ctx, int b, ir_block *bb, FILE *f)
 {
diff '--color=auto' -Naur php-8.4.18/ext/opcache/jit/ir/ir_sccp.c php-8.4.20RC1/ext/opcache/jit/ir/ir_sccp.c
--- php-8.4.18/ext/opcache/jit/ir/ir_sccp.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/opcache/jit/ir/ir_sccp.c	2026-04-01 04:35:36.010678971 +0000
@@ -19,7 +19,6 @@
 #define IR_TOP                  IR_UNUSED
 #define IR_BOTTOM               IR_LAST_OP
 
-#define IR_MAKE_TOP(ref)        do {IR_ASSERT(ref > 0); _values[ref].optx = IR_TOP;} while (0)
 #define IR_MAKE_BOTTOM(ref)     do {IR_ASSERT(ref > 0); _values[ref].optx = IR_BOTTOM;} while (0)
 
 #define IR_IS_TOP(ref)          (ref >= 0 && _values[ref].op == IR_TOP)
@@ -27,17 +26,57 @@
 #define IR_IS_REACHABLE(ref)    _ir_is_reachable_ctrl(ctx, _values, ref)
 #define IR_IS_CONST(ref)        (IR_IS_CONST_REF(ref) || IR_IS_CONST_OP(_values[ref].op))
 
-IR_ALWAYS_INLINE bool _ir_is_reachable_ctrl(ir_ctx *ctx, ir_insn *_values, ir_ref ref)
+typedef struct {
+	union {
+		struct {
+			IR_STRUCT_LOHI(
+				union {
+					IR_STRUCT_LOHI(
+						union {
+							IR_STRUCT_LOHI(
+								uint8_t        op,   /* [IR_TOP - unreachable, IR_BOTTOM - reachable} for control */
+								                     /* {IR_TOP | IR_COPY() | IR_CONST() | IR_BOTTOM} for data */
+								                     /* {IR_TOP | IR_MERGE() | IR_BOTTOM} for IR_MERGE */
+								                     /* {IR_TOP | IR_IF() | IR_BOTTOM} for IR_IF and IR_SWITCH */
+								uint8_t        type
+							);
+							uint16_t           opt;
+						},
+						uint16_t               _space_1
+					);
+					uint32_t                   optx;
+				},
+				union {
+					ir_ref                     copy;              /* identity for IR_COPY */
+					ir_ref                     unfeasible_inputs; /* number of unfeasible inputs for IR_MERGE */
+					ir_ref                     single_output;     /* reachable output for IR_IF */
+					ir_ref                     visited;           /* for IR_TOP */
+				}
+			);
+			union {
+				struct {
+					ir_ref                     next; /* double-linked identities list for IR_COPY */
+					ir_ref                     prev; /* double-linked identities list for IR_COPY */
+				};
+				ir_val                         val;  /* constant value for IR_CONST */
+			};
+		};
+		ir_insn                                insn; /* constant insn for IR_CONST */
+	};
+} ir_sccp_val;
+
+IR_ALWAYS_INLINE bool _ir_is_reachable_ctrl(const ir_ctx *ctx, const ir_sccp_val *_values, ir_ref ref)
 {
 	IR_ASSERT(!IR_IS_CONST_REF(ref));
 	IR_ASSERT(ir_op_flags[ctx->ir_base[ref].op] & IR_OP_FLAG_CONTROL);
 	return _values[ref].op != IR_TOP; /* BOTTOM, IF or MERGE */
 }
 
-IR_ALWAYS_INLINE void ir_sccp_add_uses(ir_ctx *ctx, ir_insn *_values, ir_bitqueue *worklist, ir_ref ref)
+IR_ALWAYS_INLINE void ir_sccp_add_uses(const ir_ctx *ctx, const ir_sccp_val *_values, ir_bitqueue *worklist, ir_ref ref)
 {
-	ir_use_list *use_list;
-	ir_ref n, *p, use;
+	const ir_use_list *use_list;
+	const ir_ref *p;
+	ir_ref n, use;
 
 	IR_ASSERT(!IR_IS_CONST_REF(ref));
 	use_list = &ctx->use_lists[ref];
@@ -50,23 +89,23 @@
 	}
 }
 
-IR_ALWAYS_INLINE void ir_sccp_add_input(ir_ctx *ctx, ir_insn *_values, ir_bitqueue *worklist, ir_ref ref)
+IR_ALWAYS_INLINE void ir_sccp_add_input(const ir_ctx *ctx, ir_sccp_val *_values, ir_bitqueue *worklist, ir_ref ref)
 {
 	IR_ASSERT(!IR_IS_CONST_REF(ref));
 	IR_ASSERT(_values[ref].op == IR_TOP);
 	/* do backward propagaton only once */
-	if (!_values[ref].op1) {
-		_values[ref].op1 = 1;
+	if (!_values[ref].visited) {
+		_values[ref].visited = 1;
 		ir_bitqueue_add(worklist, ref);
 	}
 }
 
 #if IR_COMBO_COPY_PROPAGATION
-IR_ALWAYS_INLINE ir_ref ir_sccp_identity(ir_ctx *ctx, ir_insn *_values, ir_ref a)
+IR_ALWAYS_INLINE ir_ref ir_sccp_identity(const ir_ctx *ctx, const ir_sccp_val *_values, ir_ref a)
 {
 	if (a > 0 && _values[a].op == IR_COPY) {
 		do {
-			a = _values[a].op1;
+			a = _values[a].copy;
 			IR_ASSERT(a > 0);
 		} while (_values[a].op == IR_COPY);
 		IR_ASSERT(_values[a].op == IR_BOTTOM);
@@ -75,7 +114,7 @@
 }
 
 #if 0
-static void CHECK_LIST(ir_insn *_values, ir_ref ref)
+static void CHECK_LIST(ir_sccp_val *_values, ir_ref ref)
 {
 	ir_ref member = _values[ref].op2;
 	while (member != ref) {
@@ -88,44 +127,44 @@
 # define CHECK_LIST(_values, ref)
 #endif
 
-static void ir_sccp_add_identity(ir_ctx *ctx, ir_insn *_values, ir_ref src, ir_ref dst)
+static void ir_sccp_add_identity(const ir_ctx *ctx, ir_sccp_val *_values, ir_ref src, ir_ref dst)
 {
 	IR_ASSERT(dst > 0 && _values[dst].op != IR_BOTTOM && _values[dst].op != IR_COPY);
 	IR_ASSERT((src > 0 && (_values[src].op == IR_BOTTOM || _values[src].op == IR_COPY)));
 	IR_ASSERT(ir_sccp_identity(ctx, _values, src) != dst);
 
 	_values[dst].optx = IR_COPY;
-	_values[dst].op1 = src;
+	_values[dst].copy = src;
 
 	if (_values[src].op == IR_BOTTOM) {
 		/* initialize empty double-linked list */
-		if (_values[src].op1 != src) {
-			_values[src].op1 = src;
-			_values[src].op2 = src;
-			_values[src].op3 = src;
+		if (_values[src].copy != src) {
+			_values[src].copy = src;
+			_values[src].next = src;
+			_values[src].prev = src;
 		}
 	} else {
 		src = ir_sccp_identity(ctx, _values, src);
 	}
 
 	/* insert into circular double-linked list */
-	ir_ref prev = _values[src].op3;
-	_values[dst].op2 = src;
-	_values[dst].op3 = prev;
-	_values[src].op3 = dst;
-	_values[prev].op2 = dst;
+	ir_ref prev = _values[src].prev;
+	_values[dst].next = src;
+	_values[dst].prev = prev;
+	_values[src].prev = dst;
+	_values[prev].next = dst;
 	CHECK_LIST(_values, dst);
 }
 
-static void ir_sccp_split_partition(ir_ctx *ctx, ir_insn *_values, ir_bitqueue *worklist, ir_ref ref)
+static void ir_sccp_split_partition(const ir_ctx *ctx, ir_sccp_val *_values, ir_bitqueue *worklist, ir_ref ref)
 {
 	ir_ref member, head, tail, next, prev;
 
 	CHECK_LIST(_values, ref);
 	IR_MAKE_BOTTOM(ref);
-	_values[ref].op1 = ref;
+	_values[ref].copy = ref;
 
-	member = _values[ref].op2;
+	member = _values[ref].next;
 	head = tail = IR_UNUSED;
 	while (member != ref) {
 		if (_values[member].op != IR_BOTTOM) {
@@ -133,19 +172,19 @@
 		}
 		ir_sccp_add_uses(ctx, _values, worklist, member);
 
-		next = _values[member].op2;
+		next = _values[member].next;
 		if (ir_sccp_identity(ctx, _values, member) == ref) {
 			/* remove "member" from the old circular double-linked list */
-			prev = _values[member].op3;
-			_values[prev].op2 = next;
-			_values[next].op3 = prev;
+			prev = _values[member].prev;
+			_values[prev].next = next;
+			_values[next].prev = prev;
 
 			/* insert "member" into the new double-linked list */
 			if (!head) {
 				head = tail = member;
 			} else {
-				_values[tail].op2 = member;
-				_values[member].op3 = tail;
+				_values[tail].next = member;
+				_values[member].prev = tail;
 				tail = member;
 			}
 		}
@@ -153,26 +192,26 @@
 	}
 
 	/* remove "ref" from the old circular double-linked list */
-	next = _values[ref].op2;
-	prev = _values[ref].op3;
-	_values[prev].op2 = next;
-	_values[next].op3 = prev;
+	next = _values[ref].next;
+	prev = _values[ref].prev;
+	_values[prev].next = next;
+	_values[next].prev = prev;
 	CHECK_LIST(_values, next);
 
 	/* close the new circle */
 	if (head) {
-		_values[ref].op2 = head;
-		_values[ref].op3 = tail;
-		_values[tail].op2 = ref;
-		_values[head].op3 = ref;
+		_values[ref].next = head;
+		_values[ref].prev = tail;
+		_values[tail].next = ref;
+		_values[head].prev = ref;
 	} else {
-		_values[ref].op2 = ref;
-		_values[ref].op3 = ref;
+		_values[ref].next = ref;
+		_values[ref].prev = ref;
 	}
 	CHECK_LIST(_values, ref);
 }
 
-IR_ALWAYS_INLINE void ir_sccp_make_bottom_ex(ir_ctx *ctx, ir_insn *_values, ir_bitqueue *worklist, ir_ref ref)
+IR_ALWAYS_INLINE void ir_sccp_make_bottom_ex(const ir_ctx *ctx, ir_sccp_val *_values, ir_bitqueue *worklist, ir_ref ref)
 {
 	if (_values[ref].op == IR_COPY) {
 		ir_sccp_split_partition(ctx, _values, worklist, ref);
@@ -187,7 +226,7 @@
 # define IR_MAKE_BOTTOM_EX(ref) IR_MAKE_BOTTOM(ref)
 #endif
 
-IR_ALWAYS_INLINE bool ir_sccp_meet_const(ir_ctx *ctx, ir_insn *_values, ir_bitqueue *worklist, ir_ref ref, ir_insn *val_insn)
+IR_ALWAYS_INLINE bool ir_sccp_meet_const(const ir_ctx *ctx, ir_sccp_val *_values, ir_bitqueue *worklist, ir_ref ref, const ir_insn *val_insn)
 {
 	IR_ASSERT(IR_IS_CONST_OP(val_insn->op) || IR_IS_SYM_CONST(val_insn->op));
 
@@ -207,46 +246,51 @@
 	return 1;
 }
 
-IR_ALWAYS_INLINE bool ir_sccp_meet(ir_ctx *ctx, ir_insn *_values, ir_bitqueue *worklist, ir_ref ref, ir_ref val)
+IR_ALWAYS_INLINE bool ir_sccp_meet_copy(const ir_ctx *ctx, ir_sccp_val *_values, ir_bitqueue *worklist, ir_ref ref, ir_ref val)
+{
+#if IR_COMBO_COPY_PROPAGATION
+	if (_values[ref].op == IR_COPY) {
+		/* COPY(OLD_VAL) meet COPY(NEW_VAL) =>
+		 *   (IDENTITY(OLD_VAL) == IDENTITY(NEW_VAL) ? COPY(OLD_VAL) ? BOTTOM */
+		if (ir_sccp_identity(ctx, _values, ref) == ir_sccp_identity(ctx, _values, val)) {
+			return 0; /* not changed */
+		}
+		ir_sccp_split_partition(ctx, _values, worklist, ref);
+		return 1;
+	} else {
+		IR_ASSERT(_values[ref].op != IR_BOTTOM);
+		/* TOP       meet COPY(NEW_VAL) -> COPY(NEW_VAL) */
+		/* OLD_CONST meet COPY(NEW_VAL) -> COPY(NEW_VAL) */
+		ir_sccp_add_identity(ctx, _values, val, ref);
+		return 1;
+	}
+#endif
+	IR_MAKE_BOTTOM(ref);
+	return 1;
+}
+
+#if 0
+IR_ALWAYS_INLINE bool ir_sccp_meet(const ir_ctx *ctx, ir_sccp_val *_values, ir_bitqueue *worklist, ir_ref ref, ir_ref val)
 {
-	ir_ref val_identity = ir_sccp_identity(ctx, _values, val);
-	ir_insn *val_insn;
+	const ir_insn *val_insn;
 
-	if (IR_IS_CONST_REF(val_identity)) {
-		val_insn = &ctx->ir_base[val_identity];
+	if (IR_IS_CONST_REF(val)) {
+		val_insn = &ctx->ir_base[val];
 	} else {
-		val_insn = &_values[val_identity];
+		val_insn = &_values[val].insn;
 
 		if (!IR_IS_CONST_OP(val_insn->op) && !IR_IS_SYM_CONST(val_insn->op)) {
-#if IR_COMBO_COPY_PROPAGATION
-			if (_values[ref].op == IR_COPY) {
-				/* COPY(OLD_VAL) meet COPY(NEW_VAL) =>
-				 *   (IDENTITY(OLD_VAL) == IDENTITY(NEW_VAL) ? COPY(OLD_VAL) ? BOTTOM */
-				if (ir_sccp_identity(ctx, _values, ref) == val_identity) {
-					return 0; /* not changed */
-				}
-				ir_sccp_split_partition(ctx, _values, worklist, ref);
-				return 1;
-			} else {
-				IR_ASSERT(_values[ref].op != IR_BOTTOM);
-				/* TOP       meet COPY(NEW_VAL) -> COPY(NEW_VAL) */
-				/* OLD_CONST meet COPY(NEW_VAL) -> COPY(NEW_VAL) */
-				ir_sccp_add_identity(ctx, _values, val, ref);
-				return 1;
-			}
-#endif
-
-			IR_MAKE_BOTTOM(ref);
-			return 1;
+			return ir_sccp_meet_copy(ctx, _values, worklist, ref, val);
 		}
 	}
 
 	return ir_sccp_meet_const(ctx, _values, worklist, ref, val_insn);
 }
+#endif
 
-static ir_ref ir_sccp_fold(ir_ctx *ctx, ir_insn *_values, ir_bitqueue *worklist, ir_ref ref, ir_insn *insn)
+static ir_ref ir_sccp_fold(const ir_ctx *ctx, ir_sccp_val *_values, ir_bitqueue *worklist, ir_ref ref, const ir_insn *insn)
 {
-	ir_insn *op1_insn, *op2_insn, *op3_insn;
+	const ir_insn *op1_insn, *op2_insn, *op3_insn;
 	ir_ref op1, op2, op3, copy;
 	uint32_t opt = insn->opt;
 
@@ -255,11 +299,11 @@
 	op3 = ir_sccp_identity(ctx, _values, insn->op3);
 
 restart:
-	op1_insn = (op1 > 0 && IR_IS_CONST_OP(_values[op1].op)) ? _values + op1 : ctx->ir_base + op1;
-	op2_insn = (op2 > 0 && IR_IS_CONST_OP(_values[op2].op)) ? _values + op2 : ctx->ir_base + op2;
-	op3_insn = (op3 > 0 && IR_IS_CONST_OP(_values[op3].op)) ? _values + op3 : ctx->ir_base + op3;
+	op1_insn = (op1 > 0 && IR_IS_CONST_OP(_values[op1].op)) ? &_values[op1].insn : ctx->ir_base + op1;
+	op2_insn = (op2 > 0 && IR_IS_CONST_OP(_values[op2].op)) ? &_values[op2].insn : ctx->ir_base + op2;
+	op3_insn = (op3 > 0 && IR_IS_CONST_OP(_values[op3].op)) ? &_values[op3].insn : ctx->ir_base + op3;
 
-	switch (ir_folding(ctx, opt, op1, op2, op3, op1_insn, op2_insn, op3_insn)) {
+	switch (ir_folding((ir_ctx*)ctx, opt, op1, op2, op3, op1_insn, op2_insn, op3_insn)) {
 		case IR_FOLD_DO_RESTART:
 			opt = ctx->fold_insn.optx;
 			op1 = ctx->fold_insn.op1;
@@ -272,19 +316,30 @@
 			return 1;
 		case IR_FOLD_DO_COPY:
 			copy = ctx->fold_insn.op1;
-			return ir_sccp_meet(ctx, _values, worklist, ref, copy);
+			if (IR_IS_CONST_REF(copy)) {
+				insn = &ctx->ir_base[copy];
+			} else {
+				insn = &_values[copy].insn;
+				if (!IR_IS_CONST_OP(insn->op) && !IR_IS_SYM_CONST(insn->op)) {
+					return ir_sccp_meet_copy(ctx, _values, worklist, ref, copy);
+				}
+		    }
+			goto meet_const;
 		case IR_FOLD_DO_CONST:
-			return ir_sccp_meet_const(ctx, _values, worklist, ref, &ctx->fold_insn);
+			insn = &ctx->fold_insn;
+meet_const:
+			return ir_sccp_meet_const(ctx, _values, worklist, ref, insn);
 		default:
 			IR_ASSERT(0);
 			return 0;
 	}
 }
 
-static bool ir_sccp_analyze_phi(ir_ctx *ctx, ir_insn *_values, ir_bitqueue *worklist, ir_ref i, ir_insn *insn)
+static bool ir_sccp_analyze_phi(const ir_ctx *ctx, ir_sccp_val *_values, ir_bitqueue *worklist, ir_ref i, const ir_insn *insn)
 {
-	ir_ref j, n, input, *merge_input, *p;
-	ir_insn *v, *new_const = NULL;
+	ir_ref j, n, input;
+	const ir_ref *merge_input, *p;
+	const ir_insn *v, *new_const = NULL;
 #if IR_COMBO_COPY_PROPAGATION
 	ir_ref new_copy = IR_UNUSED;
 	ir_ref new_copy_identity = IR_UNUSED;
@@ -315,7 +370,7 @@
 		} else if (input == i) {
 			continue;
 		} else {
-			v = &_values[input];
+			v = &_values[input].insn;
 			if (v->op == IR_TOP) {
 				ir_sccp_add_input(ctx, _values, worklist, input);
 				continue;
@@ -369,7 +424,7 @@
 		} else if (input == i) {
 			continue;
 		} else {
-			v = &_values[input];
+			v = &_values[input].insn;
 			if (v->op == IR_TOP) {
 				ir_sccp_add_input(ctx, _values, worklist, input);
 				continue;
@@ -398,7 +453,9 @@
 
 #if IR_COMBO_COPY_PROPAGATION
 	if (new_copy) {
-		return ir_sccp_meet(ctx, _values, worklist, i, new_copy);
+		IR_ASSERT(!IR_IS_CONST_REF(new_copy));
+		IR_ASSERT(!IR_IS_CONST_OP(_values[new_copy].op) && !IR_IS_SYM_CONST(_values[new_copy].op));
+		return ir_sccp_meet_copy(ctx, _values, worklist, i, new_copy);
 	}
 #endif
 
@@ -409,7 +466,7 @@
 	return 1;
 }
 
-static bool ir_is_dead_load_ex(ir_ctx *ctx, ir_ref ref, uint32_t flags, ir_insn *insn)
+static bool ir_is_dead_load_ex(const ir_ctx *ctx, ir_ref ref, uint32_t flags, const ir_insn *insn)
 {
 	if ((flags & (IR_OP_FLAG_MEM|IR_OP_FLAG_MEM_MASK)) == (IR_OP_FLAG_MEM|IR_OP_FLAG_MEM_LOAD)) {
 		return ctx->use_lists[ref].count == 1;
@@ -419,10 +476,10 @@
 	return 0;
 }
 
-static bool ir_is_dead_load(ir_ctx *ctx, ir_ref ref)
+static bool ir_is_dead_load(const ir_ctx *ctx, ir_ref ref)
 {
 	if (ctx->use_lists[ref].count == 1) {
-		ir_insn *insn = &ctx->ir_base[ref];
+		const ir_insn *insn = &ctx->ir_base[ref];
 		uint32_t flags = ir_op_flags[insn->op];
 
 		if ((flags & (IR_OP_FLAG_MEM|IR_OP_FLAG_MEM_MASK)) == (IR_OP_FLAG_MEM|IR_OP_FLAG_MEM_LOAD)) {
@@ -434,7 +491,7 @@
 	return 0;
 }
 
-static bool ir_is_dead(ir_ctx *ctx, ir_ref ref)
+static bool ir_is_dead(const ir_ctx *ctx, ir_ref ref)
 {
 	if (ctx->use_lists[ref].count == 0) {
 		return IR_IS_FOLDABLE_OP(ctx->ir_base[ref].op);
@@ -444,28 +501,28 @@
 	return 0;
 }
 
-static bool ir_sccp_is_true(ir_ctx *ctx, ir_insn *_values, ir_ref a)
+static bool ir_sccp_is_true(const ir_ctx *ctx, const ir_sccp_val *_values, ir_ref a)
 {
-	ir_insn *v = IR_IS_CONST_REF(a) ? &ctx->ir_base[a] : &_values[a];
+	const ir_insn *v = IR_IS_CONST_REF(a) ? &ctx->ir_base[a] : &_values[a].insn;
 
 	return ir_const_is_true(v);
 }
 
-static bool ir_sccp_is_equal(ir_ctx *ctx, ir_insn *_values, ir_ref a, ir_ref b)
+static bool ir_sccp_is_equal(const ir_ctx *ctx, const ir_sccp_val *_values, ir_ref a, ir_ref b)
 {
-	ir_insn *v1 = IR_IS_CONST_REF(a) ? &ctx->ir_base[a] : &_values[a];
-	ir_insn *v2 = IR_IS_CONST_REF(b) ? &ctx->ir_base[b] : &_values[b];
+	const ir_insn *v1 = IR_IS_CONST_REF(a) ? &ctx->ir_base[a] : &_values[a].insn;
+	const ir_insn *v2 = IR_IS_CONST_REF(b) ? &ctx->ir_base[b] : &_values[b].insn;
 
 	IR_ASSERT(!IR_IS_SYM_CONST(v1->op));
 	IR_ASSERT(!IR_IS_SYM_CONST(v2->op));
 	return v1->val.u64 == v2->val.u64;
 }
 
-static bool ir_sccp_in_range(ir_ctx *ctx, ir_insn *_values, ir_ref a, ir_ref b, ir_ref c)
+static bool ir_sccp_in_range(const ir_ctx *ctx, const ir_sccp_val *_values, ir_ref a, ir_ref b, ir_ref c)
 {
-	ir_insn *v1 = IR_IS_CONST_REF(a) ? &ctx->ir_base[a] : &_values[a];
-	ir_insn *v2 = IR_IS_CONST_REF(b) ? &ctx->ir_base[b] : &_values[b];
-	ir_insn *v3 = IR_IS_CONST_REF(c) ? &ctx->ir_base[c] : &_values[c];
+	const ir_insn *v1 = IR_IS_CONST_REF(a) ? &ctx->ir_base[a] : &_values[a].insn;
+	const ir_insn *v2 = IR_IS_CONST_REF(b) ? &ctx->ir_base[b] : &_values[b].insn;
+	const ir_insn *v3 = IR_IS_CONST_REF(c) ? &ctx->ir_base[c] : &_values[c].insn;
 
 	IR_ASSERT(!IR_IS_SYM_CONST(v1->op));
 	IR_ASSERT(!IR_IS_SYM_CONST(v2->op));
@@ -478,13 +535,13 @@
 }
 
 #ifdef IR_SCCP_TRACE
-static void ir_sccp_trace_val(ir_ctx *ctx, ir_insn *_values, ir_ref i)
+static void ir_sccp_trace_val(const ir_ctx *ctx, const ir_sccp_val *_values, ir_ref i)
 {
 	if (IR_IS_BOTTOM(i)) {
 		fprintf(stderr, "BOTTOM");
 	} else if (IR_IS_CONST_OP(_values[i].op) || IR_IS_SYM_CONST(_values[i].op)) {
 		fprintf(stderr, "CONST(");
-		ir_print_const(ctx, &_values[i], stderr, true);
+		ir_print_const(ctx, &_values[i].insn, stderr, true);
 		fprintf(stderr, ")");
 #if IR_COMBO_COPY_PROPAGATION
 	} else if (_values[i].op == IR_COPY) {
@@ -501,13 +558,13 @@
 	}
 }
 
-static void ir_sccp_trace_start(ir_ctx *ctx, ir_insn *_values, ir_ref i)
+static void ir_sccp_trace_start(const ir_ctx *ctx, const ir_sccp_val *_values, ir_ref i)
 {
 	fprintf(stderr, "%d. ", i);
 	ir_sccp_trace_val(ctx, _values, i);
 }
 
-static void ir_sccp_trace_end(ir_ctx *ctx, ir_insn *_values, ir_ref i)
+static void ir_sccp_trace_end(const ir_ctx *ctx, const ir_sccp_val *_values, ir_ref i)
 {
 	fprintf(stderr, " -> ");
 	ir_sccp_trace_val(ctx, _values, i);
@@ -518,11 +575,12 @@
 # define ir_sccp_trace_end(c, v, i)
 #endif
 
-static IR_NEVER_INLINE void ir_sccp_analyze(ir_ctx *ctx, ir_insn *_values, ir_bitqueue *worklist, ir_bitqueue *iter_worklist)
+static IR_NEVER_INLINE void ir_sccp_analyze(const ir_ctx *ctx, ir_sccp_val *_values, ir_bitqueue *worklist, ir_bitqueue *iter_worklist)
 {
-	ir_ref i, j, n, *p, use;
-	ir_use_list *use_list;
-	ir_insn *insn, *use_insn;
+	ir_ref i, j, n, use;
+	const ir_ref *p;
+	const ir_use_list *use_list;
+	const ir_insn *insn, *use_insn;
 	uint32_t flags;
 
 	/* A bit modified SCCP algorithm of M. N. Wegman and F. K. Zadeck */
@@ -610,7 +668,7 @@
 					}
 				}
 				for (p = insn->ops + 1; n > 0; p++, n--) {
-					ir_ref input = *p;
+					const ir_ref input = *p;
 					IR_ASSERT(input > 0);
 					if (!IR_IS_REACHABLE(input)) {
 						unfeasible_inputs++;
@@ -618,9 +676,9 @@
 				}
 				if (unfeasible_inputs == 0) {
 					IR_MAKE_BOTTOM(i);
-				} else if (_values[i].op != IR_MERGE || _values[i].op1 != unfeasible_inputs) {
+				} else if (_values[i].op != IR_MERGE || _values[i].unfeasible_inputs != unfeasible_inputs) {
 					_values[i].optx = IR_MERGE;
-					_values[i].op1 = unfeasible_inputs;
+					_values[i].unfeasible_inputs = unfeasible_inputs;
 				} else {
 					continue;
 				}
@@ -674,10 +732,10 @@
 					}
 					if (_values[i].op == IR_TOP) {
 						_values[i].optx = IR_IF;
-						_values[i].op1 = use;
+						_values[i].single_output = use;
 						ir_bitqueue_add(worklist, use);
 						continue;
-					} else if (_values[i].op == IR_IF && _values[i].op1 == use) {
+					} else if (_values[i].op == IR_IF && _values[i].single_output == use) {
 						continue;
 					}
 				}
@@ -715,10 +773,10 @@
 						use_insn = &ctx->ir_base[use_case];
 						if (_values[i].op == IR_TOP) {
 							_values[i].optx = IR_IF;
-							_values[i].op1 = use_case;
+							_values[i].single_output = use_case;
 							ir_bitqueue_add(worklist, use_case);
 							continue;
-						} else if (_values[i].op == IR_IF || _values[i].op1 == use_case) {
+						} else if (_values[i].op == IR_IF || _values[i].single_output == use_case) {
 							continue;
 						}
 					}
@@ -768,18 +826,20 @@
 		for (i = 1; i < ctx->insns_count; i++) {
 			if (IR_IS_CONST_OP(_values[i].op) || IR_IS_SYM_CONST(_values[i].op)) {
 				fprintf(stderr, "%d. CONST(", i);
-				ir_print_const(ctx, &_values[i], stderr, true);
+				ir_print_const(ctx, &_values[i].insn, stderr, true);
 				fprintf(stderr, ")\n");
 #if IR_COMBO_COPY_PROPAGATION
 			} else if (_values[i].op == IR_COPY) {
-				fprintf(stderr, "%d. COPY(%d)\n", i, _values[i].op1);
+				fprintf(stderr, "%d. COPY(%d)\n", i, _values[i].copy);
 #endif
 			} else if (IR_IS_TOP(i)) {
-				fprintf(stderr, "%d. TOP\n", i);
+				if (ctx->ir_base[i].op != IR_TOP) {
+					fprintf(stderr, "%d. TOP\n", i);
+				}
 			} else if (_values[i].op == IR_IF) {
-				fprintf(stderr, "%d. IF(%d)\n", i, _values[i].op1);
+				fprintf(stderr, "%d. IF(%d)\n", i, _values[i].single_output);
 			} else if (_values[i].op == IR_MERGE) {
-				fprintf(stderr, "%d. MERGE(%d)\n", i, _values[i].op1);
+				fprintf(stderr, "%d. MERGE(%d)\n", i, _values[i].unfeasible_inputs);
 			} else if (!IR_IS_BOTTOM(i)) {
 				fprintf(stderr, "%d. %d\n", i, _values[i].op);
 			}
@@ -806,7 +866,7 @@
 	}
 }
 
-static void ir_sccp_remove_insn(ir_ctx *ctx, ir_insn *_values, ir_ref ref, ir_bitqueue *worklist)
+static void ir_sccp_remove_insn(ir_ctx *ctx, const ir_sccp_val *_values, ir_ref ref, ir_bitqueue *worklist)
 {
 	ir_ref j, n, *p;
 	ir_insn *insn;
@@ -820,7 +880,7 @@
 		*p = IR_UNUSED;
 		/* we may skip nodes that are going to be removed by SCCP (TOP, CONST and COPY) */
 		if (input > 0 && _values[input].op > IR_COPY) {
-			ir_use_list_remove_all(ctx, input, ref);
+			ir_use_list_remove_one(ctx, input, ref);
 			if (ir_is_dead(ctx, input)) {
 				/* schedule DCE */
 				ir_bitqueue_add(worklist, input);
@@ -829,7 +889,7 @@
 	}
 }
 
-static void ir_sccp_replace_insn(ir_ctx *ctx, ir_insn *_values, ir_ref ref, ir_ref new_ref, ir_bitqueue *worklist)
+static void ir_sccp_replace_insn(ir_ctx *ctx, const ir_sccp_val *_values, ir_ref ref, ir_ref new_ref, ir_bitqueue *worklist)
 {
 	ir_ref j, n, *p, use, i;
 	ir_insn *insn;
@@ -858,7 +918,7 @@
 		*p = IR_UNUSED;
 		/* we may skip nodes that are going to be removed by SCCP (TOP, CONST and COPY) */
 		if (input > 0 && _values[input].op > IR_COPY) {
-			ir_use_list_remove_all(ctx, input, ref);
+			ir_use_list_remove_one(ctx, input, ref);
 			if (ir_is_dead(ctx, input)) {
 				/* schedule DCE */
 				ir_bitqueue_add(worklist, input);
@@ -907,7 +967,7 @@
 	CLEAR_USES(ref);
 }
 
-static void ir_sccp_remove_if(ir_ctx *ctx, ir_insn *_values, ir_ref ref, ir_ref dst)
+static void ir_sccp_remove_if(ir_ctx *ctx, const ir_sccp_val *_values, ir_ref ref, ir_ref dst)
 {
 	ir_ref next;
 	ir_insn *insn, *next_insn;
@@ -1054,10 +1114,10 @@
 	return 1;
 }
 
-static IR_NEVER_INLINE void ir_sccp_transform(ir_ctx *ctx, ir_insn *_values, ir_bitqueue *worklist, ir_bitqueue *iter_worklist)
+static IR_NEVER_INLINE void ir_sccp_transform(ir_ctx *ctx, const ir_sccp_val *_values, ir_bitqueue *worklist, ir_bitqueue *iter_worklist)
 {
 	ir_ref i, j;
-	ir_insn *value;
+	const ir_sccp_val *value;
 
 	for (i = 1, value = _values + i; i < ctx->insns_count; value++, i++) {
 		if (value->op == IR_BOTTOM) {
@@ -1072,7 +1132,7 @@
 			ir_sccp_replace_insn(ctx, _values, i, j, iter_worklist);
 #if IR_COMBO_COPY_PROPAGATION
 		} else if (value->op == IR_COPY) {
-			ir_sccp_replace_insn(ctx, _values, i, ir_sccp_identity(ctx, _values, value->op1), iter_worklist);
+			ir_sccp_replace_insn(ctx, _values, i, ir_sccp_identity(ctx, _values, value->copy), iter_worklist);
 #endif
 		} else if (value->op == IR_TOP) {
 			/* remove unreachable instruction */
@@ -1104,7 +1164,7 @@
 			}
 		} else if (value->op == IR_IF) {
 			/* remove one way IF/SWITCH */
-			ir_sccp_remove_if(ctx, _values, i, value->op1);
+			ir_sccp_remove_if(ctx, _values, i, value->single_output);
 		} else if (value->op == IR_MERGE) {
 			/* schedule merge to remove unfeasible MERGE inputs */
 			ir_bitqueue_add(worklist, i);
@@ -1121,6 +1181,16 @@
 /* Iterative Optimizations */
 /***************************/
 
+void ir_iter_add_uses(ir_ctx *ctx, ir_ref ref, ir_bitqueue *worklist)
+{
+	ir_use_list *use_list = &ctx->use_lists[ref];
+	ir_ref *p, n = use_list->count;
+
+	for (p = &ctx->use_edges[use_list->refs]; n > 0; p++, n--) {
+		ir_bitqueue_add(worklist, *p);
+	}
+}
+
 /* Modification of some instruction may open new optimization oprtunities for other
  * instructions that use this one.
  *
@@ -1132,16 +1202,16 @@
  *
  * TODO: Think abput a more general solution ???
  */
-static void ir_iter_add_related_uses(ir_ctx *ctx, ir_ref ref, ir_bitqueue *worklist)
+static void ir_iter_add_related_uses(const ir_ctx *ctx, ir_ref ref, ir_bitqueue *worklist)
 {
-	ir_insn *insn = &ctx->ir_base[ref];
+	const ir_insn *insn = &ctx->ir_base[ref];
 
 	if (insn->op == IR_ADD || insn->op == IR_SUB) {
-		ir_use_list *use_list = &ctx->use_lists[ref];
+		const ir_use_list *use_list = &ctx->use_lists[ref];
 
 		if (use_list->count == 1) {
 			ir_ref use = ctx->use_edges[use_list->refs];
-			ir_insn *use_insn = &ctx->ir_base[ref];
+			const ir_insn *use_insn = &ctx->ir_base[ref];
 
 			if (use_insn->op == IR_ADD || use_insn->op == IR_SUB) {
 				ir_bitqueue_add(worklist, use);
@@ -1163,7 +1233,7 @@
 		ir_ref input = *p;
 		*p = IR_UNUSED;
 		if (input > 0) {
-			ir_use_list_remove_all(ctx, input, ref);
+			ir_use_list_remove_one(ctx, input, ref);
 			if (ir_is_dead(ctx, input)) {
 				/* schedule DCE */
 				ir_bitqueue_add(worklist, input);
@@ -1231,7 +1301,7 @@
 		ir_ref input = *p;
 		*p = IR_UNUSED;
 		if (input > 0) {
-			ir_use_list_remove_all(ctx, input, ref);
+			ir_use_list_remove_one(ctx, input, ref);
 			if (ir_is_dead(ctx, input)) {
 				/* schedule DCE */
 				ir_bitqueue_add(worklist, input);
@@ -1266,16 +1336,17 @@
 	}
 }
 
-static ir_ref ir_iter_find_cse1(ir_ctx *ctx, uint32_t optx, ir_ref op1)
+static ir_ref ir_iter_find_cse1(const ir_ctx *ctx, uint32_t optx, ir_ref op1)
 {
 	IR_ASSERT(!IR_IS_CONST_REF(op1));
 
-	ir_use_list *use_list = &ctx->use_lists[op1];
-	ir_ref *p, n = use_list->count;
+	const ir_use_list *use_list = &ctx->use_lists[op1];
+	const ir_ref *p;
+	ir_ref n = use_list->count;
 
 	for (p = ctx->use_edges + use_list->refs; n > 0; p++, n--) {
 		ir_ref use = *p;
-		ir_insn *use_insn = &ctx->ir_base[use];
+		const ir_insn *use_insn = &ctx->ir_base[use];
 
 		if (use_insn->optx == optx) {
 			IR_ASSERT(use_insn->op1 == op1);
@@ -1285,12 +1356,13 @@
 	return IR_UNUSED;
 }
 
-static ir_ref ir_iter_find_cse(ir_ctx *ctx, ir_ref ref, uint32_t opt, ir_ref op1, ir_ref op2, ir_ref op3, ir_bitqueue *worklist)
+static ir_ref ir_iter_find_cse(const ir_ctx *ctx, ir_ref ref, uint32_t opt, ir_ref op1, ir_ref op2, ir_ref op3, ir_bitqueue *worklist)
 {
 	uint32_t n = IR_INPUT_EDGES_COUNT(ir_op_flags[opt & IR_OPT_OP_MASK]);
-	ir_use_list *use_list = NULL;
-	ir_ref *p, use;
-	ir_insn *use_insn;
+	const ir_use_list *use_list = NULL;
+	const ir_ref *p;
+	ir_ref use;
+	const ir_insn *use_insn;
 
 	if (n == 2) {
 		if (!IR_IS_CONST_REF(op1)) {
@@ -1373,7 +1445,8 @@
 {
 	uint32_t opt;
 	ir_ref op1, op2, op3, copy;
-	ir_insn *op1_insn, *op2_insn, *op3_insn, *insn;
+	const ir_insn *op1_insn, *op2_insn, *op3_insn;
+	ir_insn *insn;
 
 	insn = &ctx->ir_base[ref];
 	opt = insn->opt;
@@ -1408,9 +1481,6 @@
 			 || insn->op2 != ctx->fold_insn.op2
 			 || insn->op3 != ctx->fold_insn.op3) {
 
-				ir_use_list *use_list;
-				ir_ref n, j, *p, use;
-
 				insn->optx = ctx->fold_insn.opt;
 				IR_ASSERT(!IR_OP_HAS_VAR_INPUTS(ir_op_flags[opt & IR_OPT_OP_MASK]));
 				insn->inputs_count = IR_INPUT_EDGES_COUNT(ir_op_flags[opt & IR_OPT_OP_MASK]);
@@ -1442,12 +1512,7 @@
 				insn->op2 = ctx->fold_insn.op2;
 				insn->op3 = ctx->fold_insn.op3;
 
-				use_list = &ctx->use_lists[ref];
-				n = use_list->count;
-				for (j = 0, p = &ctx->use_edges[use_list->refs]; j < n; j++, p++) {
-					use = *p;
-					ir_bitqueue_add(worklist, use);
-				}
+				ir_iter_add_uses(ctx, ref, worklist);
 			}
 			break;
 		case IR_FOLD_DO_COPY:
@@ -1464,9 +1529,9 @@
 	}
 }
 
-static bool ir_may_promote_d2f(ir_ctx *ctx, ir_ref ref)
+static bool ir_may_promote_d2f(const ir_ctx *ctx, ir_ref ref)
 {
-	ir_insn *insn = &ctx->ir_base[ref];
+	const ir_insn *insn = &ctx->ir_base[ref];
 
 	IR_ASSERT(insn->type == IR_DOUBLE);
 	if (IR_IS_CONST_REF(ref)) {
@@ -1497,9 +1562,9 @@
 	return 0;
 }
 
-static bool ir_may_promote_f2d(ir_ctx *ctx, ir_ref ref)
+static bool ir_may_promote_f2d(const ir_ctx *ctx, ir_ref ref)
 {
-	ir_insn *insn = &ctx->ir_base[ref];
+	const ir_insn *insn = &ctx->ir_base[ref];
 
 	IR_ASSERT(insn->type == IR_FLOAT);
 	if (IR_IS_CONST_REF(ref)) {
@@ -1668,10 +1733,11 @@
 	return ref;
 }
 
-static bool ir_may_promote_trunc(ir_ctx *ctx, ir_type type, ir_ref ref)
+static bool ir_may_promote_trunc(const ir_ctx *ctx, ir_type type, ir_ref ref)
 {
-	ir_insn *insn = &ctx->ir_base[ref];
-	ir_ref *p, n, input;
+	const ir_insn *insn = &ctx->ir_base[ref];
+	const ir_ref *p;
+	ir_ref n, input;
 
 	if (IR_IS_CONST_REF(ref)) {
 		return !IR_IS_SYM_CONST(insn->op);
@@ -1777,6 +1843,7 @@
 						}
 					}
 					insn->type = type;
+					ir_iter_add_uses(ctx, ref, worklist);
 					return ref;
 				}
 
@@ -1857,7 +1924,7 @@
 	return ref;
 }
 
-static ir_ref ir_ext_const(ir_ctx *ctx, ir_insn *val_insn, ir_op op, ir_type type)
+static ir_ref ir_ext_const(ir_ctx *ctx, const ir_insn *val_insn, ir_op op, ir_type type)
 {
 	ir_val new_val;
 
@@ -1921,10 +1988,11 @@
 	return ref;
 }
 
-static uint32_t _ir_estimated_control(ir_ctx *ctx, ir_ref val, ir_ref loop)
+static uint32_t _ir_estimated_control(const ir_ctx *ctx, ir_ref val, ir_ref loop)
 {
-	ir_insn *insn;
-	ir_ref n, *p, input, result, ctrl;
+	const ir_insn *insn;
+	const ir_ref *p;
+	ir_ref n, input, result, ctrl;
 
 	if (IR_IS_CONST_REF(val)) {
 		return 1; /* IR_START */
@@ -1955,18 +2023,18 @@
 	return result;
 }
 
-static bool ir_is_loop_invariant(ir_ctx *ctx, ir_ref ref, ir_ref loop)
+static bool ir_is_loop_invariant(const ir_ctx *ctx, ir_ref ref, ir_ref loop)
 {
 	ref = _ir_estimated_control(ctx, ref, loop);
 	return ref < loop; // TODO: check dominance instead of order
 }
 
-static bool ir_is_cheaper_ext(ir_ctx *ctx, ir_ref ref, ir_ref loop, ir_ref ext_ref, ir_op op)
+static bool ir_is_cheaper_ext(const ir_ctx *ctx, ir_ref ref, ir_ref loop, ir_ref ext_ref, ir_op op)
 {
 	if (IR_IS_CONST_REF(ref)) {
 		return 1;
 	} else {
-		ir_insn *insn = &ctx->ir_base[ref];
+		const ir_insn *insn = &ctx->ir_base[ref];
 
 		if (insn->op == IR_LOAD) {
 			if (ir_is_loop_invariant(ctx, ref, loop)) {
@@ -1982,7 +2050,7 @@
 					for (p = &ctx->use_edges[use_list->refs], n = use_list->count; n > 0; p++, n--) {
 						use = *p;
 						if (use != ext_ref) {
-							ir_insn *use_insn = &ctx->ir_base[use];
+							const ir_insn *use_insn = &ctx->ir_base[use];
 
 							if (use_insn->op != op
 							 && (!(ir_op_flags[use_insn->op] & (IR_OP_FLAG_CONTROL|IR_OP_FLAG_MEM))
@@ -2018,7 +2086,7 @@
 			if (use == op_ref || use == ext_ref) {
 				continue;
 			} else {
-				ir_insn *use_insn = &ctx->ir_base[use];
+				const ir_insn *use_insn = &ctx->ir_base[use];
 
 				if (use_insn->op >= IR_EQ && use_insn->op <= IR_UGT) {
 					if (use_insn->op1 == phi_ref) {
@@ -2057,7 +2125,7 @@
 			if (use == phi_ref || use == ext_ref) {
 				continue;
 			} else {
-				ir_insn *use_insn = &ctx->ir_base[use];
+				const ir_insn *use_insn = &ctx->ir_base[use];
 
 				if (use_insn->op >= IR_EQ && use_insn->op <= IR_UGT) {
 					if (use_insn->op1 == phi_ref) {
@@ -2194,7 +2262,7 @@
 }
 
 static bool ir_try_promote_ext(ir_ctx *ctx, ir_ref ext_ref, ir_insn *insn, ir_bitqueue *worklist)
- {
+{
 	ir_ref ref = insn->op1;
 
 	/* Check for simple induction variable in the form: x2 = PHI(loop, x1, x3); x3 = ADD(x2, _); */
@@ -2359,7 +2427,7 @@
 		next->op1 = root->op1;
 		ir_use_list_replace_one(ctx, root->op1, root_ref, next_ref);
 		if (!IR_IS_CONST_REF(root->op2)) {
-			ir_use_list_remove_all(ctx, root->op2, root_ref);
+			ir_use_list_remove_one(ctx, root->op2, root_ref);
 			if (ir_is_dead(ctx, root->op2)) {
 				ir_bitqueue_add(worklist, root->op2);
 			}
@@ -2417,7 +2485,7 @@
 		ir_use_list_replace_one(ctx, root->op1, root_ref, next_ref);
 
 		if (!IR_IS_CONST_REF(root->op2)) {
-			ir_use_list_remove_all(ctx, root->op2, root_ref);
+			ir_use_list_remove_one(ctx, root->op2, root_ref);
 			if (ir_is_dead(ctx, root->op2)) {
 				ir_bitqueue_add(worklist, root->op2);
 			}
@@ -2445,7 +2513,7 @@
 	}
 }
 
-static bool ir_is_zero(ir_ctx *ctx, ir_ref ref)
+static bool ir_is_zero(const ir_ctx *ctx, ir_ref ref)
 {
 	return IR_IS_CONST_REF(ref)
 		&& !IR_IS_SYM_CONST(ctx->ir_base[ref].op)
@@ -2470,7 +2538,7 @@
 			ir_ref root_ref = start1->op1;
 			ir_insn *root = &ctx->ir_base[root_ref];
 
-			if (root->op == IR_IF && !IR_IS_CONST_REF(root->op2) && ctx->use_lists[root->op2].count == 1) {
+			if (root->op == IR_IF && !IR_IS_CONST_REF(root->op2)) {
 				ir_ref cond_ref = root->op2;
 				ir_insn *cond = &ctx->ir_base[cond_ref];
 				ir_type type = insn->type;
@@ -2544,13 +2612,17 @@
 					next->op1 = root->op1;
 					ir_use_list_replace_one(ctx, root->op1, root_ref, next_ref);
 					if (!IR_IS_CONST_REF(insn->op1)) {
-						ir_use_list_remove_all(ctx, insn->op1, cond_ref);
+						ir_use_list_remove_one(ctx, insn->op1, cond_ref);
 					}
 					if (!IR_IS_CONST_REF(insn->op2)) {
-						ir_use_list_remove_all(ctx, insn->op2, cond_ref);
+						ir_use_list_remove_one(ctx, insn->op2, cond_ref);
 					}
 
-					MAKE_NOP(cond);   CLEAR_USES(cond_ref);
+					if (ctx->use_lists[cond_ref].count == 1) {
+						MAKE_NOP(cond);   CLEAR_USES(cond_ref);
+					} else {
+						ir_use_list_remove_one(ctx, cond_ref, root_ref);
+					}
 					MAKE_NOP(root);   CLEAR_USES(root_ref);
 					MAKE_NOP(start1); CLEAR_USES(start1_ref);
 					MAKE_NOP(start2); CLEAR_USES(start2_ref);
@@ -2633,10 +2705,14 @@
 					ir_use_list_replace_one(ctx, root->op1, root_ref, next_ref);
 					ir_use_list_remove_one(ctx, insn->op1, neg_ref);
 					if (!IR_IS_CONST_REF(insn->op1)) {
-						ir_use_list_remove_all(ctx, insn->op1, cond_ref);
+						ir_use_list_remove_one(ctx, insn->op1, cond_ref);
 					}
 
-					MAKE_NOP(cond);   CLEAR_USES(cond_ref);
+					if (ctx->use_lists[cond_ref].count == 1) {
+						MAKE_NOP(cond);   CLEAR_USES(cond_ref);
+					} else {
+						ir_use_list_remove_one(ctx, cond_ref, root_ref);
+				    }
 					MAKE_NOP(root);   CLEAR_USES(root_ref);
 					MAKE_NOP(start1); CLEAR_USES(start1_ref);
 					MAKE_NOP(start2); CLEAR_USES(start2_ref);
@@ -2650,8 +2726,7 @@
 					}
 
 					return 1;
-#if 0
-				} else {
+				} else if (cond->op != IR_OVERFLOW && insn->op2 <= cond_ref && insn->op3 <= cond_ref) {
 					/* COND
 					 *
 					 *    prev                     prev
@@ -2696,7 +2771,7 @@
 					next->op1 = root->op1;
 					ir_use_list_replace_one(ctx, cond_ref, root_ref, ref);
 					ir_use_list_replace_one(ctx, root->op1, root_ref, next_ref);
-					ir_use_list_remove_all(ctx, root->op2, root_ref);
+					ir_use_list_remove_one(ctx, root->op2, root_ref);
 
 					MAKE_NOP(root);   CLEAR_USES(root_ref);
 					MAKE_NOP(start1); CLEAR_USES(start1_ref);
@@ -2705,12 +2780,12 @@
 					MAKE_NOP(end2);   CLEAR_USES(end2_ref);
 					MAKE_NOP(merge);  CLEAR_USES(merge_ref);
 
+					ir_bitqueue_add(worklist, ref);
 					if (ctx->ir_base[next->op1].op == IR_BEGIN || ctx->ir_base[next->op1].op == IR_MERGE) {
 						ir_bitqueue_add(worklist, next->op1);
 					}
 
 					return 1;
-#endif
 				}
 			}
 		}
@@ -2719,7 +2794,7 @@
 	return 0;
 }
 
-static bool ir_cmp_is_true(ir_op op, ir_insn *op1, ir_insn *op2)
+static bool ir_cmp_is_true(ir_op op, const ir_insn *op1, const ir_insn *op2)
 {
 	IR_ASSERT(op1->type == op2->type);
 	if (IR_IS_TYPE_INT(op1->type)) {
@@ -2960,8 +3035,8 @@
 				 *    IF_FALSE  |              MERGE
 				 *    |                        |
 				 */
-				ir_use_list_remove_all(ctx, merge_ref, cond_ref);
-				ir_use_list_remove_all(ctx, ref, if_true_ref);
+				ir_use_list_remove_one(ctx, merge_ref, cond_ref);
+				ir_use_list_remove_one(ctx, ref, if_true_ref);
 				if (!IR_IS_CONST_REF(cond->op3)) {
 					ir_use_list_replace_one(ctx, cond->op3, cond_ref, end2_ref);
 				}
@@ -3155,8 +3230,8 @@
 						 *    |                        |
 						 */
 
-						ir_use_list_remove_all(ctx, merge_ref, phi_ref);
-						ir_use_list_remove_all(ctx, ref, if_true_ref);
+						ir_use_list_remove_one(ctx, merge_ref, phi_ref);
+						ir_use_list_remove_one(ctx, ref, if_true_ref);
 						if (!IR_IS_CONST_REF(phi->op3)) {
 							ir_use_list_replace_one(ctx, phi->op3, phi_ref, insn->op2);
 						}
@@ -3246,7 +3321,7 @@
 	}
 }
 
-static ir_ref ir_find_ext_use(ir_ctx *ctx, ir_ref ref)
+static ir_ref ir_find_ext_use(const ir_ctx *ctx, ir_ref ref)
 {
 	ir_use_list *use_list = &ctx->use_lists[ref];
 	ir_ref *p, n, use;
@@ -3628,6 +3703,7 @@
 					insn->op1 = val;
 					insn->op2 = IR_UNUSED;
 					ir_bitqueue_add(worklist, i);
+					ir_iter_add_uses(ctx, i, worklist);
 				}
 			}
 		} else if (insn->op == IR_STORE) {
@@ -3677,11 +3753,11 @@
 int ir_sccp(ir_ctx *ctx)
 {
 	ir_bitqueue sccp_worklist, iter_worklist;
-	ir_insn *_values;
+	ir_sccp_val *_values;
 
 	ir_bitqueue_init(&iter_worklist, ctx->insns_count);
 	ir_bitqueue_init(&sccp_worklist, ctx->insns_count);
-	_values = ir_mem_calloc(ctx->insns_count, sizeof(ir_insn));
+	_values = ir_mem_calloc(ctx->insns_count, sizeof(ir_sccp_val));
 
 	ctx->flags2 |= IR_OPT_IN_SCCP;
 	ir_sccp_analyze(ctx, _values, &sccp_worklist, &iter_worklist);
diff '--color=auto' -Naur php-8.4.18/ext/opcache/jit/ir/ir_x86.dasc php-8.4.20RC1/ext/opcache/jit/ir/ir_x86.dasc
--- php-8.4.18/ext/opcache/jit/ir/ir_x86.dasc	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/opcache/jit/ir/ir_x86.dasc	2026-04-01 04:35:36.011343056 +0000
@@ -1167,6 +1167,7 @@
 	_(CMP_AND_BRANCH_FP)   \
 	_(TEST_AND_BRANCH_INT) \
 	_(JCC_INT)             \
+	_(COND_TEST_INT)       \
 	_(COND_CMP_INT)        \
 	_(COND_CMP_FP)         \
 	_(GUARD_CMP_INT)       \
@@ -1405,6 +1406,7 @@
 			}
 			IR_FALLTHROUGH;
 		case IR_COND_CMP_INT:
+		case IR_COND_TEST_INT:
 			insn = &ctx->ir_base[ref];
 			if (IR_IS_TYPE_INT(insn->type)) {
 				if (IR_IS_CONST_REF(insn->op3) || ir_rule(ctx, insn->op3) == IR_STATIC_ALLOCA) {
@@ -2125,6 +2127,34 @@
 	return 0;
 }
 
+static bool all_usages_are_fusable(ir_ctx *ctx, ir_ref ref)
+{
+	ir_insn *insn = &ctx->ir_base[ref];
+
+	if (insn->op >= IR_EQ && insn->op <= IR_UNORDERED) {
+		ir_use_list *use_list = &ctx->use_lists[ref];
+		ir_ref n = use_list->count;
+
+		if (n > 0) {
+			ir_ref *p = ctx->use_edges + use_list->refs;
+
+			do {
+				insn = &ctx->ir_base[*p];
+				if (insn->op != IR_IF
+				 && insn->op != IR_GUARD
+				 && insn->op != IR_GUARD_NOT
+				 && (insn->op != IR_COND || insn->op2 == ref || insn->op3 == ref)) {
+					return 0;
+				}
+				p++;
+				n--;
+			} while (n);
+			return 1;
+		}
+	}
+	return 0;
+}
+
 static uint32_t ir_match_insn(ir_ctx *ctx, ir_ref ref)
 {
 	ir_insn *op2_insn;
@@ -2877,7 +2907,7 @@
 				return IR_RETURN_FP;
 			}
 		case IR_IF:
-			if (!IR_IS_CONST_REF(insn->op2) && ctx->use_lists[insn->op2].count == 1) {
+			if (!IR_IS_CONST_REF(insn->op2) && (ctx->use_lists[insn->op2].count == 1 || all_usages_are_fusable(ctx, insn->op2))) {
 				op2_insn = &ctx->ir_base[insn->op2];
 				if (op2_insn->op >= IR_EQ && op2_insn->op <= IR_UNORDERED) {
 					if (IR_IS_TYPE_INT(ctx->ir_base[op2_insn->op1].type)) {
@@ -2889,7 +2919,9 @@
 
 							if (op1_insn->op == IR_AND && ctx->use_lists[op2_insn->op1].count == 1) {
 								/* v = AND(_, _); c = CMP(v, 0) ... IF(c) => SKIP_TEST; SKIP ... TEST_AND_BRANCH */
-								ir_match_fuse_load_test_int(ctx, op1_insn, ref);
+								if (ctx->use_lists[insn->op2].count == 1) {
+									ir_match_fuse_load_test_int(ctx, op1_insn, ref);
+								}
 								ctx->rules[op2_insn->op1] = IR_FUSED | IR_TEST_INT;
 								ctx->rules[insn->op2] = IR_FUSED | IR_SIMPLE | IR_NOP;
 								return IR_TEST_AND_BRANCH_INT;
@@ -2901,10 +2933,14 @@
 												op2_insn->op == IR_LT || op2_insn->op == IR_GE)))) {
 								/* v = BINOP(_, _); c = CMP(v, 0) ... IF(c) => BINOP; SKIP_CMP ... JCC */
 								if (ir_op_flags[op1_insn->op] & IR_OP_FLAG_COMMUTATIVE) {
-									ir_match_fuse_load_commutative_int(ctx, op1_insn, ref);
+									if (ctx->use_lists[insn->op2].count == 1) {
+										ir_match_fuse_load_commutative_int(ctx, op1_insn, ref);
+									}
 									ctx->rules[op2_insn->op1] = IR_BINOP_INT | IR_MAY_SWAP;
 								} else {
-									ir_match_fuse_load(ctx, op1_insn->op2, ref);
+									if (ctx->use_lists[insn->op2].count == 1) {
+										ir_match_fuse_load(ctx, op1_insn->op2, ref);
+									}
 									ctx->rules[op2_insn->op1] = IR_BINOP_INT;
 								}
 								ctx->rules[insn->op2] = IR_FUSED | IR_CMP_INT;
@@ -2912,12 +2948,16 @@
 							}
 						}
 						/* c = CMP(_, _) ... IF(c) => SKIP_CMP ... CMP_AND_BRANCH */
-						ir_match_fuse_load_cmp_int(ctx, op2_insn, ref);
+						if (ctx->use_lists[insn->op2].count == 1) {
+							ir_match_fuse_load_cmp_int(ctx, op2_insn, ref);
+						}
 						ctx->rules[insn->op2] = IR_FUSED | IR_CMP_INT;
 						return IR_CMP_AND_BRANCH_INT;
 					} else {
 						/* c = CMP(_, _) ... IF(c) => SKIP_CMP ... CMP_AND_BRANCH */
-						ir_match_fuse_load_cmp_fp_br(ctx, op2_insn, ref);
+						if (ctx->use_lists[insn->op2].count == 1) {
+							ir_match_fuse_load_cmp_fp_br(ctx, op2_insn, ref);
+						}
 						ctx->rules[insn->op2] = IR_FUSED | IR_CMP_FP;
 						return IR_CMP_AND_BRANCH_FP;
 					}
@@ -3005,31 +3045,43 @@
 				break;
 			}
 		case IR_COND:
-			if (!IR_IS_CONST_REF(insn->op1) && ctx->use_lists[insn->op1].count == 1) {
+			if (!IR_IS_CONST_REF(insn->op1) && (ctx->use_lists[insn->op1].count == 1 || all_usages_are_fusable(ctx, insn->op1))) {
 				ir_insn *op1_insn = &ctx->ir_base[insn->op1];
 
 				if (op1_insn->op >= IR_EQ && op1_insn->op <= IR_UNORDERED) {
 					if (IR_IS_TYPE_INT(ctx->ir_base[op1_insn->op1].type)) {
-						ir_match_fuse_load_cmp_int(ctx, op1_insn, ref);
+						if (ctx->use_lists[insn->op1].count == 1) {
+							ir_match_fuse_load_cmp_int(ctx, op1_insn, ref);
+						}
 						ctx->rules[insn->op1] = IR_FUSED | IR_CMP_INT;
 						return IR_COND_CMP_INT;
 					} else {
-						ir_match_fuse_load_cmp_fp_br(ctx, op1_insn, ref);
+						if (ctx->use_lists[insn->op1].count == 1) {
+							ir_match_fuse_load_cmp_fp_br(ctx, op1_insn, ref);
+						}
 						ctx->rules[insn->op1] = IR_FUSED | IR_CMP_FP;
 						return IR_COND_CMP_FP;
 					}
+				} else if (op1_insn->op == IR_AND) {
+					/* c = AND(_, _) ... IF(c) => SKIP_TEST ... TEST_AND_BRANCH */
+					ir_match_fuse_load_test_int(ctx, op1_insn, ref);
+					ctx->rules[insn->op1] = IR_FUSED | IR_TEST_INT;
+					return IR_COND_TEST_INT;
 				}
 			}
+			if (IR_IS_TYPE_INT(ctx->ir_base[insn->op1].type)) {
+				ir_match_fuse_load(ctx, insn->op1, ref);
+			}
 			return IR_COND;
 		case IR_GUARD:
 		case IR_GUARD_NOT:
-			if (!IR_IS_CONST_REF(insn->op2) && ctx->use_lists[insn->op2].count == 1) {
+			if (!IR_IS_CONST_REF(insn->op2) && (ctx->use_lists[insn->op2].count == 1 || all_usages_are_fusable(ctx, insn->op2))) {
 				op2_insn = &ctx->ir_base[insn->op2];
-				if (op2_insn->op >= IR_EQ && op2_insn->op <= IR_UNORDERED
+				if (op2_insn->op >= IR_EQ && op2_insn->op <= IR_UNORDERED) {
 					// TODO: register allocator may clobber operands of CMP before they are used in the GUARD_CMP
-				 && (insn->op2 == ref - 1 ||
-				     (insn->op2 == ctx->prev_ref[ref] - 1
-				   && ctx->ir_base[ctx->prev_ref[ref]].op == IR_SNAPSHOT))) {
+//???				 && (insn->op2 == ref - 1 ||
+//???				     (insn->op2 == ctx->prev_ref[ref] - 1
+//???				   && ctx->ir_base[ctx->prev_ref[ref]].op == IR_SNAPSHOT))) {
 					if (IR_IS_TYPE_INT(ctx->ir_base[op2_insn->op1].type)) {
 						if (IR_IS_CONST_REF(op2_insn->op2)
 						 && !IR_IS_SYM_CONST(ctx->ir_base[op2_insn->op2].op)
@@ -3043,10 +3095,14 @@
 											(op2_insn->op == IR_EQ || op2_insn->op == IR_NE ||
 												op2_insn->op == IR_LT || op2_insn->op == IR_GE))) {
 									if (ir_op_flags[op1_insn->op] & IR_OP_FLAG_COMMUTATIVE) {
-										ir_match_fuse_load_commutative_int(ctx, op1_insn, ref);
+										if (ctx->use_lists[insn->op2].count == 1) {
+											ir_match_fuse_load_commutative_int(ctx, op1_insn, ref);
+										}
 										ctx->rules[op2_insn->op1] = IR_BINOP_INT | IR_MAY_SWAP;
 									} else {
-										ir_match_fuse_load(ctx, op1_insn->op2, ref);
+										if (ctx->use_lists[insn->op2].count == 1) {
+											ir_match_fuse_load(ctx, op1_insn->op2, ref);
+										}
 										ctx->rules[op2_insn->op1] = IR_BINOP_INT;
 									}
 									/* v = BINOP(_, _); c = CMP(v, 0) ... IF(c) => BINOP; SKIP_CMP ... GUARD_JCC */
@@ -3054,6 +3110,7 @@
 									return IR_GUARD_JCC_INT;
 								}
 							} else if ((ctx->flags & IR_OPT_CODEGEN)
+							 && ctx->use_lists[insn->op2].count == 1
 							 && op2_insn->op1 == insn->op2 - 2 /* before previous instruction */
 							 && ir_in_same_block(ctx, op2_insn->op1)
 							 && ctx->use_lists[op2_insn->op1].count == 2) {
@@ -3101,12 +3158,16 @@
 							}
 						}
 						/* c = CMP(_, _) ... GUARD(c) => SKIP_CMP ... GUARD_CMP */
-						ir_match_fuse_load_cmp_int(ctx, op2_insn, ref);
+						if (ctx->use_lists[insn->op2].count == 1) {
+							ir_match_fuse_load_cmp_int(ctx, op2_insn, ref);
+						}
 						ctx->rules[insn->op2] = IR_FUSED | IR_CMP_INT;
 						return IR_GUARD_CMP_INT;
 					} else {
 						/* c = CMP(_, _) ... GUARD(c) => SKIP_CMP ... GUARD_CMP */
-						ir_match_fuse_load_cmp_fp_br(ctx, op2_insn, ref);
+						if (ctx->use_lists[insn->op2].count == 1) {
+							ir_match_fuse_load_cmp_fp_br(ctx, op2_insn, ref);
+						}
 						ctx->rules[insn->op2] = IR_FUSED | IR_CMP_FP;
 						return IR_GUARD_CMP_FP;
 					}
@@ -6051,8 +6112,15 @@
 	ir_type type = ctx->ir_base[cmp_insn->op1].type;
 	ir_ref op1 = cmp_insn->op1;
 	ir_ref op2 = cmp_insn->op2;
-	ir_reg op1_reg = ctx->regs[ref][1];
-	ir_reg op2_reg = ctx->regs[ref][2];
+	ir_reg op1_reg, op2_reg;
+
+	if (UNEXPECTED(ctx->rules[ref] & IR_FUSED_REG)) {
+		op1_reg = ir_get_fused_reg(ctx, root, ref * sizeof(ir_ref) + 1);
+		op2_reg = ir_get_fused_reg(ctx, root, ref * sizeof(ir_ref) + 2);
+	} else {
+		op1_reg = ctx->regs[ref][1];
+		op2_reg = ctx->regs[ref][2];
+	}
 
 	if (op1_reg != IR_REG_NONE && IR_REG_SPILLED(op1_reg)) {
 		op1_reg = IR_REG_NUM(op1_reg);
@@ -6218,8 +6286,15 @@
 	ir_type type = binop_insn->type;
 	ir_ref op1 = binop_insn->op1;
 	ir_ref op2 = binop_insn->op2;
-	ir_reg op1_reg = ctx->regs[ref][1];
-	ir_reg op2_reg = ctx->regs[ref][2];
+	ir_reg op1_reg, op2_reg;
+
+	if (UNEXPECTED(ctx->rules[ref] & IR_FUSED_REG)) {
+		op1_reg = ir_get_fused_reg(ctx, root, ref * sizeof(ir_ref) + 1);
+		op2_reg = ir_get_fused_reg(ctx, root, ref * sizeof(ir_ref) + 2);
+	} else {
+		op1_reg = ctx->regs[ref][1];
+		op2_reg = ctx->regs[ref][2];
+	}
 
 	IR_ASSERT(binop_insn->op == IR_AND);
 	if (op1_reg != IR_REG_NONE) {
@@ -6329,8 +6404,13 @@
 
 	op1 = cmp_insn->op1;
 	op2 = cmp_insn->op2;
-	op1_reg = ctx->regs[cmp_ref][1];
-	op2_reg = ctx->regs[cmp_ref][2];
+	if (UNEXPECTED(ctx->rules[cmp_ref] & IR_FUSED_REG)) {
+		op1_reg = ir_get_fused_reg(ctx, root, cmp_ref * sizeof(ir_ref) + 1);
+		op2_reg = ir_get_fused_reg(ctx, root, cmp_ref * sizeof(ir_ref) + 2);
+	} else {
+		op1_reg = ctx->regs[cmp_ref][1];
+		op2_reg = ctx->regs[cmp_ref][2];
+	}
 
 	if (op1_reg == IR_REG_NONE && op2_reg != IR_REG_NONE && (op == IR_EQ || op == IR_NE)) {
 		ir_reg tmp_reg;
@@ -6603,8 +6683,15 @@
 	ir_type type = ctx->ir_base[cmp_insn->op1].type;
 	ir_ref op1 = cmp_insn->op1;
 	ir_ref op2 = cmp_insn->op2;
-	ir_reg op1_reg = ctx->regs[insn->op2][1];
-	ir_reg op2_reg = ctx->regs[insn->op2][2];
+	ir_reg op1_reg, op2_reg;
+
+	if (UNEXPECTED(ctx->rules[insn->op2] & IR_FUSED_REG)) {
+		op1_reg = ir_get_fused_reg(ctx, def, insn->op2 * sizeof(ir_ref) + 1);
+		op2_reg = ir_get_fused_reg(ctx, def, insn->op2 * sizeof(ir_ref) + 2);
+	} else {
+		op1_reg = ctx->regs[insn->op2][1];
+		op2_reg = ctx->regs[insn->op2][2];
+	}
 
 	if (op1_reg != IR_REG_NONE && IR_REG_SPILLED(op1_reg)) {
 		op1_reg = IR_REG_NUM(op1_reg);
@@ -6735,37 +6822,24 @@
 
 	IR_ASSERT(def_reg != IR_REG_NONE);
 
-	if (op2 != op3) {
-		if (op2_reg != IR_REG_NONE && IR_REG_SPILLED(op2_reg)) {
-			op2_reg = IR_REG_NUM(op2_reg);
-			ir_emit_load(ctx, type, op2_reg, op2);
-			if (op1 == op2) {
-				op1_reg = op2_reg;
-			}
-		}
-		if (op3_reg != IR_REG_NONE && IR_REG_SPILLED(op3_reg)) {
-			op3_reg = IR_REG_NUM(op3_reg);
-			ir_emit_load(ctx, type, op3_reg, op3);
-			if (op1 == op2) {
-				op1_reg = op3_reg;
-			}
-		}
-	} else if (op2_reg != IR_REG_NONE && IR_REG_SPILLED(op2_reg)) {
+	if (op2_reg != IR_REG_NONE && IR_REG_SPILLED(op2_reg)) {
 		op2_reg = IR_REG_NUM(op2_reg);
 		ir_emit_load(ctx, type, op2_reg, op2);
-		op3_reg = op2_reg;
 		if (op1 == op2) {
 			op1_reg = op2_reg;
 		}
-	} else if (op3_reg != IR_REG_NONE && IR_REG_SPILLED(op3_reg)) {
+		if (op3 == op2) {
+			op3_reg = op2_reg;
+		}
+	}
+	if (op3_reg != IR_REG_NONE && IR_REG_SPILLED(op3_reg)) {
 		op3_reg = IR_REG_NUM(op3_reg);
 		ir_emit_load(ctx, type, op3_reg, op3);
-		op2_reg = op3_reg;
 		if (op1 == op3) {
-			op1_reg = op3_reg;
+			op1_reg = op2_reg;
 		}
 	}
-	if (op1_reg != IR_REG_NONE && op1 != op2 && op1 != op3 && IR_REG_SPILLED(op1_reg)) {
+	if (op1_reg != IR_REG_NONE && IR_REG_SPILLED(op1_reg)) {
 		op1_reg = IR_REG_NUM(op1_reg);
 		ir_emit_load(ctx, op1_type, op1_reg, op1);
 	}
@@ -6774,7 +6848,13 @@
 		if (op1_reg != IR_REG_NONE) {
 			|	ASM_REG_REG_OP test, op1_type, op1_reg, op1_reg
 		} else {
-			ir_mem mem = ir_ref_spill_slot(ctx, op1);
+			ir_mem mem;
+
+			if (ir_rule(ctx, insn->op1) & IR_FUSED) {
+				mem = ir_fuse_load(ctx, def, insn->op1);
+			} else {
+				mem = ir_ref_spill_slot(ctx, insn->op1);
+			}
 
 			|	ASM_MEM_IMM_OP cmp, op1_type, mem, 0
 		}
@@ -6864,6 +6944,115 @@
 	}
 }
 
+static void ir_emit_cond_test_int(ir_ctx *ctx, ir_ref def, ir_insn *insn)
+{
+	ir_backend_data *data = ctx->data;
+	dasm_State **Dst = &data->dasm_state;
+	ir_type type = insn->type;
+	ir_ref op2 = insn->op2;
+	ir_ref op3 = insn->op3;
+	ir_reg def_reg = IR_REG_NUM(ctx->regs[def][0]);
+	ir_reg op2_reg = ctx->regs[def][2];
+	ir_reg op3_reg = ctx->regs[def][3];
+
+	if (op2 != op3) {
+		if (op2_reg != IR_REG_NONE && IR_REG_SPILLED(op2_reg)) {
+			op2_reg = IR_REG_NUM(op2_reg);
+			ir_emit_load(ctx, type, op2_reg, op2);
+		}
+		if (op3_reg != IR_REG_NONE && IR_REG_SPILLED(op3_reg)) {
+			op3_reg = IR_REG_NUM(op3_reg);
+			ir_emit_load(ctx, type, op3_reg, op3);
+		}
+	} else if (op2_reg != IR_REG_NONE && IR_REG_SPILLED(op2_reg)) {
+		op2_reg = IR_REG_NUM(op2_reg);
+		ir_emit_load(ctx, type, op2_reg, op2);
+		op3_reg = op2_reg;
+	} else if (op3_reg != IR_REG_NONE && IR_REG_SPILLED(op3_reg)) {
+		op3_reg = IR_REG_NUM(op3_reg);
+		ir_emit_load(ctx, type, op3_reg, op3);
+		op2_reg = op3_reg;
+	}
+
+	ir_emit_test_int_common(ctx, def, insn->op1, IR_NE);
+
+	if (IR_IS_TYPE_INT(type)) {
+		bool eq = 0;
+
+		if (op3_reg != IR_REG_NONE) {
+			if (op3_reg == def_reg) {
+				IR_ASSERT(op2_reg != IR_REG_NONE);
+				op3_reg = op2_reg;
+				eq = 1; // reverse
+			} else {
+				if (op2_reg != IR_REG_NONE) {
+					if (def_reg != op2_reg) {
+//						if (IR_IS_TYPE_INT(type)) {
+							ir_emit_mov(ctx, type, def_reg, op2_reg);
+//						} else {
+//							ir_emit_fp_mov(ctx, type, def_reg, op2_reg);
+//						}
+					}
+				} else if (IR_IS_CONST_REF(op2) && !IR_IS_SYM_CONST(ctx->ir_base[op2].op)) {
+					/* prevent "xor" and flags clobbering */
+					ir_emit_mov_imm_int(ctx, type, def_reg, ctx->ir_base[op2].val.i64);
+				} else {
+					ir_emit_load_ex(ctx, type, def_reg, op2, def);
+				}
+			}
+		} else {
+			IR_ASSERT(op2_reg != IR_REG_NONE && op2_reg != def_reg);
+			if (IR_IS_CONST_REF(op3) && !IR_IS_SYM_CONST(ctx->ir_base[op3].op)) {
+				/* prevent "xor" and flags clobbering */
+				ir_emit_mov_imm_int(ctx, type, def_reg, ctx->ir_base[op3].val.i64);
+			} else {
+				ir_emit_load_ex(ctx, type, def_reg, op3, def);
+			}
+			op3_reg = op2_reg;
+			eq = 1; // reverse
+		}
+
+		if (eq) {
+			|	ASM_REG_REG_OP2 cmovne, type, def_reg, op3_reg
+		} else {
+			|	ASM_REG_REG_OP2 cmove, type, def_reg, op3_reg
+		}
+	} else {
+		|	jne >2
+		|1:
+
+		if (op2_reg != IR_REG_NONE) {
+			if (def_reg != op2_reg) {
+				if (IR_IS_TYPE_INT(type)) {
+					ir_emit_mov(ctx, type, def_reg, op2_reg);
+				} else {
+					ir_emit_fp_mov(ctx, type, def_reg, op2_reg);
+				}
+			}
+		} else {
+			ir_emit_load_ex(ctx, type, def_reg, op2, def);
+		}
+		|	jmp >3
+		|2:
+		if (op3_reg != IR_REG_NONE) {
+			if (def_reg != op3_reg) {
+				if (IR_IS_TYPE_INT(type)) {
+					ir_emit_mov(ctx, type, def_reg, op3_reg);
+				} else {
+					ir_emit_fp_mov(ctx, type, def_reg, op3_reg);
+				}
+			}
+		} else {
+			ir_emit_load_ex(ctx, type, def_reg, op3, def);
+		}
+		|3:
+	}
+
+	if (IR_REG_SPILLED(ctx->regs[def][0])) {
+		ir_emit_store(ctx, type, def, def_reg);
+	}
+}
+
 static void ir_emit_cond_cmp_int(ir_ctx *ctx, ir_ref def, ir_insn *insn)
 {
 	ir_backend_data *data = ctx->data;
@@ -10454,9 +10643,16 @@
 	ir_type type = ctx->ir_base[cmp_insn->op1].type;
 	ir_ref op1 = cmp_insn->op1;
 	ir_ref op2 = cmp_insn->op2;
-	ir_reg op1_reg = ctx->regs[insn->op2][1];
-	ir_reg op2_reg = ctx->regs[insn->op2][2];
 	void *addr;
+	ir_reg op1_reg, op2_reg;
+
+	if (UNEXPECTED(ctx->rules[insn->op2] & IR_FUSED_REG)) {
+		op1_reg = ir_get_fused_reg(ctx, def, insn->op2 * sizeof(ir_ref) + 1);
+		op2_reg = ir_get_fused_reg(ctx, def, insn->op2 * sizeof(ir_ref) + 2);
+	} else {
+		op1_reg = ctx->regs[insn->op2][1];
+		op2_reg = ctx->regs[insn->op2][2];
+	}
 
 	if (op1_reg != IR_REG_NONE && IR_REG_SPILLED(op1_reg)) {
 		op1_reg = IR_REG_NUM(op1_reg);
@@ -11714,6 +11910,9 @@
 				case IR_COND:
 					ir_emit_cond(ctx, i, insn);
 					break;
+				case IR_COND_TEST_INT:
+					ir_emit_cond_test_int(ctx, i, insn);
+					break;
 				case IR_COND_CMP_INT:
 					ir_emit_cond_cmp_int(ctx, i, insn);
 					break;
@@ -12107,7 +12306,7 @@
 
 		do {
 			/* _cldemote(p); */
-			asm volatile(".byte 0x0f, 0x1c, 0x06" :: "S" (p));
+			__asm__ volatile(".byte 0x0f, 0x1c, 0x06" :: "S" (p));
 			p += 64;
 		} while (p < start + size);
 	}
@@ -12180,7 +12379,7 @@
 	return entry;
 }
 
-bool ir_needs_thunk(ir_code_buffer *code_buffer, void *addr)
+bool ir_needs_thunk(const ir_code_buffer *code_buffer, void *addr)
 {
 	return sizeof(void*) == 8 && !IR_MAY_USE_32BIT_ADDR(code_buffer, addr);
 }
diff '--color=auto' -Naur php-8.4.18/ext/opcache/jit/zend_jit_helpers.c php-8.4.20RC1/ext/opcache/jit/zend_jit_helpers.c
--- php-8.4.18/ext/opcache/jit/zend_jit_helpers.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/opcache/jit/zend_jit_helpers.c	2026-04-01 04:35:36.012030555 +0000
@@ -2776,7 +2776,7 @@
 //???				} else {
 //???					prop_info = zend_object_fetch_property_type_info(Z_OBJ_P(object), orig_zptr);
 //???				}
-				if (prop_info) {
+				if (prop_info && ZEND_TYPE_IS_SET(prop_info->type)) {
 					/* special case for typed properties */
 					zend_jit_assign_op_to_typed_prop(zptr, prop_info, value, binary_op);
 				} else {
@@ -2972,6 +2972,9 @@
 			}
 		} else {
 			zend_property_info *prop_info = (zend_property_info *) CACHED_PTR_EX(cache_slot + 2);
+			if (prop_info && !ZEND_TYPE_IS_SET(prop_info->type)) {
+				prop_info = NULL;
+			}
 
 			if (EXPECTED(Z_TYPE_P(prop) == IS_LONG)) {
 				fast_long_increment_function(prop);
@@ -3042,6 +3045,9 @@
 			}
 		} else {
 			zend_property_info *prop_info = (zend_property_info *) CACHED_PTR_EX(cache_slot + 2);
+			if (prop_info && !ZEND_TYPE_IS_SET(prop_info->type)) {
+				prop_info = NULL;
+			}
 
 			if (EXPECTED(Z_TYPE_P(prop) == IS_LONG)) {
 				fast_long_decrement_function(prop);
@@ -3110,6 +3116,9 @@
 			ZVAL_NULL(result);
 		} else {
 			zend_property_info *prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2);
+			if (prop_info && !ZEND_TYPE_IS_SET(prop_info->type)) {
+				prop_info = NULL;
+			}
 
 			if (EXPECTED(Z_TYPE_P(prop) == IS_LONG)) {
 				ZVAL_LONG(result, Z_LVAL_P(prop));
@@ -3171,6 +3180,9 @@
 			ZVAL_NULL(result);
 		} else {
 			zend_property_info *prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2);
+			if (prop_info && !ZEND_TYPE_IS_SET(prop_info->type)) {
+				prop_info = NULL;
+			}
 
 			if (EXPECTED(Z_TYPE_P(prop) == IS_LONG)) {
 				ZVAL_LONG(result, Z_LVAL_P(prop));
diff '--color=auto' -Naur php-8.4.18/ext/opcache/jit/zend_jit_ir.c php-8.4.20RC1/ext/opcache/jit/zend_jit_ir.c
--- php-8.4.18/ext/opcache/jit/zend_jit_ir.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/opcache/jit/zend_jit_ir.c	2026-04-01 04:35:36.012936332 +0000
@@ -8066,7 +8066,7 @@
 	return 1;
 }
 
-static int zend_jit_escape_if_undef(zend_jit_ctx *jit, int var, uint32_t flags, const zend_op *opline, int8_t reg)
+static int zend_jit_escape_if_undef(zend_jit_ctx *jit, int var, uint32_t flags, const zend_op *opline, const zend_op_array *op_array, int8_t reg)
 {
 	zend_jit_addr reg_addr = ZEND_ADDR_REF_ZVAL(zend_jit_deopt_rload(jit, IR_ADDR, reg));
 	ir_ref if_def = ir_IF(jit_Z_TYPE(jit, reg_addr));
@@ -8089,7 +8089,20 @@
 	}
 
 	jit_LOAD_IP_ADDR(jit, opline - 1);
-	ir_IJMP(jit_STUB_ADDR(jit, jit_stub_trace_escape));
+
+	/* We can't use trace_escape() because opcode handler may be overridden by JIT */
+	zend_jit_op_array_trace_extension *jit_extension =
+		(zend_jit_op_array_trace_extension*)ZEND_FUNC_INFO(op_array);
+	size_t offset = jit_extension->offset;
+	ir_ref ref = ir_CONST_ADDR(ZEND_OP_TRACE_INFO((opline - 1), offset)->orig_handler);
+	if (GCC_GLOBAL_REGS) {
+		ir_TAILCALL(IR_VOID, ref);
+	} else {
+#if defined(IR_TARGET_X86)
+		ref = ir_CAST_FC_FUNC(ref);
+#endif
+		ir_TAILCALL_1(IR_I32, ref, jit_FP(jit));
+	}
 
 	ir_IF_TRUE(if_def);
 
diff '--color=auto' -Naur php-8.4.18/ext/opcache/jit/zend_jit_trace.c php-8.4.20RC1/ext/opcache/jit/zend_jit_trace.c
--- php-8.4.18/ext/opcache/jit/zend_jit_trace.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/opcache/jit/zend_jit_trace.c	2026-04-01 04:35:36.013758600 +0000
@@ -3603,7 +3603,7 @@
 
 		ZEND_ASSERT(STACK_FLAGS(parent_stack, check2) == ZREG_ZVAL_COPY);
 		ZEND_ASSERT(reg != ZREG_NONE);
-		if (!zend_jit_escape_if_undef(jit, check2, flags, opline, reg)) {
+		if (!zend_jit_escape_if_undef(jit, check2, flags, opline, exit_info->op_array, reg)) {
 			return 0;
 		}
 		if (!zend_jit_restore_zval(jit, EX_NUM_TO_VAR(check2), reg)) {
@@ -4510,6 +4510,12 @@
 						op2_info = OP2_INFO();
 						op2_addr = OP2_REG_ADDR();
 						if ((op1_info & MAY_BE_UNDEF) || (op2_info & MAY_BE_UNDEF)) {
+							if (op1_type == IS_LONG || op1_type == IS_DOUBLE) {
+								CHECK_OP1_TRACE_TYPE();
+							}
+							if (op2_type == IS_LONG || op2_type == IS_DOUBLE) {
+								CHECK_OP2_TRACE_TYPE();
+							}
 							break;
 						}
 						if (opline->opcode == ZEND_ADD &&
@@ -4518,6 +4524,12 @@
 							/* pass */
 						} else if (!(op1_info & (MAY_BE_LONG|MAY_BE_DOUBLE)) ||
 						    !(op2_info & (MAY_BE_LONG|MAY_BE_DOUBLE))) {
+							if (op1_type == IS_LONG || op1_type == IS_DOUBLE) {
+								CHECK_OP1_TRACE_TYPE();
+							}
+							if (op2_type == IS_LONG || op2_type == IS_DOUBLE) {
+								CHECK_OP2_TRACE_TYPE();
+							}
 							break;
 						}
 						if (orig_op1_type != IS_UNKNOWN
diff '--color=auto' -Naur php-8.4.18/ext/opcache/shared_alloc_shm.c php-8.4.20RC1/ext/opcache/shared_alloc_shm.c
--- php-8.4.18/ext/opcache/shared_alloc_shm.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/opcache/shared_alloc_shm.c	2026-04-01 04:35:36.014208390 +0000
@@ -42,7 +42,6 @@
 # define MIN(x, y) ((x) > (y)? (y) : (x))
 #endif
 
-#define SEG_ALLOC_SIZE_MAX 32*1024*1024
 #define SEG_ALLOC_SIZE_MIN 2*1024*1024
 
 typedef struct  {
@@ -53,36 +52,38 @@
 static int create_segments(size_t requested_size, zend_shared_segment_shm ***shared_segments_p, int *shared_segments_count, const char **error_in)
 {
 	int i;
-	size_t allocate_size = 0, remaining_bytes = requested_size, seg_allocate_size;
+	size_t allocate_size = 0, remaining_bytes, seg_allocate_size;
 	int first_segment_id = -1;
 	key_t first_segment_key = -1;
 	struct shmid_ds sds;
 	int shmget_flags;
 	zend_shared_segment_shm *shared_segments;
 
-	seg_allocate_size = SEG_ALLOC_SIZE_MAX;
-	/* determine segment size we _really_ need:
-	 * no more than to include requested_size
-	 */
-	while (requested_size * 2 <= seg_allocate_size && seg_allocate_size > SEG_ALLOC_SIZE_MIN) {
-		seg_allocate_size >>= 1;
-	}
-
 	shmget_flags = IPC_CREAT|SHM_R|SHM_W|IPC_EXCL;
 
-	/* try allocating this much, if not - try shrinking */
-	while (seg_allocate_size >= SEG_ALLOC_SIZE_MIN) {
-		allocate_size = MIN(requested_size, seg_allocate_size);
-		first_segment_id = shmget(first_segment_key, allocate_size, shmget_flags);
-		if (first_segment_id != -1) {
-			break;
+	/* Try contiguous allocation first. */
+	seg_allocate_size = requested_size;
+	first_segment_id = shmget(first_segment_key, seg_allocate_size, shmget_flags);
+	if (UNEXPECTED(first_segment_id == -1)) {
+		/* Search for biggest n^2 < requested_size. */
+		seg_allocate_size = SEG_ALLOC_SIZE_MIN;
+		while (seg_allocate_size < requested_size / 2) {
+			seg_allocate_size *= 2;
 		}
-		seg_allocate_size >>= 1; /* shrink the allocated block */
-	}
 
-	if (first_segment_id == -1) {
-		*error_in = "shmget";
-		return ALLOC_FAILURE;
+		/* try allocating this much, if not - try shrinking */
+		while (seg_allocate_size >= SEG_ALLOC_SIZE_MIN) {
+			first_segment_id = shmget(first_segment_key, seg_allocate_size, shmget_flags);
+			if (first_segment_id != -1) {
+				break;
+			}
+			seg_allocate_size >>= 1; /* shrink the allocated block */
+		}
+
+		if (first_segment_id == -1) {
+			*error_in = "shmget";
+			return ALLOC_FAILURE;
+		}
 	}
 
 	*shared_segments_count = ((requested_size - 1) / seg_allocate_size) + 1;
diff '--color=auto' -Naur php-8.4.18/ext/opcache/tests/gh21052_a.inc php-8.4.20RC1/ext/opcache/tests/gh21052_a.inc
--- php-8.4.18/ext/opcache/tests/gh21052_a.inc	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/ext/opcache/tests/gh21052_a.inc	2026-04-01 04:35:36.014397848 +0000
@@ -0,0 +1,13 @@
+<?php
+
+class A {
+    const C = ['foo'];
+
+    public static function test() {
+        return ['foo'];
+    }
+}
+
+function test() {
+    return ['foo'];
+}
diff '--color=auto' -Naur php-8.4.18/ext/opcache/tests/gh21052_b.inc php-8.4.20RC1/ext/opcache/tests/gh21052_b.inc
--- php-8.4.18/ext/opcache/tests/gh21052_b.inc	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/ext/opcache/tests/gh21052_b.inc	2026-04-01 04:35:36.014488058 +0000
@@ -0,0 +1,5 @@
+<?php
+
+var_dump(A::C);
+var_dump(A::test());
+var_dump(test());
diff '--color=auto' -Naur php-8.4.18/ext/opcache/tests/gh21052.phpt php-8.4.20RC1/ext/opcache/tests/gh21052.phpt
--- php-8.4.18/ext/opcache/tests/gh21052.phpt	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/ext/opcache/tests/gh21052.phpt	2026-04-01 04:35:36.014317657 +0000
@@ -0,0 +1,32 @@
+--TEST--
+GH-21052: Preloaded constant erroneously propagated to file-cached script
+--CREDITS--
+Grummfy
+--EXTENSIONS--
+opcache
+--INI--
+opcache.enable=1
+opcache.enable_cli=1
+opcache.file_cache="{TMP}"
+opcache.preload={PWD}/gh21052_a.inc
+--SKIPIF--
+<?php
+if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
+?>
+--FILE--
+<?php
+require __DIR__ . '/gh21052_b.inc';
+?>
+--EXPECT--
+array(1) {
+  [0]=>
+  string(3) "foo"
+}
+array(1) {
+  [0]=>
+  string(3) "foo"
+}
+array(1) {
+  [0]=>
+  string(3) "foo"
+}
diff '--color=auto' -Naur php-8.4.18/ext/opcache/tests/gh21227.phpt php-8.4.20RC1/ext/opcache/tests/gh21227.phpt
--- php-8.4.18/ext/opcache/tests/gh21227.phpt	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/ext/opcache/tests/gh21227.phpt	2026-04-01 04:35:36.014563601 +0000
@@ -0,0 +1,23 @@
+--TEST--
+GH-21227: Borked SCCP of array containing partial object
+--CREDITS--
+Daniel Chong (chongwick)
+--EXTENSIONS--
+opcache
+--INI--
+opcache.enable=1
+opcache.enable_cli=1
+--FILE--
+<?php
+
+function test() {
+    $obj->a = 3;
+    $objs = [];
+    $obj = new stdClass;
+    $objs[] = $obj;
+}
+
+?>
+===DONE===
+--EXPECT--
+===DONE===
diff '--color=auto' -Naur php-8.4.18/ext/opcache/tests/jit/gh20838.inc php-8.4.20RC1/ext/opcache/tests/jit/gh20838.inc
--- php-8.4.18/ext/opcache/tests/jit/gh20838.inc	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/ext/opcache/tests/jit/gh20838.inc	2026-04-01 04:35:36.014698536 +0000
@@ -0,0 +1,53 @@
+<?php
+$result = json_decode('[{"ID":"49"},{"ID":"1080"},{"ID":"4415"},{"ID":"4763"},{"ID":"4926"},{"ID":"4933"},{"ID":"4935"},{"ID":"4938"},{"ID":"4939"},{"ID":"4947"},{"ID":"4952"},{"ID":"4953"},{"ID":"4962"},{"ID":"8558"},{"ID":"14888"},{"ID":"16879"},{"ID":"100003"},{"ID":"100007"},{"ID":"100013"},{"ID":"100017"},{"ID":"100019"},{"ID":"100027"},{"ID":"100031"},{"ID":"106427"},{"ID":"217955"},{"ID":"240000"},{"ID":"240010"},{"ID":"240021"},{"ID":"240079"},{"ID":"240210"},{"ID":"240227"},{"ID":"240249"},{"ID":"240273"},{"ID":"240333"},{"ID":"240335"},{"ID":"300024"},{"ID":"310001"},{"ID":"310025"},{"ID":"310034"},{"ID":"310042"},{"ID":"310111"},{"ID":"310191"},{"ID":"310219"},{"ID":"310236"},{"ID":"310322"},{"ID":"310356"},{"ID":"310360"},{"ID":"310394"},{"ID":"310405"},{"ID":"310411"}]', true);
+
+$result1 = json_decode('[{"ID":"1080","cat":"6","vote":"2"},{"ID":"4415","cat":"1","vote":"5"},{"ID":"4415","cat":"5","vote":"-5"},{"ID":"4763","cat":"1","vote":"5"},{"ID":"4926","cat":"1","vote":"5"},{"ID":"4933","cat":"1","vote":"4"},{"ID":"4935","cat":"1","vote":"5"},{"ID":"4938","cat":"1","vote":"5"},{"ID":"4939","cat":"1","vote":"5"},{"ID":"4947","cat":"1","vote":"4"},{"ID":"4952","cat":"1","vote":"3"},{"ID":"4953","cat":"1","vote":"5"},{"ID":"4962","cat":"1","vote":"4"},{"ID":"8558","cat":"1","vote":"3"},{"ID":"14888","cat":"4","vote":"5"},{"ID":"16879","cat":"4","vote":"-2"},{"ID":"16879","cat":"6","vote":"3"},{"ID":"100003","cat":"1","vote":"0"},{"ID":"100007","cat":"1","vote":"4"},{"ID":"100013","cat":"1","vote":"0"},{"ID":"100017","cat":"6","vote":"4"},{"ID":"100017","cat":"4","vote":"-4"},{"ID":"100019","cat":"1","vote":"1"},{"ID":"100027","cat":"1","vote":"3"},{"ID":"100031","cat":"1","vote":"2"},{"ID":"106427","cat":"5","vote":"-5"},{"ID":"217955","cat":"4","vote":"-1"},{"ID":"217955","cat":"4","vote":"-1"},{"ID":"240000","cat":"1","vote":"2"},{"ID":"240010","cat":"1","vote":"4"},{"ID":"240021","cat":"1","vote":"3"},{"ID":"240079","cat":"1","vote":"4"},{"ID":"240079","cat":"7","vote":"4"},{"ID":"240079","cat":"6","vote":"2"},{"ID":"240210","cat":"1","vote":"3"},{"ID":"240227","cat":"1","vote":"3"},{"ID":"240249","cat":"1","vote":"5"},{"ID":"240273","cat":"1","vote":"5"},{"ID":"240333","cat":"1","vote":"2"},{"ID":"240335","cat":"1","vote":"4"},{"ID":"300024","cat":"3","vote":"4"},{"ID":"300024","cat":"1","vote":"5"},{"ID":"310001","cat":"1","vote":"3"},{"ID":"310025","cat":"1","vote":"3"},{"ID":"310034","cat":"1","vote":"4"},{"ID":"310042","cat":"1","vote":"2"},{"ID":"310111","cat":"1","vote":"5"},{"ID":"310191","cat":"1","vote":"3"},{"ID":"310219","cat":"1","vote":"5"},{"ID":"310236","cat":"1","vote":"1"},{"ID":"310322","cat":"1","vote":"3"},{"ID":"310356","cat":"1","vote":"2"},{"ID":"310360","cat":"1","vote":"3"},{"ID":"310360","cat":"4","vote":"-5"},{"ID":"310394","cat":"1","vote":"1"},{"ID":"310394","cat":"3","vote":"2"},{"ID":"310405","cat":"1","vote":"5"},{"ID":"310411","cat":"1","vote":"4"}]', true);
+
+foreach ($result as $arr) {
+    $v = [];
+    foreach ($result1 as $arr1) {
+        if ($arr1['ID'] == $arr['ID']) $v[] = $arr1;
+    }
+    TLVotesStatUpdateBAD($arr['ID'], $v);
+}
+
+function TLVotesStatUpdateBAD(int $id, ?array $v = null): float
+{
+    static $k;
+    if (!isset($k)) $k = json_decode('{"4":{"tp":"20","st":"sum"},"3":{"tp":"30","st":"caa"},"2":{"tp":"60","st":"sum"},"1":{"tp":"50","st":"unique"},"5":{"tp":"50","st":"caa"},"6":{"tp":"20","st":"caa"},"7":{"tp":"60","st":"caa"},"8":{"tp":"60","st":"caa"},"255":{"tp":"0","st":"correction"}}', true);
+
+    $pav = 50;
+    $s = 0.0;
+    $corrections = 0;
+    $av = [];
+    $avc = [];
+
+    foreach ($v as $arr) {
+        if ($k[$arr['cat']]['st'] == 'unique') $av[$arr['cat']] = $arr['vote'];
+        elseif ($k[$arr['cat']]['st'] == 'correction') {
+            $av[$arr['cat']] = $arr['vote'];
+            $corrections++;
+        } else {
+            if ($arr['vote'] < 0) $arr['vote'] = $arr['vote'] / 2;
+            $av[$arr['cat']] ??= 0;
+            $avc[$arr['cat']] ??= 0;
+            $av[$arr['cat']] += $arr['vote'];
+            $avc[$arr['cat']]++;
+        }
+    }
+
+    if (($c = count($av))) {
+        $c -= $corrections;
+        foreach ($av as $key => $value) {
+            if ($k[$key]['st'] == 'correction') $s += $value;
+            else {
+                if ($k[$key]['st'] == 'caa') $value = $value / $avc[$key];
+                $s += $value / 5 * $k[$key]['tp'] * (1 + 50 / $k[$key]['tp'] * $pav / (100 * $c));
+            }
+        }
+    }
+
+    echo("$id $s\n");
+
+    return $s;
+}
diff '--color=auto' -Naur php-8.4.18/ext/opcache/tests/jit/gh20838.phpt php-8.4.20RC1/ext/opcache/tests/jit/gh20838.phpt
--- php-8.4.18/ext/opcache/tests/jit/gh20838.phpt	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/ext/opcache/tests/jit/gh20838.phpt	2026-04-01 04:35:36.014783507 +0000
@@ -0,0 +1,66 @@
+--TEST--
+GH-20838 (JIT compiler produces wrong arithmetic results)
+--INI--
+opcache.enable=1
+opcache.enable_cli=1
+opcache.jit=tracing
+opcache.jit_buffer_size=64M
+opcache.jit_hot_loop=61
+opcache.jit_hot_func=127
+opcache.jit_hot_return=8
+opcache.jit_hot_side_exit=8
+--EXTENSIONS--
+opcache
+--FILE_EXTERNAL--
+gh20838.inc
+--EXPECT--
+49 0
+1080 18
+4415 31.25
+4763 75
+4926 75
+4933 60
+4935 75
+4938 75
+4939 75
+4947 60
+4952 45
+4953 75
+4962 60
+8558 45
+14888 45
+16879 13
+100003 0
+100007 60
+100013 0
+100017 13
+100019 15
+100027 45
+100031 30
+106427 -37.5
+217955 -9
+240000 30
+240010 60
+240021 45
+240079 112.66666666667
+240210 45
+240227 45
+240249 75
+240273 75
+240333 30
+240335 60
+300024 96.5
+310001 45
+310025 45
+310034 60
+310042 30
+310111 75
+310191 45
+310219 75
+310236 15
+310322 45
+310356 30
+310360 21.25
+310394 29.5
+310405 75
+310411 60
diff '--color=auto' -Naur php-8.4.18/ext/opcache/tests/jit/gh21267_blacklist.phpt php-8.4.20RC1/ext/opcache/tests/jit/gh21267_blacklist.phpt
--- php-8.4.18/ext/opcache/tests/jit/gh21267_blacklist.phpt	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/ext/opcache/tests/jit/gh21267_blacklist.phpt	2026-04-01 04:35:36.014945122 +0000
@@ -0,0 +1,36 @@
+--TEST--
+GH-21267 (JIT infinite loop on FETCH_OBJ_R with IS_UNDEF via blacklisted trace exit)
+--INI--
+opcache.enable=1
+opcache.enable_cli=1
+opcache.jit=tracing
+opcache.jit_buffer_size=64M
+opcache.jit_hot_loop=0
+opcache.jit_hot_func=2
+opcache.jit_hot_return=0
+opcache.jit_hot_side_exit=1
+opcache.jit_max_side_traces=0
+--FILE--
+<?php
+class C {
+    public $x = true;
+    public function __get($name) { return null; }
+    public function getX() { return $this->x; }
+}
+
+$o1 = new C;
+$o2 = new C;
+$o2->x = false;
+$o3 = new C;
+unset($o3->x);
+$a = [$o1, $o2, $o3];
+
+for ($i = 0; $i < 8; $i++) {
+    $m = $a[$i % 3];
+    $m->getX();
+    $m->getX();
+}
+?>
+OK
+--EXPECT--
+OK
diff '--color=auto' -Naur php-8.4.18/ext/opcache/tests/jit/gh21267.phpt php-8.4.20RC1/ext/opcache/tests/jit/gh21267.phpt
--- php-8.4.18/ext/opcache/tests/jit/gh21267.phpt	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/ext/opcache/tests/jit/gh21267.phpt	2026-04-01 04:35:36.014864069 +0000
@@ -0,0 +1,35 @@
+--TEST--
+GH-21267 (JIT infinite loop on FETCH_OBJ_R with IS_UNDEF property in polymorphic context)
+--INI--
+opcache.enable=1
+opcache.enable_cli=1
+opcache.jit=tracing
+opcache.jit_buffer_size=64M
+opcache.jit_hot_loop=0
+opcache.jit_hot_func=2
+opcache.jit_hot_return=0
+opcache.jit_hot_side_exit=1
+--FILE--
+<?php
+class C {
+    public $x = true;
+    public function __get($name) { return null; }
+    public function getX() { return $this->x; }
+}
+
+$o1 = new C;
+$o2 = new C;
+$o2->x = false;
+$o3 = new C;
+unset($o3->x);
+$a = [$o1, $o2, $o3];
+
+for ($i = 0; $i < 8; $i++) {
+    $m = $a[$i % 3];
+    $m->getX();
+    $m->getX();
+}
+?>
+OK
+--EXPECT--
+OK
diff '--color=auto' -Naur php-8.4.18/ext/opcache/zend_accelerator_util_funcs.c php-8.4.20RC1/ext/opcache/zend_accelerator_util_funcs.c
--- php-8.4.18/ext/opcache/zend_accelerator_util_funcs.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/opcache/zend_accelerator_util_funcs.c	2026-04-01 04:35:36.015047886 +0000
@@ -360,6 +360,12 @@
 					: NULL;
 				if (parent_ce || (orig_ce->ce_flags & ZEND_ACC_LINKED)) {
 					ce = zend_try_early_bind(orig_ce, parent_ce, early_binding->lcname, zv);
+				} else if (ZSTR_LEN(early_binding->lc_parent_name) == 0) {
+					/* Parentless class: use the same binding path as the VM handler */
+					zval lcname_zv[2];
+					ZVAL_STR(&lcname_zv[0], early_binding->lcname);
+					ZVAL_STR(&lcname_zv[1], early_binding->rtd_key);
+					ce = zend_bind_class_in_slot(zv, lcname_zv, early_binding->lc_parent_name);
 				}
 			}
 			if (ce && early_binding->cache_slot != (uint32_t) -1) {
diff '--color=auto' -Naur php-8.4.18/ext/openssl/openssl.c php-8.4.20RC1/ext/openssl/openssl.c
--- php-8.4.18/ext/openssl/openssl.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/openssl/openssl.c	2026-04-01 04:35:36.015288010 +0000
@@ -2291,21 +2291,13 @@
 	X509_INFO *xi;
 	char cert_path[MAXPATHLEN];
 
-	if(!(stack = sk_X509_new_null())) {
-		php_openssl_store_errors();
-		php_error_docref(NULL, E_ERROR, "Memory allocation failure");
-		goto end;
-	}
-
 	if (!php_openssl_check_path(cert_file, cert_file_len, cert_path, arg_num)) {
-		sk_X509_free(stack);
 		goto end;
 	}
 
 	if (!(in = BIO_new_file(cert_path, PHP_OPENSSL_BIO_MODE_R(PKCS7_BINARY)))) {
 		php_openssl_store_errors();
 		php_error_docref(NULL, E_WARNING, "Error opening the file, %s", cert_path);
-		sk_X509_free(stack);
 		goto end;
 	}
 
@@ -2313,7 +2305,11 @@
 	if (!(sk = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL))) {
 		php_openssl_store_errors();
 		php_error_docref(NULL, E_WARNING, "Error reading the file, %s", cert_path);
-		sk_X509_free(stack);
+		goto end;
+	}
+
+	if(!(stack = sk_X509_new_reserve(NULL, sk_X509_INFO_num(sk)))) {
+		php_openssl_store_errors();
 		goto end;
 	}
 
@@ -2585,7 +2581,10 @@
 				}
 
 			}
-			sk_X509_push(sk, cert);
+			if (sk_X509_push(sk, cert) <= 0) {
+				X509_free(cert);
+				goto push_fail_exit;
+			}
 		} ZEND_HASH_FOREACH_END();
 	} else {
 		/* a single certificate */
@@ -2603,11 +2602,20 @@
 				goto clean_exit;
 			}
 		}
-		sk_X509_push(sk, cert);
+		if (sk_X509_push(sk, cert) <= 0) {
+			X509_free(cert);
+			goto push_fail_exit;
+		}
 	}
 
 clean_exit:
 	return sk;
+
+push_fail_exit:
+	php_openssl_store_errors();
+	php_sk_X509_free(sk);
+	sk = NULL;
+	goto clean_exit;
 }
 /* }}} */
 
@@ -2676,6 +2684,9 @@
 
 	if (args && (item = zend_hash_str_find(Z_ARRVAL_P(args), "extracerts", sizeof("extracerts")-1)) != NULL) {
 		ca = php_array_to_X509_sk(item, 5, "extracerts");
+		if (!ca) {
+			goto cleanup;
+		}
 	}
 	/* end parse extra config */
 
@@ -2769,6 +2780,9 @@
 
 	if (args && (item = zend_hash_str_find(Z_ARRVAL_P(args), "extracerts", sizeof("extracerts")-1)) != NULL) {
 		ca = php_array_to_X509_sk(item, 5, "extracerts");
+		if (!ca) {
+			goto cleanup;
+		}
 	}
 	/* end parse extra config */
 
@@ -3814,7 +3828,10 @@
 /* {{{ php_openssl_generate_private_key */
 static EVP_PKEY * php_openssl_generate_private_key(struct php_x509_request * req)
 {
-	if (req->priv_key_bits < MIN_KEY_LENGTH) {
+	if ((req->priv_key_type == OPENSSL_KEYTYPE_RSA ||
+			req->priv_key_type == OPENSSL_KEYTYPE_DH ||
+			req->priv_key_type == OPENSSL_KEYTYPE_DSA) &&
+			req->priv_key_bits < MIN_KEY_LENGTH) {
 		php_error_docref(NULL, E_WARNING, "Private key length must be at least %d bits, configured to %d",
 			MIN_KEY_LENGTH, req->priv_key_bits);
 		return NULL;
@@ -5835,7 +5852,10 @@
 					goto clean_exit;
 				}
 			}
-			sk_X509_push(recipcerts, cert);
+			if (sk_X509_push(recipcerts, cert) <= 0) {
+				X509_free(cert);
+				goto clean_exit;
+			}
 		} ZEND_HASH_FOREACH_END();
 	} else {
 		/* a single certificate */
@@ -5856,7 +5876,10 @@
 				goto clean_exit;
 			}
 		}
-		sk_X509_push(recipcerts, cert);
+		if (sk_X509_push(recipcerts, cert) <= 0) {
+			X509_free(cert);
+			goto clean_exit;
+		}
 	}
 
 	/* sanity check the cipher */
@@ -5877,16 +5900,21 @@
 	/* tack on extra headers */
 	if (zheaders) {
 		ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(zheaders), strindex, zcertval) {
+			int ret;
 			zend_string *str = zval_try_get_string(zcertval);
 			if (UNEXPECTED(!str)) {
 				goto clean_exit;
 			}
 			if (strindex) {
-				BIO_printf(outfile, "%s: %s\n", ZSTR_VAL(strindex), ZSTR_VAL(str));
+				ret = BIO_printf(outfile, "%s: %s\n", ZSTR_VAL(strindex), ZSTR_VAL(str));
 			} else {
-				BIO_printf(outfile, "%s\n", ZSTR_VAL(str));
+				ret = BIO_printf(outfile, "%s\n", ZSTR_VAL(str));
 			}
 			zend_string_release(str);
+			if (ret < 0) {
+				php_openssl_store_errors();
+				goto clean_exit;
+			}
 		} ZEND_HASH_FOREACH_END();
 	}
 
@@ -6105,6 +6133,7 @@
 			zend_string_release(str);
 			if (ret < 0) {
 				php_openssl_store_errors();
+				goto clean_exit;
 			}
 		} ZEND_HASH_FOREACH_END();
 	}
@@ -6444,7 +6473,10 @@
 					goto clean_exit;
 				}
 			}
-			sk_X509_push(recipcerts, cert);
+			if (sk_X509_push(recipcerts, cert) <= 0) {
+				php_openssl_store_errors();
+				goto clean_exit;
+			}
 		} ZEND_HASH_FOREACH_END();
 	} else {
 		/* a single certificate */
@@ -6464,7 +6496,10 @@
 				goto clean_exit;
 			}
 		}
-		sk_X509_push(recipcerts, cert);
+		if (sk_X509_push(recipcerts, cert) <= 0) {
+			php_openssl_store_errors();
+			goto clean_exit;
+		}
 	}
 
 	/* sanity check the cipher */
@@ -6489,16 +6524,21 @@
 	/* tack on extra headers */
 	if (zheaders && encoding == ENCODING_SMIME) {
 		ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(zheaders), strindex, zcertval) {
+			int ret;
 			zend_string *str = zval_try_get_string(zcertval);
 			if (UNEXPECTED(!str)) {
 				goto clean_exit;
 			}
 			if (strindex) {
-				BIO_printf(outfile, "%s: %s\n", ZSTR_VAL(strindex), ZSTR_VAL(str));
+				ret = BIO_printf(outfile, "%s: %s\n", ZSTR_VAL(strindex), ZSTR_VAL(str));
 			} else {
-				BIO_printf(outfile, "%s\n", ZSTR_VAL(str));
+				ret = BIO_printf(outfile, "%s\n", ZSTR_VAL(str));
 			}
 			zend_string_release(str);
+			if (ret < 0) {
+				php_openssl_store_errors();
+				goto clean_exit;
+			}
 		} ZEND_HASH_FOREACH_END();
 	}
 
@@ -6778,6 +6818,7 @@
 			zend_string_release(str);
 			if (ret < 0) {
 				php_openssl_store_errors();
+				goto clean_exit;
 			}
 		} ZEND_HASH_FOREACH_END();
 	}
diff '--color=auto' -Naur php-8.4.18/ext/openssl/tests/gh21083.phpt php-8.4.20RC1/ext/openssl/tests/gh21083.phpt
--- php-8.4.18/ext/openssl/tests/gh21083.phpt	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/ext/openssl/tests/gh21083.phpt	2026-04-01 04:35:36.015727841 +0000
@@ -0,0 +1,61 @@
+--TEST--
+GH-21083 (openssl_pkey_new() fails for EC keys when private_key_bits is not set)
+--EXTENSIONS--
+openssl
+--SKIPIF--
+<?php if (!defined("OPENSSL_KEYTYPE_EC")) die("skip EC disabled"); ?>
+--ENV--
+OPENSSL_CONF=
+--FILE--
+<?php
+// Create a minimal openssl.cnf without default_bits (simulates OpenSSL 3.6 default config)
+$conf = tempnam(sys_get_temp_dir(), 'ossl');
+file_put_contents($conf, "[req]\ndistinguished_name = req_dn\n[req_dn]\n");
+
+// EC key - size is determined by the curve, private_key_bits should not be required
+$key = openssl_pkey_new([
+    'config' => $conf,
+    'private_key_type' => OPENSSL_KEYTYPE_EC,
+    'curve_name' => 'prime256v1',
+]);
+var_dump($key !== false);
+$details = openssl_pkey_get_details($key);
+var_dump($details['bits']);
+var_dump($details['type'] === OPENSSL_KEYTYPE_EC);
+echo "EC OK\n";
+
+// X25519 - fixed size key, private_key_bits should not be required
+if (defined('OPENSSL_KEYTYPE_X25519')) {
+    $key = openssl_pkey_new([
+        'config' => $conf,
+        'private_key_type' => OPENSSL_KEYTYPE_X25519,
+    ]);
+    var_dump($key !== false);
+    echo "X25519 OK\n";
+} else {
+    echo "bool(true)\nX25519 OK\n";
+}
+
+// Ed25519 - fixed size key, private_key_bits should not be required
+if (defined('OPENSSL_KEYTYPE_ED25519')) {
+    $key = openssl_pkey_new([
+        'config' => $conf,
+        'private_key_type' => OPENSSL_KEYTYPE_ED25519,
+    ]);
+    var_dump($key !== false);
+    echo "Ed25519 OK\n";
+} else {
+    echo "bool(true)\nEd25519 OK\n";
+}
+
+unlink($conf);
+?>
+--EXPECT--
+bool(true)
+int(256)
+bool(true)
+EC OK
+bool(true)
+X25519 OK
+bool(true)
+Ed25519 OK
diff '--color=auto' -Naur php-8.4.18/ext/pcntl/pcntl.c php-8.4.20RC1/ext/pcntl/pcntl.c
--- php-8.4.18/ext/pcntl/pcntl.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/pcntl/pcntl.c	2026-04-01 04:35:36.015863858 +0000
@@ -798,15 +798,16 @@
 		RETURN_THROWS();
 	}
 
-	/* Add the function name to our signal table */
-	handle = zend_hash_index_update(&PCNTL_G(php_signal_table), signo, handle);
-	Z_TRY_ADDREF_P(handle);
-
+	/* Register with the OS first so that on failure we don't record a handler that was never installed */
 	if (php_signal4(signo, pcntl_signal_handler, (int) restart_syscalls, 1) == (void *)SIG_ERR) {
 		PCNTL_G(last_error) = errno;
 		php_error_docref(NULL, E_WARNING, "Error assigning signal");
 		RETURN_FALSE;
 	}
+
+	/* Add the function name to our signal table */
+	handle = zend_hash_index_update(&PCNTL_G(php_signal_table), signo, handle);
+	Z_TRY_ADDREF_P(handle);
 	RETURN_TRUE;
 }
 /* }}} */
@@ -1342,6 +1343,7 @@
 
 	queue = PCNTL_G(head);
 	PCNTL_G(head) = NULL; /* simple stores are atomic */
+	PCNTL_G(tail) = NULL;
 
 	/* Allocate */
 	while (queue) {
@@ -1363,6 +1365,9 @@
 #ifdef HAVE_STRUCT_SIGINFO_T
 				zval_ptr_dtor(&params[1]);
 #endif
+				if (EG(exception)) {
+					break;
+				}
 			}
 		}
 
@@ -1372,6 +1377,14 @@
 		queue = next;
 	}
 
+	/* drain the remaining in case of exception thrown */
+	while (queue) {
+		next = queue->next;
+		queue->next = PCNTL_G(spares);
+		PCNTL_G(spares) = queue;
+		queue = next;
+	}
+
 	PCNTL_G(pending_signals) = 0;
 
 	/* Re-enable queue */
@@ -1584,7 +1597,7 @@
 
 	pid = pid_is_null ? getpid() : pid;
 	fd = syscall(SYS_pidfd_open, pid, 0);
-	if (errno) {
+	if (fd == -1) {
 		PCNTL_G(last_error) = errno;
 		switch (errno) {
 			case EINVAL:
@@ -1610,11 +1623,12 @@
 		RETURN_FALSE;
 	}
 	ret = setns(fd, (int)nstype);
+	int setns_errno = errno;
 	close(fd);
 
 	if (ret == -1) {
-		PCNTL_G(last_error) = errno;
-		switch (errno) {
+		PCNTL_G(last_error) = setns_errno;
+		switch (setns_errno) {
 			case ESRCH:
 				zend_argument_value_error(1, "process no longer available (" ZEND_LONG_FMT ")", pid);
 				RETURN_THROWS();
@@ -1624,11 +1638,11 @@
 				RETURN_THROWS();
 
 			case EPERM:
-				php_error_docref(NULL, E_WARNING, "Error %d: No required capability for this process", errno);
+				php_error_docref(NULL, E_WARNING, "Error %d: No required capability for this process", setns_errno);
 				break;
 
 			default:
-			        php_error_docref(NULL, E_WARNING, "Error %d", errno);
+			        php_error_docref(NULL, E_WARNING, "Error %d", setns_errno);
 		}
 		RETURN_FALSE;
 	} else {
@@ -1733,6 +1747,7 @@
 
 		if (cpu < 0 || cpu >= maxcpus) {
 			zend_argument_value_error(2, "cpu id must be between 0 and " ZEND_ULONG_FMT " (" ZEND_LONG_FMT ")", maxcpus, cpu);
+			PCNTL_CPU_DESTROY(mask);
 			RETURN_THROWS();
 		}
 
diff '--color=auto' -Naur php-8.4.18/ext/pcntl/tests/pcntl_signal_dispatch_exception.phpt php-8.4.20RC1/ext/pcntl/tests/pcntl_signal_dispatch_exception.phpt
--- php-8.4.18/ext/pcntl/tests/pcntl_signal_dispatch_exception.phpt	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/ext/pcntl/tests/pcntl_signal_dispatch_exception.phpt	2026-04-01 04:35:36.016037105 +0000
@@ -0,0 +1,34 @@
+--TEST--
+pcntl_signal_dispatch() stops dispatching after handler throws exception
+--EXTENSIONS--
+pcntl
+posix
+--FILE--
+<?php
+
+$called = [];
+
+pcntl_signal(SIGUSR1, function ($signo) use (&$called) {
+    $called[] = 'SIGUSR1';
+    throw new \Exception('Exception in signal handler');
+});
+
+pcntl_signal(SIGUSR2, function ($signo) use (&$called) {
+    $called[] = 'SIGUSR2';
+});
+
+posix_kill(posix_getpid(), SIGUSR1);
+posix_kill(posix_getpid(), SIGUSR2);
+
+try {
+    pcntl_signal_dispatch();
+} catch (\Exception $e) {
+    echo $e->getMessage() . "\n";
+}
+
+echo "Handlers called: " . implode(', ', $called) . "\n";
+
+?>
+--EXPECT--
+Exception in signal handler
+Handlers called: SIGUSR1
diff '--color=auto' -Naur php-8.4.18/ext/pcntl/tests/pcntl_signal_functions_invalid_signals.phpt php-8.4.20RC1/ext/pcntl/tests/pcntl_signal_functions_invalid_signals.phpt
--- php-8.4.18/ext/pcntl/tests/pcntl_signal_functions_invalid_signals.phpt	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/ext/pcntl/tests/pcntl_signal_functions_invalid_signals.phpt	2026-04-01 04:35:36.016099994 +0000
@@ -0,0 +1,80 @@
+--TEST--
+pcntl_sigprocmask(), pcntl_sigwaitinfo(), and pcntl_sigtimedwait() properly throw on invalid signals
+--EXTENSIONS--
+pcntl
+--SKIPIF--
+<?php
+if (!function_exists("pcntl_sigprocmask")) die("skip pcntl_sigprocmask() not available");
+if (!function_exists("pcntl_sigwaitinfo")) die("skip pcntl_sigwaitinfo() not available");
+if (!function_exists("pcntl_sigtimedwait")) die("skip pcntl_sigtimedwait() not available");
+?>
+--INI--
+max_execution_time=0
+--FILE--
+<?php
+
+try {
+    pcntl_sigprocmask(SIG_BLOCK, ["not_a_signal"]);
+} catch (TypeError $e) {
+    echo $e->getMessage() . PHP_EOL;
+}
+
+try {
+    pcntl_sigprocmask(SIG_BLOCK, [0]);
+} catch (ValueError $e) {
+    echo $e->getMessage() . PHP_EOL;
+}
+
+try {
+    pcntl_sigprocmask(SIG_BLOCK, []);
+} catch (ValueError $e) {
+    echo $e->getMessage() . PHP_EOL;
+}
+
+try {
+    pcntl_sigwaitinfo(["not_a_signal"]);
+} catch (TypeError $e) {
+    echo $e->getMessage() . PHP_EOL;
+}
+
+try {
+    pcntl_sigwaitinfo([0]);
+} catch (ValueError $e) {
+    echo $e->getMessage() . PHP_EOL;
+}
+
+try {
+    pcntl_sigwaitinfo([]);
+} catch (ValueError $e) {
+    echo $e->getMessage() . PHP_EOL;
+}
+
+try {
+    pcntl_sigtimedwait(["not_a_signal"], $info, 1);
+} catch (TypeError $e) {
+    echo $e->getMessage() . PHP_EOL;
+}
+
+try {
+    pcntl_sigtimedwait([0], $info, 1);
+} catch (ValueError $e) {
+    echo $e->getMessage() . PHP_EOL;
+}
+
+try {
+    pcntl_sigtimedwait([], $info, 1);
+} catch (ValueError $e) {
+    echo $e->getMessage() . PHP_EOL;
+}
+
+?>
+--EXPECTF--
+pcntl_sigprocmask(): Argument #2 ($signals) signals must be of type int, string given
+pcntl_sigprocmask(): Argument #2 ($signals) signals must be between 1 and %d
+pcntl_sigprocmask(): Argument #2 ($signals) must not be empty
+pcntl_sigwaitinfo(): Argument #1 ($signals) signals must be of type int, string given
+pcntl_sigwaitinfo(): Argument #1 ($signals) signals must be between 1 and %d
+pcntl_sigwaitinfo(): Argument #1 ($signals) must not be empty
+pcntl_sigtimedwait(): Argument #1 ($signals) signals must be of type int, string given
+pcntl_sigtimedwait(): Argument #1 ($signals) signals must be between 1 and %d
+pcntl_sigtimedwait(): Argument #1 ($signals) must not be empty
diff '--color=auto' -Naur php-8.4.18/ext/pcre/php_pcre.c php-8.4.20RC1/ext/pcre/php_pcre.c
--- php-8.4.18/ext/pcre/php_pcre.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/pcre/php_pcre.c	2026-04-01 04:35:36.016264385 +0000
@@ -840,6 +840,7 @@
 		if (key != regex) {
 			zend_string_release_ex(key, 0);
 		}
+		pcre2_code_free(new_entry.re);
 		php_error_docref(NULL, E_WARNING, "Internal pcre2_pattern_info() error %d", rc);
 		pcre_handle_exec_error(PCRE2_ERROR_INTERNAL);
 		return NULL;
@@ -850,6 +851,7 @@
 		if (key != regex) {
 			zend_string_release_ex(key, 0);
 		}
+		pcre2_code_free(new_entry.re);
 		php_error_docref(NULL, E_WARNING, "Internal pcre_pattern_info() error %d", rc);
 		pcre_handle_exec_error(PCRE2_ERROR_INTERNAL);
 		return NULL;
@@ -1173,6 +1175,7 @@
 	HashTable		*marks = NULL;		/* Array of marks for PREG_PATTERN_ORDER */
 	pcre2_match_data *match_data;
 	PCRE2_SIZE		 start_offset2, orig_start_offset;
+	bool old_mdata_used;
 
 	char *subject = ZSTR_VAL(subject_str);
 	size_t subject_len = ZSTR_LEN(subject_str);
@@ -1242,7 +1245,9 @@
 	matched = 0;
 	PCRE_G(error_code) = PHP_PCRE_NO_ERROR;
 
-	if (!mdata_used && num_subpats <= PHP_PCRE_PREALLOC_MDATA_SIZE) {
+	old_mdata_used = mdata_used;
+	if (!old_mdata_used && num_subpats <= PHP_PCRE_PREALLOC_MDATA_SIZE) {
+		mdata_used = true;
 		match_data = mdata;
 	} else {
 		match_data = pcre2_match_data_create_from_pattern(pce->re, PCRE_G(gctx_zmm));
@@ -1294,7 +1299,18 @@
 			if (subpats != NULL) {
 				/* Try to get the list of substrings and display a warning if failed. */
 				if (UNEXPECTED(offsets[1] < offsets[0])) {
-					if (match_sets) efree(match_sets);
+					if (match_sets) {
+						for (i = 0; i < num_subpats; i++) {
+							zend_array_destroy(match_sets[i]);
+						}
+						efree(match_sets);
+					}
+					if (marks) {
+						zend_array_destroy(marks);
+					}
+					if (match_data != mdata) {
+						pcre2_match_data_free(match_data);
+					}
 					php_error_docref(NULL, E_WARNING, "Get subpatterns list failed");
 					RETURN_FALSE;
 				}
@@ -1428,6 +1444,7 @@
 	if (match_data != mdata) {
 		pcre2_match_data_free(match_data);
 	}
+	mdata_used = old_mdata_used;
 
 	/* Add the match sets to the output array and clean up */
 	if (match_sets) {
@@ -1489,7 +1506,8 @@
 	/* Compile regex or get it from cache. */
 	pcre_cache_entry *pce;
 	if ((pce = pcre_get_compiled_regex_cache(regex)) == NULL) {
-		RETURN_FALSE;
+		RETVAL_FALSE;
+		goto flf_clean;
 	}
 
 	pce->refcount++;
@@ -1631,6 +1649,7 @@
 	size_t			result_len; 		/* Length of result */
 	zend_string		*result;			/* Result of replacement */
 	pcre2_match_data *match_data;
+	bool old_mdata_used;
 
 	/* Calculate the size of the offsets array, and allocate memory for it. */
 	num_subpats = pce->capture_count + 1;
@@ -1644,7 +1663,9 @@
 	result_len = 0;
 	PCRE_G(error_code) = PHP_PCRE_NO_ERROR;
 
-	if (!mdata_used && num_subpats <= PHP_PCRE_PREALLOC_MDATA_SIZE) {
+	old_mdata_used = mdata_used;
+	if (!old_mdata_used && num_subpats <= PHP_PCRE_PREALLOC_MDATA_SIZE) {
+		mdata_used = true;
 		match_data = mdata;
 	} else {
 		match_data = pcre2_match_data_create_from_pattern(pce->re, PCRE_G(gctx_zmm));
@@ -1846,6 +1867,7 @@
 	if (match_data != mdata) {
 		pcre2_match_data_free(match_data);
 	}
+	mdata_used = old_mdata_used;
 
 	return result;
 }
@@ -2574,6 +2596,7 @@
 	uint32_t		 num_subpats;		/* Number of captured subpatterns */
 	zval			 tmp;
 	pcre2_match_data *match_data;
+	bool old_mdata_used;
 	char *subject = ZSTR_VAL(subject_str);
 
 	no_empty = flags & PREG_SPLIT_NO_EMPTY;
@@ -2600,7 +2623,9 @@
 		goto last;
 	}
 
-	if (!mdata_used && num_subpats <= PHP_PCRE_PREALLOC_MDATA_SIZE) {
+	old_mdata_used = mdata_used;
+	if (!old_mdata_used && num_subpats <= PHP_PCRE_PREALLOC_MDATA_SIZE) {
+		mdata_used = true;
 		match_data = mdata;
 	} else {
 		match_data = pcre2_match_data_create_from_pattern(pce->re, PCRE_G(gctx_zmm));
@@ -2729,6 +2754,7 @@
 	if (match_data != mdata) {
 		pcre2_match_data_free(match_data);
 	}
+	mdata_used = old_mdata_used;
 
 	if (PCRE_G(error_code) != PHP_PCRE_NO_ERROR) {
 		zval_ptr_dtor(return_value);
@@ -2928,6 +2954,7 @@
 	zend_ulong		 num_key;
 	bool		 invert;			/* Whether to return non-matching
 										   entries */
+	bool old_mdata_used;
 	pcre2_match_data *match_data;
 	invert = flags & PREG_GREP_INVERT ? 1 : 0;
 
@@ -2940,7 +2967,9 @@
 
 	PCRE_G(error_code) = PHP_PCRE_NO_ERROR;
 
-	if (!mdata_used && num_subpats <= PHP_PCRE_PREALLOC_MDATA_SIZE) {
+	old_mdata_used = mdata_used;
+	if (!old_mdata_used && num_subpats <= PHP_PCRE_PREALLOC_MDATA_SIZE) {
+		mdata_used = true;
 		match_data = mdata;
 	} else {
 		match_data = pcre2_match_data_create_from_pattern(pce->re, PCRE_G(gctx_zmm));
@@ -3005,6 +3034,7 @@
 	if (match_data != mdata) {
 		pcre2_match_data_free(match_data);
 	}
+	mdata_used = old_mdata_used;
 }
 /* }}} */
 
diff '--color=auto' -Naur php-8.4.18/ext/pcre/tests/pcre_reentrancy.phpt php-8.4.20RC1/ext/pcre/tests/pcre_reentrancy.phpt
--- php-8.4.18/ext/pcre/tests/pcre_reentrancy.phpt	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/ext/pcre/tests/pcre_reentrancy.phpt	2026-04-01 04:35:36.016544294 +0000
@@ -0,0 +1,58 @@
+--TEST--
+PCRE re-entrancy: nested calls should not corrupt global match data
+--EXTENSIONS--
+pcre
+--FILE--
+<?php
+
+echo "Testing nested PCRE calls..." . PHP_EOL;
+
+$subject = 'abc';
+
+// preg_replace_callback is the most common way to trigger re-entrancy
+$result = preg_replace_callback('/./', function($m) {
+    $char = $m[0];
+    echo "Outer match: $char" . PHP_EOL;
+
+    // 1. Nested preg_match
+    preg_match('/./', 'inner', $inner_m);
+
+    // 2. Nested preg_replace (string version)
+    preg_replace('/n/', 'N', 'inner');
+
+    // 3. Nested preg_split
+    preg_split('/n/', 'inner');
+
+    // 4. Nested preg_grep
+    preg_grep('/n/', ['inner']);
+
+    // If any of the above stole the global mdata buffer without setting mdata_used,
+    // the 'offsets' used by this outer preg_replace_callback loop would be corrupted.
+
+    return strtoupper($char);
+}, $subject);
+
+var_dump($result);
+
+echo PHP_EOL . "Testing deep nesting..." . PHP_EOL;
+
+$result = preg_replace_callback('/a/', function($m) {
+    return preg_replace_callback('/b/', function($m) {
+        return preg_replace_callback('/c/', function($m) {
+            return "SUCCESS";
+        }, 'c');
+    }, 'b');
+}, 'a');
+
+var_dump($result);
+
+?>
+--EXPECT--
+Testing nested PCRE calls...
+Outer match: a
+Outer match: b
+Outer match: c
+string(3) "ABC"
+
+Testing deep nesting...
+string(7) "SUCCESS"
diff '--color=auto' -Naur php-8.4.18/ext/pcre/tests/preg_match_all_negative_length_match.phpt php-8.4.20RC1/ext/pcre/tests/preg_match_all_negative_length_match.phpt
--- php-8.4.18/ext/pcre/tests/preg_match_all_negative_length_match.phpt	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/ext/pcre/tests/preg_match_all_negative_length_match.phpt	2026-04-01 04:35:36.016621790 +0000
@@ -0,0 +1,10 @@
+--TEST--
+preg_match_all() resource cleanup when \K in lookahead causes negative-length match
+--FILE--
+<?php
+$result = preg_match_all('/(?=ab\K)a/', 'ab', $matches);
+var_dump($result);
+?>
+--EXPECTF--
+Warning: preg_match_all(): Get subpatterns list failed in %s on line %d
+bool(false)
diff '--color=auto' -Naur php-8.4.18/ext/pcre/tests/preg_match_frameless_leak.phpt php-8.4.20RC1/ext/pcre/tests/preg_match_frameless_leak.phpt
--- php-8.4.18/ext/pcre/tests/preg_match_frameless_leak.phpt	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/ext/pcre/tests/preg_match_frameless_leak.phpt	2026-04-01 04:35:36.016708494 +0000
@@ -0,0 +1,23 @@
+--TEST--
+Memory leak in preg_match() frameless function with invalid regex and object arguments
+--FILE--
+<?php
+class Str {
+    private $val;
+    public function __construct($val) {
+        $this->val = str_repeat($val, random_int(1, 1));
+    }
+    public function __toString() {
+        return $this->val;
+    }
+}
+
+$regex = new Str("invalid regex");
+$subject = new Str("some subject");
+
+@preg_match($regex, $subject);
+
+echo "Done";
+?>
+--EXPECT--
+Done
diff '--color=auto' -Naur php-8.4.18/ext/pcre/tests/preg_match_negative_length_match.phpt php-8.4.20RC1/ext/pcre/tests/preg_match_negative_length_match.phpt
--- php-8.4.18/ext/pcre/tests/preg_match_negative_length_match.phpt	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/ext/pcre/tests/preg_match_negative_length_match.phpt	2026-04-01 04:35:36.016789287 +0000
@@ -0,0 +1,10 @@
+--TEST--
+preg_match() resource cleanup when \K in lookahead causes negative-length match
+--FILE--
+<?php
+$result = preg_match('/(?=ab\K)a/', 'ab', $matches);
+var_dump($result);
+?>
+--EXPECTF--
+Warning: preg_match(): Get subpatterns list failed in %s on line %d
+bool(false)
diff '--color=auto' -Naur php-8.4.18/ext/pdo_dblib/tests/GHSA-5hqh-c84r-qjcv.phpt php-8.4.20RC1/ext/pdo_dblib/tests/GHSA-5hqh-c84r-qjcv.phpt
--- php-8.4.18/ext/pdo_dblib/tests/GHSA-5hqh-c84r-qjcv.phpt	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/pdo_dblib/tests/GHSA-5hqh-c84r-qjcv.phpt	2026-04-01 04:35:36.016897581 +0000
@@ -4,6 +4,7 @@
 pdo_dblib
 --SKIPIF--
 <?php
+if (!getenv('RUN_RESOURCE_HEAVY_TESTS')) die('skip resource-heavy test');
 if (PHP_INT_SIZE != 4) die("skip for 32bit platforms only");
 if (PHP_OS_FAMILY === "Windows") die("skip not for Windows because the virtual address space for application is only 2GiB");
 if (getenv("SKIP_SLOW_TESTS")) die("skip slow test");
diff '--color=auto' -Naur php-8.4.18/ext/pdo_pgsql/pgsql_driver.c php-8.4.20RC1/ext/pdo_pgsql/pgsql_driver.c
--- php-8.4.18/ext/pdo_pgsql/pgsql_driver.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/pdo_pgsql/pgsql_driver.c	2026-04-01 04:35:36.017003171 +0000
@@ -509,7 +509,7 @@
 					break;
 #endif
 #ifdef CONNECTION_GSS_STARTUP
-				case CONNECTION_SSL_STARTUP:
+				case CONNECTION_GSS_STARTUP:
 					ZVAL_STRINGL(return_value, "Negotiating GSSAPI.", strlen("Negotiating GSSAPI."));
 					break;
 #endif
diff '--color=auto' -Naur php-8.4.18/ext/pdo_sqlite/tests/bug81740.phpt php-8.4.20RC1/ext/pdo_sqlite/tests/bug81740.phpt
--- php-8.4.18/ext/pdo_sqlite/tests/bug81740.phpt	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/pdo_sqlite/tests/bug81740.phpt	2026-04-01 04:35:36.017132165 +0000
@@ -5,6 +5,7 @@
 pdo_sqlite
 --SKIPIF--
 <?php
+if (!getenv('RUN_RESOURCE_HEAVY_TESTS')) die('skip resource-heavy test');
 if (PHP_INT_SIZE != 8) die("skip this test is for 64bit platforms only");
 if (getenv("SKIP_SLOW_TESTS")) die("skip slow test");
 ?>
diff '--color=auto' -Naur php-8.4.18/ext/pgsql/pgsql_arginfo.h php-8.4.20RC1/ext/pgsql/pgsql_arginfo.h
--- php-8.4.18/ext/pgsql/pgsql_arginfo.h	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/pgsql/pgsql_arginfo.h	2026-04-01 04:35:36.017754070 +0000
@@ -1,5 +1,5 @@
 /* This is a generated file, edit the .stub.php file instead.
- * Stub hash: 14b0bdd019480b850940b2c2b012b5f6d51746b8 */
+ * Stub hash: c7e052b85d35ac885704016224e488c67cb83df3 */
 
 ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_pg_connect, 0, 1, PgSql\\Connection, MAY_BE_FALSE)
 	ZEND_ARG_TYPE_INFO(0, connection_string, IS_STRING, 0)
@@ -828,7 +828,7 @@
 	REGISTER_LONG_CONSTANT("PGSQL_DML_EXEC", PGSQL_DML_EXEC, CONST_PERSISTENT);
 	REGISTER_LONG_CONSTANT("PGSQL_DML_ASYNC", PGSQL_DML_ASYNC, CONST_PERSISTENT);
 	REGISTER_LONG_CONSTANT("PGSQL_DML_STRING", PGSQL_DML_STRING, CONST_PERSISTENT);
-#if defined(PQTRACE_SUPPPRESS_TIMESTAMPS)
+#if defined(PQTRACE_SUPPRESS_TIMESTAMPS)
 	REGISTER_LONG_CONSTANT("PGSQL_TRACE_SUPPRESS_TIMESTAMPS", PQTRACE_SUPPRESS_TIMESTAMPS, CONST_PERSISTENT);
 #endif
 #if defined(PQTRACE_REGRESS_MODE)
diff '--color=auto' -Naur php-8.4.18/ext/pgsql/pgsql.c php-8.4.20RC1/ext/pgsql/pgsql.c
--- php-8.4.18/ext/pgsql/pgsql.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/pgsql/pgsql.c	2026-04-01 04:35:36.017319488 +0000
@@ -705,10 +705,12 @@
 			/* create the link */
 			pgsql = PQconnectdb(connstring);
 			if (pgsql == NULL || PQstatus(pgsql) == CONNECTION_BAD) {
-				PHP_PQ_ERROR("Unable to connect to PostgreSQL server: %s", pgsql)
+				zend_string *msgbuf = _php_pgsql_trim_message(PQerrorMessage(pgsql));
 				if (pgsql) {
 					PQfinish(pgsql);
 				}
+				php_error_docref(NULL, E_WARNING, "Unable to connect to PostgreSQL server: %s", ZSTR_VAL(msgbuf));
+				zend_string_release(msgbuf);
 				goto err;
 			}
 
@@ -789,19 +791,23 @@
 		if (connect_type & PGSQL_CONNECT_ASYNC) {
 			pgsql = PQconnectStart(connstring);
 			if (pgsql==NULL || PQstatus(pgsql)==CONNECTION_BAD) {
-				PHP_PQ_ERROR("Unable to connect to PostgreSQL server: %s", pgsql);
+				zend_string *msgbuf = _php_pgsql_trim_message(PQerrorMessage(pgsql));
 				if (pgsql) {
 					PQfinish(pgsql);
 				}
+				php_error_docref(NULL, E_WARNING, "Unable to connect to PostgreSQL server: %s", ZSTR_VAL(msgbuf));
+				zend_string_release(msgbuf);
 				goto err;
 			}
 		} else {
 			pgsql = PQconnectdb(connstring);
 			if (pgsql==NULL || PQstatus(pgsql)==CONNECTION_BAD) {
-				PHP_PQ_ERROR("Unable to connect to PostgreSQL server: %s", pgsql);
+				zend_string *msgbuf = _php_pgsql_trim_message(PQerrorMessage(pgsql));
 				if (pgsql) {
 					PQfinish(pgsql);
 				}
+				php_error_docref(NULL, E_WARNING, "Unable to connect to PostgreSQL server: %s", ZSTR_VAL(msgbuf));
+				zend_string_release(msgbuf);
 				goto err;
 			}
 		}
diff '--color=auto' -Naur php-8.4.18/ext/pgsql/pgsql.stub.php php-8.4.20RC1/ext/pgsql/pgsql.stub.php
--- php-8.4.18/ext/pgsql/pgsql.stub.php	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/pgsql/pgsql.stub.php	2026-04-01 04:35:36.017632730 +0000
@@ -432,7 +432,7 @@
      * @cvalue PGSQL_DML_STRING
      */
     const PGSQL_DML_STRING = UNKNOWN;
-#ifdef PQTRACE_SUPPPRESS_TIMESTAMPS
+#ifdef PQTRACE_SUPPRESS_TIMESTAMPS
     /**
      * @var int
      * @cvalue PQTRACE_SUPPRESS_TIMESTAMPS
diff '--color=auto' -Naur php-8.4.18/ext/pgsql/tests/gh21162.phpt php-8.4.20RC1/ext/pgsql/tests/gh21162.phpt
--- php-8.4.18/ext/pgsql/tests/gh21162.phpt	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/ext/pgsql/tests/gh21162.phpt	2026-04-01 04:35:36.017889185 +0000
@@ -0,0 +1,18 @@
+--TEST--
+GH-21162 (pg_connect() on error memory leak)
+--EXTENSIONS--
+pgsql
+--FILE--
+<?php
+
+set_error_handler(function (int $errno, string $errstr) {
+    echo "Warning caught\n";
+});
+
+pg_connect('host=blablahost.');
+
+echo "Done\n";
+?>
+--EXPECT--
+Warning caught
+Done
diff '--color=auto' -Naur php-8.4.18/ext/phar/tests/phar_extract2.phpt php-8.4.20RC1/ext/phar/tests/phar_extract2.phpt
--- php-8.4.18/ext/phar/tests/phar_extract2.phpt	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/phar/tests/phar_extract2.phpt	2026-04-01 04:35:36.017981078 +0000
@@ -46,8 +46,6 @@
 @rmdir($dir . 'one/level');
 @rmdir($dir . 'one');
 @rmdir($dir);
-$dir = __DIR__ . '/extract1/';
-@rmdir($dir);
 ?>
 --EXPECTF--
 %sextract2%cfile1.txt
diff '--color=auto' -Naur php-8.4.18/ext/snmp/snmp.c php-8.4.20RC1/ext/snmp/snmp.c
--- php-8.4.18/ext/snmp/snmp.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/snmp/snmp.c	2026-04-01 04:35:36.018113238 +0000
@@ -959,7 +959,7 @@
 /* }}} */
 
 /* {{{ Set the authentication protocol in the snmpv3 session */
-static bool netsnmp_session_set_auth_protocol(struct snmp_session *s, zend_string *prot)
+static ZEND_ATTRIBUTE_NONNULL bool netsnmp_session_set_auth_protocol(struct snmp_session *s, zend_string *prot)
 {
 #ifndef DISABLE_MD5
 	if (zend_string_equals_literal_ci(prot, "MD5")) {
@@ -1011,7 +1011,7 @@
 /* }}} */
 
 /* {{{ Set the security protocol in the snmpv3 session */
-static bool netsnmp_session_set_sec_protocol(struct snmp_session *s, zend_string *prot)
+static ZEND_ATTRIBUTE_NONNULL bool netsnmp_session_set_sec_protocol(struct snmp_session *s, zend_string *prot)
 {
 #ifndef NETSNMP_DISABLE_DES
 	if (zend_string_equals_literal_ci(prot, "DES")) {
@@ -1048,9 +1048,10 @@
 /* }}} */
 
 /* {{{ Make key from pass phrase in the snmpv3 session */
-static bool netsnmp_session_gen_auth_key(struct snmp_session *s, zend_string *pass)
+static ZEND_ATTRIBUTE_NONNULL bool netsnmp_session_gen_auth_key(struct snmp_session *s, zend_string *pass)
 {
 	int snmp_errno;
+
 	s->securityAuthKeyLen = USM_AUTH_KU_LEN;
 	if ((snmp_errno = generate_Ku(s->securityAuthProto, s->securityAuthProtoLen,
 			(uint8_t *) ZSTR_VAL(pass), ZSTR_LEN(pass),
@@ -1063,7 +1064,7 @@
 /* }}} */
 
 /* {{{ Make key from pass phrase in the snmpv3 session */
-static bool netsnmp_session_gen_sec_key(struct snmp_session *s, zend_string *pass)
+static ZEND_ATTRIBUTE_NONNULL bool netsnmp_session_gen_sec_key(struct snmp_session *s, zend_string *pass)
 {
 	int snmp_errno;
 
@@ -1102,9 +1103,10 @@
 /* }}} */
 
 /* {{{ Set all snmpv3-related security options */
-static bool netsnmp_session_set_security(struct snmp_session *session, zend_string *sec_level,
+static ZEND_ATTRIBUTE_NONNULL_ARGS(2) bool netsnmp_session_set_security(struct snmp_session *session, zend_string *sec_level,
 	zend_string *auth_protocol, zend_string *auth_passphrase, zend_string *priv_protocol,
-	zend_string *priv_passphrase, zend_string *contextName, zend_string *contextEngineID)
+	zend_string *priv_passphrase, zend_string *contextName, zend_string *contextEngineID,
+	uint32_t auth_protocol_argnum)
 {
 
 	/* Setting the security level. */
@@ -1115,12 +1117,22 @@
 
 	if (session->securityLevel == SNMP_SEC_LEVEL_AUTHNOPRIV || session->securityLevel == SNMP_SEC_LEVEL_AUTHPRIV) {
 
+		if (!auth_protocol) {
+			zend_argument_value_error(auth_protocol_argnum, "cannot be null when security level is \"authNoPriv\" or \"authPriv\"");
+			return false;
+		}
+
 		/* Setting the authentication protocol. */
 		if (!netsnmp_session_set_auth_protocol(session, auth_protocol)) {
 			/* ValueError already generated, just bail out */
 			return false;
 		}
 
+		if (!auth_passphrase) {
+			zend_argument_value_error(auth_protocol_argnum + 1, "cannot be null when security level is \"authNoPriv\" or \"authPriv\"");
+			return false;
+		}
+
 		/* Setting the authentication passphrase. */
 		if (!netsnmp_session_gen_auth_key(session, auth_passphrase)) {
 			/* Warning message sent already, just bail out */
@@ -1128,12 +1140,23 @@
 		}
 
 		if (session->securityLevel == SNMP_SEC_LEVEL_AUTHPRIV) {
+
+			if (!priv_protocol) {
+				zend_argument_value_error(auth_protocol_argnum + 2, "cannot be null when security level is \"authPriv\"");
+				return false;
+			}
+
 			/* Setting the security protocol. */
 			if (!netsnmp_session_set_sec_protocol(session, priv_protocol)) {
 				/* ValueError already generated, just bail out */
 				return false;
 			}
 
+			if (!priv_passphrase) {
+				zend_argument_value_error(auth_protocol_argnum + 3, "cannot be null when security level is \"authPriv\"");
+				return false;
+			}
+
 			/* Setting the security protocol passphrase. */
 			if (!netsnmp_session_gen_sec_key(session, priv_passphrase)) {
 				/* Warning message sent already, just bail out */
@@ -1294,7 +1317,7 @@
 			netsnmp_session_free(&session);
 			RETURN_FALSE;
 		}
-		if (version == SNMP_VERSION_3 && !netsnmp_session_set_security(session, a3, a4, a5, a6, a7, NULL, NULL)) {
+		if (version == SNMP_VERSION_3 && !netsnmp_session_set_security(session, a3, a4, a5, a6, a7, NULL, NULL, 4)) {
 			php_free_objid_query(&objid_query, oid_ht, value_ht, st);
 			netsnmp_session_free(&session);
 			/* Warning message sent already, just bail out */
@@ -1669,7 +1692,7 @@
 		RETURN_THROWS();
 	}
 
-	if (!netsnmp_session_set_security(snmp_object->session, a1, a2, a3, a4, a5, a6, a7)) {
+	if (!netsnmp_session_set_security(snmp_object->session, a1, a2, a3, a4, a5, a6, a7, 2)) {
 		/* Warning message sent already, just bail out */
 		RETURN_FALSE;
 	}
diff '--color=auto' -Naur php-8.4.18/ext/snmp/tests/gh21336.phpt php-8.4.20RC1/ext/snmp/tests/gh21336.phpt
--- php-8.4.18/ext/snmp/tests/gh21336.phpt	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/ext/snmp/tests/gh21336.phpt	2026-04-01 04:35:36.018298959 +0000
@@ -0,0 +1,41 @@
+--TEST--
+GH-21336 (undefined behavior in snmp - NULL pointer dereference in setSecurity)
+--EXTENSIONS--
+snmp
+--FILE--
+<?php
+$session = new SNMP(SNMP::VERSION_3, 'localhost', 'user');
+
+// auth protocol NULL
+try {
+	$session->setSecurity('authPriv');
+} catch (ValueError $e) {
+	echo $e->getMessage() . PHP_EOL;
+}
+
+// auth passphrase NULL
+try {
+	$session->setSecurity('authNoPriv', 'MD5');
+} catch (ValueError $e) {
+	echo $e->getMessage() . PHP_EOL;
+}
+
+// priv protocol NULL
+try {
+	$session->setSecurity('authPriv', 'MD5', 'test12345');
+} catch (ValueError $e) {
+	echo $e->getMessage() . PHP_EOL;
+}
+
+// priv passphrase NULL
+try {
+	$session->setSecurity('authPriv', 'MD5', 'test12345', 'AES');
+} catch (ValueError $e) {
+	echo $e->getMessage() . PHP_EOL;
+}
+?>
+--EXPECT--
+SNMP::setSecurity(): Argument #2 ($authProtocol) cannot be null when security level is "authNoPriv" or "authPriv"
+SNMP::setSecurity(): Argument #3 ($authPassphrase) cannot be null when security level is "authNoPriv" or "authPriv"
+SNMP::setSecurity(): Argument #4 ($privacyProtocol) cannot be null when security level is "authPriv"
+SNMP::setSecurity(): Argument #5 ($privacyPassphrase) cannot be null when security level is "authPriv"
diff '--color=auto' -Naur php-8.4.18/ext/soap/php_encoding.c php-8.4.20RC1/ext/soap/php_encoding.c
--- php-8.4.18/ext/soap/php_encoding.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/soap/php_encoding.c	2026-04-01 04:35:36.018495951 +0000
@@ -2534,19 +2534,20 @@
 		xmlNsPtr nsptr;
 
 		parse_namespace(attr->children->content, &type, &ns);
+		char *type_dup = estrdup(type);
 		nsptr = xmlSearchNs(attr->doc, attr->parent, BAD_CAST(ns));
 
-		end = strrchr(type,'[');
+		end = strrchr(type_dup,'[');
 		if (end) {
 			*end = '\0';
 			dimension = calc_dimension(end+1);
 			dims = get_position(dimension, end+1);
 		}
 		if (nsptr != NULL) {
-			enc = get_encoder(SOAP_GLOBAL(sdl), (char*)nsptr->href, type);
+			enc = get_encoder(SOAP_GLOBAL(sdl), (char*)nsptr->href, type_dup);
 		}
 		if (ns) {efree(ns);}
-
+		if (type_dup) efree(type_dup);
 	} else if ((attr = get_attribute(data->properties,"itemType")) &&
 	    attr->children &&
 	    attr->children->content) {
diff '--color=auto' -Naur php-8.4.18/ext/soap/php_http.c php-8.4.20RC1/ext/soap/php_http.c
--- php-8.4.18/ext/soap/php_http.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/soap/php_http.c	2026-04-01 04:35:36.018754620 +0000
@@ -1010,23 +1010,23 @@
 		char *sempos = strstr(cookie, ";");
 		if (eqpos != NULL && (sempos == NULL || sempos > eqpos)) {
 			smart_str name = {0};
-			int cookie_len;
 			zval zcookie;
+			size_t cookie_value_len;
 
 			if (sempos != NULL) {
-				cookie_len = sempos-(eqpos+1);
+				cookie_value_len = sempos-(eqpos+1);
 			} else {
-				cookie_len = strlen(cookie)-(eqpos-cookie)-1;
+				cookie_value_len = strlen(cookie)-(eqpos-cookie)-1;
 			}
 
 			smart_str_appendl(&name, cookie, eqpos - cookie);
 			smart_str_0(&name);
 
 			array_init(&zcookie);
-			add_index_stringl(&zcookie, 0, eqpos + 1, cookie_len);
+			add_index_stringl(&zcookie, 0, eqpos + 1, cookie_value_len);
 
 			if (sempos != NULL) {
-				char *options = cookie + cookie_len+1;
+				char *options = sempos + 1;
 				while (*options) {
 					while (*options == ' ') {options++;}
 					sempos = strstr(options, ";");
diff '--color=auto' -Naur php-8.4.18/ext/soap/tests/bugs/cookie_parse_options_offset.phpt php-8.4.20RC1/ext/soap/tests/bugs/cookie_parse_options_offset.phpt
--- php-8.4.18/ext/soap/tests/bugs/cookie_parse_options_offset.phpt	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/ext/soap/tests/bugs/cookie_parse_options_offset.phpt	2026-04-01 04:35:36.018924401 +0000
@@ -0,0 +1,61 @@
+--TEST--
+SOAP Set-Cookie option parsing starts at wrong offset due to variable shadowing
+--EXTENSIONS--
+soap
+--SKIPIF--
+<?php
+if (!file_exists(__DIR__ . "/../../../../sapi/cli/tests/php_cli_server.inc")) {
+    echo "skip sapi/cli/tests/php_cli_server.inc required but not found";
+}
+?>
+--FILE--
+<?php
+
+include __DIR__ . "/../../../../sapi/cli/tests/php_cli_server.inc";
+
+$args = ["-d", "extension_dir=" . ini_get("extension_dir"), "-d", "extension=" . (substr(PHP_OS, 0, 3) == "WIN" ? "php_" : "") . "soap." . PHP_SHLIB_SUFFIX];
+if (php_ini_loaded_file()) {
+    $args[] = "-c";
+    $args[] = php_ini_loaded_file();
+}
+
+// A 10-char name makes the wrong offset land exactly on the value "path=/evil",
+// falsely matching it as a path attribute.
+$code = <<<'PHP'
+header("Content-Type: text/xml");
+header("Set-Cookie: sessionkey=path=/evil;domain=good.com");
+echo <<<XML
+<?xml version="1.0" encoding="UTF-8"?>
+<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="test-uri">
+  <SOAP-ENV:Body>
+    <ns1:testResponse/>
+  </SOAP-ENV:Body>
+</SOAP-ENV:Envelope>
+XML;
+PHP;
+
+php_cli_server_start($code, null, $args);
+
+$client = new SoapClient(null, [
+    'location' => 'http://' . PHP_CLI_SERVER_ADDRESS . '/test/endpoint',
+    'uri' => 'test-uri',
+    'trace' => true,
+]);
+
+try {
+    $client->__soapCall("test", []);
+} catch (SoapFault $e) {
+    // Response parsing may fault, cookies are still stored
+}
+
+$cookies = $client->__getCookies();
+
+// path should default to "/test" from the request URI, not "/evil" from the value.
+echo "value: " . $cookies['sessionkey'][0] . "\n";
+echo "path: " . $cookies['sessionkey'][1] . "\n";
+echo "domain: " . $cookies['sessionkey'][2] . "\n";
+?>
+--EXPECT--
+value: path=/evil
+path: /test
+domain: good.com
diff '--color=auto' -Naur php-8.4.18/ext/soap/tests/soap_qname_crash.phpt php-8.4.20RC1/ext/soap/tests/soap_qname_crash.phpt
--- php-8.4.18/ext/soap/tests/soap_qname_crash.phpt	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/soap/tests/soap_qname_crash.phpt	2026-04-01 04:35:36.019019981 +0000
@@ -4,6 +4,7 @@
 soap
 --SKIPIF--
 <?php
+if (!getenv('RUN_RESOURCE_HEAVY_TESTS')) die('skip resource-heavy test');
 if (PHP_INT_SIZE != 8) die("skip: 64-bit only");
 ?>
 --INI--
diff '--color=auto' -Naur php-8.4.18/ext/sockets/conversions.c php-8.4.20RC1/ext/sockets/conversions.c
--- php-8.4.18/ext/sockets/conversions.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/sockets/conversions.c	2026-04-01 04:35:36.019127645 +0000
@@ -611,7 +611,7 @@
 	} else {
 		/* error already emitted, but let's emit another more relevant */
 		do_from_zval_err(ctx, "could not resolve address '%s' to get an AF_INET6 "
-				"address", Z_STRVAL_P(zaddr_str));
+				"address", ZSTR_VAL(addr_str));
 	}
 
 	zend_tmp_string_release(tmp_addr_str);
diff '--color=auto' -Naur php-8.4.18/ext/sockets/sockets.c php-8.4.20RC1/ext/sockets/sockets.c
--- php-8.4.18/ext/sockets/sockets.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/sockets/sockets.c	2026-04-01 04:35:36.019294059 +0000
@@ -1584,6 +1584,12 @@
 	switch (php_sock->type) {
 		case AF_UNIX:
 			memset(&s_un, 0, sizeof(s_un));
+
+			if (addr_len >= sizeof(s_un.sun_path)) {
+				zend_argument_value_error(5, "must be less than %d", sizeof(s_un.sun_path));
+				RETURN_THROWS();
+			}
+
 			s_un.sun_family = AF_UNIX;
 			snprintf(s_un.sun_path, sizeof(s_un.sun_path), "%s", addr);
 
diff '--color=auto' -Naur php-8.4.18/ext/sockets/tests/gh21161.phpt php-8.4.20RC1/ext/sockets/tests/gh21161.phpt
--- php-8.4.18/ext/sockets/tests/gh21161.phpt	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/ext/sockets/tests/gh21161.phpt	2026-04-01 04:35:36.019484379 +0000
@@ -0,0 +1,19 @@
+--TEST--
+GH-21161 (IPV6_PKTINFO socket option crash with null addr array entry)
+--EXTENSIONS--
+sockets
+--SKIPIF--
+<?php
+if (substr(PHP_OS, 0, 3) == 'WIN') {
+    die('skip.. Not valid for Windows');
+}
+?>
+--FILE--
+<?php
+$sock = socket_create(AF_INET6, SOCK_DGRAM, 0);
+socket_set_option($sock, IPPROTO_IPV6, IPV6_PKTINFO, ['addr' => null, 'ifindex' => 0]);
+?>
+--EXPECTF--
+Warning: socket_set_option(): Host lookup failed [%i]: %s on line %d
+
+Warning: socket_set_option(): error converting user data (path: in6_pktinfo > addr): could not resolve address '' to get an AF_INET6 address in %s on line %d
diff '--color=auto' -Naur php-8.4.18/ext/sockets/tests/socket_sendto_unix_addr_too_long.phpt php-8.4.20RC1/ext/sockets/tests/socket_sendto_unix_addr_too_long.phpt
--- php-8.4.18/ext/sockets/tests/socket_sendto_unix_addr_too_long.phpt	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/ext/sockets/tests/socket_sendto_unix_addr_too_long.phpt	2026-04-01 04:35:36.019552277 +0000
@@ -0,0 +1,29 @@
+--TEST--
+socket_sendto() with AF_UNIX rejects address exceeding sun_path limit
+--EXTENSIONS--
+sockets
+--SKIPIF--
+<?php
+if (substr(PHP_OS, 0, 3) == 'WIN') {
+    die('skip not valid for Windows');
+}
+?>
+--FILE--
+<?php
+$socket = socket_create(AF_UNIX, SOCK_DGRAM, 0);
+if (!$socket) {
+    die('Unable to create AF_UNIX socket');
+}
+
+$long_addr = str_repeat('a', 512);
+
+try {
+    socket_sendto($socket, "data", 4, 0, $long_addr);
+} catch (\ValueError $e) {
+    echo $e->getMessage() . PHP_EOL;
+}
+
+socket_close($socket);
+?>
+--EXPECTF--
+socket_sendto(): Argument #5 ($address) must be less than %d
diff '--color=auto' -Naur php-8.4.18/ext/spl/spl_heap.c php-8.4.20RC1/ext/spl/spl_heap.c
--- php-8.4.18/ext/spl/spl_heap.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/spl/spl_heap.c	2026-04-01 04:35:36.019681081 +0000
@@ -961,7 +961,7 @@
 {
 	spl_heap_object *object = Z_SPLHEAP_P(&iter->data);
 
-	if (UNEXPECTED(spl_heap_consistency_validations(object, false) != SUCCESS)) {
+	if (UNEXPECTED(spl_heap_consistency_validations(object, true) != SUCCESS)) {
 		return;
 	}
 
@@ -992,6 +992,10 @@
 		RETURN_THROWS();
 	}
 
+	if (UNEXPECTED(spl_heap_consistency_validations(intern, true) != SUCCESS)) {
+		RETURN_THROWS();
+	}
+
 	spl_ptr_heap_delete_top(intern->heap, NULL, ZEND_THIS);
 }
 /* }}} */
diff '--color=auto' -Naur php-8.4.18/ext/spl/tests/heap_next_write_lock.phpt php-8.4.20RC1/ext/spl/tests/heap_next_write_lock.phpt
--- php-8.4.18/ext/spl/tests/heap_next_write_lock.phpt	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/ext/spl/tests/heap_next_write_lock.phpt	2026-04-01 04:35:36.019808051 +0000
@@ -0,0 +1,34 @@
+--TEST--
+SplHeap::next() write lock
+--CREDITS--
+cnitlrt
+--FILE--
+<?php
+
+class EvilPQ extends SplPriorityQueue {
+    private bool $did = false;
+
+    public function compare(mixed $p1, mixed $p2): int {
+        if (!$this->did) {
+            $this->did = true;
+            // Re-entrant write during internal heap insertion comparison.
+            if (!$this->isEmpty()) {
+                $this->next(); // no write-lock validation
+            }
+        }
+        return parent::compare($p1, $p2);
+    }
+}
+
+$q = new EvilPQ();
+try {
+    for ($i = 0; $i < 200; $i++) {
+        $q->insert("d$i", 100 - $i);
+    }
+} catch (RuntimeException $e) {
+    echo $e::class, ": ", $e->getMessage(), "\n";
+}
+
+?>
+--EXPECT--
+RuntimeException: Heap cannot be changed when it is already being modified.
diff '--color=auto' -Naur php-8.4.18/ext/standard/basic_functions.c php-8.4.20RC1/ext/standard/basic_functions.c
--- php-8.4.18/ext/standard/basic_functions.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/standard/basic_functions.c	2026-04-01 04:35:36.019945510 +0000
@@ -1768,7 +1768,10 @@
 	}
 
 	if (i) {
-		php_output_start_default();
+		if (UNEXPECTED(php_output_start_default() != SUCCESS)) {
+			zend_throw_error(NULL, "Unable to start output handler");
+			RETURN_THROWS();
+		}
 	}
 
 	php_get_highlight_struct(&syntax_highlighter_ini);
@@ -1803,7 +1806,10 @@
 		Z_PARAM_PATH_STR(filename)
 	ZEND_PARSE_PARAMETERS_END();
 
-	php_output_start_default();
+	if (UNEXPECTED(php_output_start_default() != SUCCESS)) {
+		zend_throw_error(NULL, "Unable to start output handler");
+		RETURN_THROWS();
+	}
 
 	zend_stream_init_filename_ex(&file_handle, filename);
 	zend_save_lexical_state(&original_lex_state);
@@ -1840,7 +1846,10 @@
 	ZEND_PARSE_PARAMETERS_END();
 
 	if (i) {
-		php_output_start_default();
+		if (UNEXPECTED(php_output_start_default() != SUCCESS)) {
+			zend_throw_error(NULL, "Unable to start output handler");
+			RETURN_THROWS();
+		}
 	}
 
 	EG(error_reporting) = E_ERROR;
diff '--color=auto' -Naur php-8.4.18/ext/standard/exec.c php-8.4.20RC1/ext/standard/exec.c
--- php-8.4.18/ext/standard/exec.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/standard/exec.c	2026-04-01 04:35:36.020108188 +0000
@@ -282,7 +282,7 @@
 	size_t x, y;
 	zend_string *cmd;
 #ifndef PHP_WIN32
-	char *p = NULL;
+	const char *p = NULL;
 #endif
 
 	ZEND_ASSERT(ZSTR_LEN(unescaped_cmd) == strlen(ZSTR_VAL(unescaped_cmd)) && "Must be a binary safe string");
diff '--color=auto' -Naur php-8.4.18/ext/standard/filters.c php-8.4.20RC1/ext/standard/filters.c
--- php-8.4.18/ext/standard/filters.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/standard/filters.c	2026-04-01 04:35:36.020229847 +0000
@@ -1559,7 +1559,7 @@
 	php_convert_filter *inst;
 	php_stream_filter *retval = NULL;
 
-	char *dot;
+	const char *dot;
 	int conv_mode = 0;
 
 	if (filterparams != NULL && Z_TYPE_P(filterparams) != IS_ARRAY) {
diff '--color=auto' -Naur php-8.4.18/ext/standard/libavifinfo/avifinfo.c php-8.4.20RC1/ext/standard/libavifinfo/avifinfo.c
--- php-8.4.18/ext/standard/libavifinfo/avifinfo.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/standard/libavifinfo/avifinfo.c	2026-04-01 04:35:36.020473528 +0000
@@ -34,14 +34,15 @@
 // uint32_t is used everywhere in this file. It is unlikely to be insufficient
 // to parse AVIF headers.
 #define AVIFINFO_MAX_SIZE UINT32_MAX
-// AvifInfoInternalFeatures uses uint8_t to store values and the number of
-// values is clamped to 32 to limit the stack size.
+// Be reasonable. Avoid timeouts and out-of-memory.
+#define AVIFINFO_MAX_NUM_BOXES 4096
+// AvifInfoInternalFeatures uses uint8_t to store values.
 #define AVIFINFO_MAX_VALUE UINT8_MAX
-#define AVIFINFO_UNDEFINED 0
 // Maximum number of stored associations. Past that, they are skipped.
 #define AVIFINFO_MAX_TILES 16
 #define AVIFINFO_MAX_PROPS 32
 #define AVIFINFO_MAX_FEATURES 8
+#define AVIFINFO_UNDEFINED 0
 
 // Reads an unsigned integer from 'input' with most significant bits first.
 // 'input' must be at least 'num_bytes'-long.
@@ -93,6 +94,12 @@
 #define AVIFINFO_CHECK_NOT_FOUND(check_status) \
   AVIFINFO_CHECK_STATUS_IS((check_status), kNotFound)
 
+#if defined(AVIFINFO_ENABLE_DEBUG_LOG)
+#define AVIF_DEBUG_LOG(...) printf(__VA_ARGS__)
+#else
+#define AVIF_DEBUG_LOG(...)
+#endif
+
 //------------------------------------------------------------------------------
 // Streamed input struct and helper functions.
 
@@ -101,6 +108,7 @@
   read_stream_t read;       // Used to fetch more bytes from the 'stream'.
   skip_stream_t skip;       // Used to advance the position in the 'stream'.
                             // Fallback to 'read' if 'skip' is null.
+  uint64_t num_read_bytes;  // Number of bytes read or skipped.
 } AvifInfoInternalStream;
 
 // Reads 'num_bytes' from the 'stream'. They are available at '*data'.
@@ -109,6 +117,7 @@
     AvifInfoInternalStream* stream, uint32_t num_bytes, const uint8_t** data) {
   *data = stream->read(stream->stream, num_bytes);
   AVIFINFO_CHECK(*data != NULL, kTruncated);
+  stream->num_read_bytes += num_bytes;
   return kFound;
 }
 
@@ -127,6 +136,7 @@
       return AvifInfoInternalRead(stream, num_bytes, &unused);
     }
     stream->skip(stream->stream, num_bytes);
+    stream->num_read_bytes += num_bytes;
   }
   return kFound;
 }
@@ -137,6 +147,7 @@
 typedef struct {
   uint8_t tile_item_id;
   uint8_t parent_item_id;
+  uint8_t dimg_idx;      // Index of this association in the dimg box (0-based).
 } AvifInfoInternalTile;  // Tile item id <-> parent item id associations.
 
 typedef struct {
@@ -156,10 +167,15 @@
 
 typedef struct {
   uint8_t has_primary_item;  // True if "pitm" was parsed.
-  uint8_t has_alpha;         // True if an alpha "auxC" was parsed.
+  uint8_t has_alpha;    // True if an alpha "auxC" was parsed.
+  // Index of the gain map auxC property.
+  uint8_t gainmap_property_index;
   uint8_t primary_item_id;
   AvifInfoFeatures primary_item_features;  // Deduced from the data below.
   uint8_t data_was_skipped;  // True if some loops/indices were skipped.
+  uint8_t tone_mapped_item_id;  // Id of the "tmap" box, > 0 if present.
+  uint8_t iinf_parsed;  // True if the "iinf" (item info) box was parsed.
+  uint8_t iref_parsed;  // True if the "iref" (item reference) box was parsed.
 
   uint8_t num_tiles;
   AvifInfoInternalTile tiles[AVIFINFO_MAX_TILES];
@@ -227,6 +243,36 @@
   AVIFINFO_CHECK(f->has_primary_item, kNotFound);
   // Early exit.
   AVIFINFO_CHECK(f->num_dim_props > 0 && f->num_chan_props, kNotFound);
+
+  // Look for a gain map.
+  // HEIF scheme: gain map is a hidden input of a derived item.
+  if (f->tone_mapped_item_id) {
+    for (uint32_t tile = 0; tile < f->num_tiles; ++tile) {
+      if (f->tiles[tile].parent_item_id == f->tone_mapped_item_id &&
+          f->tiles[tile].dimg_idx == 1) {
+        f->primary_item_features.has_gainmap = 1;
+        f->primary_item_features.gainmap_item_id = f->tiles[tile].tile_item_id;
+        break;
+      }
+    }
+  }
+  // Adobe scheme: gain map is an auxiliary item.
+  if (!f->primary_item_features.has_gainmap && f->gainmap_property_index > 0) {
+    for (uint32_t prop_item = 0; prop_item < f->num_props; ++prop_item) {
+      if (f->props[prop_item].property_index == f->gainmap_property_index) {
+        f->primary_item_features.has_gainmap = 1;
+        f->primary_item_features.gainmap_item_id = f->props[prop_item].item_id;
+        break;
+      }
+    }
+  }
+  // If the gain map has not been found but we haven't read all the relevant
+  // metadata, we might still find one later and cannot stop now.
+  if (!f->primary_item_features.has_gainmap &&
+      (!f->iinf_parsed || (f->tone_mapped_item_id && !f->iref_parsed))) {
+    return kNotFound;
+  }
+
   AVIFINFO_CHECK_FOUND(
       AvifInfoInternalGetItemFeatures(f, f->primary_item_id, /*tile_depth=*/0));
 
@@ -250,8 +296,9 @@
 // 'num_remaining_bytes' is the remaining size of the container of the 'box'
 // (either the file size itself or the content size of the parent of the 'box').
 static AvifInfoInternalStatus AvifInfoInternalParseBox(
-    AvifInfoInternalStream* stream, uint32_t num_remaining_bytes,
-    uint32_t* num_parsed_boxes, AvifInfoInternalBox* box) {
+    int nesting_level, AvifInfoInternalStream* stream,
+    uint32_t num_remaining_bytes, uint32_t* num_parsed_boxes,
+    AvifInfoInternalBox* box) {
   const uint8_t* data;
   // See ISO/IEC 14496-12:2012(E) 4.2
   uint32_t box_header_size = 8;  // box 32b size + 32b type (at least)
@@ -271,22 +318,38 @@
     // Read the 32 least-significant bits.
     box->size = AvifInfoInternalReadBigEndian(data + 4, sizeof(uint32_t));
   } else if (box->size == 0) {
+    // ISO/IEC 14496-12 4.2.2:
+    //   if size is 0, then this box shall be in a top-level box
+    //   (i.e. not contained in another box)
+    AVIFINFO_CHECK(nesting_level == 0, kInvalid);
     box->size = num_remaining_bytes;
   }
   AVIFINFO_CHECK(box->size >= box_header_size, kInvalid);
   AVIFINFO_CHECK(box->size <= num_remaining_bytes, kInvalid);
 
+  // 16 bytes of usertype should be read here if the box type is 'uuid'.
+  // 'uuid' boxes are skipped so usertype is part of the skipped body.
+
   const int has_fullbox_header =
       !memcmp(box->type, "meta", 4) || !memcmp(box->type, "pitm", 4) ||
       !memcmp(box->type, "ipma", 4) || !memcmp(box->type, "ispe", 4) ||
       !memcmp(box->type, "pixi", 4) || !memcmp(box->type, "iref", 4) ||
-      !memcmp(box->type, "auxC", 4);
+      !memcmp(box->type, "auxC", 4) || !memcmp(box->type, "iinf", 4) ||
+      !memcmp(box->type, "infe", 4);
   if (has_fullbox_header) box_header_size += 4;
   AVIFINFO_CHECK(box->size >= box_header_size, kInvalid);
   box->content_size = box->size - box_header_size;
-  // Avoid timeouts. The maximum number of parsed boxes is arbitrary.
-  ++*num_parsed_boxes;
-  AVIFINFO_CHECK(*num_parsed_boxes < 4096, kAborted);
+  // AvifInfoGetFeaturesStream() can be called on a full stream or on a stream
+  // where the 'ftyp' box was already read. Do not count 'ftyp' boxes towards
+  // AVIFINFO_MAX_NUM_BOXES, so that this function returns the same status in
+  // both situations (because of the AVIFINFO_MAX_NUM_BOXES check that would
+  // compare a different box count otherwise). This is fine because top-level
+  // 'ftyp' boxes are just skipped anyway.
+  if (nesting_level != 0 || memcmp(box->type, "ftyp", 4)) {
+    // Avoid timeouts. The maximum number of parsed boxes is arbitrary.
+    ++*num_parsed_boxes;
+    AVIFINFO_CHECK(*num_parsed_boxes < AVIFINFO_MAX_NUM_BOXES, kAborted);
+  }
 
   box->version = 0;
   box->flags = 0;
@@ -297,17 +360,22 @@
     // See AV1 Image File Format (AVIF) 8.1
     // at https://aomediacodec.github.io/av1-avif/#avif-boxes (available when
     // https://github.com/AOMediaCodec/av1-avif/pull/170 is merged).
-    uint32_t is_parsable = 1;
-    if (!memcmp(box->type, "meta", 4)) is_parsable = (box->version <= 0);
-    if (!memcmp(box->type, "pitm", 4)) is_parsable = (box->version <= 1);
-    if (!memcmp(box->type, "ipma", 4)) is_parsable = (box->version <= 1);
-    if (!memcmp(box->type, "ispe", 4)) is_parsable = (box->version <= 0);
-    if (!memcmp(box->type, "pixi", 4)) is_parsable = (box->version <= 0);
-    if (!memcmp(box->type, "iref", 4)) is_parsable = (box->version <= 1);
-    if (!memcmp(box->type, "auxC", 4)) is_parsable = (box->version <= 0);
+    const uint32_t is_parsable =
+        (!memcmp(box->type, "meta", 4) && box->version <= 0) ||
+        (!memcmp(box->type, "pitm", 4) && box->version <= 1) ||
+        (!memcmp(box->type, "ipma", 4) && box->version <= 1) ||
+        (!memcmp(box->type, "ispe", 4) && box->version <= 0) ||
+        (!memcmp(box->type, "pixi", 4) && box->version <= 0) ||
+        (!memcmp(box->type, "iref", 4) && box->version <= 1) ||
+        (!memcmp(box->type, "auxC", 4) && box->version <= 0) ||
+        (!memcmp(box->type, "iinf", 4) && box->version <= 1) ||
+        (!memcmp(box->type, "infe", 4) && box->version >= 2 &&
+         box->version <= 3);
     // Instead of considering this file as invalid, skip unparsable boxes.
-    if (!is_parsable) memcpy(box->type, "\0skp", 4);  // \0 so not a valid type
+    if (!is_parsable) memcpy(box->type, "skip", 4);  // FreeSpaceBox
   }
+  AVIF_DEBUG_LOG("%*c", nesting_level * 2, ' ');
+  AVIF_DEBUG_LOG("Box type %.4s size %d\n", box->type, box->size);
   return kFound;
 }
 
@@ -316,15 +384,16 @@
 // Parses a 'stream' of an "ipco" box into 'features'.
 // "ispe" is used for width and height, "pixi" and "av1C" are used for bit depth
 // and number of channels, and "auxC" is used for alpha.
-static AvifInfoInternalStatus ParseIpco(AvifInfoInternalStream* stream,
+static AvifInfoInternalStatus ParseIpco(int nesting_level,
+                                        AvifInfoInternalStream* stream,
                                         uint32_t num_remaining_bytes,
                                         uint32_t* num_parsed_boxes,
                                         AvifInfoInternalFeatures* features) {
   uint32_t box_index = 1;  // 1-based index. Used for iterating over properties.
   do {
     AvifInfoInternalBox box;
-    AVIFINFO_CHECK_FOUND(AvifInfoInternalParseBox(stream, num_remaining_bytes,
-                                                  num_parsed_boxes, &box));
+    AVIFINFO_CHECK_FOUND(AvifInfoInternalParseBox(
+        nesting_level, stream, num_remaining_bytes, num_parsed_boxes, &box));
 
     if (!memcmp(box.type, "ispe", 4)) {
       // See ISO/IEC 23008-12:2017(E) 6.5.3.2
@@ -407,21 +476,43 @@
       // at https://aomediacodec.github.io/av1-avif/#auxiliary-images
       const char* kAlphaStr = "urn:mpeg:mpegB:cicp:systems:auxiliary:alpha";
       const uint32_t kAlphaStrLength = 44;  // Includes terminating character.
-      if (box.content_size >= kAlphaStrLength) {
+      const char* kGainmapStr = "urn:com:photo:aux:hdrgainmap";
+      const uint32_t kGainmapStrLength = 29;  // Includes terminating character.
+      uint32_t num_read_bytes = 0;
+      // Check for a gain map or for an alpha plane. Start with the gain map
+      // since the identifier is shorter.
+      if (box.content_size >= kGainmapStrLength) {
         const uint8_t* data;
         AVIFINFO_CHECK_FOUND(
-            AvifInfoInternalRead(stream, kAlphaStrLength, &data));
+            AvifInfoInternalRead(stream, kGainmapStrLength, &data));
+        num_read_bytes = kGainmapStrLength;
         const char* const aux_type = (const char*)data;
-        if (strcmp(aux_type, kAlphaStr) == 0) {
-          // Note: It is unlikely but it is possible that this alpha plane does
-          //       not belong to the primary item or a tile. Ignore this issue.
-          features->has_alpha = 1;
+        if (strcmp(aux_type, kGainmapStr) == 0) {
+          // Note: It is unlikely but it is possible that this gain map
+          // does not belong to the primary item or a tile. Ignore this issue.
+          if (box_index <= AVIFINFO_MAX_VALUE) {
+            features->gainmap_property_index = (uint8_t)box_index;
+          } else {
+            features->data_was_skipped = 1;
+          }
+        } else if (box.content_size >= kAlphaStrLength &&
+                   memcmp(aux_type, kAlphaStr, kGainmapStrLength) == 0) {
+          // The beginning of the aux type matches the alpha aux type string.
+          // Check the end as well.
+          const uint8_t* data2;
+          const uint32_t kEndLength = kAlphaStrLength - kGainmapStrLength;
+          AVIFINFO_CHECK_FOUND(
+              AvifInfoInternalRead(stream, kEndLength, &data2));
+          num_read_bytes = kAlphaStrLength;
+          if (strcmp((const char*)data2, &kAlphaStr[kGainmapStrLength]) == 0) {
+            // Note: It is unlikely but it is possible that this alpha plane
+            // does not belong to the primary item or a tile. Ignore this issue.
+            features->has_alpha = 1;
+          }
         }
-        AVIFINFO_CHECK_FOUND(
-            AvifInfoInternalSkip(stream, box.content_size - kAlphaStrLength));
-      } else {
-        AVIFINFO_CHECK_FOUND(AvifInfoInternalSkip(stream, box.content_size));
       }
+      AVIFINFO_CHECK_FOUND(
+          AvifInfoInternalSkip(stream, box.content_size - num_read_bytes));
     } else {
       AVIFINFO_CHECK_FOUND(AvifInfoInternalSkip(stream, box.content_size));
     }
@@ -431,20 +522,22 @@
   AVIFINFO_RETURN(kNotFound);
 }
 
-// Parses a 'stream' of an "iprp" box into 'features'. The "ipco" box contain
+// Parses a 'stream' of an "iprp" box into 'features'. The "ipco" box contains
 // the properties which are linked to items by the "ipma" box.
-static AvifInfoInternalStatus ParseIprp(AvifInfoInternalStream* stream,
+static AvifInfoInternalStatus ParseIprp(int nesting_level,
+                                        AvifInfoInternalStream* stream,
                                         uint32_t num_remaining_bytes,
                                         uint32_t* num_parsed_boxes,
                                         AvifInfoInternalFeatures* features) {
   do {
     AvifInfoInternalBox box;
-    AVIFINFO_CHECK_FOUND(AvifInfoInternalParseBox(stream, num_remaining_bytes,
-                                                  num_parsed_boxes, &box));
+    AVIFINFO_CHECK_FOUND(AvifInfoInternalParseBox(
+        nesting_level, stream, num_remaining_bytes, num_parsed_boxes, &box));
 
     if (!memcmp(box.type, "ipco", 4)) {
-      AVIFINFO_CHECK_NOT_FOUND(
-          ParseIpco(stream, box.content_size, num_parsed_boxes, features));
+      AVIFINFO_CHECK_NOT_FOUND(ParseIpco(nesting_level + 1, stream,
+                                         box.content_size, num_parsed_boxes,
+                                         features));
     } else if (!memcmp(box.type, "ipma", 4)) {
       // See ISO/IEC 23008-12:2017(E) 9.3.2
       uint32_t num_read_bytes = 4;
@@ -503,6 +596,7 @@
       AVIFINFO_CHECK_NOT_FOUND(
           AvifInfoInternalGetPrimaryItemFeatures(features));
 
+      // Mostly if 'data_was_skipped'.
       AVIFINFO_CHECK_FOUND(
           AvifInfoInternalSkip(stream, box.content_size - num_read_bytes));
     } else {
@@ -519,14 +613,17 @@
 // The "dimg" boxes contain links between tiles and their parent items, which
 // can be used to infer bit depth and number of channels for the primary item
 // when the latter does not have these properties.
-static AvifInfoInternalStatus ParseIref(AvifInfoInternalStream* stream,
+static AvifInfoInternalStatus ParseIref(int nesting_level,
+                                        AvifInfoInternalStream* stream,
                                         uint32_t num_remaining_bytes,
                                         uint32_t* num_parsed_boxes,
                                         AvifInfoInternalFeatures* features) {
-  do {
+  features->iref_parsed = 1;
+
+  while (num_remaining_bytes > 0) {
     AvifInfoInternalBox box;
-    AVIFINFO_CHECK_FOUND(AvifInfoInternalParseBox(stream, num_remaining_bytes,
-                                                  num_parsed_boxes, &box));
+    AVIFINFO_CHECK_FOUND(AvifInfoInternalParseBox(
+        nesting_level, stream, num_remaining_bytes, num_parsed_boxes, &box));
 
     if (!memcmp(box.type, "dimg", 4)) {
       // See ISO/IEC 14496-12:2015(E) 8.11.12.2
@@ -557,6 +654,7 @@
             features->num_tiles < AVIFINFO_MAX_TILES) {
           features->tiles[features->num_tiles].tile_item_id = to_item_id;
           features->tiles[features->num_tiles].parent_item_id = from_item_id;
+          features->tiles[features->num_tiles].dimg_idx = i;
           ++features->num_tiles;
         } else {
           features->data_was_skipped = 1;
@@ -566,11 +664,77 @@
       // If all features are available now, do not look further.
       AVIFINFO_CHECK_NOT_FOUND(
           AvifInfoInternalGetPrimaryItemFeatures(features));
+
+      // Mostly if 'data_was_skipped'.
+      AVIFINFO_CHECK_FOUND(
+          AvifInfoInternalSkip(stream, box.content_size - num_read_bytes));
     } else {
       AVIFINFO_CHECK_FOUND(AvifInfoInternalSkip(stream, box.content_size));
     }
     num_remaining_bytes -= box.size;
-  } while (num_remaining_bytes > 0);
+  }
+  AVIFINFO_RETURN(kNotFound);
+}
+
+//------------------------------------------------------------------------------
+
+// Parses a 'stream' of an "iinf" box into 'features'.
+static AvifInfoInternalStatus ParseIinf(int nesting_level,
+                                        AvifInfoInternalStream* stream,
+                                        uint32_t num_remaining_bytes,
+                                        uint32_t box_version,
+                                        uint32_t* num_parsed_boxes,
+                                        AvifInfoInternalFeatures* features) {
+  features->iinf_parsed = 1;
+
+  const uint32_t num_bytes_per_entry_count = box_version == 0 ? 2 : 4;
+  AVIFINFO_CHECK(num_bytes_per_entry_count <= num_remaining_bytes, kInvalid);
+  const uint8_t* data;
+  AVIFINFO_CHECK_FOUND(
+      AvifInfoInternalRead(stream, num_bytes_per_entry_count, &data));
+  num_remaining_bytes -= num_bytes_per_entry_count;
+  const uint32_t entry_count =
+      AvifInfoInternalReadBigEndian(data, num_bytes_per_entry_count);
+
+  for (int i = 0; i < entry_count; ++i) {
+    AvifInfoInternalBox box;
+    AVIFINFO_CHECK_FOUND(AvifInfoInternalParseBox(
+        nesting_level, stream, num_remaining_bytes, num_parsed_boxes, &box));
+
+    if (!memcmp(box.type, "infe", 4)) {
+      // See ISO/IEC 14496-12:2015(E) 8.11.6.2
+      const uint32_t num_bytes_per_id = (box.version == 2) ? 2 : 4;
+      const uint8_t* data;
+      // item_ID (16 or 32) + item_protection_index (16) + item_type (32).
+      AVIFINFO_CHECK(num_bytes_per_id + 2 + 4 <= box.content_size, kInvalid);
+      AVIFINFO_CHECK_FOUND(
+          AvifInfoInternalRead(stream, num_bytes_per_id, &data));
+      const uint32_t item_id =
+          AvifInfoInternalReadBigEndian(data, num_bytes_per_id);
+
+      // Skip item_protection_index.
+      AVIFINFO_CHECK_FOUND(AvifInfoInternalSkip(stream, 2));
+
+      const uint8_t* item_type;
+      AVIFINFO_CHECK_FOUND(AvifInfoInternalRead(stream, 4, &item_type));
+      if (!memcmp(item_type, "tmap", 4)) {
+        // Tone Mapped Image: indicates the presence of a gain map.
+        if (item_id <= AVIFINFO_MAX_VALUE) {
+          features->tone_mapped_item_id = (uint8_t)item_id;
+        } else {
+          features->data_was_skipped = 1;
+        }
+      }
+
+      AVIFINFO_CHECK_FOUND(AvifInfoInternalSkip(
+          stream, box.content_size - (num_bytes_per_id + 2 + 4)));
+    } else {
+      AVIFINFO_CHECK_FOUND(AvifInfoInternalSkip(stream, box.content_size));
+    }
+
+    num_remaining_bytes -= box.size;
+    if (num_remaining_bytes == 0) break;  // Ignore entry_count bigger than box.
+  }
   AVIFINFO_RETURN(kNotFound);
 }
 
@@ -578,18 +742,19 @@
 
 // Parses a 'stream' of a "meta" box. It looks for the primary item ID in the
 // "pitm" box and recurses into other boxes to find its 'features'.
-static AvifInfoInternalStatus ParseMeta(AvifInfoInternalStream* stream,
+static AvifInfoInternalStatus ParseMeta(int nesting_level,
+                                        AvifInfoInternalStream* stream,
                                         uint32_t num_remaining_bytes,
                                         uint32_t* num_parsed_boxes,
                                         AvifInfoInternalFeatures* features) {
   do {
     AvifInfoInternalBox box;
-    AVIFINFO_CHECK_FOUND(AvifInfoInternalParseBox(stream, num_remaining_bytes,
-                                                  num_parsed_boxes, &box));
-
+    AVIFINFO_CHECK_FOUND(AvifInfoInternalParseBox(
+        nesting_level, stream, num_remaining_bytes, num_parsed_boxes, &box));
     if (!memcmp(box.type, "pitm", 4)) {
       // See ISO/IEC 14496-12:2015(E) 8.11.4.2
       const uint32_t num_bytes_per_id = (box.version == 0) ? 2 : 4;
+      const uint64_t primary_item_id_location = stream->num_read_bytes;
       const uint8_t* data;
       AVIFINFO_CHECK(num_bytes_per_id <= num_remaining_bytes, kInvalid);
       AVIFINFO_CHECK_FOUND(
@@ -599,14 +764,23 @@
       AVIFINFO_CHECK(primary_item_id <= AVIFINFO_MAX_VALUE, kAborted);
       features->has_primary_item = 1;
       features->primary_item_id = primary_item_id;
+      features->primary_item_features.primary_item_id_location =
+          primary_item_id_location;
+      features->primary_item_features.primary_item_id_bytes = num_bytes_per_id;
       AVIFINFO_CHECK_FOUND(
           AvifInfoInternalSkip(stream, box.content_size - num_bytes_per_id));
     } else if (!memcmp(box.type, "iprp", 4)) {
-      AVIFINFO_CHECK_NOT_FOUND(
-          ParseIprp(stream, box.content_size, num_parsed_boxes, features));
+      AVIFINFO_CHECK_NOT_FOUND(ParseIprp(nesting_level + 1, stream,
+                                         box.content_size, num_parsed_boxes,
+                                         features));
     } else if (!memcmp(box.type, "iref", 4)) {
-      AVIFINFO_CHECK_NOT_FOUND(
-          ParseIref(stream, box.content_size, num_parsed_boxes, features));
+      AVIFINFO_CHECK_NOT_FOUND(ParseIref(nesting_level + 1, stream,
+                                         box.content_size, num_parsed_boxes,
+                                         features));
+    } else if (!memcmp(box.type, "iinf", 4)) {
+      AVIFINFO_CHECK_NOT_FOUND(ParseIinf(nesting_level + 1, stream,
+                                         box.content_size, box.version,
+                                         num_parsed_boxes, features));
     } else {
       AVIFINFO_CHECK_FOUND(AvifInfoInternalSkip(stream, box.content_size));
     }
@@ -622,8 +796,9 @@
 static AvifInfoInternalStatus ParseFtyp(AvifInfoInternalStream* stream) {
   AvifInfoInternalBox box;
   uint32_t num_parsed_boxes = 0;
-  AVIFINFO_CHECK_FOUND(AvifInfoInternalParseBox(stream, AVIFINFO_MAX_SIZE,
-                                                &num_parsed_boxes, &box));
+  const int nesting_level = 0;
+  AVIFINFO_CHECK_FOUND(AvifInfoInternalParseBox(
+      nesting_level, stream, AVIFINFO_MAX_SIZE, &num_parsed_boxes, &box));
   AVIFINFO_CHECK(!memcmp(box.type, "ftyp", 4), kInvalid);
   // Iterate over brands. See ISO/IEC 14496-12:2012(E) 4.3.1
   AVIFINFO_CHECK(box.content_size >= 8, kInvalid);  // major_brand,minor_version
@@ -647,15 +822,16 @@
                                         AvifInfoInternalFeatures* features) {
   while (1) {
     AvifInfoInternalBox box;
-    AVIFINFO_CHECK_FOUND(AvifInfoInternalParseBox(stream, AVIFINFO_MAX_SIZE,
-                                                  num_parsed_boxes, &box));
+    AVIFINFO_CHECK_FOUND(AvifInfoInternalParseBox(
+        /*nesting_level=*/0, stream, AVIFINFO_MAX_SIZE, num_parsed_boxes,
+        &box));
     if (!memcmp(box.type, "meta", 4)) {
-      return ParseMeta(stream, box.content_size, num_parsed_boxes, features);
+      return ParseMeta(/*nesting_level=*/1, stream, box.content_size,
+                       num_parsed_boxes, features);
     } else {
       AVIFINFO_CHECK_FOUND(AvifInfoInternalSkip(stream, box.content_size));
     }
   }
-  AVIFINFO_RETURN(kInvalid);  // No "meta" no good.
 }
 
 //------------------------------------------------------------------------------
@@ -698,6 +874,11 @@
 
 AvifInfoStatus AvifInfoGetFeatures(const uint8_t* data, size_t data_size,
                                    AvifInfoFeatures* features) {
+  const AvifInfoStatus status = AvifInfoIdentify(data, data_size);
+  if (status != kAvifInfoOk) {
+    if (features != NULL) memset(features, 0, sizeof(*features));
+    return status;
+  }
   AvifInfoInternalForward stream;
   stream.data = data;
   stream.data_size = data_size;
@@ -710,19 +891,20 @@
 // Streamed input API
 
 AvifInfoStatus AvifInfoIdentifyStream(void* stream, read_stream_t read,
-                                    skip_stream_t skip) {
+                                      skip_stream_t skip) {
   if (read == NULL) return kAvifInfoNotEnoughData;
 
   AvifInfoInternalStream internal_stream;
   internal_stream.stream = stream;
   internal_stream.read = read;
   internal_stream.skip = skip;  // Fallbacks to 'read' if null.
+  internal_stream.num_read_bytes = 0;
   return AvifInfoInternalConvertStatus(ParseFtyp(&internal_stream));
 }
 
 AvifInfoStatus AvifInfoGetFeaturesStream(void* stream, read_stream_t read,
-                                    skip_stream_t skip,
-                                    AvifInfoFeatures* features) {
+                                         skip_stream_t skip,
+                                         AvifInfoFeatures* features) {
   if (features != NULL) memset(features, 0, sizeof(*features));
   if (read == NULL) return kAvifInfoNotEnoughData;
 
@@ -730,6 +912,7 @@
   internal_stream.stream = stream;
   internal_stream.read = read;
   internal_stream.skip = skip;  // Fallbacks to 'read' if null.
+  internal_stream.num_read_bytes = 0;
   uint32_t num_parsed_boxes = 0;
   AvifInfoInternalFeatures internal_features;
   memset(&internal_features, AVIFINFO_UNDEFINED, sizeof(internal_features));
diff '--color=auto' -Naur php-8.4.18/ext/standard/libavifinfo/avifinfo.h php-8.4.20RC1/ext/standard/libavifinfo/avifinfo.h
--- php-8.4.18/ext/standard/libavifinfo/avifinfo.h	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/standard/libavifinfo/avifinfo.h	2026-04-01 04:35:36.020720855 +0000
@@ -35,10 +35,22 @@
 } AvifInfoStatus;
 
 typedef struct {
-  uint32_t width, height;  // In number of pixels. Ignores mirror and rotation.
-  uint32_t bit_depth;      // Likely 8, 10 or 12 bits per channel per pixel.
-  uint32_t num_channels;   // Likely 1, 2, 3 or 4 channels:
-                           //   (1 monochrome or 3 colors) + (0 or 1 alpha)
+  uint32_t width, height;   // In number of pixels. Ignores crop and rotation.
+  uint32_t bit_depth;       // Likely 8, 10 or 12 bits per channel per pixel.
+  uint32_t num_channels;    // Likely 1, 2, 3 or 4 channels:
+                            //   (1 monochrome or 3 colors) + (0 or 1 alpha)
+  uint8_t has_gainmap;      // True if a gain map was found.
+  // Id of the gain map item. Assumes there is at most one. If there are several
+  // gain map items (e.g. because the main image is tiled and each tile has an
+  // independent gain map), then this is one of the ids, arbitrarily chosen.
+  uint8_t gainmap_item_id;
+  // Start location in bytes of the primary item id, relative to the beginning
+  // of the given payload. The primary item id is a big endian number stored on
+  // bytes primary_item_id_location to
+  // primary_item_id_location+primary_item_id_bytes-1 inclusive.
+  uint64_t primary_item_id_location;
+  // Number of bytes of the primary item id.
+  uint8_t primary_item_id_bytes;
 } AvifInfoFeatures;
 
 //------------------------------------------------------------------------------
@@ -46,13 +58,19 @@
 // Use this API if a raw byte array of fixed size is available as input.
 
 // Parses the 'data' and returns kAvifInfoOk if it is identified as an AVIF.
+// 'data' can be partial but must point to the beginning of the AVIF file.
 // The file type can be identified in the first 12 bytes of most AVIF files.
 AvifInfoStatus AvifInfoIdentify(const uint8_t* data, size_t data_size);
 
-// Parses the identified AVIF 'data' and extracts its 'features'.
+// Parses the 'data' and returns kAvifInfoOk and its 'features' if it is
+// identified as an AVIF file.
 // 'data' can be partial but must point to the beginning of the AVIF file.
 // The 'features' can be parsed in the first 450 bytes of most AVIF files.
 // 'features' are set to 0 unless kAvifInfoOk is returned.
+// There is no need to call AvifInfoIdentify() before AvifInfoGetFeatures().
+// AvifInfoGetFeatures() parses the file further than AvifInfoIdentify() so it
+// is possible that AvifInfoGetFeatures() returns errors while
+// AvifInfoIdentify() returns kAvifInfoOk on the same given input bytes.
 AvifInfoStatus AvifInfoGetFeatures(const uint8_t* data, size_t data_size,
                                    AvifInfoFeatures* features);
 
@@ -78,7 +96,15 @@
 // 'read' cannot be null. If 'skip' is null, 'read' is called instead.
 AvifInfoStatus AvifInfoIdentifyStream(void* stream, read_stream_t read,
                                       skip_stream_t skip);
-// Can be called right after AvifInfoIdentifyStream() with the same 'stream'.
+
+// Can be called right after AvifInfoIdentifyStream() with the same 'stream'
+// object if AvifInfoIdentifyStream() returned kAvifInfoOk.
+// Any location-dependent feature such as 'primary_item_id_location' is relative
+// to the given 'stream', and must be offset by the number of bytes read or
+// skipped during AvifInfoIdentifyStream() if it was called prior to
+// AvifInfoGetFeaturesStream() on the same 'stream' object.
+// AvifInfoGetFeaturesStream() should only be called if AvifInfoIdentifyStream()
+// returned kAvifInfoOk with the same input bytes.
 AvifInfoStatus AvifInfoGetFeaturesStream(void* stream, read_stream_t read,
                                          skip_stream_t skip,
                                          AvifInfoFeatures* features);
diff '--color=auto' -Naur php-8.4.18/ext/standard/libavifinfo/README.md php-8.4.20RC1/ext/standard/libavifinfo/README.md
--- php-8.4.18/ext/standard/libavifinfo/README.md	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/standard/libavifinfo/README.md	2026-04-01 04:35:36.020377627 +0000
@@ -7,5 +7,5 @@
 channel count without depending on the full libavif library.
 
 `avifinfo.h`, `avifinfo.c`, `LICENSE` and `PATENTS` were copied verbatim from: \
-https://aomedia.googlesource.com/libavifinfo/+/96f34d945ac7dac229feddfa94dbae66e202b838 \
+https://aomedia.googlesource.com/libavifinfo/+/2b924defa4c2cd227540efe164067a8cc913eeba \
 They can easily be kept up-to-date the same way.
diff '--color=auto' -Naur php-8.4.18/ext/standard/tests/file/bug52820.phpt php-8.4.20RC1/ext/standard/tests/file/bug52820.phpt
--- php-8.4.18/ext/standard/tests/file/bug52820.phpt	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/standard/tests/file/bug52820.phpt	2026-04-01 04:35:36.020825262 +0000
@@ -45,22 +45,18 @@
 --EXPECTREGEX--
 temp stream \(close after\):
 About to rewind!
-(\* processing: file:\/\/\/i_dont_exist\/\n)?\* (Couldn't|Could not) open file \/i_dont_exist\/
-\* [Cc]losing connection( #?-?\d+)?
+(\* processing: file:\/\/\/i_dont_exist\/\n)?\* (Couldn't|Could not) open file \/i_dont_exist\/(\n\* [Cc]losing connection( #?-?\d+)?)?
 
 memory stream \(close after\):
 About to rewind!
-(\* processing: file:\/\/\/i_dont_exist\/\n)?\* (Couldn't|Could not) open file \/i_dont_exist\/
-\* [Cc]losing connection( #?-?\d+)?
+(\* processing: file:\/\/\/i_dont_exist\/\n)?\* (Couldn't|Could not) open file \/i_dont_exist\/(\n\* [Cc]losing connection( #?-?\d+)?)?
 
 temp stream \(leak\):
 About to rewind!
-(\* processing: file:\/\/\/i_dont_exist\/\n)?\* (Couldn't|Could not) open file \/i_dont_exist\/
-\* [Cc]losing connection( #?-?\d+)?
+(\* processing: file:\/\/\/i_dont_exist\/\n)?\* (Couldn't|Could not) open file \/i_dont_exist\/(\n\* [Cc]losing connection( #?-?\d+)?)?
 
 memory stream \(leak\):
 About to rewind!
-(\* processing: file:\/\/\/i_dont_exist\/\n)?\* (Couldn't|Could not) open file \/i_dont_exist\/
-\* [Cc]losing connection( #?-?\d+)?
+(\* processing: file:\/\/\/i_dont_exist\/\n)?\* (Couldn't|Could not) open file \/i_dont_exist\/(\n\* [Cc]losing connection( #?-?\d+)?)?
 
 Done\.
diff '--color=auto' -Naur php-8.4.18/ext/standard/tests/file/file_get_contents_file_put_contents_5gb.phpt php-8.4.20RC1/ext/standard/tests/file/file_get_contents_file_put_contents_5gb.phpt
--- php-8.4.18/ext/standard/tests/file/file_get_contents_file_put_contents_5gb.phpt	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/standard/tests/file/file_get_contents_file_put_contents_5gb.phpt	2026-04-01 04:35:36.020907498 +0000
@@ -2,6 +2,7 @@
 Test file_put_contents() and file_get_contents() functions with 5GB string
 --SKIPIF--
 <?php
+if (!getenv('RUN_RESOURCE_HEAVY_TESTS')) die('skip resource-heavy test');
 if (PHP_INT_SIZE < 5) {
     // 4=4gb, 5=549gb, 8=9exabytes
     die("skip PHP_INT_SIZE<5 will not fit test string in RAM");
diff '--color=auto' -Naur php-8.4.18/ext/standard/tests/general_functions/gh20840.phpt php-8.4.20RC1/ext/standard/tests/general_functions/gh20840.phpt
--- php-8.4.18/ext/standard/tests/general_functions/gh20840.phpt	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/standard/tests/general_functions/gh20840.phpt	2026-04-01 04:35:36.020986207 +0000
@@ -12,7 +12,7 @@
 }
 ?>
 --INI--
-zend.max_allowed_stack_size=128K
+zend.max_allowed_stack_size=256K
 --FILE--
 <?php
 class Node {
diff '--color=auto' -Naur php-8.4.18/ext/standard/tests/http/http_build_query/gh20583.phpt php-8.4.20RC1/ext/standard/tests/http/http_build_query/gh20583.phpt
--- php-8.4.18/ext/standard/tests/http/http_build_query/gh20583.phpt	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/standard/tests/http/http_build_query/gh20583.phpt	2026-04-01 04:35:36.021066719 +0000
@@ -10,11 +10,11 @@
 }
 ?>
 --INI--
-zend.max_allowed_stack_size=128K
+zend.max_allowed_stack_size=256K
 --FILE--
 <?php
 $a = null;
-for ($i = 0; $i < 1000; $i++) {
+for ($i = 0; $i < 3000; $i++) {
  $a = [$i => $a];
 }
 try {
diff '--color=auto' -Naur php-8.4.18/ext/standard/tests/strings/gh15613.phpt php-8.4.20RC1/ext/standard/tests/strings/gh15613.phpt
--- php-8.4.18/ext/standard/tests/strings/gh15613.phpt	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/standard/tests/strings/gh15613.phpt	2026-04-01 04:35:36.021143594 +0000
@@ -2,6 +2,7 @@
 GH-15613 overflow on hex strings repeater value
 --SKIPIF--
 <?php
+if (!getenv('RUN_RESOURCE_HEAVY_TESTS')) die('skip resource-heavy test');
 if (PHP_INT_SIZE != 8) die("skip this test is for 64 bit platform only");
 ?>
 --INI--
diff '--color=auto' -Naur php-8.4.18/ext/standard/tests/strings/gh18976.phpt php-8.4.20RC1/ext/standard/tests/strings/gh18976.phpt
--- php-8.4.18/ext/standard/tests/strings/gh18976.phpt	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/standard/tests/strings/gh18976.phpt	2026-04-01 04:35:36.021239585 +0000
@@ -2,6 +2,10 @@
 GH-18976 (pack overflow with h/H format)
 --INI--
 memory_limit=-1
+--SKIPIF--
+<?php
+if (!getenv('RUN_RESOURCE_HEAVY_TESTS')) die('skip resource-heavy test');
+?>
 --FILE--
 <?php
 pack('h2147483647', 1);
diff '--color=auto' -Naur php-8.4.18/ext/standard/tests/strings/gh20906_1.phpt php-8.4.20RC1/ext/standard/tests/strings/gh20906_1.phpt
--- php-8.4.18/ext/standard/tests/strings/gh20906_1.phpt	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/ext/standard/tests/strings/gh20906_1.phpt	2026-04-01 04:35:36.021319156 +0000
@@ -0,0 +1,25 @@
+--TEST--
+GH-20906 (Assertion failure when messing up output buffers) - php_strip_whitespace
+--CREDITS--
+vi3tL0u1s
+--FILE--
+<?php
+class A {
+    function __destruct() {
+        php_strip_whitespace(__FILE__);
+        echo "x";
+        $c = new A;
+        ob_start(function () use ($c) { return '/'; }, 1);
+        ob_start(function () use (&$c) { $c = new A; return '/'; }, 1);
+    }
+}
+
+try {
+  new A;
+} catch (Throwable $e) {
+  echo $e::class, ": ", $e->getMessage(), "\n";
+}
+?>
+--EXPECTF--
+%a
+Fatal error: php_strip_whitespace(): Cannot use output buffering in output buffering display handlers in %s on line %d
diff '--color=auto' -Naur php-8.4.18/ext/standard/tests/strings/gh20906_2.phpt php-8.4.20RC1/ext/standard/tests/strings/gh20906_2.phpt
--- php-8.4.18/ext/standard/tests/strings/gh20906_2.phpt	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/ext/standard/tests/strings/gh20906_2.phpt	2026-04-01 04:35:36.021398395 +0000
@@ -0,0 +1,21 @@
+--TEST--
+GH-20906 (Assertion failure when messing up output buffers) - highlight_file
+--CREDITS--
+vi3tL0u1s
+--FILE--
+<?php
+class A {
+    function __destruct() {
+        highlight_file(__FILE__, true);
+        echo "x";
+        $c = new A;
+        ob_start(function () use ($c) { return '/'; }, 1);
+        ob_start(function () use (&$c) { $c = new A; return '/'; }, 1);
+    }
+}
+
+new A;
+?>
+--EXPECTF--
+%a
+Fatal error: highlight_file(): Cannot use output buffering in output buffering display handlers in %s on line %d
diff '--color=auto' -Naur php-8.4.18/ext/standard/tests/strings/gh20906_3.phpt php-8.4.20RC1/ext/standard/tests/strings/gh20906_3.phpt
--- php-8.4.18/ext/standard/tests/strings/gh20906_3.phpt	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/ext/standard/tests/strings/gh20906_3.phpt	2026-04-01 04:35:36.021495168 +0000
@@ -0,0 +1,21 @@
+--TEST--
+GH-20906 (Assertion failure when messing up output buffers) - highlight_string
+--CREDITS--
+vi3tL0u1s
+--FILE--
+<?php
+class A {
+    function __destruct() {
+        highlight_string(__FILE__, true);
+        echo "x";
+        $c = new A;
+        ob_start(function () use ($c) { return '/'; }, 1);
+        ob_start(function () use (&$c) { $c = new A; return '/'; }, 1);
+    }
+}
+
+new A;
+?>
+--EXPECTF--
+%a
+Fatal error: highlight_string(): Cannot use output buffering in output buffering display handlers in %s on line %d
diff '--color=auto' -Naur php-8.4.18/ext/standard/user_filters.c php-8.4.20RC1/ext/standard/user_filters.c
--- php-8.4.18/ext/standard/user_filters.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/standard/user_filters.c	2026-04-01 04:35:36.021607741 +0000
@@ -259,8 +259,8 @@
 	len = strlen(filtername);
 
 	/* determine the classname/class entry */
-	if (NULL == (fdat = zend_hash_str_find_ptr(BG(user_filter_map), (char*)filtername, len))) {
-		char *period;
+	if (NULL == (fdat = zend_hash_str_find_ptr(BG(user_filter_map), filtername, len))) {
+		const char *period;
 
 		/* Userspace Filters using ambiguous wildcards could cause problems.
            i.e.: myfilter.foo.bar will always call into myfilter.foo.*
@@ -272,16 +272,16 @@
 
 			/* Search for wildcard matches instead */
 			memcpy(wildcard, filtername, len + 1); /* copy \0 */
-			period = wildcard + (period - filtername);
-			while (period) {
-				ZEND_ASSERT(period[0] == '.');
-				period[1] = '*';
-				period[2] = '\0';
+			char *new_period = wildcard + (period - filtername);
+			while (new_period) {
+				ZEND_ASSERT(new_period[0] == '.');
+				new_period[1] = '*';
+				new_period[2] = '\0';
 				if (NULL != (fdat = zend_hash_str_find_ptr(BG(user_filter_map), wildcard, strlen(wildcard)))) {
-					period = NULL;
+					new_period = NULL;
 				} else {
-					*period = '\0';
-					period = strrchr(wildcard, '.');
+					*new_period = '\0';
+					new_period = strrchr(wildcard, '.');
 				}
 			}
 			efree(wildcard);
@@ -311,7 +311,7 @@
 	}
 
 	/* filtername */
-	add_property_string(&obj, "filtername", (char*)filtername);
+	add_property_string(&obj, "filtername", filtername);
 
 	/* and the parameters, if any */
 	if (filterparams) {
diff '--color=auto' -Naur php-8.4.18/ext/sysvshm/sysvshm.c php-8.4.20RC1/ext/sysvshm/sysvshm.c
--- php-8.4.18/ext/sysvshm/sysvshm.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/sysvshm/sysvshm.c	2026-04-01 04:35:36.021721255 +0000
@@ -309,11 +309,13 @@
 	shm_data = &shm_var->mem;
 
 	PHP_VAR_UNSERIALIZE_INIT(var_hash);
-	if (php_var_unserialize(return_value, (const unsigned char **) &shm_data, (unsigned char *) shm_data + shm_var->length, &var_hash) != 1) {
+	int res = php_var_unserialize(return_value, (const unsigned char **) &shm_data, (unsigned char *) shm_data + shm_var->length, &var_hash);
+	PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+	if (res != 1) {
 		php_error_docref(NULL, E_WARNING, "Variable data in shared memory is corrupted");
-		RETVAL_FALSE;
+		zval_ptr_dtor(return_value);
+		RETURN_FALSE;
 	}
-	PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
 }
 /* }}} */
 
diff '--color=auto' -Naur php-8.4.18/ext/sysvshm/tests/shm_get_var_leak.phpt php-8.4.20RC1/ext/sysvshm/tests/shm_get_var_leak.phpt
--- php-8.4.18/ext/sysvshm/tests/shm_get_var_leak.phpt	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/ext/sysvshm/tests/shm_get_var_leak.phpt	2026-04-01 04:35:36.021805765 +0000
@@ -0,0 +1,37 @@
+--TEST--
+shm_get_var() leaks if variable is corrupted
+--EXTENSIONS--
+sysvshm
+ffi
+--INI--
+ffi.enable=1
+--SKIPIF--
+<?php
+if (!function_exists('ftok')) die('skip needs ftok');
+if (PHP_INT_SIZE !== 8) die('skip only for 64-bit');
+if (PHP_OS_FAMILY !== 'Linux') die('skip only for decent operating systems');
+?>
+--FILE--
+<?php
+
+$key = ftok(__FILE__, 't');
+$s = shm_attach($key, 128);
+
+shm_put_var($s, 0, [1, 2]);
+
+$ffi = FFI::cdef(<<<CODE
+int shmget(int, size_t, int);
+char *shmat(int, const void *, int);
+CODE);
+$ptr = $ffi->shmat($ffi->shmget($key, 0, 0), $ffi->new('void *'), 0);
+
+$ptr[0x40 + 13] = 0; // Corrupt first byte of second element of serialized data
+
+var_dump(shm_get_var($s, 0));
+
+shm_remove($s);
+
+?>
+--EXPECTF--
+Warning: shm_get_var(): Variable data in shared memory is corrupted in %s on line %d
+bool(false)
diff '--color=auto' -Naur php-8.4.18/ext/tidy/tests/parsing_file_too_large.phpt php-8.4.20RC1/ext/tidy/tests/parsing_file_too_large.phpt
--- php-8.4.18/ext/tidy/tests/parsing_file_too_large.phpt	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/tidy/tests/parsing_file_too_large.phpt	2026-04-01 04:35:36.021908479 +0000
@@ -4,6 +4,7 @@
 tidy
 --SKIPIF--
 <?php
+if (!getenv('RUN_RESOURCE_HEAVY_TESTS')) die('skip resource-heavy test');
 if (PHP_INT_SIZE != 8) die("skip this test is for 64bit platform only");
 if (getenv("SKIP_SLOW_TESTS")) die("skip slow test");
 if (getenv("SKIP_ASAN")) die("skip too big for asan");
diff '--color=auto' -Naur php-8.4.18/ext/xml/tests/bug81481.phpt php-8.4.20RC1/ext/xml/tests/bug81481.phpt
--- php-8.4.18/ext/xml/tests/bug81481.phpt	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/xml/tests/bug81481.phpt	2026-04-01 04:35:36.021985685 +0000
@@ -8,6 +8,7 @@
 memory_limit=-1
 --SKIPIF--
 <?php
+if (!getenv('RUN_RESOURCE_HEAVY_TESTS')) die('skip resource-heavy test');
 require __DIR__ . '/libxml_expat_skipif.inc';
 skipif(want_expat: false);
 if (getenv("SKIP_SLOW_TESTS")) die("skip slow test");
diff '--color=auto' -Naur php-8.4.18/ext/xsl/tests/auto_registration_namespaces_new_dom.phpt php-8.4.20RC1/ext/xsl/tests/auto_registration_namespaces_new_dom.phpt
--- php-8.4.18/ext/xsl/tests/auto_registration_namespaces_new_dom.phpt	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/xsl/tests/auto_registration_namespaces_new_dom.phpt	2026-04-01 04:35:36.022076427 +0000
@@ -24,7 +24,7 @@
 XML);
 
 // Make sure it will auto-register urn:test
-$sheet->documentElement->append($sheet->createElementNS('urn:test', 'test:dummy'));
+$sheet->documentElement->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:test', 'urn:test');
 
 $input = Dom\XMLDocument::createFromString(<<<XML
 <root>
diff '--color=auto' -Naur php-8.4.18/ext/xsl/tests/gh21357_1.phpt php-8.4.20RC1/ext/xsl/tests/gh21357_1.phpt
--- php-8.4.18/ext/xsl/tests/gh21357_1.phpt	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/ext/xsl/tests/gh21357_1.phpt	2026-04-01 04:35:36.022139876 +0000
@@ -0,0 +1,20 @@
+--TEST--
+GH-21357 (XSLTProcessor works with \DOMDocument, but fails with \Dom\XMLDocument)
+--EXTENSIONS--
+dom
+xsl
+--CREDITS--
+jacekkow
+--FILE--
+<?php
+$xml = <<<'XML'
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:tns="urn:myns" version="1.0">
+	<xsl:template match="tns:referee"/>
+</xsl:stylesheet>
+XML;
+
+$dom = Dom\XMLDocument::createFromString($xml);
+var_dump(new XSLTProcessor()->importStylesheet($dom));
+?>
+--EXPECT--
+bool(true)
diff '--color=auto' -Naur php-8.4.18/ext/xsl/tests/gh21357_2.phpt php-8.4.20RC1/ext/xsl/tests/gh21357_2.phpt
--- php-8.4.18/ext/xsl/tests/gh21357_2.phpt	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/ext/xsl/tests/gh21357_2.phpt	2026-04-01 04:35:36.022198928 +0000
@@ -0,0 +1,35 @@
+--TEST--
+GH-21357 (XSLTProcessor works with \DOMDocument, but fails with \Dom\XMLDocument)
+--EXTENSIONS--
+dom
+xsl
+--CREDITS--
+jacekkow
+--FILE--
+<?php
+$xsl = '<?xml version="1.0" encoding="utf-8"?>
+<xsl:stylesheet
+    version="1.0"
+    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+    xmlns:old="http://something/old/"
+    xmlns:new="http://something/new/">
+  <xsl:template match="node()|@*">
+    <xsl:copy>
+      <xsl:apply-templates select="node()|@*"/>
+    </xsl:copy>
+  </xsl:template>
+  <xsl:template match="old:*">
+    <xsl:element name="{local-name()}" xmlns="http://something/new/" >
+      <xsl:apply-templates select="node()|@*"/>
+    </xsl:element>
+  </xsl:template>
+</xsl:stylesheet>';
+$dom = Dom\XMLDocument::createFromString($xsl);
+$xsl = new XSLTProcessor();
+$xsl->importStylesheet($dom);
+var_dump($xsl->transformToXml(\Dom\XMLDocument::createFromString('<test xmlns="http://something/old/"/>')));
+?>
+--EXPECT--
+string(138) "<?xml version="1.0"?>
+<test xmlns="http://something/new/" xmlns:ns_1="http://www.w3.org/2000/xmlns/" ns_1:xmlns="http://something/old/"/>
+"
diff '--color=auto' -Naur php-8.4.18/ext/xsl/xsltprocessor.c php-8.4.20RC1/ext/xsl/xsltprocessor.c
--- php-8.4.18/ext/xsl/xsltprocessor.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/xsl/xsltprocessor.c	2026-04-01 04:35:36.022329404 +0000
@@ -123,65 +123,38 @@
 	}
 }
 
-static void xsl_add_ns_to_map(xmlHashTablePtr table, xsltStylesheetPtr sheet, const xmlNode *cur, const xmlChar *prefix, const xmlChar *uri)
+static void xsl_add_ns_def(xmlNodePtr node)
 {
-	const xmlChar *existing_url = xmlHashLookup(table, prefix);
-	if (existing_url != NULL && !xmlStrEqual(existing_url, uri)) {
-		xsltTransformError(NULL, sheet, (xmlNodePtr) cur, "Namespaces prefix %s used for multiple namespaces\n", prefix);
-		sheet->warnings++;
-	} else if (existing_url == NULL) {
-		xmlHashUpdateEntry(table, prefix, (void *) uri, NULL);
-	}
-}
+	if (node->type == XML_ELEMENT_NODE) {
+		for (xmlAttrPtr attr = node->properties; attr; attr = attr->next) {
+			if (php_dom_ns_is_fast((const xmlNode *) attr, php_dom_ns_is_xmlns_magic_token)) {
+				xmlNsPtr ns = xmlMalloc(sizeof(*ns));
+				if (!ns) {
+					return;
+				}
 
-/* Adds all namespace declaration (not using nsDef) into a hash map that maps prefix to uri. Warns on conflicting declarations. */
-static void xsl_build_ns_map(xmlHashTablePtr table, xsltStylesheetPtr sheet, php_dom_libxml_ns_mapper *ns_mapper, const xmlDoc *doc)
-{
-	const xmlNode *cur = xmlDocGetRootElement(doc);
+				bool should_free;
+				xmlChar *attr_value = php_libxml_attr_value(attr, &should_free);
 
-	while (cur != NULL) {
-		if (cur->type == XML_ELEMENT_NODE) {
-			if (cur->ns != NULL && cur->ns->prefix != NULL) {
-				xsl_add_ns_to_map(table, sheet, cur, cur->ns->prefix, cur->ns->href);
-			}
-
-			for (const xmlAttr *attr = cur->properties; attr != NULL; attr = attr->next) {
-				if (attr->ns != NULL && attr->ns->prefix != NULL && php_dom_ns_is_fast_ex(attr->ns, php_dom_ns_is_xmlns_magic_token)
-					&& attr->children != NULL && attr->children->content != NULL) {
-					/* This attribute declares a namespace, get the relevant instance.
-					 * The declared namespace is not the same as the namespace of this attribute (which is xmlns). */
-					const xmlChar *prefix = attr->name;
-					xmlNsPtr ns = php_dom_libxml_ns_mapper_get_ns_raw_strings_nullsafe(ns_mapper, (const char *) prefix, (const char *) attr->children->content);
-					xsl_add_ns_to_map(table, sheet, cur, prefix, ns->href);
-				}
+				memset(ns, 0, sizeof(*ns));
+				ns->type = XML_LOCAL_NAMESPACE;
+				ns->href = should_free ? attr_value : xmlStrdup(attr_value);
+				ns->prefix = attr->ns->prefix ? xmlStrdup(attr->name) : NULL;
+				ns->next = node->nsDef;
+				node->nsDef = ns;
 			}
 		}
-
-		cur = php_dom_next_in_tree_order(cur, (const xmlNode *) doc);
 	}
 }
 
-/* Apply namespace corrections for new DOM */
-typedef enum {
-	XSL_NS_HASH_CORRECTION_NONE = 0,
-	XSL_NS_HASH_CORRECTION_APPLIED = 1,
-	XSL_NS_HASH_CORRECTION_FAILED = 2
-} xsl_ns_hash_correction_status;
-
-static zend_always_inline xsl_ns_hash_correction_status xsl_apply_ns_hash_corrections(xsltStylesheetPtr sheetp, xmlNodePtr nodep, xmlDocPtr doc)
+static void xsl_add_ns_defs(xmlDocPtr doc)
 {
-	if (sheetp->nsHash == NULL) {
-		dom_object *node_intern = php_dom_object_get_data(nodep);
-		if (node_intern != NULL && php_dom_follow_spec_intern(node_intern)) {
-			sheetp->nsHash = xmlHashCreate(10);
-			if (UNEXPECTED(!sheetp->nsHash)) {
-				return XSL_NS_HASH_CORRECTION_FAILED;
-			}
-			xsl_build_ns_map(sheetp->nsHash, sheetp, php_dom_get_ns_mapper(node_intern), doc);
-			return XSL_NS_HASH_CORRECTION_APPLIED;
-		}
+	xmlNodePtr base = (xmlNodePtr) doc;
+	xmlNodePtr node = base->children;
+	while (node != NULL) {
+		xsl_add_ns_def(node);
+		node = php_dom_next_in_tree_order(node, base);
 	}
-	return XSL_NS_HASH_CORRECTION_NONE;
 }
 
 /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#
@@ -190,11 +163,11 @@
 PHP_METHOD(XSLTProcessor, importStylesheet)
 {
 	zval *id, *docp = NULL;
-	xmlDoc *doc = NULL, *newdoc = NULL;
+	xmlDoc *newdoc = NULL;
 	xsltStylesheetPtr sheetp;
 	bool clone_docu = false;
 	xmlNode *nodep = NULL;
-	zval *cloneDocu, rv;
+	zval *cloneDocu, rv, clone_zv;
 	zend_string *member;
 
 	id = ZEND_THIS;
@@ -202,51 +175,59 @@
 		RETURN_THROWS();
 	}
 
-	nodep = php_libxml_import_node(docp);
+	/* libxslt uses _private, so we must copy the imported
+	 * stylesheet document otherwise the node proxies will be a mess.
+	 * We will clone the object and detach the libxml internals later. */
+	zend_object *clone = Z_OBJ_HANDLER_P(docp, clone_obj)(Z_OBJ_P(docp));
+	if (!clone) {
+		RETURN_THROWS();
+	}
+
+	ZVAL_OBJ(&clone_zv, clone);
+	nodep = php_libxml_import_node(&clone_zv);
 
 	if (nodep) {
-		doc = nodep->doc;
+		newdoc = nodep->doc;
 	}
-	if (doc == NULL) {
+	if (newdoc == NULL) {
+		OBJ_RELEASE(clone);
 		zend_argument_type_error(1, "must be a valid XML node");
 		RETURN_THROWS();
 	}
 
-	/* libxslt uses _private, so we must copy the imported
-	stylesheet document otherwise the node proxies will be a mess */
-	newdoc = xmlCopyDoc(doc, 1);
-	xmlNodeSetBase((xmlNodePtr) newdoc, (xmlChar *)doc->URL);
+	php_libxml_node_object *clone_lxml_obj = Z_LIBXML_NODE_P(&clone_zv);
+
 	PHP_LIBXML_SANITIZE_GLOBALS(parse);
 	ZEND_DIAGNOSTIC_IGNORED_START("-Wdeprecated-declarations")
 	xmlSubstituteEntitiesDefault(1);
 	xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
 	ZEND_DIAGNOSTIC_IGNORED_END
 
+	if (clone_lxml_obj->document->class_type == PHP_LIBXML_CLASS_MODERN) {
+		xsl_add_ns_defs(newdoc);
+	}
+
 	sheetp = xsltParseStylesheetDoc(newdoc);
 	PHP_LIBXML_RESTORE_GLOBALS(parse);
 
 	if (!sheetp) {
-		xmlFreeDoc(newdoc);
+		OBJ_RELEASE(clone);
 		RETURN_FALSE;
 	}
 
 	xsl_object *intern = Z_XSL_P(id);
 
-	xsl_ns_hash_correction_status status = xsl_apply_ns_hash_corrections(sheetp, nodep, doc);
-	if (UNEXPECTED(status == XSL_NS_HASH_CORRECTION_FAILED)) {
-		xsltFreeStylesheet(sheetp);
-		xmlFreeDoc(newdoc);
-		RETURN_FALSE;
-	} else if (status == XSL_NS_HASH_CORRECTION_APPLIED) {
-		/* The namespace mappings need to be kept alive.
-		 * This is stored in the ref obj outside of libxml2, but that means that the sheet won't keep it alive
-		 * unlike with namespaces from old DOM. */
-		if (intern->sheet_ref_obj) {
-			php_libxml_decrement_doc_ref_directly(intern->sheet_ref_obj);
-		}
-		intern->sheet_ref_obj = Z_LIBXML_NODE_P(docp)->document;
-		intern->sheet_ref_obj->refcount++;
-	}
+	/* Detach object */
+	clone_lxml_obj->document->ptr = NULL;
+	/* The namespace mappings need to be kept alive.
+	 * This is stored in the ref obj outside of libxml2, but that means that the sheet won't keep it alive
+	 * unlike with namespaces from old DOM. */
+	if (intern->sheet_ref_obj) {
+		php_libxml_decrement_doc_ref_directly(intern->sheet_ref_obj);
+	}
+	intern->sheet_ref_obj = clone_lxml_obj->document;
+	intern->sheet_ref_obj->refcount++;
+	OBJ_RELEASE(clone);
 
 	member = ZSTR_INIT_LITERAL("cloneDocument", 0);
 	cloneDocu = zend_std_read_property(Z_OBJ_P(id), member, BP_VAR_R, NULL, &rv);
diff '--color=auto' -Naur php-8.4.18/ext/zip/php_zip.h php-8.4.20RC1/ext/zip/php_zip.h
--- php-8.4.18/ext/zip/php_zip.h	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/zip/php_zip.h	2026-04-01 04:35:36.022464820 +0000
@@ -39,7 +39,7 @@
 /* Additionnal flags not from libzip */
 #define ZIP_FL_OPEN_FILE_NOW (1u<<30)
 
-#define PHP_ZIP_VERSION "1.22.7"
+#define PHP_ZIP_VERSION "1.22.8"
 
 #ifdef HAVE_LIBZIP_VERSION
 #define LIBZIP_VERSION_STR zip_libzip_version()
diff '--color=auto' -Naur php-8.4.18/ext/zip/zip_stream.c php-8.4.20RC1/ext/zip/zip_stream.c
--- php-8.4.18/ext/zip/zip_stream.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/ext/zip/zip_stream.c	2026-04-01 04:35:36.022537868 +0000
@@ -125,12 +125,11 @@
 	size_t path_len = strlen(stream->orig_path);
 	char file_dirname[MAXPATHLEN];
 	struct zip *za;
-	char *fragment;
 	size_t fragment_len;
 	int err;
 	zend_string *file_basename;
 
-	fragment = strchr(path, '#');
+	const char *fragment = strchr(path, '#');
 	if (!fragment) {
 		return -1;
 	}
@@ -286,14 +285,13 @@
 
 	struct zip *za;
 	struct zip_file *zf = NULL;
-	char *fragment;
 	size_t fragment_len;
 	int err;
 
 	php_stream *stream = NULL;
 	struct php_zip_stream_data_t *self;
 
-	fragment = strchr(path, '#');
+	const char *fragment = strchr(path, '#');
 	if (!fragment) {
 		return NULL;
 	}
diff '--color=auto' -Naur php-8.4.18/EXTENSIONS php-8.4.20RC1/EXTENSIONS
--- php-8.4.18/EXTENSIONS	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/EXTENSIONS	2026-04-01 04:35:35.982361296 +0000
@@ -170,57 +170,57 @@
 PRIMARY MAINTAINER:  Christian Stocker <chregu@php.net> (2003 - 2011)
                      Rob Richards <rrichards@php.net> (2003 - 2012)
                      Marcus Börger <helly@php.net> (2003 - 2006)
-                     Niels Dossche <nielsdos@php.net> (2023 - 2025)
-MAINTENANCE:         Maintained
+                     Nora Dossche <nielsdos@php.net> (2023 - 2026)
+MAINTENANCE:         Odd fixes
 STATUS:              Working
 SINCE:               5.0
 -------------------------------------------------------------------------------
 EXTENSION:           simplexml
 PRIMARY MAINTAINER:  Marcus Börger <helly@php.net> (2003 - 2008)
-                     Niels Dossche <nielsdos@php.net> (2023 - 2025)
-MAINTENANCE:         Maintained
+                     Nora Dossche <nielsdos@php.net> (2023 - 2026)
+MAINTENANCE:         Odd fixes
 STATUS:              Working
 SINCE:               5.0
 -------------------------------------------------------------------------------
 EXTENSION:           soap
 PRIMARY MAINTAINER:  Dmitry Stogov <dmitry@php.net> (2004 - 2018)
-                     Niels Dossche <nielsdos@php.net> (2024 - 2025)
+                     Nora Dossche <nielsdos@php.net> (2024 - 2026)
 MAINTENANCE:         Odd fixes
 STATUS:              Working
 -------------------------------------------------------------------------------
 EXTENSION:           xml
 PRIMARY MAINTAINER:  Thies C. Arntzen <thies@thieso.net> (1999 - 2002)
                      Rob Richards <rrichards@php.net> (2003 - 2013)
-                     Niels Dossche <nielsdos@php.net> (2023 - 2025)
-MAINTENANCE:         Maintained
+                     Nora Dossche <nielsdos@php.net> (2023 - 2026)
+MAINTENANCE:         Odd fixes
 STATUS:              Working
 -------------------------------------------------------------------------------
 EXTENSION:           libxml
 PRIMARY MAINTAINER:  Rob Richards <rrichards@php.net> (2003 - 2009)
                      Christian Stocker <chregu@php.net> (2004 - 2011)
-                     Niels Dossche <nielsdos@php.net> (2023 - 2025)
-MAINTENANCE:         Maintained
+                     Nora Dossche <nielsdos@php.net> (2023 - 2026)
+MAINTENANCE:         Odd fixes
 STATUS:              Working
 -------------------------------------------------------------------------------
 EXTENSION:           xmlreader
 PRIMARY MAINTAINER:  Rob Richards <rrichards@php.net> (2004 - 2010)
                      Christian Stocker <chregu@php.net> (2004 - 2004)
-                     Niels Dossche <nielsdos@php.net> (2023 - 2025)
-MAINTENANCE:         Maintained
+                     Nora Dossche <nielsdos@php.net> (2023 - 2026)
+MAINTENANCE:         Odd fixes
 STATUS:              Working
 -------------------------------------------------------------------------------
 EXTENSION:           xmlwriter
 PRIMARY MAINTAINER:  Rob Richards <rrichards@php.net> (2004 - 2010)
                      Pierre-Alain Joye <pajoye@php.net> (2005-2009)
-                     Niels Dossche <nielsdos@php.net> (2023 - 2025)
-MAINTENANCE:         Maintained
+                     Nora Dossche <nielsdos@php.net> (2023 - 2026)
+MAINTENANCE:         Odd fixes
 STATUS:              Working
 -------------------------------------------------------------------------------
 EXTENSION:           xsl
 PRIMARY MAINTAINER:  Christian Stocker <chregu@php.net> (2003 - 2011)
                      Rob Richards <rrichards@php.net> (2003 - 2010)
-                     Niels Dossche <nielsdos@php.net> (2023 - 2025)
-MAINTENANCE:         Maintained
+                     Nora Dossche <nielsdos@php.net> (2023 - 2026)
+MAINTENANCE:         Odd fixes
 STATUS:              Working
 SINCE:               5.0
 -------------------------------------------------------------------------------
@@ -486,8 +486,8 @@
 PRIMARY MAINTAINER:  John Coggeshall <john@php.net> (2003 - 2006)
                      Ilia Alshanetsky <iliaa@php.net> (2003 - 2009)
                      Nuno Lopes <nlopess@php.net> (2006 - 2012)
-                     Niels Dossche <nielsdos@php.net> (2025 - 2025)
-MAINTENANCE:         Maintained
+                     Nora Dossche <nielsdos@php.net> (2025 - 2026)
+MAINTENANCE:         Odd fixes
 STATUS:              Working
 -------------------------------------------------------------------------------
 EXTENSION:           tokenizer
diff '--color=auto' -Naur php-8.4.18/.github/actions/brew/action.yml php-8.4.20RC1/.github/actions/brew/action.yml
--- php-8.4.18/.github/actions/brew/action.yml	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/.github/actions/brew/action.yml	2026-04-01 04:35:35.980577746 +0000
@@ -13,11 +13,17 @@
 
         # Some packages exist on x86 but not arm, or vice versa.
         # Install them with reinstall to avoid warnings.
-        brew reinstall autoconf webp tidy-html5 libzip libsodium icu4c
-        brew install \
+        brew reinstall -v \
+          autoconf \
+          webp \
+          tidy-html5 \
+          libzip \
+          libsodium \
+          icu4c
+        brew install -v \
           bison \
           re2c
-        brew install \
+        brew install -v \
           bzip2 \
           enchant \
           libffi \
diff '--color=auto' -Naur php-8.4.18/.github/actions/ccache/action.yml php-8.4.20RC1/.github/actions/ccache/action.yml
--- php-8.4.18/.github/actions/ccache/action.yml	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/.github/actions/ccache/action.yml	2026-04-01 04:35:35.980690659 +0000
@@ -0,0 +1,39 @@
+name: ccache
+inputs:
+  name:
+    required: true
+  php_directory:
+    required: false
+    default: '.'
+  cc:
+    required: false
+    default: 'gcc'
+  cxx:
+    required: false
+    default: 'g++'
+runs:
+  using: composite
+  steps:
+    - name: Get cache key
+      shell: bash
+      id: cache_key
+      run: |
+        major=$(cat ${{ inputs.php_directory }}/main/php_version.h | sed -En 's/^#define PHP_MAJOR_VERSION ([0-9]+)/\1/p')
+        minor=$(cat ${{ inputs.php_directory }}/main/php_version.h | sed -En 's/^#define PHP_MINOR_VERSION ([0-9]+)/\1/p')
+        release=$(cat ${{ inputs.php_directory }}/main/php_version.h | sed -En 's/^#define PHP_RELEASE_VERSION ([0-9]+)/\1/p')
+        week=$(date +"%Y-%W")
+        prefix="${{ inputs.name }}-$major.$minor.$release"
+        echo "key=$prefix-$week" >> $GITHUB_OUTPUT
+        echo "prefix=$prefix-" >> $GITHUB_OUTPUT
+    - name: ccache
+      uses: hendrikmuhs/ccache-action@v1.2
+      with:
+        key: "${{ steps.cache_key.outputs.key }}"
+        append-timestamp: false
+        restore-keys: "${{ steps.cache_key.outputs.prefix }}"
+        save: ${{ github.event_name != 'pull_request' }}
+    - name: Export CC/CXX
+      shell: bash
+      run: |
+        echo "CC=ccache ${{ inputs.cc }}" >> $GITHUB_ENV
+        echo "CXX=ccache ${{ inputs.cxx }}" >> $GITHUB_ENV
diff '--color=auto' -Naur php-8.4.18/.github/actions/freebsd/action.yml php-8.4.20RC1/.github/actions/freebsd/action.yml
--- php-8.4.18/.github/actions/freebsd/action.yml	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/.github/actions/freebsd/action.yml	2026-04-01 04:35:35.980810085 +0000
@@ -15,6 +15,7 @@
         release: '13.5'
         usesh: true
         copyback: false
+        disable-cache: true
         # Temporarily disable sqlite, as FreeBSD ships it with disabled double quotes. We'll need to fix our tests.
         # https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=269889
         prepare: |
@@ -106,6 +107,7 @@
           export SKIP_IO_CAPTURE_TESTS=1
           export CI_NO_IPV6=1
           export STACK_LIMIT_DEFAULTS_CHECK=1
+          export RUN_RESOURCE_HEAVY_TESTS=1
           sapi/cli/php run-tests.php \
             -P -q -j2 \
             -g FAIL,BORK,LEAK,XLEAK \
diff '--color=auto' -Naur php-8.4.18/.github/actions/solaris/action.yml php-8.4.20RC1/.github/actions/solaris/action.yml
--- php-8.4.18/.github/actions/solaris/action.yml	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/.github/actions/solaris/action.yml	2026-04-01 04:35:35.980934700 +0000
@@ -0,0 +1,88 @@
+name: Solaris
+inputs:
+  configurationParameters:
+    default: ''
+    required: false
+  runExtraTests:
+    default: false
+    required: false
+runs:
+  using: composite
+  steps:
+    - name: Solaris
+      uses: vmactions/solaris-vm@v1
+      with:
+        release: "11.4-gcc"
+        usesh: true
+        copyback: false
+        disable-cache: true
+        prepare: |
+          cd $GITHUB_WORKSPACE
+          pkg install bison developer/icu libzip oniguruma re2c
+
+          ./buildconf -f
+          CC=gcc CXX=g++ \
+          CFLAGS="-Wno-char-subscripts" \
+          PATH=/usr/gnu/bin:/usr/bin \
+          PKG_CONFIG_PATH=/usr/lib/amd64/pkgconfig \
+          ./configure \
+            --prefix=/usr/local \
+            --enable-debug \
+            --enable-werror \
+            --enable-option-checking=fatal \
+            --enable-fpm \
+            --without-pear \
+            --with-bz2 \
+            --with-jpeg \
+            --with-webp \
+            --with-freetype \
+            --enable-gd \
+            --enable-exif \
+            --with-zip \
+            --with-zlib \
+            --enable-soap \
+            --enable-xmlreader \
+            --with-xsl \
+            --with-libxml \
+            --enable-shmop \
+            --enable-pcntl \
+            --enable-mbstring \
+            --with-curl \
+            --enable-sockets \
+            --with-openssl \
+            --enable-bcmath \
+            --enable-calendar \
+            --enable-ftp \
+            --enable-zend-test \
+            --enable-dl-test=shared \
+            --enable-intl \
+            --with-mhash \
+            --with-config-file-path=/etc \
+            --with-config-file-scan-dir=/etc/php.d \
+            ${{ inputs.configurationParameters }}
+
+          gmake -j2
+          mkdir /etc/php.d
+          gmake install > /dev/null
+          echo opcache.enable_cli=1 > /etc/php.d/opcache.ini
+          echo opcache.protect_memory=1 >> /etc/php.d/opcache.ini
+          echo opcache.preload_user=root >> /etc/php.d/opcache.ini
+        run: |
+          cd $GITHUB_WORKSPACE
+
+          export SKIP_IO_CAPTURE_TESTS=1
+          export CI_NO_IPV6=1
+          export STACK_LIMIT_DEFAULTS_CHECK=1
+          PATH=/usr/gnu/bin:/usr/bin \
+          sapi/cli/php run-tests.php \
+            -P -q -j1 \
+            -g FAIL,BORK,LEAK,XLEAK \
+            --no-progress \
+            --offline \
+            --show-diff \
+            --show-slow 1000 \
+            --set-timeout 120
+
+          if test "${{ inputs.runExtraTests }}" = "true"; then
+            sapi/cli/php run-extra-tests.php
+          fi
diff '--color=auto' -Naur php-8.4.18/.github/actions/test-alpine/action.yml php-8.4.20RC1/.github/actions/test-alpine/action.yml
--- php-8.4.18/.github/actions/test-alpine/action.yml	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/.github/actions/test-alpine/action.yml	2026-04-01 04:35:35.981058945 +0000
@@ -3,6 +3,9 @@
   runTestsParameters:
     default: ''
     required: false
+  enableOpcache:
+    default: 'false'
+    required: false
   jitType:
     default: 'disable'
     required: false
@@ -15,6 +18,7 @@
         export SKIP_IO_CAPTURE_TESTS=1
         export STACK_LIMIT_DEFAULTS_CHECK=1
         sapi/cli/php run-tests.php -P -q ${{ inputs.runTestsParameters }} \
+          ${{ inputs.enableOpcache == 'true' && '-d zend_extension=opcache.so -d opcache.enable_cli=1' || '' }} \
           -d opcache.jit=${{ inputs.jitType }} \
           -d opcache.jit_buffer_size=64M \
           -j$(nproc) \
diff '--color=auto' -Naur php-8.4.18/.github/actions/test-gentoo/action.yml php-8.4.20RC1/.github/actions/test-gentoo/action.yml
--- php-8.4.18/.github/actions/test-gentoo/action.yml	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/.github/actions/test-gentoo/action.yml	2026-04-01 04:35:35.981146921 +0000
@@ -25,6 +25,7 @@
         # Slow tests criteron is doubled because this runner isn't as fast as others
         export SKIP_IO_CAPTURE_TESTS=1
         export STACK_LIMIT_DEFAULTS_CHECK=1
+        export RUN_RESOURCE_HEAVY_TESTS=1
         sapi/cli/php run-tests.php -P -q ${{ inputs.runTestsParameters }} \
           -j$(nproc) \
           -g FAIL,BORK,LEAK,XLEAK \
diff '--color=auto' -Naur php-8.4.18/.github/actions/test-libmysqlclient/action.yml php-8.4.20RC1/.github/actions/test-libmysqlclient/action.yml
--- php-8.4.18/.github/actions/test-libmysqlclient/action.yml	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/.github/actions/test-libmysqlclient/action.yml	2026-04-01 04:35:35.981232172 +0000
@@ -9,6 +9,7 @@
         export PDO_MYSQL_TEST_HOST=127.0.0.1
         export PDO_MYSQL_TEST_USER=root
         export PDO_MYSQL_TEST_PASS=root
+        export RUN_RESOURCE_HEAVY_TESTS=1
         sapi/cli/php run-tests.php -P -q \
           -g FAIL,BORK,LEAK,XLEAK \
           --no-progress --offline --show-diff --show-slow 1000 --set-timeout 120 \
diff '--color=auto' -Naur php-8.4.18/.github/actions/test-linux/action.yml php-8.4.20RC1/.github/actions/test-linux/action.yml
--- php-8.4.18/.github/actions/test-linux/action.yml	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/.github/actions/test-linux/action.yml	2026-04-01 04:35:35.981298998 +0000
@@ -3,6 +3,9 @@
   runTestsParameters:
     default: ''
     required: false
+  enableOpcache:
+    default: 'false'
+    required: false
   jitType:
     default: 'disable'
     required: false
@@ -39,7 +42,9 @@
         export PDO_ODBC_TEST_DSN="odbc:Driver={ODBC Driver 17 for SQL Server};Server=127.0.0.1;Database=pdo_odbc;uid=$ODBC_TEST_USER;pwd=$ODBC_TEST_PASS"
         export SKIP_IO_CAPTURE_TESTS=1
         export STACK_LIMIT_DEFAULTS_CHECK=1
+        export RUN_RESOURCE_HEAVY_TESTS=1
         sapi/cli/php run-tests.php -P -q ${{ inputs.runTestsParameters }} \
+          ${{ inputs.enableOpcache == 'true' && '-d zend_extension=opcache.so -d opcache.enable_cli=1' || '' }} \
           -d opcache.jit=${{ inputs.jitType }} \
           -d opcache.protect_memory=1 \
           -d opcache.jit_buffer_size=64M \
diff '--color=auto' -Naur php-8.4.18/.github/actions/test-macos/action.yml php-8.4.20RC1/.github/actions/test-macos/action.yml
--- php-8.4.18/.github/actions/test-macos/action.yml	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/.github/actions/test-macos/action.yml	2026-04-01 04:35:35.981359793 +0000
@@ -3,6 +3,9 @@
   runTestsParameters:
     default: ''
     required: false
+  enableOpcache:
+    default: 'false'
+    required: false
   jitType:
     default: 'disable'
     required: false
@@ -15,7 +18,9 @@
         export SKIP_IO_CAPTURE_TESTS=1
         export CI_NO_IPV6=1
         export STACK_LIMIT_DEFAULTS_CHECK=1
+        export RUN_RESOURCE_HEAVY_TESTS=1
         sapi/cli/php run-tests.php -P -q ${{ inputs.runTestsParameters }} \
+          ${{ inputs.enableOpcache == 'true' && '-d zend_extension=opcache.so -d opcache.enable_cli=1' || '' }} \
           -d opcache.jit=${{ inputs.jitType }} \
           -d opcache.protect_memory=1 \
           -d opcache.jit_buffer_size=64M \
diff '--color=auto' -Naur php-8.4.18/.github/matrix.php php-8.4.20RC1/.github/matrix.php
--- php-8.4.18/.github/matrix.php	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/.github/matrix.php	2026-04-01 04:35:35.981455755 +0000
@@ -0,0 +1,203 @@
+<?php
+
+const BRANCHES = [
+    ['name' => 'master', 'ref' => 'master', 'version' => [8, 6]],
+    ['name' => 'PHP-8.5', 'ref' => 'PHP-8.5', 'version' => [8, 5]],
+    ['name' => 'PHP-8.4', 'ref' => 'PHP-8.4', 'version' => [8, 4]],
+    ['name' => 'PHP-8.3', 'ref' => 'PHP-8.3', 'version' => [8, 3]],
+    ['name' => 'PHP-8.2', 'ref' => 'PHP-8.2', 'version' => [8, 2]],
+];
+
+function get_branch_commit_cache_file_path(): string {
+    return dirname(__DIR__) . '/branch-commit-cache.json';
+}
+
+function get_branches() {
+    $branch_commit_cache_file = get_branch_commit_cache_file_path();
+    $branch_commit_map = [];
+    if (file_exists($branch_commit_cache_file)) {
+        $branch_commit_map = json_decode(file_get_contents($branch_commit_cache_file), JSON_THROW_ON_ERROR);
+    }
+
+    $changed_branches = [];
+    foreach (BRANCHES as $branch) {
+        $previous_commit_hash = $branch_commit_map[$branch['ref']] ?? null;
+        $current_commit_hash = trim(shell_exec('git rev-parse origin/' . $branch['ref']));
+
+        if ($previous_commit_hash !== $current_commit_hash) {
+            $changed_branches[] = $branch;
+        }
+
+        $branch_commit_map[$branch['ref']] = $current_commit_hash;
+    }
+
+    file_put_contents($branch_commit_cache_file, json_encode($branch_commit_map));
+
+    return $changed_branches;
+}
+
+function get_current_version(): array {
+    $file = dirname(__DIR__) . '/main/php_version.h';
+    $content = file_get_contents($file);
+    preg_match('(^#define PHP_MAJOR_VERSION (?<num>\d+)$)m', $content, $matches);
+    $major = (int) $matches['num'];
+    preg_match('(^#define PHP_MINOR_VERSION (?<num>\d+)$)m', $content, $matches);
+    $minor = (int) $matches['num'];
+    return [$major, $minor];
+}
+
+function select_jobs($repository, $trigger, $nightly, $labels, $php_version, $ref, $all_variations) {
+    $no_jobs = in_array('CI: No jobs', $labels, true);
+    $all_jobs = in_array('CI: All jobs', $labels, true) || $nightly;
+    $test_alpine = in_array('CI: Alpine', $labels, true);
+    $test_benchmarking = in_array('CI: Benchmarking', $labels, true);
+    $test_community = in_array('CI: Community', $labels, true);
+    $test_coverage = in_array('CI: Coverage', $labels, true);
+    $test_freebsd = in_array('CI: FreeBSD', $labels, true);
+    $test_libmysqlclient = in_array('CI: libmysqlclient', $labels, true);
+    $test_linux_ppc64 = in_array('CI: Linux PPC64', $labels, true);
+    $test_linux_x32 = in_array('CI: Linux X32', $labels, true);
+    $test_linux_x64 = in_array('CI: Linux X64', $labels, true);
+    $test_macos = in_array('CI: macOS', $labels, true);
+    $test_msan = in_array('CI: MSAN', $labels, true);
+    $test_opcache_variation = in_array('CI: Opcache Variation', $labels, true);
+    $test_pecl = in_array('CI: PECL', $labels, true);
+    $test_solaris = in_array('CI: Solaris', $labels, true);
+    $test_windows = in_array('CI: Windows', $labels, true);
+
+    $jobs = [];
+    if (version_compare($php_version, '8.4', '>=') && ($all_jobs || !$no_jobs || $test_alpine)) {
+        $jobs['ALPINE'] = true;
+    }
+    if (version_compare($php_version, '8.4', '>=')
+        && !$nightly
+        && ($all_jobs || !$no_jobs || $test_benchmarking)
+        // push trigger is restricted to official repository.
+        && ($repository === 'php/php-src' || $trigger === 'pull_request')) {
+        $jobs['BENCHMARKING']['config']['integrated_opcache'] = version_compare($php_version, '8.5', '>=');
+    }
+    if ($all_jobs || $test_community) {
+        $jobs['COMMUNITY']['matrix'] = version_compare($php_version, '8.4', '>=')
+            ? ['type' => ['asan', 'verify_type_inference']]
+            : ['type' => ['asan']];
+        $jobs['COMMUNITY']['config']['symfony_version'] = match (true) {
+            version_compare($php_version, '8.3', '<=') => '7.4',
+            default => '',
+        };
+        $jobs['COMMUNITY']['config']['laravel_version'] = match (true) {
+            version_compare($php_version, '8.2', '<=') => '12.x',
+            default => '',
+        };
+    }
+    if (($all_jobs && $ref === 'master') || $test_coverage) {
+        $jobs['COVERAGE'] = true;
+    }
+    if ($all_jobs || $test_libmysqlclient) {
+        $jobs['LIBMYSQLCLIENT'] = true;
+    }
+    if (version_compare($php_version, '8.4', '>=') && ($all_jobs || $test_linux_ppc64)) {
+        $jobs['LINUX_PPC64'] = true;
+    }
+    if ($all_jobs || !$no_jobs || $test_linux_x64) {
+        $jobs['LINUX_X64']['matrix'] = $all_variations
+            ? [
+                'name' => [''],
+                'asan' => [false],
+                'debug' => [true, false],
+                'repeat' => [false],
+                'variation' => [false],
+                'zts' => [true, false],
+                'include' => [
+                    ['name' => '_ASAN', 'asan' => true, 'debug' => true, 'repeat' => false, 'variation' => false, 'zts' => true],
+                    ['name' => '_REPEAT', 'asan' => false, 'debug' => true, 'repeat' => true, 'variation' => false, 'zts' => false],
+                    ['name' => '_VARIATION', 'asan' => false, 'debug' => true, 'repeat' => false, 'variation' => true, 'zts' => true],
+                ],
+            ]
+            : ['include' => [
+                ['name' => '', 'asan' => false, 'debug' => false, 'repeat' => false, 'variation' => false, 'zts' => false],
+                ['name' => '_ASAN', 'asan' => true, 'debug' => true, 'repeat' => false, 'variation' => false, 'zts' => true],
+            ]];
+        $jobs['LINUX_X64']['config']['variation_enable_zend_max_execution_timers'] = version_compare($php_version, '8.3', '>=');
+    }
+    if ($all_jobs || !$no_jobs || $test_linux_x32) {
+        $jobs['LINUX_X32']['matrix'] = $all_variations
+            ? ['debug' => [true, false], 'zts' => [true, false]]
+            : ['debug' => [true], 'zts' => [true]];
+    }
+    if ($all_jobs || !$no_jobs || $test_macos) {
+        $test_arm = version_compare($php_version, '8.4', '>=');
+        $jobs['MACOS']['matrix'] = $all_variations
+            ? ['arch' => $test_arm ? ['X64', 'ARM64'] : ['X64'], 'debug' => [true, false], 'zts' => [true, false]]
+            : ['include' => [['arch' => $test_arm ? 'ARM64' : 'X64', 'debug' => true, 'zts' => false]]];
+        $jobs['MACOS']['config']['arm64_version'] = version_compare($php_version, '8.4', '>=') ? '15' : '14';
+    }
+    if ($all_jobs || $test_msan) {
+        $jobs['MSAN'] = true;
+    }
+    if ($all_jobs || $test_opcache_variation) {
+        $jobs['OPCACHE_VARIATION'] = true;
+    }
+    if (($all_jobs && $ref === 'master') || $test_pecl) {
+        $jobs['PECL'] = true;
+    }
+    if (version_compare($php_version, '8.6', '>=') && ($all_jobs || $test_solaris)) {
+        $jobs['SOLARIS'] = true;
+    }
+    if ($all_jobs || !$no_jobs || $test_windows) {
+        $jobs['WINDOWS']['matrix'] = $all_variations
+            ? ['include' => [
+                ['asan' => true, 'opcache' => true, 'x64' => true, 'zts' => true],
+                ['asan' => false, 'opcache' => false, 'x64' => false, 'zts' => false],
+            ]]
+            : ['include' => [['asan' => false, 'opcache' => true, 'x64' => true, 'zts' => true]]];
+        $jobs['WINDOWS']['config'] = version_compare($php_version, '8.4', '>=')
+            ? ['vs_crt_version' => 'vs17']
+            : ['vs_crt_version' => 'vs16'];
+    }
+    if ($all_jobs || !$no_jobs || $test_freebsd) {
+        $jobs['FREEBSD']['matrix'] = $all_variations && version_compare($php_version, '8.3', '>=')
+            ? ['zts' => [true, false]]
+            : ['zts' => [false]];
+    }
+    return $jobs;
+}
+
+$trigger = $argv[1] ?? 'schedule';
+$attempt = (int) ($argv[2] ?? 1);
+$sunday = date('w', time()) === '0';
+$discard_cache = $sunday
+    || ($trigger === 'schedule' && $attempt !== 1)
+    || $trigger === 'workflow_dispatch';
+if ($discard_cache) {
+    @unlink(get_branch_commit_cache_file_path());
+}
+$branch = $argv[3] ?? 'master';
+$nightly = $trigger === 'schedule' || $trigger === 'workflow_dispatch';
+$branches = $nightly && $branch === 'master'
+    ? get_branches()
+    : [['name' => 'Suite', 'ref' => $branch, 'version' => get_current_version()]];
+
+$labels = json_decode($argv[4] ?? '[]', true) ?? [];
+$labels = array_column($labels, 'name');
+$all_variations = $nightly || in_array('CI: All variations', $labels, true);
+
+$repository = $argv[5] ?? null;
+
+foreach ($branches as &$branch) {
+    $php_version = $branch['version'][0] . '.' . $branch['version'][1];
+    $branch['jobs'] = select_jobs($repository, $trigger, $nightly, $labels, $php_version, $branch['ref'], $all_variations);
+    $branch['config']['ubuntu_version'] = version_compare($php_version, '8.5', '>=') ? '24.04' : '22.04';
+}
+
+echo "All variations:";
+echo json_encode($all_variations, JSON_UNESCAPED_SLASHES|JSON_PRETTY_PRINT);
+echo "\n\nBranches:\n";
+echo json_encode($branches, JSON_UNESCAPED_SLASHES|JSON_PRETTY_PRINT);
+echo "\n";
+
+if (false !== ($github_output = getenv('GITHUB_OUTPUT'))) {
+    $f = fopen($github_output, 'a');
+    fwrite($f, 'branches=' . json_encode($branches, JSON_UNESCAPED_SLASHES) . "\n");
+    fwrite($f, 'all_variations=' . json_encode($all_variations, JSON_UNESCAPED_SLASHES) . "\n");
+    fclose($f);
+}
diff '--color=auto' -Naur php-8.4.18/.github/nightly_matrix.php php-8.4.20RC1/.github/nightly_matrix.php
--- php-8.4.18/.github/nightly_matrix.php	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/.github/nightly_matrix.php	1970-01-01 00:00:00.000000000 +0000
@@ -1,65 +0,0 @@
-<?php
-
-const BRANCHES = [
-    ['ref' => 'master', 'version' => [8, 6]],
-    ['ref' => 'PHP-8.5', 'version' => [8, 5]],
-    ['ref' => 'PHP-8.4', 'version' => [8, 4]],
-    ['ref' => 'PHP-8.3', 'version' => [8, 3]],
-    ['ref' => 'PHP-8.2', 'version' => [8, 2]],
-];
-
-function get_branch_commit_cache_file_path(): string {
-    return dirname(__DIR__) . '/branch-commit-cache.json';
-}
-
-function get_branches() {
-    $branch_commit_cache_file = get_branch_commit_cache_file_path();
-    $branch_commit_map = [];
-    if (file_exists($branch_commit_cache_file)) {
-        $branch_commit_map = json_decode(file_get_contents($branch_commit_cache_file), JSON_THROW_ON_ERROR);
-    }
-
-    $changed_branches = [];
-    foreach (BRANCHES as $branch) {
-        $previous_commit_hash = $branch_commit_map[$branch['ref']] ?? null;
-        $current_commit_hash = trim(shell_exec('git rev-parse origin/' . $branch['ref']));
-
-        if ($previous_commit_hash !== $current_commit_hash) {
-            $changed_branches[] = $branch;
-        }
-
-        $branch_commit_map[$branch['ref']] = $current_commit_hash;
-    }
-
-    file_put_contents($branch_commit_cache_file, json_encode($branch_commit_map));
-
-    return $changed_branches;
-}
-
-function get_current_version(): array {
-    $file = dirname(__DIR__) . '/main/php_version.h';
-    $content = file_get_contents($file);
-    preg_match('(^#define PHP_MAJOR_VERSION (?<num>\d+)$)m', $content, $matches);
-    $major = (int) $matches['num'];
-    preg_match('(^#define PHP_MINOR_VERSION (?<num>\d+)$)m', $content, $matches);
-    $minor = (int) $matches['num'];
-    return [$major, $minor];
-}
-
-$trigger = $argv[1] ?? 'schedule';
-$attempt = (int) ($argv[2] ?? 1);
-$sunday = date('w', time()) === '0';
-$discard_cache = $sunday
-    || ($trigger === 'schedule' && $attempt !== 1)
-    || $trigger === 'workflow_dispatch';
-if ($discard_cache) {
-    @unlink(get_branch_commit_cache_file_path());
-}
-$branch = $argv[3] ?? 'master';
-$branches = $branch === 'master'
-    ? get_branches()
-    : [['ref' => $branch, 'version' => get_current_version()]];
-
-$f = fopen(getenv('GITHUB_OUTPUT'), 'a');
-fwrite($f, 'branches=' . json_encode($branches, JSON_UNESCAPED_SLASHES) . "\n");
-fclose($f);
diff '--color=auto' -Naur php-8.4.18/.github/workflows/nightly-results.yml php-8.4.20RC1/.github/workflows/nightly-results.yml
--- php-8.4.18/.github/workflows/nightly-results.yml	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/.github/workflows/nightly-results.yml	2026-04-01 04:35:35.981645723 +0000
@@ -2,13 +2,13 @@
 on:
   workflow_run:
     workflows:
-      - Nightly
+      - Test
     types:
       - completed
 jobs:
   on-failure:
     runs-on: ubuntu-latest
-    if: ${{ github.repository == 'php/php-src' && github.event.workflow_run.conclusion == 'failure' }}
+    if: ${{ github.repository == 'php/php-src' && github.event.workflow_run.event == 'schedule' && github.event.workflow_run.conclusion == 'failure' }}
     steps:
       - run: |
           export DEBIAN_FRONTEND=noninteractive
diff '--color=auto' -Naur php-8.4.18/.github/workflows/nightly.yml php-8.4.20RC1/.github/workflows/nightly.yml
--- php-8.4.18/.github/workflows/nightly.yml	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/.github/workflows/nightly.yml	1970-01-01 00:00:00.000000000 +0000
@@ -1,1042 +0,0 @@
-name: Test suite
-on:
-  workflow_call:
-    inputs:
-      asan_ubuntu_version:
-        required: true
-        type: string
-      branch:
-        required: true
-        type: string
-      community_verify_type_inference:
-        required: true
-        type: boolean
-      run_alpine:
-        required: true
-        type: boolean
-      run_linux_ppc64:
-        required: true
-        type: boolean
-      run_macos_arm64:
-        required: true
-        type: boolean
-      run_freebsd_zts:
-        required: true
-        type: boolean
-      ubuntu_version:
-        required: true
-        type: string
-      windows_version:
-        required: true
-        type: string
-      vs_crt_version:
-        required: true
-        type: string
-      skip_laravel:
-        required: true
-        type: boolean
-      symfony_version:
-        required: true
-        type: string
-      skip_wordpress:
-        required: true
-        type: boolean
-      variation_enable_zend_max_execution_timers:
-        required: true
-        type: boolean
-permissions:
-  contents: read
-jobs:
-  LINUX_PPC64:
-    if: inputs.run_linux_ppc64
-    name: LINUX_PPC64_ASAN_UBSAN_DEBUG_ZTS
-    # This runs on a self-hosted runner; see https://wiki.php.net/systems/ci
-    runs-on: [self-hosted, gentoo, ppc64]
-    steps:
-      - name: git checkout
-        uses: actions/checkout@v6
-        with:
-          ref: ${{ inputs.branch }}
-      - name: System info
-        run: |
-          echo "::group::Show host CPU info"
-          lscpu
-          echo "::endgroup::"
-          echo "::group::Show installed packages"
-          cat /var/lib/portage/world
-          echo "::endgroup::"
-      - name: ./configure
-        uses: ./.github/actions/configure-gentoo
-        with:
-          configurationParameters: >-
-            CFLAGS="-fsanitize=undefined,address -fno-sanitize=function -DZEND_TRACK_ARENA_ALLOC"
-            LDFLAGS="-fsanitize=undefined,address -fno-sanitize=function"
-            CC=clang-17
-            CXX=clang++-17
-            --enable-debug
-            --enable-zts
-          skipSlow: false # FIXME: This should likely include slow extensions
-      - name: make
-        run: make -j$(/usr/bin/nproc) >/dev/null
-      # Skip an install action for now
-      - name: Tests
-        uses: ./.github/actions/test-gentoo
-        # There is no PPC JIT, so rip this out
-        with:
-          runTestsParameters: >-
-            --asan -x
-      - name: Extra tests
-        uses: ./.github/actions/extra-tests
-  ALPINE:
-    if: inputs.run_alpine
-    name: ALPINE_X64_ASAN_UBSAN_DEBUG_ZTS
-    runs-on: ubuntu-24.04
-    container:
-      image: 'alpine:3.22'
-    steps:
-      - name: git checkout
-        uses: actions/checkout@v6
-        with:
-          ref: ${{ inputs.branch }}
-      - name: apk
-        uses: ./.github/actions/apk
-      - name: System info
-        run: |
-          echo "::group::Show host CPU info"
-          lscpu
-          echo "::endgroup::"
-          echo "::group::Show installed package versions"
-          apk list
-          echo "::endgroup::"
-      - name: ./configure
-        uses: ./.github/actions/configure-alpine
-        with:
-          configurationParameters: >-
-            CFLAGS="-fsanitize=undefined,address -fno-sanitize=function -DZEND_TRACK_ARENA_ALLOC"
-            LDFLAGS="-fsanitize=undefined,address -fno-sanitize=function"
-            CC=clang-20
-            CXX=clang++-20
-            --enable-debug
-            --enable-zts
-          skipSlow: true # FIXME: This should likely include slow extensions
-      - name: make
-        run: make -j$(/usr/bin/nproc) >/dev/null
-      - name: make install
-        uses: ./.github/actions/install-alpine
-      - name: Test Tracing JIT
-        uses: ./.github/actions/test-alpine
-        with:
-          jitType: tracing
-          runTestsParameters: >-
-            --asan -x
-            -d zend_extension=opcache.so
-            -d opcache.enable_cli=1
-      - name: Extra tests
-        uses: ./.github/actions/extra-tests
-  LINUX_X64:
-    services:
-      mysql:
-        image: mysql:8.3
-        ports:
-          - 3306:3306
-        env:
-          MYSQL_DATABASE: test
-          MYSQL_ROOT_PASSWORD: root
-      postgres:
-        image: postgres
-        env:
-          POSTGRES_USER: postgres
-          POSTGRES_PASSWORD: postgres
-          POSTGRES_DB: test
-      firebird:
-        image: jacobalberty/firebird
-        ports:
-          - 3050:3050
-        env:
-          ISC_PASSWORD: test
-          FIREBIRD_DATABASE: test.fdb
-          FIREBIRD_USER: test
-          FIREBIRD_PASSWORD: test
-    strategy:
-      fail-fast: false
-      matrix:
-        configuration_parameters: ['']
-        debug: [true, false]
-        name: ['']
-        run_tests_parameters: ['']
-        test_function_jit: [true]
-        zts: [true, false]
-        include:
-          - name: _ASAN_UBSAN
-            debug: true
-            zts: true
-            configuration_parameters: >-
-              CFLAGS="-fsanitize=undefined,address -DZEND_TRACK_ARENA_ALLOC"
-              LDFLAGS="-fsanitize=undefined,address"
-            run_tests_parameters: '--asan'
-            test_function_jit: false
-            asan: true
-          - name: _REPEAT
-            debug: true
-            zts: false
-            run_tests_parameters: --repeat 2
-            timeout_minutes: 360
-            test_function_jit: true
-            asan: false
-          - name: _VARIATION
-            debug: true
-            zts: true
-            configuration_parameters: >-
-              CFLAGS="-DZEND_RC_DEBUG=1 -DPROFITABILITY_CHECKS=0 -DZEND_VERIFY_FUNC_INFO=1 -DZEND_VERIFY_TYPE_INFERENCE"
-              ${{ inputs.variation_enable_zend_max_execution_timers && '--enable-zend-max-execution-timers' || '' }}
-            run_tests_parameters: -d zend_test.observer.enabled=1 -d zend_test.observer.show_output=0
-            timeout_minutes: 360
-            test_function_jit: true
-            asan: false
-    name: "LINUX_X64${{ matrix.name }}_${{ matrix.debug && 'DEBUG' || 'RELEASE' }}_${{ matrix.zts && 'ZTS' || 'NTS' }}"
-    runs-on: ubuntu-${{ matrix.asan && inputs.asan_ubuntu_version || inputs.ubuntu_version }}
-    steps:
-      - name: git checkout
-        uses: actions/checkout@v6
-        with:
-          ref: ${{ inputs.branch }}
-      - name: Create MSSQL container
-        uses: ./.github/actions/setup-mssql
-      - name: apt
-        uses: ./.github/actions/apt-x64
-        with:
-          asan: ${{ matrix.asan && 'true' || 'false' }}
-      - name: System info
-        run: |
-          echo "::group::Show host CPU info"
-          lscpu
-          echo "::endgroup::"
-          echo "::group::Show installed package versions"
-          dpkg -l
-          echo "::endgroup::"
-      - name: ./configure
-        uses: ./.github/actions/configure-x64
-        with:
-          configurationParameters: >-
-            ${{ matrix.configuration_parameters }}
-            --${{ matrix.debug && 'enable' || 'disable' }}-debug
-            --${{ matrix.zts && 'enable' || 'disable' }}-zts
-          asan: ${{ matrix.asan && 'true' || 'false' }}
-      - name: make
-        run: make -j$(/usr/bin/nproc) >/dev/null
-      - name: make install
-        uses: ./.github/actions/install-linux
-      - name: Setup
-        uses: ./.github/actions/setup-x64
-      - name: Test
-        uses: ./.github/actions/test-linux
-        with:
-          runTestsParameters: >-
-            ${{ matrix.run_tests_parameters }}
-          idleCpu: ${{ matrix.asan && 'true' || 'false' }}
-      - name: Test Tracing JIT
-        uses: ./.github/actions/test-linux
-        with:
-          jitType: tracing
-          runTestsParameters: >-
-            ${{ matrix.run_tests_parameters }}
-            -d zend_extension=opcache.so
-            -d opcache.enable_cli=1
-      - name: Test OpCache
-        uses: ./.github/actions/test-linux
-        with:
-          runTestsParameters: >-
-            ${{ matrix.run_tests_parameters }}
-            -d zend_extension=opcache.so
-            -d opcache.enable_cli=1
-      - name: Test Function JIT
-        # ASAN frequently timeouts. Each test run takes ~90 minutes, we can
-        # avoid running into the 6 hour timeout by skipping the function JIT.
-        if: matrix.test_function_jit
-        uses: ./.github/actions/test-linux
-        with:
-          jitType: function
-          runTestsParameters: >-
-            ${{ matrix.run_tests_parameters }}
-            -d zend_extension=opcache.so
-            -d opcache.enable_cli=1
-      - name: Extra tests
-        uses: ./.github/actions/extra-tests
-      - name: Verify generated files are up to date
-        uses: ./.github/actions/verify-generated-files
-  LINUX_X32:
-    strategy:
-      fail-fast: false
-      matrix:
-        debug: [true, false]
-        zts: [true, false]
-    name: "LINUX_X32_${{ matrix.debug && 'DEBUG' || 'RELEASE' }}_${{ matrix.zts && 'ZTS' || 'NTS' }}"
-    runs-on: ubuntu-latest
-    container:
-      image: ubuntu:${{ inputs.ubuntu_version }}
-    env:
-      PDO_FIREBIRD_TEST_DSN: firebird:dbname=firebird:test.fdb
-    services:
-      mysql:
-        image: mysql:8.3
-        ports:
-          - 3306:3306
-        env:
-          MYSQL_DATABASE: test
-          MYSQL_ROOT_PASSWORD: root
-      firebird:
-        image: jacobalberty/firebird
-        ports:
-          - 3050:3050
-        env:
-          ISC_PASSWORD: test
-          FIREBIRD_DATABASE: test.fdb
-          FIREBIRD_USER: test
-          FIREBIRD_PASSWORD: test
-    steps:
-      - name: git checkout
-        uses: actions/checkout@v6
-        with:
-          ref: ${{ inputs.branch }}
-      - name: apt
-        uses: ./.github/actions/apt-x32
-      - name: System info
-        run: |
-          echo "::group::Show host CPU info"
-          lscpu
-          echo "::endgroup::"
-          echo "::group::Show installed package versions"
-          dpkg -l
-          echo "::endgroup::"
-      - name: ./configure
-        uses: ./.github/actions/configure-x32
-        with:
-          configurationParameters: >-
-            --${{ matrix.debug && 'enable' || 'disable' }}-debug
-            --${{ matrix.zts && 'enable' || 'disable' }}-zts
-      - name: make
-        run: make -j$(/usr/bin/nproc) >/dev/null
-      - name: make install
-        uses: ./.github/actions/install-linux-x32
-      - name: Test
-        uses: ./.github/actions/test-linux
-        with:
-          runTestsParameters: >-
-            ${{ matrix.run_tests_parameters }}
-      - name: Test Tracing JIT
-        uses: ./.github/actions/test-linux
-        with:
-          jitType: tracing
-          runTestsParameters: >-
-            ${{ matrix.run_tests_parameters }}
-            -d zend_extension=opcache.so
-            -d opcache.enable_cli=1
-      - name: Test OpCache
-        uses: ./.github/actions/test-linux
-        with:
-          runTestsParameters: >-
-            ${{ matrix.run_tests_parameters }}
-            -d zend_extension=opcache.so
-            -d opcache.enable_cli=1
-      - name: Test Function JIT
-        uses: ./.github/actions/test-linux
-        with:
-          jitType: function
-          runTestsParameters: >-
-            ${{ matrix.run_tests_parameters }}
-            -d zend_extension=opcache.so
-            -d opcache.enable_cli=1
-      - name: Extra tests
-        uses: ./.github/actions/extra-tests
-  MACOS:
-    strategy:
-      fail-fast: false
-      matrix:
-        debug: [true, false]
-        zts: [true, false]
-        os: ['13', '14']
-        exclude:
-          - os: ${{ !inputs.run_macos_arm64 && '14' || '*never*' }}
-    name: "MACOS_${{ matrix.os == '13' && 'X64' || 'ARM64' }}_${{ matrix.debug && 'DEBUG' || 'RELEASE' }}_${{ matrix.zts && 'ZTS' || 'NTS' }}"
-    runs-on: macos-${{ matrix.os }}
-    steps:
-      - name: git checkout
-        uses: actions/checkout@v6
-        with:
-          ref: ${{ inputs.branch }}
-      - name: Update clang
-        uses: ./.github/actions/macos-update-clang
-      - name: brew
-        uses: ./.github/actions/brew
-      - name: ./configure
-        uses: ./.github/actions/configure-macos
-        with:
-          configurationParameters: >-
-            --${{ matrix.debug && 'enable' || 'disable' }}-debug
-            --${{ matrix.zts && 'enable' || 'disable' }}-zts
-      - name: make
-        run: |-
-          export PATH="$(brew --prefix)/opt/bison/bin:$PATH"
-          make -j$(sysctl -n hw.logicalcpu) >/dev/null
-      - name: make install
-        run: sudo make install
-      - name: Test
-        uses: ./.github/actions/test-macos
-      - name: Test Tracing JIT
-        if: matrix.os != '14' || !matrix.zts
-        uses: ./.github/actions/test-macos
-        with:
-          jitType: tracing
-          runTestsParameters: >-
-            -d zend_extension=opcache.so
-            -d opcache.enable_cli=1
-      - name: Test OpCache
-        uses: ./.github/actions/test-macos
-        with:
-          runTestsParameters: >-
-            -d zend_extension=opcache.so
-            -d opcache.enable_cli=1
-      - name: Test Function JIT
-        if: matrix.os != '14' || !matrix.zts
-        uses: ./.github/actions/test-macos
-        with:
-          jitType: function
-          runTestsParameters: >-
-            -d zend_extension=opcache.so
-            -d opcache.enable_cli=1
-      - name: Extra tests
-        uses: ./.github/actions/extra-tests
-      - name: Verify generated files are up to date
-        uses: ./.github/actions/verify-generated-files
-  COVERAGE_DEBUG_NTS:
-    if: inputs.branch == 'master'
-    services:
-      mysql:
-        image: mysql:8.3
-        ports:
-          - 3306:3306
-        env:
-          MYSQL_DATABASE: test
-          MYSQL_ROOT_PASSWORD: root
-      postgres:
-        image: postgres
-        env:
-          POSTGRES_USER: postgres
-          POSTGRES_PASSWORD: postgres
-          POSTGRES_DB: test
-      firebird:
-        image: jacobalberty/firebird
-        ports:
-          - 3050:3050
-        env:
-          ISC_PASSWORD: test
-          FIREBIRD_DATABASE: test.fdb
-          FIREBIRD_USER: test
-          FIREBIRD_PASSWORD: test
-    runs-on: ubuntu-24.04
-    steps:
-      - name: git checkout
-        uses: actions/checkout@v6
-        with:
-          ref: ${{ inputs.branch }}
-      - name: Create MSSQL container
-        uses: ./.github/actions/setup-mssql
-      - name: apt
-        uses: ./.github/actions/apt-x64
-      - name: Install gcovr
-        run: sudo -H pip install gcovr
-      - name: ./configure
-        uses: ./.github/actions/configure-x64
-        with:
-          configurationParameters: --enable-debug --disable-zts --enable-gcov
-      - name: make
-        run: make -j$(/usr/bin/nproc) >/dev/null
-      - name: make install
-        uses: ./.github/actions/install-linux
-      - name: Setup
-        uses: ./.github/actions/setup-x64
-      # We only test with OpCache, the difference in coverage is negligible
-      - name: Test OpCache
-        uses: ./.github/actions/test-linux
-        with:
-          jitType: tracing
-          runTestsParameters: >-
-            -d zend_extension=opcache.so
-            -d opcache.enable_cli=1
-      - uses: codecov/codecov-action@v4
-        if: ${{ !cancelled() }}
-        with:
-          fail_ci_if_error: true
-          token: ${{ secrets.CODECOV_TOKEN }}
-          verbose: true
-  COMMUNITY:
-    strategy:
-      fail-fast: false
-      matrix:
-        type: ['asan', 'verify_type_inference']
-        exclude:
-          - type: ${{ !inputs.community_verify_type_inference && 'verify_type_inference' || '*never*' }}
-    name: "COMMUNITY_${{ matrix.type }}"
-    runs-on: ubuntu-${{ inputs.ubuntu_version }}
-    env:
-      ASAN_OPTIONS: exitcode=139
-      UBSAN_OPTIONS: print_stacktrace=1
-      USE_ZEND_ALLOC: 0
-      USE_TRACKED_ALLOC: 1
-    steps:
-      - name: git checkout
-        uses: actions/checkout@v6
-        with:
-          ref: ${{ inputs.branch }}
-      - name: apt
-        uses: ./.github/actions/apt-x64
-      - name: ./configure
-        uses: ./.github/actions/configure-x64
-        with:
-          # CFLAGS removes O2, so we have to add it again...
-          configurationParameters: >-
-            --enable-zts
-            ${{ matrix.type == 'asan' && '--enable-debug CFLAGS="-fsanitize=undefined,address -fno-sanitize-recover -DZEND_TRACK_ARENA_ALLOC" LDFLAGS="-fsanitize=undefined,address"' || '' }}
-            ${{ matrix.type == 'verify_type_inference' && 'CFLAGS="-DZEND_VERIFY_TYPE_INFERENCE -O2"' || '' }}
-      - name: make
-        run: make -j$(/usr/bin/nproc) >/dev/null
-      - name: make install
-        uses: ./.github/actions/install-linux
-      - name: Setup
-        run: |
-          sudo service mysql start
-          mysql -uroot -proot -e "CREATE DATABASE IF NOT EXISTS test"
-          mysql -uroot -proot -e "SET GLOBAL local_infile = true"
-      - name: Enable Opcache
-        run: |
-          echo memory_limit=-1 >> /etc/php.d/opcache.ini
-          echo zend_extension=opcache.so > /etc/php.d/opcache.ini
-          echo opcache.enable_cli=1 >> /etc/php.d/opcache.ini
-          echo opcache.enable=1 >> /etc/php.d/opcache.ini
-          echo opcache.protect_memory=1 >> /etc/php.d/opcache.ini
-          echo opcache.memory_consumption=256M >> /etc/php.d/opcache.ini
-          echo opcache.file_update_protection=0 >> /etc/php.d/opcache.ini
-          echo opcache.interned_strings_buffer=64 >> /etc/php.d/opcache.ini
-          echo opcache.max_accelerated_files=100000 >> /etc/php.d/opcache.ini
-      - name: Enable JIT
-        if: matrix.type != 'verify_type_inference'
-        run: |
-          echo opcache.jit=tracing >> /etc/php.d/opcache.ini
-          echo opcache.jit_buffer_size=1G >> /etc/php.d/opcache.ini
-          echo opcache.jit_max_root_traces=100000 >> /etc/php.d/opcache.ini
-          echo opcache.jit_max_side_traces=100000 >> /etc/php.d/opcache.ini
-          echo opcache.jit_max_exit_counters=100000 >> /etc/php.d/opcache.ini
-          echo opcache.jit_hot_loop=1 >> /etc/php.d/opcache.ini
-          echo opcache.jit_hot_func=1 >> /etc/php.d/opcache.ini
-          echo opcache.jit_hot_return=1 >> /etc/php.d/opcache.ini
-          echo opcache.jit_hot_side_exit=1 >> /etc/php.d/opcache.ini
-          php -v
-      - name: Test AMPHP
-        if: ${{ !cancelled() }}
-        run: |
-          repositories="amp cache dns file http parallel parser pipeline process serialization socket sync websocket-client websocket-server"
-          X=0
-          for repository in $repositories; do
-            echo "::group::$repository"
-            git clone "https://github.com/amphp/$repository.git" "amphp-$repository" --depth 1
-            cd "amphp-$repository"
-            git rev-parse HEAD
-            php /usr/bin/composer install --no-progress --ignore-platform-req=php+
-            EXIT_CODE=0
-            vendor/bin/phpunit || EXIT_CODE=$?
-            echo -e "\n::endgroup::"
-            if [ ${EXIT_CODE:-0} -gt 128 ]; then
-              X=1;
-              echo "Failed"
-            fi
-            cd ..
-          done
-          exit $X
-      - name: Test Laravel
-        if: ${{ !cancelled() && !inputs.skip_laravel }}
-        run: |
-          git clone https://github.com/laravel/framework.git --depth=1
-          cd framework
-          git rev-parse HEAD
-          php /usr/bin/composer install --no-progress --ignore-platform-req=php+
-          # Hack to disable a test that hangs
-          php -r '$c = file_get_contents("tests/Filesystem/FilesystemTest.php"); $c = str_replace("public function testSharedGet()", "#[\\PHPUnit\\Framework\\Attributes\\Group('"'"'skip'"'"')]\n    public function testSharedGet()", $c); file_put_contents("tests/Filesystem/FilesystemTest.php", $c);'
-          php vendor/bin/phpunit --exclude-group skip || EXIT_CODE=$?
-          if [ ${EXIT_CODE:-0} -gt 128 ]; then
-            exit 1
-          fi
-      - name: Test ReactPHP
-        if: ${{ !cancelled() }}
-        run: |
-          repositories="async cache child-process datagram dns event-loop promise promise-stream promise-timer stream"
-          X=0
-          for repository in $repositories; do
-            echo "::group::$repository"
-            git clone "https://github.com/reactphp/$repository.git" "reactphp-$repository" --depth 1
-            cd "reactphp-$repository"
-            git rev-parse HEAD
-            php /usr/bin/composer install --no-progress --ignore-platform-req=php+
-            EXIT_CODE=0
-            vendor/bin/phpunit || EXIT_CODE=$?
-            echo -e "\n::endgroup::"
-            if [ $[EXIT_CODE:-0} -gt 128 ]; then
-              X=1;
-              echo "Failed"
-            fi
-            cd ..
-          done
-          exit $X
-      - name: Test Revolt PHP
-        if: ${{ !cancelled() }}
-        run: |
-          git clone https://github.com/revoltphp/event-loop.git --depth=1
-          cd event-loop
-          git rev-parse HEAD
-          php /usr/bin/composer install --no-progress --ignore-platform-req=php+
-          vendor/bin/phpunit || EXIT_CODE=$?
-          if [ ${EXIT_CODE:-0} -gt 128 ]; then
-            exit 1
-          fi
-      - name: Test Symfony
-        if: ${{ !cancelled() && inputs.symfony_version != '' }}
-        run: |
-          git clone https://github.com/symfony/symfony.git --depth=1 --branch="${{ inputs.symfony_version }}"
-          cd symfony
-          git rev-parse HEAD
-          php /usr/bin/composer install --no-progress --ignore-platform-req=php+
-          php ./phpunit install
-          # Test causes a heap-buffer-overflow but I cannot reproduce it locally...
-          php -r '$c = file_get_contents("src/Symfony/Component/HtmlSanitizer/Tests/HtmlSanitizerCustomTest.php"); $c = str_replace("public function testSanitizeDeepNestedString()", "#[\\PHPUnit\\Framework\\Attributes\\Group('"'"'skip'"'"')]\n    public function testSanitizeDeepNestedString()", $c); file_put_contents("src/Symfony/Component/HtmlSanitizer/Tests/HtmlSanitizerCustomTest.php", $c);'
-          # Buggy FFI test in Symfony, see https://github.com/symfony/symfony/issues/47668
-          php -r '$c = file_get_contents("src/Symfony/Component/VarDumper/Tests/Caster/FFICasterTest.php"); $c = str_replace("public function testCastNonTrailingCharPointer()", "#[\\PHPUnit\\Framework\\Attributes\\Group('"'"'skip'"'"')]\n    public function testCastNonTrailingCharPointer()", $c); file_put_contents("src/Symfony/Component/VarDumper/Tests/Caster/FFICasterTest.php", $c);'
-          export SYMFONY_DEPRECATIONS_HELPER=max[total]=999
-          X=0
-          for component in $(find src/Symfony -mindepth 2 -type f -name phpunit.xml.dist -printf '%h\n'); do
-            echo "::group::$component"
-            EXIT_CODE=0
-            php ./phpunit $component --exclude-group tty --exclude-group benchmark --exclude-group intl-data --exclude-group transient --exclude-group skip || EXIT_CODE=$?
-            echo -e "\n::endgroup::"
-            if [ ${EXIT_CODE:-0} -gt 128 ]; then
-              X=1;
-              echo "Failed"
-            fi
-          done
-          exit $X
-      - name: Test PHPUnit
-        if: ${{ !cancelled() }}
-        run: |
-          git clone https://github.com/sebastianbergmann/phpunit.git --branch=main --depth=1
-          cd phpunit
-          git rev-parse HEAD
-          php /usr/bin/composer install --no-progress --ignore-platform-req=php+
-          php ./phpunit || EXIT_CODE=$?
-          if [ ${EXIT_CODE:-0} -gt 128 ]; then
-            exit 1
-          fi
-      - name: 'Symfony Preloading'
-        # composer create-project will automatically pick the right Symfony version for us.
-        if: ${{ !cancelled() && inputs.symfony_version != '' }}
-        run: |
-          php /usr/bin/composer create-project symfony/symfony-demo symfony_demo --no-progress --ignore-platform-req=php+
-          cd symfony_demo
-          git rev-parse HEAD
-          sed -i 's/PHP_SAPI/"cli-server"/g' var/cache/dev/App_KernelDevDebugContainer.preload.php
-          php -d opcache.preload=var/cache/dev/App_KernelDevDebugContainer.preload.php public/index.php
-      - name: Test Wordpress
-        if: ${{ !cancelled() && !inputs.skip_wordpress }}
-        run: |
-          git clone https://github.com/WordPress/wordpress-develop.git wordpress --depth=1
-          cd wordpress
-          git rev-parse HEAD
-          php /usr/bin/composer install --no-progress --ignore-platform-req=php+
-          cp wp-tests-config-sample.php wp-tests-config.php
-          sed -i 's/youremptytestdbnamehere/test/g' wp-tests-config.php
-          sed -i 's/yourusernamehere/root/g' wp-tests-config.php
-          sed -i 's/yourpasswordhere/root/g' wp-tests-config.php
-          php vendor/bin/phpunit || EXIT_CODE=$?
-          if [ $EXIT_CODE -gt 128 ]; then
-            exit 1
-          fi
-  OPCACHE_VARIATION:
-    services:
-      mysql:
-        image: mysql:8.3
-        ports:
-          - 3306:3306
-        env:
-          MYSQL_DATABASE: test
-          MYSQL_ROOT_PASSWORD: root
-      postgres:
-        image: postgres
-        env:
-          POSTGRES_USER: postgres
-          POSTGRES_PASSWORD: postgres
-          POSTGRES_DB: test
-      firebird:
-        image: jacobalberty/firebird
-        ports:
-          - 3050:3050
-        env:
-          ISC_PASSWORD: test
-          FIREBIRD_DATABASE: test.fdb
-          FIREBIRD_USER: test
-          FIREBIRD_PASSWORD: test
-    name: OPCACHE_VARIATION
-    runs-on: ubuntu-${{ inputs.ubuntu_version }}
-    steps:
-      - name: git checkout
-        uses: actions/checkout@v6
-        with:
-          ref: ${{ inputs.branch }}
-      - name: Create MSSQL container
-        uses: ./.github/actions/setup-mssql
-      - name: apt
-        uses: ./.github/actions/apt-x64
-      - name: ./configure
-        uses: ./.github/actions/configure-x64
-        with:
-          configurationParameters: >-
-            --enable-debug --disable-zts
-      - name: make
-        run: make -j$(/usr/bin/nproc) >/dev/null
-      - name: make install
-        uses: ./.github/actions/install-linux
-      - name: Setup
-        uses: ./.github/actions/setup-x64
-      - name: Test File Cache (prime shm)
-        uses: ./.github/actions/test-linux
-        with:
-          runTestsParameters: >-
-            -d zend_extension=opcache.so
-            -d opcache.enable_cli=1
-            --file-cache-prime
-      - name: Test File Cache (prime shm, use shm)
-        uses: ./.github/actions/test-linux
-        with:
-          runTestsParameters: >-
-            -d zend_extension=opcache.so
-            -d opcache.enable_cli=1
-            --file-cache-use
-      - name: Test File Cache (prime shm, use file)
-        uses: ./.github/actions/test-linux
-        with:
-          runTestsParameters: >-
-            -d zend_extension=opcache.so
-            -d opcache.enable_cli=1
-            --file-cache-use
-            -d opcache.file_cache_only=1
-      - name: Test File Cache Only (prime)
-        uses: ./.github/actions/test-linux
-        with:
-          runTestsParameters: >-
-            -d zend_extension=opcache.so
-            -d opcache.enable_cli=1
-            --file-cache-prime
-            -d opcache.file_cache_only=1
-      - name: Test File Cache Only (use)
-        uses: ./.github/actions/test-linux
-        with:
-          runTestsParameters: >-
-            -d zend_extension=opcache.so
-            -d opcache.enable_cli=1
-            --file-cache-use
-            -d opcache.file_cache_only=1
-      - name: Verify generated files are up to date
-        uses: ./.github/actions/verify-generated-files
-  MSAN:
-    name: MSAN
-    runs-on: ubuntu-${{ inputs.ubuntu_version }}
-    steps:
-      - name: git checkout
-        uses: actions/checkout@v6
-        with:
-          ref: ${{ inputs.branch }}
-      - name: apt
-        uses: ./.github/actions/apt-x64
-      - name: ./configure
-        run: |
-          export CC=clang
-          export CXX=clang++
-          export CFLAGS="-DZEND_TRACK_ARENA_ALLOC"
-          ./buildconf --force
-          # msan requires all used libraries to be instrumented,
-          # so we should avoiding linking against anything but libc here
-          ./configure \
-            --enable-debug \
-            --enable-zts \
-            --enable-option-checking=fatal \
-            --prefix=/usr \
-            --without-sqlite3 \
-            --without-pdo-sqlite \
-            --without-libxml \
-            --disable-dom \
-            --disable-simplexml \
-            --disable-xml \
-            --disable-xmlreader \
-            --disable-xmlwriter \
-            --without-pcre-jit \
-            --disable-opcache-jit \
-            --enable-phpdbg \
-            --enable-fpm \
-            --with-pdo-mysql=mysqlnd \
-            --with-mysqli=mysqlnd \
-            --disable-mysqlnd-compression-support \
-            --without-pear \
-            --enable-exif \
-            --enable-sysvsem \
-            --enable-sysvshm \
-            --enable-shmop \
-            --enable-pcntl \
-            --enable-mbstring \
-            --disable-mbregex \
-            --enable-sockets \
-            --enable-bcmath \
-            --enable-calendar \
-            --enable-ftp \
-            --enable-zend-test \
-            --enable-werror \
-            --enable-memory-sanitizer \
-            --with-config-file-path=/etc \
-            --with-config-file-scan-dir=/etc/php.d \
-            --enable-dl-test=shared
-      - name: make
-        run: make -j$(/usr/bin/nproc) >/dev/null
-      - name: make install
-        run: |
-          sudo make install
-          sudo mkdir -p /etc/php.d
-          sudo chmod 777 /etc/php.d
-          echo mysqli.default_socket=/var/run/mysqld/mysqld.sock    > /etc/php.d/mysqli.ini
-          echo pdo_mysql.default_socket=/var/run/mysqld/mysqld.sock > /etc/php.d/pdo_mysql.ini
-      - name: Setup
-        run: |
-          set -x
-          sudo service mysql start
-          mysql -uroot -proot -e "CREATE DATABASE IF NOT EXISTS test"
-          # Ensure local_infile tests can run.
-          mysql -uroot -proot -e "SET GLOBAL local_infile = true"
-          sudo locale-gen de_DE
-      - name: Test
-        uses: ./.github/actions/test-linux
-        with:
-          runTestsParameters: >-
-            --msan
-      - name: Test Opcache
-        uses: ./.github/actions/test-linux
-        with:
-          runTestsParameters: >-
-            --msan
-            -d zend_extension=opcache.so
-            -d opcache.enable_cli=1
-      - name: Verify generated files are up to date
-        uses: ./.github/actions/verify-generated-files
-  LIBMYSQLCLIENT:
-    name: LIBMYSQLCLIENT
-    runs-on: ubuntu-${{ inputs.ubuntu_version }}
-    steps:
-      - name: git checkout
-        uses: actions/checkout@v6
-        with:
-          ref: ${{ inputs.branch }}
-      - name: apt
-        run: |
-          sudo apt-get update -y | true
-          sudo apt install bison re2c
-      - name: Setup
-        run: |
-          sudo service mysql start
-          mysql -uroot -proot -e "CREATE DATABASE IF NOT EXISTS test"
-          # Ensure local_infile tests can run.
-          mysql -uroot -proot -e "SET GLOBAL local_infile = true"
-      - name: Build mysql-8.0
-        uses: ./.github/actions/build-libmysqlclient
-        with:
-          configurationParameters: '--enable-werror'
-          libmysql: mysql-8.0.37-linux-glibc2.28-x86_64.tar.xz
-      - name: Test mysql-8.0
-        uses: ./.github/actions/test-libmysqlclient
-      - name: Build mysql-8.4
-        uses: ./.github/actions/build-libmysqlclient
-        with:
-          configurationParameters: '--enable-werror'
-          libmysql: mysql-8.4.0-linux-glibc2.28-x86_64.tar.xz
-      - name: Test mysql-8.4
-        uses: ./.github/actions/test-libmysqlclient
-      - name: Verify generated files are up to date
-        uses: ./.github/actions/verify-generated-files
-  PECL:
-    if: inputs.branch == 'master'
-    runs-on: ubuntu-24.04
-    env:
-      CC: ccache gcc
-      CXX: ccache g++
-    steps:
-      - name: git checkout PHP
-        uses: actions/checkout@v6
-        with:
-          path: php
-          ref: ${{ inputs.branch }}
-      - name: git checkout apcu
-        uses: actions/checkout@v6
-        with:
-          repository: krakjoe/apcu
-          path: apcu
-      - name: git checkout imagick
-        uses: actions/checkout@v6
-        with:
-          repository: Imagick/imagick
-          path: imagick
-      - name: git checkout memcached
-        uses: actions/checkout@v6
-        with:
-          repository: php-memcached-dev/php-memcached
-          path: memcached
-      - name: git checkout redis
-        uses: actions/checkout@v6
-        with:
-          repository: phpredis/phpredis
-          path: redis
-      - name: git checkout xdebug
-        if: false
-        uses: actions/checkout@v6
-        with:
-          repository: xdebug/xdebug
-          path: xdebug
-      - name: git checkout yaml
-        uses: actions/checkout@v6
-        with:
-          repository: php/pecl-file_formats-yaml
-          path: yaml
-      - name: apt
-        run: |
-          sudo apt-get update
-          sudo apt-get install -y --no-install-recommends \
-            ccache \
-            libmemcached-dev \
-            imagemagick \
-            libmagickwand-dev \
-            bison \
-            re2c
-      - name: ccache
-        uses: hendrikmuhs/ccache-action@v1.2
-        with:
-          key: "${{github.job}}-${{hashFiles('php/main/php_version.h')}}"
-          append-timestamp: false
-          save: ${{ github.event_name != 'pull_request' }}
-      - name: build PHP
-        run: |
-          cd php
-          ./buildconf --force
-          ./configure \
-            --enable-option-checking=fatal \
-            --prefix=/opt/php \
-            --enable-cli \
-            --disable-all \
-            --enable-session \
-            --enable-werror
-          make -j$(/usr/bin/nproc)
-          sudo make install
-      - name: build apcu
-        run: |
-          cd apcu
-          /opt/php/bin/phpize
-          ./configure --prefix=/opt/php --with-php-config=/opt/php/bin/php-config
-          make -j$(/usr/bin/nproc)
-      - name: build imagick
-        run: |
-          cd imagick
-          /opt/php/bin/phpize
-          ./configure --prefix=/opt/php --with-php-config=/opt/php/bin/php-config
-          make -j$(/usr/bin/nproc)
-      - name: build memcached
-        run: |
-          cd memcached
-          /opt/php/bin/phpize
-          ./configure --prefix=/opt/php --with-php-config=/opt/php/bin/php-config
-          make -j$(/usr/bin/nproc)
-      - name: build redis
-        run: |
-          cd redis
-          /opt/php/bin/phpize
-          ./configure --prefix=/opt/php --with-php-config=/opt/php/bin/php-config
-          make -j$(/usr/bin/nproc)
-      - name: build xdebug
-        if: false
-        run: |
-          cd xdebug
-          /opt/php/bin/phpize
-          ./configure --prefix=/opt/php --with-php-config=/opt/php/bin/php-config
-          make -j$(/usr/bin/nproc)
-      - name: build yaml
-        run: |
-          cd yaml
-          /opt/php/bin/phpize
-          ./configure --prefix=/opt/php --with-php-config=/opt/php/bin/php-config
-          make -j$(/usr/bin/nproc)
-  WINDOWS:
-    strategy:
-      fail-fast: false
-      matrix:
-        include:
-          - x64: true
-            zts: true
-            opcache: true
-            asan: false
-          - x64: false
-            zts: false
-            opcache: false
-            asan: false
-          - x64: true
-            zts: true
-            opcache: true
-            asan: true
-            branch: 'master'
-            timeout: 120
-    name: "WINDOWS_${{ matrix.x64 && 'X64' || 'X86' }}_${{ matrix.zts && 'ZTS' || 'NTS' }}${{ matrix.asan && '_ASAN' || ''}}"
-    runs-on: windows-${{ inputs.windows_version }}
-    env:
-      PHP_BUILD_CACHE_BASE_DIR: C:\build-cache
-      PHP_BUILD_OBJ_DIR: C:\obj
-      PHP_BUILD_CACHE_SDK_DIR: C:\build-cache\sdk
-      PHP_BUILD_SDK_BRANCH: php-sdk-2.3.0
-      PHP_BUILD_CRT: ${{ inputs.vs_crt_version }}
-      PLATFORM: ${{ matrix.x64 && 'x64' || 'x86' }}
-      THREAD_SAFE: "${{ matrix.zts && '1' || '0' }}"
-      INTRINSICS: "${{ matrix.zts && 'AVX2' || '' }}"
-      PARALLEL: -j2
-      OPCACHE: "${{ matrix.opcache && '1' || '0' }}"
-      ASAN: "${{ matrix.asan && '1' || '0' }}"
-    steps:
-      - name: git config
-        run: git config --global core.autocrlf false && git config --global core.eol lf
-      - name: git checkout
-        uses: actions/checkout@v6
-        with:
-          ref: ${{ inputs.branch }}
-      - name: Setup
-        uses: ./.github/actions/setup-windows
-      - name: Build
-        run: .github/scripts/windows/build.bat
-      - name: Test
-        run: .github/scripts/windows/test.bat
-  FREEBSD:
-    strategy:
-      fail-fast: false
-      matrix:
-        zts: [true, false]
-        exclude:
-          - zts: ${{ !inputs.run_freebsd_zts && true || '*never*' }}
-    name: "FREEBSD_${{ matrix.zts && 'ZTS' || 'NTS' }}"
-    runs-on: ubuntu-latest
-    timeout-minutes: 50
-    steps:
-      - name: git checkout
-        uses: actions/checkout@v6
-        with:
-          ref: ${{ inputs.branch }}
-      - name: FreeBSD
-        uses: ./.github/actions/freebsd
-        with:
-          configurationParameters: >-
-            --${{ matrix.zts && 'enable' || 'disable' }}-zts
-          runExtraTests: true
diff '--color=auto' -Naur php-8.4.18/.github/workflows/push.yml php-8.4.20RC1/.github/workflows/push.yml
--- php-8.4.18/.github/workflows/push.yml	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/.github/workflows/push.yml	1970-01-01 00:00:00.000000000 +0000
@@ -1,408 +0,0 @@
-name: Push
-on:
-  push:
-    paths-ignore:
-      - docs/**
-      - NEWS
-      - UPGRADING
-      - UPGRADING.INTERNALS
-      - '**/README.*'
-      - CONTRIBUTING.md
-      - CODING_STANDARDS.md
-      - .cirrus.yml
-      - .circleci/**
-    branches:
-      - PHP-8.1
-      - PHP-8.2
-      - PHP-8.3
-      - PHP-8.4
-      - master
-  pull_request:
-    paths-ignore:
-      - docs/**
-      - NEWS
-      - UPGRADING
-      - UPGRADING.INTERNALS
-      - '**/README.*'
-      - CONTRIBUTING.md
-      - CODING_STANDARDS.md
-      - .cirrus.yml
-      - .circleci/**
-    branches:
-      - '**'
-  workflow_dispatch: ~
-permissions:
-  contents: read
-concurrency:
-  group: ${{ github.workflow }}-${{ github.event.pull_request.url || github.run_id }}
-  cancel-in-progress: true
-env:
-  CC: ccache gcc
-  CXX: ccache g++
-jobs:
-  ALPINE:
-    if: github.repository == 'php/php-src' || github.event_name == 'pull_request'
-    name: ALPINE_X64_ASAN_UBSAN_DEBUG_ZTS
-    runs-on: ubuntu-24.04
-    container:
-      image: 'alpine:3.22'
-    steps:
-      - name: git checkout
-        uses: actions/checkout@v6
-      - name: apk
-        uses: ./.github/actions/apk
-      - name: System info
-        run: |
-          echo "::group::Show host CPU info"
-          lscpu
-          echo "::endgroup::"
-          echo "::group::Show installed package versions"
-          apk list
-          echo "::endgroup::"
-      - name: ./configure
-        uses: ./.github/actions/configure-alpine
-        with:
-          configurationParameters: >-
-            CFLAGS="-fsanitize=undefined,address -fno-sanitize=function -DZEND_TRACK_ARENA_ALLOC"
-            LDFLAGS="-fsanitize=undefined,address -fno-sanitize=function"
-            CC=clang-20
-            CXX=clang++-20
-            --enable-debug
-            --enable-zts
-          skipSlow: true # FIXME: This should likely include slow extensions
-      - name: make
-        run: make -j$(/usr/bin/nproc) >/dev/null
-      - name: make install
-        uses: ./.github/actions/install-alpine
-      - name: Test Tracing JIT
-        uses: ./.github/actions/test-alpine
-        with:
-          jitType: tracing
-          runTestsParameters: >-
-            --asan -x
-            -d opcache.enable_cli=1
-  LINUX_X64:
-    if: github.repository == 'php/php-src' || github.event_name == 'pull_request'
-    services:
-      mysql:
-        image: mysql:8.3
-        ports:
-          - 3306:3306
-        env:
-          MYSQL_DATABASE: test
-          MYSQL_ROOT_PASSWORD: root
-      postgres:
-        image: postgres
-        ports:
-          - 5432:5432
-        env:
-          POSTGRES_USER: postgres
-          POSTGRES_PASSWORD: postgres
-          POSTGRES_DB: test
-      firebird:
-        image: jacobalberty/firebird
-        ports:
-          - 3050:3050
-        env:
-          ISC_PASSWORD: test
-          FIREBIRD_DATABASE: test.fdb
-          FIREBIRD_USER: test
-          FIREBIRD_PASSWORD: test
-    strategy:
-      fail-fast: false
-      matrix:
-        include:
-          - debug: false
-            zts: false
-            asan: false
-          - debug: true
-            zts: true
-            asan: true
-    name: "LINUX_X64_${{ matrix.debug && 'DEBUG' || 'RELEASE' }}_${{ matrix.zts && 'ZTS' || 'NTS' }}${{ matrix.asan && '_ASAN' || '' }}"
-    runs-on: ubuntu-${{ !matrix.asan && '22' || '24' }}.04
-    steps:
-      - name: git checkout
-        uses: actions/checkout@v6
-      - name: apt
-        uses: ./.github/actions/apt-x64
-      - name: System info
-        run: |
-          echo "::group::Show host CPU info"
-          lscpu
-          echo "::endgroup::"
-          echo "::group::Show installed package versions"
-          dpkg -l
-          echo "::endgroup::"
-      - name: Create MSSQL container
-        if: ${{ !matrix.asan }}
-        uses: ./.github/actions/setup-mssql
-      - name: Setup Caddy server
-        uses: ./.github/actions/setup-caddy
-      - name: ccache
-        uses: hendrikmuhs/ccache-action@v1.2
-        with:
-          # This duplicates the "job.name" expression above because
-          # GitHub has no way to query the job name (github.job is the
-          # job id, not the job name)
-          key: "LINUX_X64_${{ matrix.debug && 'DEBUG' || 'RELEASE' }}_${{ matrix.zts && 'ZTS' || 'NTS' }}${{ matrix.asan && '_ASAN' || '' }}-${{hashFiles('main/php_version.h')}}"
-          append-timestamp: false
-          save: ${{ github.event_name != 'pull_request' }}
-      - name: ./configure
-        uses: ./.github/actions/configure-x64
-        with:
-          configurationParameters: >-
-            --${{ matrix.debug && 'enable' || 'disable' }}-debug
-            --${{ matrix.zts && 'enable' || 'disable' }}-zts
-            ${{ matrix.asan && 'CFLAGS="-fsanitize=undefined,address -fno-sanitize=function -DZEND_TRACK_ARENA_ALLOC" LDFLAGS="-fsanitize=undefined,address -fno-sanitize=function" CC=clang CXX=clang++' || '' }}
-          skipSlow: ${{ matrix.asan }}
-      - name: make
-        run: make -j$(/usr/bin/nproc) >/dev/null
-      - name: make install
-        uses: ./.github/actions/install-linux
-      - name: Setup
-        if: ${{ !matrix.asan }}
-        uses: ./.github/actions/setup-x64
-      - name: Test
-        if: matrix.asan == false
-        uses: ./.github/actions/test-linux
-      - name: Test Tracing JIT
-        uses: ./.github/actions/test-linux
-        with:
-          jitType: tracing
-          runTestsParameters: >-
-            -d zend_extension=opcache.so
-            -d opcache.enable_cli=1
-            ${{ matrix.asan && '--asan -x' || '' }}
-      - name: Verify generated files are up to date
-        if: ${{ !matrix.asan }}
-        uses: ./.github/actions/verify-generated-files
-  LINUX_X32:
-    if: github.repository == 'php/php-src' || github.event_name == 'pull_request'
-    name: LINUX_X32_DEBUG_ZTS
-    runs-on: ubuntu-latest
-    container:
-      image: ubuntu:22.04
-    env:
-      MYSQL_TEST_HOST: mysql
-      PDO_MYSQL_TEST_DSN: mysql:host=mysql;dbname=test
-      PDO_MYSQL_TEST_HOST: mysql
-    services:
-      mysql:
-        image: mysql:8.3
-        ports:
-          - 3306:3306
-        env:
-          MYSQL_DATABASE: test
-          MYSQL_ROOT_PASSWORD: root
-    steps:
-      - name: git checkout
-        uses: actions/checkout@v6
-      - name: apt
-        uses: ./.github/actions/apt-x32
-      - name: ccache
-        uses: hendrikmuhs/ccache-action@v1.2
-        with:
-          key: "${{github.job}}-${{hashFiles('main/php_version.h')}}"
-          append-timestamp: false
-          save: ${{ github.event_name != 'pull_request' }}
-      - name: ./configure
-        uses: ./.github/actions/configure-x32
-        with:
-          configurationParameters: >-
-            --enable-debug
-            --enable-zts
-      - name: make
-        run: make -j$(/usr/bin/nproc) >/dev/null
-      - name: make install
-        uses: ./.github/actions/install-linux-x32
-      - name: Test Tracing JIT
-        uses: ./.github/actions/test-linux
-        with:
-          jitType: tracing
-          runTestsParameters: >-
-            -d zend_extension=opcache.so
-            -d opcache.enable_cli=1
-  MACOS_DEBUG_NTS:
-    if: github.repository == 'php/php-src' || github.event_name == 'pull_request'
-    strategy:
-      fail-fast: false
-      matrix:
-        include:
-          - os: 14
-            arch: ARM64
-    name: MACOS_${{ matrix.arch }}_DEBUG_NTS
-    runs-on: macos-${{ matrix.os }}
-    steps:
-      - name: git checkout
-        uses: actions/checkout@v6
-      - name: Update clang
-        uses: ./.github/actions/macos-update-clang
-      - name: brew
-        uses: ./.github/actions/brew
-      - name: ccache
-        uses: hendrikmuhs/ccache-action@v1.2
-        with:
-          key: "${{github.job}}-${{matrix.os}}-${{hashFiles('main/php_version.h')}}"
-          append-timestamp: false
-          save: ${{ github.event_name != 'pull_request' }}
-      - name: ./configure
-        uses: ./.github/actions/configure-macos
-        with:
-          configurationParameters: --enable-debug --disable-zts
-      - name: make
-        run: |-
-          export PATH="$(brew --prefix)/opt/bison/bin:$PATH"
-          make -j$(sysctl -n hw.logicalcpu) >/dev/null
-      - name: make install
-        run: sudo make install
-      - name: Test Tracing JIT
-        uses: ./.github/actions/test-macos
-        with:
-          jitType: tracing
-          runTestsParameters: >-
-            -d zend_extension=opcache.so
-            -d opcache.enable_cli=1
-      - name: Verify generated files are up to date
-        uses: ./.github/actions/verify-generated-files
-  WINDOWS:
-    if: github.repository == 'php/php-src' || github.event_name == 'pull_request'
-    name: WINDOWS_X64_ZTS
-    runs-on: windows-2022
-    env:
-      PHP_BUILD_CACHE_BASE_DIR: C:\build-cache
-      PHP_BUILD_OBJ_DIR: C:\obj
-      PHP_BUILD_CACHE_SDK_DIR: C:\build-cache\sdk
-      PHP_BUILD_SDK_BRANCH: php-sdk-2.3.0
-      PHP_BUILD_CRT: vs17
-      PLATFORM: x64
-      THREAD_SAFE: "1"
-      INTRINSICS: AVX2
-      PARALLEL: -j2
-      OPCACHE: "1"
-    steps:
-      - name: git config
-        run: git config --global core.autocrlf false && git config --global core.eol lf
-      - name: git checkout
-        uses: actions/checkout@v6
-      - name: Setup
-        uses: ./.github/actions/setup-windows
-      - name: Build
-        run: .github/scripts/windows/build.bat
-      - name: Test
-        run: .github/scripts/windows/test.bat
-  BENCHMARKING:
-    name: BENCHMARKING
-    if: github.repository == 'php/php-src' || github.event_name == 'pull_request'
-    runs-on: ubuntu-22.04
-    steps:
-      - name: git checkout
-        uses: actions/checkout@v6
-        with:
-          fetch-depth: 0
-      # ASLR can cause a lot of noise due to missed sse opportunities for memcpy
-      # and other operations, so we disable it during benchmarking.
-      - name: Disable ASLR
-        run: echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
-      - name: apt
-        run: |
-          set -x
-          sudo apt-get update
-          sudo apt-get install \
-            bison \
-            libgmp-dev \
-            libonig-dev \
-            libsqlite3-dev \
-            openssl \
-            re2c \
-            valgrind
-      - name: ccache
-        uses: hendrikmuhs/ccache-action@v1.2
-        with:
-          key: "${{github.job}}-${{hashFiles('main/php_version.h')}}"
-          append-timestamp: false
-          save: ${{ github.event_name != 'pull_request' }}
-      - name: ./configure
-        run: |
-          set -x
-          ./buildconf --force
-          ./configure \
-            --disable-debug \
-            --enable-mbstring \
-            --enable-opcache \
-            --enable-option-checking=fatal \
-            --enable-sockets \
-            --enable-werror \
-            --prefix=/usr \
-            --with-config-file-scan-dir=/etc/php.d \
-            --with-gmp \
-            --with-mysqli=mysqlnd \
-            --with-openssl \
-            --with-pdo-sqlite \
-            --with-valgrind
-      - name: make
-        run: make -j$(/usr/bin/nproc) >/dev/null
-      - name: make install
-        run: |
-          set -x
-          sudo make install
-          sudo mkdir -p /etc/php.d
-          sudo chmod 777 /etc/php.d
-          echo mysqli.default_socket=/var/run/mysqld/mysqld.sock > /etc/php.d/mysqli.ini
-          echo zend_extension=opcache.so >> /etc/php.d/opcache.ini
-          echo opcache.enable=1 >> /etc/php.d/opcache.ini
-          echo opcache.enable_cli=1 >> /etc/php.d/opcache.ini
-      - name: Setup
-        run: |
-          git config --global user.name "Benchmark"
-          git config --global user.email "benchmark@php.net"
-          sudo service mysql start
-          mysql -uroot -proot -e "CREATE DATABASE IF NOT EXISTS wordpress"
-          mysql -uroot -proot -e "CREATE USER 'wordpress'@'localhost' IDENTIFIED BY 'wordpress'; FLUSH PRIVILEGES;"
-          mysql -uroot -proot -e "GRANT ALL PRIVILEGES ON *.* TO 'wordpress'@'localhost' WITH GRANT OPTION;"
-      - name: git checkout benchmarking-data
-        uses: actions/checkout@v6
-        with:
-          repository: php/benchmarking-data
-          ssh-key: ${{ secrets.BENCHMARKING_DATA_DEPLOY_KEY }}
-          path: benchmark/repos/data
-      - name: Benchmark
-        run: php benchmark/benchmark.php true
-      - name: Store result
-        if: github.event_name == 'push'
-        run: |
-          set -x
-          cd benchmark/repos/data
-          git pull --autostash
-          if [ -e ".git/MERGE_HEAD" ]; then
-            echo "Merging, can't proceed"
-            exit 1
-          fi
-          git add .
-          if git diff --cached --quiet; then
-            exit 0
-          fi
-          git commit -m "Add result for ${{ github.repository }}@${{ github.sha }}"
-          git push
-      - name: Show diff
-        if: github.event_name == 'pull_request'
-        run: |-
-          set -x
-          php benchmark/generate_diff.php \
-            ${{ github.sha }} \
-            $(git merge-base ${{ github.event.pull_request.base.sha }} ${{ github.sha }}) \
-            > $GITHUB_STEP_SUMMARY
-      - uses: actions/upload-artifact@v6
-        with:
-          name: profiles
-          path: ${{ github.workspace }}/benchmark/profiles
-          retention-days: 30
-  FREEBSD:
-    if: github.repository == 'php/php-src' || github.event_name == 'pull_request'
-    name: FREEBSD
-    runs-on: ubuntu-latest
-    timeout-minutes: 50
-    steps:
-      - name: git checkout
-        uses: actions/checkout@v6
-      - name: FreeBSD
-        uses: ./.github/actions/freebsd
diff '--color=auto' -Naur php-8.4.18/.github/workflows/root.yml php-8.4.20RC1/.github/workflows/root.yml
--- php-8.4.18/.github/workflows/root.yml	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/.github/workflows/root.yml	1970-01-01 00:00:00.000000000 +0000
@@ -1,62 +0,0 @@
-name: Nightly
-on:
-  schedule:
-   - cron: "0 1 * * *"
-  workflow_dispatch: ~
-permissions:
-  contents: read
-jobs:
-  GENERATE_MATRIX:
-    name: Generate Matrix
-    if: github.repository == 'php/php-src' || github.event_name == 'workflow_dispatch'
-    runs-on: ubuntu-latest
-    outputs:
-      branches: ${{ steps.set-matrix.outputs.branches }}
-    steps:
-      - uses: actions/checkout@v6
-        with:
-          # Set fetch-depth to 0 to clone the full repository
-          # including all branches. This is required to find
-          # the correct commit hashes.
-          fetch-depth: 0
-      - name: Grab the commit mapping
-        uses: actions/cache@v5
-        with:
-          path: branch-commit-cache.json
-          # The cache key needs to change every time for the
-          # cache to be updated after this job finishes.
-          key: nightly-${{ github.run_id }}-${{ github.run_attempt }}
-          restore-keys: |
-            nightly-
-      - name: Generate Matrix
-        id: set-matrix
-        run: php .github/nightly_matrix.php "${{ github.event_name }}" "${{ github.run_attempt }}" "${{ github.head_ref || github.ref_name }}"
-  NIGHTLY:
-    needs: GENERATE_MATRIX
-    name: ${{ matrix.branch.ref }}
-    if: ${{ needs.GENERATE_MATRIX.outputs.branches != '[]' }}
-    uses: ./.github/workflows/nightly.yml
-    strategy:
-      fail-fast: false
-      matrix:
-        branch: ${{ fromJson(needs.GENERATE_MATRIX.outputs.branches) }}
-    with:
-      asan_ubuntu_version: ${{
-        (((matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 5) || matrix.branch.version[0] >= 9) && '24.04')
-        || '22.04' }}
-      branch: ${{ matrix.branch.ref }}
-      community_verify_type_inference: ${{ (matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 4) || matrix.branch.version[0] >= 9 }}
-      run_alpine: ${{ (matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 4) || matrix.branch.version[0] >= 9 }}
-      run_linux_ppc64: ${{ (matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 4) || matrix.branch.version[0] >= 9 }}
-      run_macos_arm64: ${{ (matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 4) || matrix.branch.version[0] >= 9 }}
-      run_freebsd_zts: ${{ (matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 3) || matrix.branch.version[0] >= 9 }}
-      ubuntu_version: ${{
-        (((matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 5) || matrix.branch.version[0] >= 9) && '24.04')
-        || '22.04' }}
-      windows_version: '2022'
-      vs_crt_version: ${{ ((matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 4) && 'vs17') || 'vs16' }}
-      skip_laravel: false
-      symfony_version: ${{ (((matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 4) || matrix.branch.version[0] >= 9) && '8.1') || '7.4' }}
-      skip_wordpress: false
-      variation_enable_zend_max_execution_timers: ${{ (matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 3) || matrix.branch.version[0] >= 9 }}
-    secrets: inherit
diff '--color=auto' -Naur php-8.4.18/.github/workflows/test-suite.yml php-8.4.20RC1/.github/workflows/test-suite.yml
--- php-8.4.18/.github/workflows/test-suite.yml	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/.github/workflows/test-suite.yml	2026-04-01 04:35:35.982004181 +0000
@@ -0,0 +1,1103 @@
+name: Test suite
+on:
+  workflow_call:
+    inputs:
+      all_variations:
+        required: true
+        type: boolean
+      branch:
+        required: true
+        type: string
+permissions:
+  contents: read
+jobs:
+  LINUX_PPC64:
+    if: ${{ fromJson(inputs.branch).jobs.LINUX_PPC64 }}
+    name: LINUX_PPC64_ASAN_DEBUG_ZTS
+    # This runs on a self-hosted runner; see https://wiki.php.net/systems/ci
+    runs-on: [self-hosted, gentoo, ppc64]
+    steps:
+      - name: git checkout
+        uses: actions/checkout@v6
+        with:
+          ref: ${{ fromJson(inputs.branch).ref }}
+      - name: System info
+        run: |
+          echo "::group::Show host CPU info"
+          lscpu
+          echo "::endgroup::"
+          echo "::group::Show installed packages"
+          cat /var/lib/portage/world
+          echo "::endgroup::"
+      - name: ./configure
+        uses: ./.github/actions/configure-gentoo
+        with:
+          configurationParameters: >-
+            CFLAGS="-fsanitize=undefined,address -fno-sanitize=function -DZEND_TRACK_ARENA_ALLOC"
+            LDFLAGS="-fsanitize=undefined,address -fno-sanitize=function"
+            CC=clang-17
+            CXX=clang++-17
+            --enable-debug
+            --enable-zts
+          skipSlow: false # FIXME: This should likely include slow extensions
+      - name: make
+        run: make -j$(/usr/bin/nproc) >/dev/null
+      # Skip an install action for now
+      - name: Tests
+        uses: ./.github/actions/test-gentoo
+        # There is no PPC JIT, so rip this out
+        with:
+          runTestsParameters: >-
+            --asan -x
+      - name: Extra tests
+        uses: ./.github/actions/extra-tests
+  ALPINE:
+    if: ${{ fromJson(inputs.branch).jobs.ALPINE }}
+    name: ALPINE_X64_ASAN_DEBUG_ZTS
+    runs-on: ubuntu-24.04
+    container:
+      image: 'alpine:3.22'
+    steps:
+      - name: git checkout
+        uses: actions/checkout@v6
+        with:
+          ref: ${{ fromJson(inputs.branch).ref }}
+      - name: apk
+        uses: ./.github/actions/apk
+      - name: System info
+        run: |
+          echo "::group::Show host CPU info"
+          lscpu
+          echo "::endgroup::"
+          echo "::group::Show installed package versions"
+          apk list
+          echo "::endgroup::"
+      - name: ccache
+        uses: ./.github/actions/ccache
+        with:
+          name: "${{ github.job }}"
+          cc: clang-20
+          cxx: clang++-20
+      - name: ./configure
+        uses: ./.github/actions/configure-alpine
+        with:
+          configurationParameters: >-
+            CFLAGS="-fsanitize=undefined,address -fno-sanitize=function -DZEND_TRACK_ARENA_ALLOC"
+            LDFLAGS="-fsanitize=undefined,address -fno-sanitize=function"
+            --enable-debug
+            --enable-zts
+          skipSlow: true # FIXME: This should likely include slow extensions
+      - name: make
+        run: make -j$(/usr/bin/nproc) >/dev/null
+      - name: make install
+        uses: ./.github/actions/install-alpine
+      - name: Test Tracing JIT
+        uses: ./.github/actions/test-alpine
+        with:
+          enableOpcache: true
+          jitType: tracing
+          runTestsParameters: >-
+            --asan -x
+      - name: Extra tests
+        uses: ./.github/actions/extra-tests
+  LINUX_X64:
+    if: ${{ fromJson(inputs.branch).jobs.LINUX_X64 }}
+    services:
+      mysql:
+        image: mysql:8.4
+        ports:
+          - 3306:3306
+        env:
+          MYSQL_DATABASE: test
+          MYSQL_ROOT_PASSWORD: root
+      postgres:
+        image: postgres
+        env:
+          POSTGRES_USER: postgres
+          POSTGRES_PASSWORD: postgres
+          POSTGRES_DB: test
+      firebird:
+        image: jacobalberty/firebird
+        ports:
+          - 3050:3050
+        env:
+          ISC_PASSWORD: test
+          FIREBIRD_DATABASE: test.fdb
+          FIREBIRD_USER: test
+          FIREBIRD_PASSWORD: test
+    strategy:
+      fail-fast: false
+      matrix: ${{ fromJson(inputs.branch).jobs.LINUX_X64.matrix }}
+    name: "LINUX_X64${{ matrix.name }}_${{ matrix.debug && 'DEBUG' || 'RELEASE' }}_${{ matrix.zts && 'ZTS' || 'NTS' }}"
+    runs-on: ubuntu-${{ fromJson(inputs.branch).config.ubuntu_version }}
+    steps:
+      - name: git checkout
+        uses: actions/checkout@v6
+        with:
+          ref: ${{ fromJson(inputs.branch).ref }}
+      - name: Create MSSQL container
+        uses: ./.github/actions/setup-mssql
+      - name: apt
+        uses: ./.github/actions/apt-x64
+        with:
+          asan: ${{ matrix.asan && 'true' || 'false' }}
+      - name: System info
+        run: |
+          echo "::group::Show host CPU info"
+          lscpu
+          echo "::endgroup::"
+          echo "::group::Show installed package versions"
+          dpkg -l
+          echo "::endgroup::"
+      - name: Setup Caddy server
+        uses: ./.github/actions/setup-caddy
+      - name: ccache
+        uses: ./.github/actions/ccache
+        with:
+          # This duplicates the "job.name" expression above because
+          # GitHub has no way to query the job name (github.job is the
+          # job id, not the job name)
+          name: "LINUX_X64${{ matrix.name }}_${{ matrix.debug && 'DEBUG' || 'RELEASE' }}_${{ matrix.zts && 'ZTS' || 'NTS' }}"
+      - name: ./configure
+        uses: ./.github/actions/configure-x64
+        with:
+          configurationParameters: >-
+            ${{ matrix.asan && 'CFLAGS="-fsanitize=undefined,address -DZEND_TRACK_ARENA_ALLOC" LDFLAGS="-fsanitize=undefined,address"' || '' }}
+            ${{ matrix.variation && 'CFLAGS="-DZEND_RC_DEBUG=1 -DPROFITABILITY_CHECKS=0 -DZEND_VERIFY_FUNC_INFO=1 -DZEND_VERIFY_TYPE_INFERENCE"' || '' }}
+            ${{ (matrix.variation && fromJson(inputs.branch).jobs.LINUX_X64.config.variation_enable_zend_max_execution_timers) && '--enable-zend-max-execution-timers' || '' }}
+            --${{ matrix.debug && 'enable' || 'disable' }}-debug
+            ${{ matrix.debug && 'CXXFLAGS="-D_GLIBCXX_ASSERTIONS"' || '' }}
+            --${{ matrix.zts && 'enable' || 'disable' }}-zts
+          asan: ${{ matrix.asan && 'true' || 'false' }}
+          skipSlow: ${{ (matrix.asan && !inputs.all_variations) && 'true' || 'false' }}
+      - name: make
+        run: make -j$(/usr/bin/nproc) >/dev/null
+      - name: make install
+        uses: ./.github/actions/install-linux
+      - name: Setup
+        if: ${{ !matrix.asan || inputs.all_variations }}
+        uses: ./.github/actions/setup-x64
+      - name: Test
+        if: ${{ inputs.all_variations || !matrix.asan }}
+        uses: ./.github/actions/test-linux
+        with:
+          runTestsParameters: >-
+            ${{ matrix.asan && '--asan' || '' }}
+            ${{ matrix.repeat && '--repeat 2' || '' }}
+            ${{ matrix.variation && '-d zend_test.observer.enabled=1 -d zend_test.observer.show_output=0' || '' }}
+          idleCpu: ${{ matrix.asan && 'true' || 'false' }}
+      - name: Test Tracing JIT
+        if: ${{ inputs.all_variations || matrix.asan }}
+        uses: ./.github/actions/test-linux
+        with:
+          enableOpcache: true
+          jitType: tracing
+          runTestsParameters: >-
+            ${{ matrix.asan && '--asan' || '' }}
+            ${{ (matrix.asan && !inputs.all_variations) && '-x' || '' }}
+            ${{ matrix.repeat && '--repeat 2' || '' }}
+            ${{ matrix.variation && '-d zend_test.observer.enabled=1 -d zend_test.observer.show_output=0' || '' }}
+      - name: Test OpCache
+        if: ${{ inputs.all_variations }}
+        uses: ./.github/actions/test-linux
+        with:
+          enableOpcache: true
+          runTestsParameters: >-
+            ${{ matrix.asan && '--asan' || '' }}
+            ${{ matrix.repeat && '--repeat 2' || '' }}
+            ${{ matrix.variation && '-d zend_test.observer.enabled=1 -d zend_test.observer.show_output=0' || '' }}
+      - name: Test Function JIT
+        # ASAN frequently timeouts. Each test run takes ~90 minutes, we can
+        # avoid running into the 6 hour timeout by skipping the function JIT.
+        if: ${{ !matrix.asan }}
+        uses: ./.github/actions/test-linux
+        with:
+          enableOpcache: true
+          jitType: function
+          runTestsParameters: >-
+            ${{ matrix.repeat && '--repeat 2' || '' }}
+            ${{ matrix.variation && '-d zend_test.observer.enabled=1 -d zend_test.observer.show_output=0' || '' }}
+      - name: Extra tests
+        uses: ./.github/actions/extra-tests
+      - name: Verify generated files are up to date
+        uses: ./.github/actions/verify-generated-files
+  LINUX_X32:
+    if: ${{ fromJson(inputs.branch).jobs.LINUX_X32 }}
+    strategy:
+      fail-fast: false
+      matrix: ${{ fromJson(inputs.branch).jobs.LINUX_X32.matrix }}
+    name: "LINUX_X32_${{ matrix.debug && 'DEBUG' || 'RELEASE' }}_${{ matrix.zts && 'ZTS' || 'NTS' }}"
+    runs-on: ubuntu-latest
+    container:
+      image: ubuntu:${{ fromJson(inputs.branch).config.ubuntu_version }}
+    env:
+      MYSQL_TEST_HOST: mysql
+      PDO_MYSQL_TEST_DSN: mysql:host=mysql;dbname=test
+      PDO_MYSQL_TEST_HOST: mysql
+      PDO_FIREBIRD_TEST_DSN: firebird:dbname=firebird:test.fdb
+    services:
+      mysql:
+        image: mysql:8.4
+        ports:
+          - 3306:3306
+        env:
+          MYSQL_DATABASE: test
+          MYSQL_ROOT_PASSWORD: root
+      firebird:
+        image: jacobalberty/firebird
+        ports:
+          - 3050:3050
+        env:
+          ISC_PASSWORD: test
+          FIREBIRD_DATABASE: test.fdb
+          FIREBIRD_USER: test
+          FIREBIRD_PASSWORD: test
+    steps:
+      - name: git checkout
+        uses: actions/checkout@v6
+        with:
+          ref: ${{ fromJson(inputs.branch).ref }}
+      - name: apt
+        uses: ./.github/actions/apt-x32
+      - name: ccache
+        uses: ./.github/actions/ccache
+        with:
+          name: "LINUX_X32_${{ matrix.debug && 'DEBUG' || 'RELEASE' }}_${{ matrix.zts && 'ZTS' || 'NTS' }}"
+      - name: System info
+        run: |
+          echo "::group::Show host CPU info"
+          lscpu
+          echo "::endgroup::"
+          echo "::group::Show installed package versions"
+          dpkg -l
+          echo "::endgroup::"
+      - name: ./configure
+        uses: ./.github/actions/configure-x32
+        with:
+          configurationParameters: >-
+            --${{ matrix.debug && 'enable' || 'disable' }}-debug
+            --${{ matrix.zts && 'enable' || 'disable' }}-zts
+      - name: make
+        run: make -j$(/usr/bin/nproc) >/dev/null
+      - name: make install
+        uses: ./.github/actions/install-linux-x32
+      - name: Test
+        if: ${{ inputs.all_variations }}
+        uses: ./.github/actions/test-linux
+      - name: Test Tracing JIT
+        uses: ./.github/actions/test-linux
+        with:
+          enableOpcache: true
+          jitType: tracing
+      - name: Test OpCache
+        if: ${{ inputs.all_variations }}
+        uses: ./.github/actions/test-linux
+        with:
+          enableOpcache: true
+      - name: Test Function JIT
+        if: ${{ inputs.all_variations }}
+        uses: ./.github/actions/test-linux
+        with:
+          enableOpcache: true
+          jitType: function
+      - name: Extra tests
+        uses: ./.github/actions/extra-tests
+  MACOS:
+    if: ${{ fromJson(inputs.branch).jobs.MACOS }}
+    strategy:
+      fail-fast: false
+      matrix: ${{ fromJson(inputs.branch).jobs.MACOS.matrix }}
+    name: "MACOS_${{ matrix.arch }}_${{ matrix.debug && 'DEBUG' || 'RELEASE' }}_${{ matrix.zts && 'ZTS' || 'NTS' }}"
+    runs-on: macos-${{ matrix.arch == 'X64' && '15-intel' || fromJson(inputs.branch).jobs.MACOS.config.arm64_version }}
+    steps:
+      - name: git checkout
+        uses: actions/checkout@v6
+        with:
+          ref: ${{ fromJson(inputs.branch).ref }}
+      - name: Update clang
+        timeout-minutes: 10
+        uses: ./.github/actions/macos-update-clang
+      - name: brew
+        timeout-minutes: 10
+        uses: ./.github/actions/brew
+      - name: ccache
+        uses: ./.github/actions/ccache
+        with:
+          name: "MACOS_${{ matrix.arch }}_${{ matrix.debug && 'DEBUG' || 'RELEASE' }}_${{ matrix.zts && 'ZTS' || 'NTS' }}"
+      - name: ./configure
+        uses: ./.github/actions/configure-macos
+        with:
+          configurationParameters: >-
+            --${{ matrix.debug && 'enable' || 'disable' }}-debug
+            --${{ matrix.zts && 'enable' || 'disable' }}-zts
+      - name: make
+        run: |-
+          export PATH="$(brew --prefix)/opt/bison/bin:$PATH"
+          make -j$(sysctl -n hw.logicalcpu) >/dev/null
+      - name: make install
+        run: sudo make install
+      - name: Test
+        if: ${{ inputs.all_variations }}
+        uses: ./.github/actions/test-macos
+      - name: Test Tracing JIT
+        if: ${{ matrix.arch == 'X64' || !matrix.zts }}
+        uses: ./.github/actions/test-macos
+        with:
+          enableOpcache: true
+          jitType: tracing
+      - name: Test OpCache
+        if: ${{ inputs.all_variations || (matrix.arch == 'ARM64' && matrix.zts) }}
+        uses: ./.github/actions/test-macos
+        with:
+          enableOpcache: true
+      - name: Test Function JIT
+        if: ${{ inputs.all_variations && (matrix.arch == 'X64' || !matrix.zts) }}
+        uses: ./.github/actions/test-macos
+        with:
+          enableOpcache: true
+          jitType: function
+      - name: Extra tests
+        uses: ./.github/actions/extra-tests
+      - name: Verify generated files are up to date
+        uses: ./.github/actions/verify-generated-files
+  COVERAGE:
+    if: ${{ fromJson(inputs.branch).jobs.COVERAGE }}
+    services:
+      mysql:
+        image: mysql:8.4
+        ports:
+          - 3306:3306
+        env:
+          MYSQL_DATABASE: test
+          MYSQL_ROOT_PASSWORD: root
+      postgres:
+        image: postgres
+        env:
+          POSTGRES_USER: postgres
+          POSTGRES_PASSWORD: postgres
+          POSTGRES_DB: test
+      firebird:
+        image: jacobalberty/firebird
+        ports:
+          - 3050:3050
+        env:
+          ISC_PASSWORD: test
+          FIREBIRD_DATABASE: test.fdb
+          FIREBIRD_USER: test
+          FIREBIRD_PASSWORD: test
+    runs-on: ubuntu-24.04
+    steps:
+      - name: git checkout
+        uses: actions/checkout@v6
+        with:
+          ref: ${{ fromJson(inputs.branch).ref }}
+      - name: Create MSSQL container
+        uses: ./.github/actions/setup-mssql
+      - name: apt
+        uses: ./.github/actions/apt-x64
+      - name: Install gcovr
+        run: sudo -H pip install gcovr
+      - name: ./configure
+        uses: ./.github/actions/configure-x64
+        with:
+          configurationParameters: --enable-debug --disable-zts --enable-gcov
+      - name: make
+        run: make -j$(/usr/bin/nproc) >/dev/null
+      - name: make install
+        uses: ./.github/actions/install-linux
+      - name: Setup
+        uses: ./.github/actions/setup-x64
+      # We only test with OpCache, the difference in coverage is negligible
+      - name: Test OpCache
+        uses: ./.github/actions/test-linux
+        with:
+          enableOpcache: true
+          jitType: tracing
+      - uses: codecov/codecov-action@v5
+        if: ${{ !cancelled() }}
+        with:
+          fail_ci_if_error: true
+          token: ${{ secrets.CODECOV_TOKEN }}
+          verbose: true
+  COMMUNITY:
+    if: ${{ fromJson(inputs.branch).jobs.COMMUNITY }}
+    strategy:
+      fail-fast: false
+      matrix: ${{ fromJson(inputs.branch).jobs.COMMUNITY.matrix }}
+    name: "COMMUNITY_${{ matrix.type }}"
+    runs-on: ubuntu-${{ fromJson(inputs.branch).config.ubuntu_version }}
+    env:
+      ASAN_OPTIONS: exitcode=139
+      UBSAN_OPTIONS: print_stacktrace=1
+      USE_ZEND_ALLOC: 0
+      USE_TRACKED_ALLOC: 1
+    steps:
+      - name: git checkout
+        uses: actions/checkout@v6
+        with:
+          ref: ${{ fromJson(inputs.branch).ref }}
+      - name: apt
+        uses: ./.github/actions/apt-x64
+      - name: ccache
+        uses: ./.github/actions/ccache
+        with:
+          name: "COMMUNITY_${{ matrix.type }}"
+      - name: ./configure
+        uses: ./.github/actions/configure-x64
+        with:
+          # CFLAGS removes O2, so we have to add it again...
+          configurationParameters: >-
+            --enable-zts
+            ${{ matrix.type == 'asan' && '--enable-debug CFLAGS="-fsanitize=undefined,address -fno-sanitize-recover -DZEND_TRACK_ARENA_ALLOC" LDFLAGS="-fsanitize=undefined,address"' || '' }}
+            ${{ matrix.type == 'verify_type_inference' && 'CFLAGS="-DZEND_VERIFY_TYPE_INFERENCE -O2"' || '' }}
+      - name: make
+        run: make -j$(/usr/bin/nproc) >/dev/null
+      - name: make install
+        uses: ./.github/actions/install-linux
+      - name: Setup
+        run: |
+          sudo service mysql start
+          mysql -uroot -proot -e "CREATE DATABASE IF NOT EXISTS test"
+          mysql -uroot -proot -e "SET GLOBAL local_infile = true"
+      - name: Enable Opcache
+        run: |
+          echo memory_limit=-1 >> /etc/php.d/opcache.ini
+          echo opcache.enable_cli=1 >> /etc/php.d/opcache.ini
+          echo opcache.enable=1 >> /etc/php.d/opcache.ini
+          echo opcache.protect_memory=1 >> /etc/php.d/opcache.ini
+          echo opcache.memory_consumption=256M >> /etc/php.d/opcache.ini
+          echo opcache.file_update_protection=0 >> /etc/php.d/opcache.ini
+          echo opcache.interned_strings_buffer=64 >> /etc/php.d/opcache.ini
+          echo opcache.max_accelerated_files=100000 >> /etc/php.d/opcache.ini
+      - name: Enable JIT
+        if: ${{ matrix.type != 'verify_type_inference' }}
+        run: |
+          echo opcache.jit=tracing >> /etc/php.d/opcache.ini
+          echo opcache.jit_buffer_size=1G >> /etc/php.d/opcache.ini
+          echo opcache.jit_max_root_traces=100000 >> /etc/php.d/opcache.ini
+          echo opcache.jit_max_side_traces=100000 >> /etc/php.d/opcache.ini
+          echo opcache.jit_max_exit_counters=100000 >> /etc/php.d/opcache.ini
+          echo opcache.jit_hot_loop=1 >> /etc/php.d/opcache.ini
+          echo opcache.jit_hot_func=1 >> /etc/php.d/opcache.ini
+          echo opcache.jit_hot_return=1 >> /etc/php.d/opcache.ini
+          echo opcache.jit_hot_side_exit=1 >> /etc/php.d/opcache.ini
+          php -v
+      - name: Test AMPHP
+        if: ${{ !cancelled() }}
+        run: |
+          repositories="amp cache dns file http parallel parser pipeline process serialization socket sync websocket-client websocket-server"
+          X=0
+          for repository in $repositories; do
+            echo "::group::$repository"
+            git clone "https://github.com/amphp/$repository.git" "amphp-$repository" --depth 1
+            cd "amphp-$repository"
+            git rev-parse HEAD
+            php /usr/bin/composer install --no-progress --ignore-platform-req=php+
+            EXIT_CODE=0
+            vendor/bin/phpunit || EXIT_CODE=$?
+            echo -e "\n::endgroup::"
+            if [ ${EXIT_CODE:-0} -gt 128 ]; then
+              X=1;
+              echo "Failed"
+            fi
+            cd ..
+          done
+          exit $X
+      - name: Test Laravel
+        if: ${{ !cancelled() }}
+        run: |
+          branch=${{ fromJson(inputs.branch).jobs.COMMUNITY.config.laravel_version }}
+          git clone https://github.com/laravel/framework.git --depth=1 ${branch:+--branch="$branch"}
+          cd framework
+          git rev-parse HEAD
+          php /usr/bin/composer install --no-progress --ignore-platform-req=php+
+          # Hack to disable a test that hangs
+          php -r '$c = file_get_contents("tests/Filesystem/FilesystemTest.php"); $c = str_replace("public function testSharedGet()", "#[\\PHPUnit\\Framework\\Attributes\\Group('"'"'skip'"'"')]\n    public function testSharedGet()", $c); file_put_contents("tests/Filesystem/FilesystemTest.php", $c);'
+          php vendor/bin/phpunit --exclude-group skip || EXIT_CODE=$?
+          if [ ${EXIT_CODE:-0} -gt 128 ]; then
+            exit 1
+          fi
+      - name: Test ReactPHP
+        if: ${{ !cancelled() }}
+        run: |
+          repositories="async cache child-process datagram dns event-loop promise promise-stream promise-timer stream"
+          X=0
+          for repository in $repositories; do
+            echo "::group::$repository"
+            git clone "https://github.com/reactphp/$repository.git" "reactphp-$repository" --depth 1
+            cd "reactphp-$repository"
+            git rev-parse HEAD
+            php /usr/bin/composer install --no-progress --ignore-platform-req=php+
+            EXIT_CODE=0
+            vendor/bin/phpunit || EXIT_CODE=$?
+            echo -e "\n::endgroup::"
+            if [ $[EXIT_CODE:-0} -gt 128 ]; then
+              X=1;
+              echo "Failed"
+            fi
+            cd ..
+          done
+          exit $X
+      - name: Test Revolt PHP
+        if: ${{ !cancelled() }}
+        run: |
+          git clone https://github.com/revoltphp/event-loop.git --depth=1
+          cd event-loop
+          git rev-parse HEAD
+          php /usr/bin/composer install --no-progress --ignore-platform-req=php+
+          vendor/bin/phpunit || EXIT_CODE=$?
+          if [ ${EXIT_CODE:-0} -gt 128 ]; then
+            exit 1
+          fi
+      - name: Test Symfony
+        if: ${{ !cancelled() }}
+        run: |
+          branch=${{ fromJson(inputs.branch).jobs.COMMUNITY.config.symfony_version }}
+          git clone https://github.com/symfony/symfony.git --depth=1 ${branch:+--branch="$branch"}
+          cd symfony
+          git rev-parse HEAD
+          php /usr/bin/composer install --no-progress --ignore-platform-req=php+
+          php ./phpunit install
+          # Test causes a heap-buffer-overflow but I cannot reproduce it locally...
+          php -r '$c = file_get_contents("src/Symfony/Component/HtmlSanitizer/Tests/HtmlSanitizerCustomTest.php"); $c = str_replace("public function testSanitizeDeepNestedString()", "#[\\PHPUnit\\Framework\\Attributes\\Group('"'"'skip'"'"')]\n    public function testSanitizeDeepNestedString()", $c); file_put_contents("src/Symfony/Component/HtmlSanitizer/Tests/HtmlSanitizerCustomTest.php", $c);'
+          # Buggy FFI test in Symfony, see https://github.com/symfony/symfony/issues/47668
+          php -r '$c = file_get_contents("src/Symfony/Component/VarDumper/Tests/Caster/FFICasterTest.php"); $c = str_replace("public function testCastNonTrailingCharPointer()", "#[\\PHPUnit\\Framework\\Attributes\\Group('"'"'skip'"'"')]\n    public function testCastNonTrailingCharPointer()", $c); file_put_contents("src/Symfony/Component/VarDumper/Tests/Caster/FFICasterTest.php", $c);'
+          export SYMFONY_DEPRECATIONS_HELPER=max[total]=999
+          X=0
+          for component in $(find src/Symfony -mindepth 2 -type f -name phpunit.xml.dist -printf '%h\n'); do
+            echo "::group::$component"
+            EXIT_CODE=0
+            php ./phpunit $component --exclude-group tty --exclude-group benchmark --exclude-group intl-data --exclude-group transient --exclude-group skip || EXIT_CODE=$?
+            echo -e "\n::endgroup::"
+            if [ ${EXIT_CODE:-0} -gt 128 ]; then
+              X=1;
+              echo "Failed"
+            fi
+          done
+          exit $X
+      - name: Test PHPUnit
+        if: ${{ !cancelled() }}
+        run: |
+          git clone https://github.com/sebastianbergmann/phpunit.git --branch=main --depth=1
+          cd phpunit
+          git rev-parse HEAD
+          php /usr/bin/composer install --no-progress --ignore-platform-req=php+
+          php ./phpunit || EXIT_CODE=$?
+          if [ ${EXIT_CODE:-0} -gt 128 ]; then
+            exit 1
+          fi
+      - name: 'Symfony Preloading'
+        # composer create-project will automatically pick the right Symfony version for us.
+        if: ${{ !cancelled() }}
+        run: |
+          php /usr/bin/composer create-project symfony/symfony-demo symfony_demo --no-progress --ignore-platform-req=php+
+          cd symfony_demo
+          git rev-parse HEAD
+          sed -i 's/PHP_SAPI/"cli-server"/g' var/cache/dev/App_KernelDevDebugContainer.preload.php
+          php -d opcache.preload=var/cache/dev/App_KernelDevDebugContainer.preload.php public/index.php
+      - name: Test Wordpress
+        if: ${{ !cancelled() }}
+        run: |
+          git clone https://github.com/WordPress/wordpress-develop.git wordpress --depth=1
+          cd wordpress
+          git rev-parse HEAD
+          php /usr/bin/composer install --no-progress --ignore-platform-req=php+
+          cp wp-tests-config-sample.php wp-tests-config.php
+          sed -i 's/youremptytestdbnamehere/test/g' wp-tests-config.php
+          sed -i 's/yourusernamehere/root/g' wp-tests-config.php
+          sed -i 's/yourpasswordhere/root/g' wp-tests-config.php
+          php vendor/bin/phpunit || EXIT_CODE=$?
+          if [ $EXIT_CODE -gt 128 ]; then
+            exit 1
+          fi
+  OPCACHE_VARIATION:
+    if: ${{ fromJson(inputs.branch).jobs.OPCACHE_VARIATION }}
+    services:
+      mysql:
+        image: mysql:8.4
+        ports:
+          - 3306:3306
+        env:
+          MYSQL_DATABASE: test
+          MYSQL_ROOT_PASSWORD: root
+      postgres:
+        image: postgres
+        env:
+          POSTGRES_USER: postgres
+          POSTGRES_PASSWORD: postgres
+          POSTGRES_DB: test
+      firebird:
+        image: jacobalberty/firebird
+        ports:
+          - 3050:3050
+        env:
+          ISC_PASSWORD: test
+          FIREBIRD_DATABASE: test.fdb
+          FIREBIRD_USER: test
+          FIREBIRD_PASSWORD: test
+    name: OPCACHE_VARIATION
+    runs-on: ubuntu-${{ fromJson(inputs.branch).config.ubuntu_version }}
+    steps:
+      - name: git checkout
+        uses: actions/checkout@v6
+        with:
+          ref: ${{ fromJson(inputs.branch).ref }}
+      - name: Create MSSQL container
+        uses: ./.github/actions/setup-mssql
+      - name: apt
+        uses: ./.github/actions/apt-x64
+      - name: ccache
+        uses: ./.github/actions/ccache
+        with:
+          name: "${{ github.job }}"
+      - name: ./configure
+        uses: ./.github/actions/configure-x64
+        with:
+          configurationParameters: >-
+            --enable-debug --disable-zts
+      - name: make
+        run: make -j$(/usr/bin/nproc) >/dev/null
+      - name: make install
+        uses: ./.github/actions/install-linux
+      - name: Setup
+        uses: ./.github/actions/setup-x64
+      - name: Test File Cache (prime shm)
+        uses: ./.github/actions/test-linux
+        with:
+          enableOpcache: true
+          runTestsParameters: >-
+            --file-cache-prime
+      - name: Test File Cache (prime shm, use shm)
+        uses: ./.github/actions/test-linux
+        with:
+          enableOpcache: true
+          runTestsParameters: >-
+            --file-cache-use
+      - name: Test File Cache (prime shm, use file)
+        uses: ./.github/actions/test-linux
+        with:
+          enableOpcache: true
+          runTestsParameters: >-
+            --file-cache-use
+            -d opcache.file_cache_only=1
+      - name: Test File Cache Only (prime)
+        uses: ./.github/actions/test-linux
+        with:
+          enableOpcache: true
+          runTestsParameters: >-
+            --file-cache-prime
+            -d opcache.file_cache_only=1
+      - name: Test File Cache Only (use)
+        uses: ./.github/actions/test-linux
+        with:
+          enableOpcache: true
+          runTestsParameters: >-
+            --file-cache-use
+            -d opcache.file_cache_only=1
+      - name: Verify generated files are up to date
+        uses: ./.github/actions/verify-generated-files
+  MSAN:
+    if: ${{ fromJson(inputs.branch).jobs.MSAN }}
+    name: MSAN
+    runs-on: ubuntu-${{ fromJson(inputs.branch).config.ubuntu_version }}
+    steps:
+      - name: git checkout
+        uses: actions/checkout@v6
+        with:
+          ref: ${{ fromJson(inputs.branch).ref }}
+      - name: apt
+        uses: ./.github/actions/apt-x64
+      - name: ccache
+        uses: ./.github/actions/ccache
+        with:
+          name: "${{ github.job }}"
+          cc: clang
+          cxx: clang++
+      - name: ./configure
+        run: |
+          export CFLAGS="-DZEND_TRACK_ARENA_ALLOC"
+          ./buildconf --force
+          # msan requires all used libraries to be instrumented,
+          # so we should avoiding linking against anything but libc here
+          ./configure \
+            --enable-debug \
+            --enable-zts \
+            --enable-option-checking=fatal \
+            --prefix=/usr \
+            --without-sqlite3 \
+            --without-pdo-sqlite \
+            --without-libxml \
+            --disable-dom \
+            --disable-simplexml \
+            --disable-xml \
+            --disable-xmlreader \
+            --disable-xmlwriter \
+            --without-pcre-jit \
+            --disable-opcache-jit \
+            --enable-phpdbg \
+            --enable-fpm \
+            --with-pdo-mysql=mysqlnd \
+            --with-mysqli=mysqlnd \
+            --disable-mysqlnd-compression-support \
+            --without-pear \
+            --enable-exif \
+            --enable-sysvsem \
+            --enable-sysvshm \
+            --enable-shmop \
+            --enable-pcntl \
+            --enable-mbstring \
+            --disable-mbregex \
+            --enable-sockets \
+            --enable-bcmath \
+            --enable-calendar \
+            --enable-ftp \
+            --enable-zend-test \
+            --enable-werror \
+            --enable-memory-sanitizer \
+            --with-config-file-path=/etc \
+            --with-config-file-scan-dir=/etc/php.d \
+            --enable-dl-test=shared
+      - name: make
+        run: make -j$(/usr/bin/nproc) >/dev/null
+      - name: make install
+        run: |
+          sudo make install
+          sudo mkdir -p /etc/php.d
+          sudo chmod 777 /etc/php.d
+          echo mysqli.default_socket=/var/run/mysqld/mysqld.sock    > /etc/php.d/mysqli.ini
+          echo pdo_mysql.default_socket=/var/run/mysqld/mysqld.sock > /etc/php.d/pdo_mysql.ini
+      - name: Setup
+        run: |
+          set -x
+          sudo service mysql start
+          mysql -uroot -proot -e "CREATE DATABASE IF NOT EXISTS test"
+          # Ensure local_infile tests can run.
+          mysql -uroot -proot -e "SET GLOBAL local_infile = true"
+          sudo locale-gen de_DE
+      - name: Test
+        uses: ./.github/actions/test-linux
+        with:
+          runTestsParameters: >-
+            --msan
+      - name: Test Opcache
+        uses: ./.github/actions/test-linux
+        with:
+          enableOpcache: true
+          runTestsParameters: >-
+            --msan
+      - name: Verify generated files are up to date
+        uses: ./.github/actions/verify-generated-files
+  LIBMYSQLCLIENT:
+    if: ${{ fromJson(inputs.branch).jobs.LIBMYSQLCLIENT }}
+    name: LIBMYSQLCLIENT
+    runs-on: ubuntu-${{ fromJson(inputs.branch).config.ubuntu_version }}
+    steps:
+      - name: git checkout
+        uses: actions/checkout@v6
+        with:
+          ref: ${{ fromJson(inputs.branch).ref }}
+      - name: apt
+        run: |
+          sudo apt-get update -y | true
+          sudo apt install bison re2c
+      - name: Setup
+        run: |
+          sudo service mysql start
+          mysql -uroot -proot -e "CREATE DATABASE IF NOT EXISTS test"
+          # Ensure local_infile tests can run.
+          mysql -uroot -proot -e "SET GLOBAL local_infile = true"
+      - name: Build mysql-8.0
+        uses: ./.github/actions/build-libmysqlclient
+        with:
+          configurationParameters: '--enable-werror'
+          libmysql: mysql-8.0.37-linux-glibc2.28-x86_64.tar.xz
+      - name: Test mysql-8.0
+        uses: ./.github/actions/test-libmysqlclient
+      - name: Build mysql-8.4
+        uses: ./.github/actions/build-libmysqlclient
+        with:
+          configurationParameters: '--enable-werror'
+          libmysql: mysql-8.4.0-linux-glibc2.28-x86_64.tar.xz
+      - name: Test mysql-8.4
+        uses: ./.github/actions/test-libmysqlclient
+      - name: Verify generated files are up to date
+        uses: ./.github/actions/verify-generated-files
+  PECL:
+    if: ${{ fromJson(inputs.branch).jobs.PECL }}
+    runs-on: ubuntu-24.04
+    steps:
+      - name: git checkout PHP
+        uses: actions/checkout@v6
+        with:
+          path: php
+          ref: ${{ fromJson(inputs.branch).ref }}
+      # Used for ccache action
+      - name: Move .github
+        run: mv php/.github .
+      - name: git checkout apcu
+        uses: actions/checkout@v6
+        with:
+          repository: krakjoe/apcu
+          path: apcu
+      - name: git checkout imagick
+        uses: actions/checkout@v6
+        with:
+          repository: Imagick/imagick
+          path: imagick
+      - name: git checkout memcached
+        uses: actions/checkout@v6
+        with:
+          repository: php-memcached-dev/php-memcached
+          path: memcached
+      - name: git checkout redis
+        if: ${{ false }}
+        uses: actions/checkout@v6
+        with:
+          repository: phpredis/phpredis
+          path: redis
+      - name: git checkout xdebug
+        uses: actions/checkout@v6
+        with:
+          repository: xdebug/xdebug
+          path: xdebug
+      - name: git checkout yaml
+        uses: actions/checkout@v6
+        with:
+          repository: php/pecl-file_formats-yaml
+          path: yaml
+      - name: apt
+        run: |
+          sudo apt-get update
+          sudo apt-get install -y --no-install-recommends \
+            ccache \
+            libmemcached-dev \
+            imagemagick \
+            libmagickwand-dev \
+            bison \
+            re2c
+      - name: ccache
+        uses: ./.github/actions/ccache
+        with:
+          name: "${{ github.job }}"
+          php_directory: php
+      - name: build PHP
+        run: |
+          cd php
+          ./buildconf --force
+          ./configure \
+            --enable-option-checking=fatal \
+            --prefix=/opt/php \
+            --enable-cli \
+            --disable-all \
+            --enable-session \
+            --enable-werror
+          make -j$(/usr/bin/nproc)
+          sudo make install
+      - name: build apcu
+        run: |
+          cd apcu
+          /opt/php/bin/phpize
+          ./configure --prefix=/opt/php --with-php-config=/opt/php/bin/php-config
+          make -j$(/usr/bin/nproc)
+      - name: build imagick
+        run: |
+          cd imagick
+          /opt/php/bin/phpize
+          ./configure --prefix=/opt/php --with-php-config=/opt/php/bin/php-config
+          make -j$(/usr/bin/nproc)
+      - name: build memcached
+        run: |
+          cd memcached
+          /opt/php/bin/phpize
+          ./configure --prefix=/opt/php --with-php-config=/opt/php/bin/php-config
+          make -j$(/usr/bin/nproc)
+      - name: build redis
+        if: ${{ false }}
+        run: |
+          cd redis
+          /opt/php/bin/phpize
+          ./configure --prefix=/opt/php --with-php-config=/opt/php/bin/php-config
+          make -j$(/usr/bin/nproc)
+      - name: build xdebug
+        run: |
+          cd xdebug
+          /opt/php/bin/phpize
+          ./configure --prefix=/opt/php --with-php-config=/opt/php/bin/php-config
+          make -j$(/usr/bin/nproc)
+      - name: build yaml
+        run: |
+          cd yaml
+          /opt/php/bin/phpize
+          ./configure --prefix=/opt/php --with-php-config=/opt/php/bin/php-config
+          make -j$(/usr/bin/nproc)
+  WINDOWS:
+    if: ${{ fromJson(inputs.branch).jobs.WINDOWS }}
+    strategy:
+      fail-fast: false
+      matrix: ${{ fromJson(inputs.branch).jobs.WINDOWS.matrix }}
+    name: "WINDOWS_${{ matrix.x64 && 'X64' || 'X86' }}_${{ matrix.zts && 'ZTS' || 'NTS' }}${{ matrix.asan && '_ASAN' || ''}}"
+    runs-on: windows-2022
+    env:
+      PHP_BUILD_CACHE_BASE_DIR: C:\build-cache
+      PHP_BUILD_OBJ_DIR: C:\obj
+      PHP_BUILD_CACHE_SDK_DIR: C:\build-cache\sdk
+      PHP_BUILD_SDK_BRANCH: php-sdk-2.5.0
+      PHP_BUILD_CRT: ${{ fromJson(inputs.branch).jobs.WINDOWS.config.vs_crt_version }}
+      PLATFORM: ${{ matrix.x64 && 'x64' || 'x86' }}
+      THREAD_SAFE: "${{ matrix.zts && '1' || '0' }}"
+      INTRINSICS: "${{ matrix.zts && 'AVX2' || '' }}"
+      PARALLEL: -j2
+      OPCACHE: "${{ matrix.opcache && '1' || '0' }}"
+      ASAN: "${{ matrix.asan && '1' || '0' }}"
+    steps:
+      - name: git config
+        run: git config --global core.autocrlf false && git config --global core.eol lf
+      - name: git checkout
+        uses: actions/checkout@v6
+        with:
+          ref: ${{ fromJson(inputs.branch).ref }}
+      - name: Setup
+        uses: ./.github/actions/setup-windows
+      - name: Build
+        run: .github/scripts/windows/build.bat
+      - name: Test
+        run: .github/scripts/windows/test.bat
+  FREEBSD:
+    if: ${{ fromJson(inputs.branch).jobs.FREEBSD }}
+    strategy:
+      fail-fast: false
+      matrix: ${{ fromJson(inputs.branch).jobs.FREEBSD.matrix }}
+    name: "FREEBSD_${{ matrix.zts && 'ZTS' || 'NTS' }}"
+    runs-on: ubuntu-latest
+    timeout-minutes: 50
+    steps:
+      - name: git checkout
+        uses: actions/checkout@v6
+        with:
+          ref: ${{ fromJson(inputs.branch).ref }}
+      - name: FreeBSD
+        uses: ./.github/actions/freebsd
+        with:
+          configurationParameters: >-
+            --${{ matrix.zts && 'enable' || 'disable' }}-zts
+          runExtraTests: true
+  SOLARIS:
+    if: ${{ fromJson(inputs.branch).jobs.SOLARIS }}
+    name: "SOLARIS"
+    runs-on: ubuntu-latest
+    timeout-minutes: 50
+    steps:
+      - name: git checkout
+        uses: actions/checkout@v5
+        with:
+          ref: ${{ fromJson(inputs.branch).ref }}
+      - name: Solaris
+        uses: ./.github/actions/solaris
+        with:
+          configurationParameters: --disable-zts
+          runExtraTests: true
+  BENCHMARKING:
+    name: BENCHMARKING
+    if: ${{ fromJson(inputs.branch).jobs.BENCHMARKING }}
+    runs-on: ubuntu-${{ fromJson(inputs.branch).config.ubuntu_version }}
+    timeout-minutes: 50
+    steps:
+      - name: git checkout
+        uses: actions/checkout@v6
+        with:
+          ref: ${{ fromJson(inputs.branch).ref }}
+          fetch-depth: 0
+      # ASLR can cause a lot of noise due to missed sse opportunities for memcpy
+      # and other operations, so we disable it during benchmarking.
+      - name: Disable ASLR
+        run: echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
+      - name: apt
+        run: |
+          set -x
+          sudo apt-get update
+          sudo apt-get install \
+            bison \
+            libgmp-dev \
+            libonig-dev \
+            libsqlite3-dev \
+            openssl \
+            re2c \
+            valgrind
+      - name: ccache
+        uses: ./.github/actions/ccache
+        with:
+          name: "${{ github.job }}"
+      - name: ./configure
+        run: |
+          set -x
+          ./buildconf --force
+          ./configure \
+            --disable-debug \
+            --enable-mbstring \
+            --enable-option-checking=fatal \
+            --enable-sockets \
+            --enable-werror \
+            --prefix=/usr \
+            --with-config-file-scan-dir=/etc/php.d \
+            --with-gmp \
+            --with-mysqli=mysqlnd \
+            --with-openssl \
+            --with-pdo-sqlite \
+            --with-valgrind
+      - name: make
+        run: make -j$(/usr/bin/nproc) >/dev/null
+      - name: make install
+        run: |
+          set -x
+          sudo make install
+          sudo mkdir -p /etc/php.d
+          sudo chmod 777 /etc/php.d
+          echo mysqli.default_socket=/var/run/mysqld/mysqld.sock > /etc/php.d/mysqli.ini
+          ${{ !fromJson(inputs.branch).jobs.BENCHMARKING.config.integrated_opcache && 'echo zend_extension=opcache.so >> /etc/php.d/opcache.ini' || '' }}
+          echo opcache.enable=1 >> /etc/php.d/opcache.ini
+          echo opcache.enable_cli=1 >> /etc/php.d/opcache.ini
+      - name: Setup
+        run: |
+          git config --global user.name "Benchmark"
+          git config --global user.email "benchmark@php.net"
+          sudo service mysql start
+          mysql -uroot -proot -e "CREATE DATABASE IF NOT EXISTS wordpress"
+          mysql -uroot -proot -e "CREATE USER 'wordpress'@'localhost' IDENTIFIED BY 'wordpress'; FLUSH PRIVILEGES;"
+          mysql -uroot -proot -e "GRANT ALL PRIVILEGES ON *.* TO 'wordpress'@'localhost' WITH GRANT OPTION;"
+      - name: git checkout benchmarking-data
+        uses: actions/checkout@v6
+        with:
+          repository: php/benchmarking-data
+          ssh-key: ${{ secrets.BENCHMARKING_DATA_DEPLOY_KEY }}
+          path: benchmark/repos/data
+      - name: Benchmark
+        run: php benchmark/benchmark.php true
+      - name: Store result
+        if: github.event_name == 'push'
+        run: |
+          set -x
+          cd benchmark/repos/data
+          git pull --autostash
+          if [ -e ".git/MERGE_HEAD" ]; then
+            echo "Merging, can't proceed"
+            exit 1
+          fi
+          git add .
+          if git diff --cached --quiet; then
+            exit 0
+          fi
+          git commit -m "Add result for ${{ github.repository }}@${{ github.sha }}"
+          git push
+      - name: Show diff
+        if: github.event_name == 'pull_request'
+        run: |-
+          set -x
+          php benchmark/generate_diff.php \
+            ${{ github.sha }} \
+            ${{ github.event.pull_request.base.sha }} \
+            > $GITHUB_STEP_SUMMARY
+      - uses: actions/upload-artifact@v6
+        with:
+          name: profiles
+          path: ${{ github.workspace }}/benchmark/profiles
+          retention-days: 30
diff '--color=auto' -Naur php-8.4.18/.github/workflows/test.yml php-8.4.20RC1/.github/workflows/test.yml
--- php-8.4.18/.github/workflows/test.yml	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/.github/workflows/test.yml	2026-04-01 04:35:35.982270023 +0000
@@ -0,0 +1,72 @@
+name: Test
+on:
+  push:
+    paths-ignore: &ignore_paths
+      - docs/**
+      - NEWS
+      - UPGRADING
+      - UPGRADING.INTERNALS
+      - '**/README.*'
+      - CONTRIBUTING.md
+      - CODING_STANDARDS.md
+      - .cirrus.yml
+      - .circleci/**
+    branches:
+      - PHP-8.2
+      - PHP-8.3
+      - PHP-8.4
+      - PHP-8.5
+      - master
+  pull_request:
+    paths-ignore: *ignore_paths
+    branches:
+      - '**'
+  schedule:
+   - cron: "0 1 * * *"
+  workflow_dispatch: ~
+permissions:
+  contents: read
+concurrency:
+  group: ${{ github.workflow }}-${{ github.event.pull_request.url || github.run_id }}
+  cancel-in-progress: true
+jobs:
+  GENERATE_MATRIX:
+    name: Generate Matrix
+    if: github.repository == 'php/php-src' || github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch'
+    runs-on: ubuntu-latest
+    outputs:
+      all_variations: ${{ steps.set-matrix.outputs.all_variations }}
+      branches: ${{ steps.set-matrix.outputs.branches }}
+    steps:
+      - uses: actions/checkout@v6
+        with:
+          # When running nightly, set fetch-depth to 0 to clone the full
+          # repository including all branches. This is required to find the
+          # correct commit hashes.
+          fetch-depth: ${{ (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') && '0' || '1' }}
+      - name: Grab the commit mapping
+        if: ${{ github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' }}
+        uses: actions/cache@v5
+        with:
+          path: branch-commit-cache.json
+          # The cache key needs to change every time for the
+          # cache to be updated after this job finishes.
+          key: nightly-${{ github.run_id }}-${{ github.run_attempt }}
+          restore-keys: |
+            nightly-
+      - name: Generate Matrix
+        id: set-matrix
+        run: php .github/matrix.php "${{ github.event_name }}" "${{ github.run_attempt }}" "${{ github.event_name == 'pull_request' && github.ref || github.ref_name }}" '${{ toJSON(github.event.pull_request.labels) }}' "${{ github.repository }}"
+  TEST:
+    needs: GENERATE_MATRIX
+    if: ${{ needs.GENERATE_MATRIX.outputs.branches != '[]' }}
+    name: ${{ matrix.branch.name }}
+    uses: ./.github/workflows/test-suite.yml
+    strategy:
+      fail-fast: false
+      matrix:
+        branch: ${{ fromJson(needs.GENERATE_MATRIX.outputs.branches) }}
+    with:
+      all_variations: ${{ needs.GENERATE_MATRIX.outputs.all_variations == 'true' }}
+      branch: ${{ toJSON(matrix.branch) }}
+    secrets: inherit
diff '--color=auto' -Naur php-8.4.18/main/debug_gdb_scripts.c php-8.4.20RC1/main/debug_gdb_scripts.c
--- php-8.4.18/main/debug_gdb_scripts.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/main/debug_gdb_scripts.c	2026-04-01 04:35:36.022662544 +0000
@@ -6,7 +6,7 @@
  *
  * See https://sourceware.org/gdb/current/onlinedocs/gdb.html/dotdebug_005fgdb_005fscripts-section.html#dotdebug_005fgdb_005fscripts-section
  */
-asm(
+__asm__(
     ".pushsection \".debug_gdb_scripts\", \"MS\",%progbits,1\n"
     ".byte 4 /* Python Text */\n"
     ".ascii \"gdb.inlined-script\\n\"\n"
diff '--color=auto' -Naur php-8.4.18/main/fastcgi.c php-8.4.20RC1/main/fastcgi.c
--- php-8.4.18/main/fastcgi.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/main/fastcgi.c	2026-04-01 04:35:36.022801286 +0000
@@ -641,7 +641,7 @@
 
 int fcgi_listen(const char *path, int backlog)
 {
-	char     *s;
+	const char *s;
 	int       tcp = 0;
 	char      host[MAXPATHLEN];
 	short     port = 0;
diff '--color=auto' -Naur php-8.4.18/main/main.c php-8.4.20RC1/main/main.c
--- php-8.4.18/main/main.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/main/main.c	2026-04-01 04:35:36.022970596 +0000
@@ -995,7 +995,7 @@
 {
 	zend_string *replace_origin = NULL;
 	char *docref_buf = NULL, *target = NULL;
-	char *docref_target = "", *docref_root = "";
+	const char *docref_target = "", *docref_root = "";
 	char *p;
 	const char *space = "";
 	const char *class_name = "";
diff '--color=auto' -Naur php-8.4.18/main/network.c php-8.4.20RC1/main/network.c
--- php-8.4.18/main/network.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/main/network.c	2026-04-01 04:35:36.023155495 +0000
@@ -553,7 +553,7 @@
 
 PHPAPI zend_result php_network_parse_network_address_with_port(const char *addr, size_t addrlen, struct sockaddr *sa, socklen_t *sl)
 {
-	char *colon;
+	const char *colon;
 	char *tmp;
 	zend_result ret = FAILURE;
 	short port;
diff '--color=auto' -Naur php-8.4.18/main/php_version.h php-8.4.20RC1/main/php_version.h
--- php-8.4.18/main/php_version.h	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/main/php_version.h	2026-04-01 04:38:20.471143120 +0000
@@ -2,7 +2,8 @@
 /* edit configure.ac to change version number */
 #define PHP_MAJOR_VERSION 8
 #define PHP_MINOR_VERSION 4
-#define PHP_RELEASE_VERSION 18
+#define PHP_RELEASE_VERSION 20
 #define PHP_EXTRA_VERSION ""
-#define PHP_VERSION "8.4.18"
-#define PHP_VERSION_ID 80418
+#define PHP_EXTRA_VERSION "RC1"
+#define PHP_VERSION "8.4.20RC1"
+#define PHP_VERSION_ID 80420
diff '--color=auto' -Naur php-8.4.18/main/php_version.h.orig php-8.4.20RC1/main/php_version.h.orig
--- php-8.4.18/main/php_version.h.orig	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/main/php_version.h.orig	2026-02-10 17:48:03.000000000 +0000
@@ -0,0 +1,8 @@
+/* automatically generated by configure */
+/* edit configure.ac to change version number */
+#define PHP_MAJOR_VERSION 8
+#define PHP_MINOR_VERSION 4
+#define PHP_RELEASE_VERSION 18
+#define PHP_EXTRA_VERSION ""
+#define PHP_VERSION "8.4.18"
+#define PHP_VERSION_ID 80418
diff '--color=auto' -Naur php-8.4.18/main/streams/filter.c php-8.4.20RC1/main/streams/filter.c
--- php-8.4.18/main/streams/filter.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/main/streams/filter.c	2026-04-01 04:35:36.023438721 +0000
@@ -224,7 +224,7 @@
 	const php_stream_filter_factory *factory = NULL;
 	php_stream_filter *filter = NULL;
 	size_t n;
-	char *period;
+	const char *period;
 
 	n = strlen(filtername);
 
@@ -236,17 +236,17 @@
 
 		wildname = safe_emalloc(1, n, 3);
 		memcpy(wildname, filtername, n+1);
-		period = wildname + (period - filtername);
-		while (period && !filter) {
-			ZEND_ASSERT(period[0] == '.');
-			period[1] = '*';
-			period[2] = '\0';
+		char *new_period = wildname + (period - filtername);
+		while (new_period && !filter) {
+			ZEND_ASSERT(new_period[0] == '.');
+			new_period[1] = '*';
+			new_period[2] = '\0';
 			if (NULL != (factory = zend_hash_str_find_ptr(filter_hash, wildname, strlen(wildname)))) {
 				filter = factory->create_filter(filtername, filterparams, persistent);
 			}
 
-			*period = '\0';
-			period = strrchr(wildname, '.');
+			*new_period = '\0';
+			new_period = strrchr(wildname, '.');
 		}
 		efree(wildname);
 	}
diff '--color=auto' -Naur php-8.4.18/main/streams/memory.c php-8.4.20RC1/main/streams/memory.c
--- php-8.4.18/main/streams/memory.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/main/streams/memory.c	2026-04-01 04:35:36.023554028 +0000
@@ -615,7 +615,8 @@
 {
 	php_stream *stream;
 	php_stream_temp_data *ts;
-	char *comma, *semi, *sep;
+	char *comma;
+	const char *semi, *sep;
 	size_t mlen, dlen, plen, vlen, ilen;
 	zend_off_t newoffs;
 	zval meta;
@@ -637,7 +638,7 @@
 		path += 2;
 	}
 
-	if ((comma = memchr(path, ',', dlen)) == NULL) {
+	if ((comma = (char *) memchr(path, ',', dlen)) == NULL) {
 		php_stream_wrapper_log_error(wrapper, options, "rfc2397: no comma in URL");
 		return NULL;
 	}
diff '--color=auto' -Naur php-8.4.18/main/streams/plain_wrapper.c php-8.4.20RC1/main/streams/plain_wrapper.c
--- php-8.4.18/main/streams/plain_wrapper.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/main/streams/plain_wrapper.c	2026-04-01 04:35:36.023672212 +0000
@@ -1775,7 +1775,7 @@
 	ptr = pathbuf;
 
 	while (ptr && *ptr) {
-		end = strchr(ptr, DEFAULT_DIR_SEPARATOR);
+		end = (char *) strchr(ptr, DEFAULT_DIR_SEPARATOR);
 		if (end != NULL) {
 			*end = '\0';
 			end++;
diff '--color=auto' -Naur php-8.4.18/main/streams/xp_socket.c php-8.4.20RC1/main/streams/xp_socket.c
--- php-8.4.18/main/streams/xp_socket.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/main/streams/xp_socket.c	2026-04-01 04:35:36.023811124 +0000
@@ -617,7 +617,7 @@
 
 static inline char *parse_ip_address_ex(const char *str, size_t str_len, int *portno, int get_err, zend_string **err)
 {
-	char *colon;
+	const char *colon;
 	char *host = NULL;
 
 	if (memchr(str, '\0', str_len)) {
@@ -628,7 +628,7 @@
 #ifdef HAVE_IPV6
 	if (*(str) == '[' && str_len > 1) {
 		/* IPV6 notation to specify raw address with port (i.e. [fe80::1]:80) */
-		char *p = memchr(str + 1, ']', str_len - 2);
+		const char *p = memchr(str + 1, ']', str_len - 2);
 		if (!p || *(p + 1) != ':') {
 			if (get_err) {
 				*err = strpprintf(0, "Failed to parse IPv6 address \"%s\"", str);
diff '--color=auto' -Naur php-8.4.18/NEWS.orig php-8.4.20RC1/NEWS.orig
--- php-8.4.18/NEWS.orig	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/NEWS.orig	2026-02-10 17:48:03.000000000 +0000
@@ -0,0 +1,2058 @@
+PHP                                                                        NEWS
+|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+12 Feb 2026, PHP 8.4.18
+
+- Core:
+  . Fixed bug GH-20837 (NULL dereference when calling ob_start() in shutdown
+    function triggered by bailout in php_output_lock_error()). (timwolla)
+  . Fix OSS-Fuzz #471533782 (Infinite loop in GC destructor fiber). (ilutov)
+  . Fix OSS-Fuzz #472563272 (Borked block_pass JMP[N]Z optimization). (ilutov)
+  . Fixed bug GH-GH-20914 (Internal enums can be cloned and compared). (Arnaud)
+  . Fix OSS-Fuzz #474613951 (Leaked parent property default value). (ilutov)
+  . Fixed bug GH-20766 (Use-after-free in FE_FREE with GC interaction). (Bob)
+  . Fix OSS-Fuzz #471486164 (Broken by-ref assignment to uninitialized hooked
+    backing value). (ilutov)
+  . Fix OSS-Fuzz #438780145 (Nested finally with repeated return type check may
+    uaf). (ilutov)
+  . Fixed bug GH-20905 (Lazy proxy bailing __clone assertion). (ilutov)
+  . Fixed bug GH-20479 (Hooked object properties overflow). (ndossche)
+
+- Date:
+  . Update timelib to 2022.16. (Derick)
+
+- DOM:
+  . Fixed GH-21041 (Dom\HTMLDocument corrupts closing tags within scripts).
+    (lexborisov)
+
+- MbString:
+  . Fixed bug GH-20833 (mb_str_pad() divide by zero if padding string is
+    invalid in the encoding). (ndossche)
+  . Fixed bug GH-20836 (Stack overflow in mb_convert_variables with
+    recursive array references). (alexandre-daubois)
+
+- Opcache:
+  . Fixed bug GH-20818 (Segfault in Tracing JIT with object reference).
+    (khasinski)
+
+- OpenSSL:
+  . Fix memory leaks when sk_X509_new_null() fails. (ndossche)
+  . Fix crash when in openssl_x509_parse() when i2s_ASN1_INTEGER() fails.
+    (ndossche)
+  . Fix crash in openssl_x509_parse() when X509_NAME_oneline() fails.
+    (ndossche)
+
+- Phar:
+  . Fixed bug GH-20882 (buildFromIterator breaks with missing base directory).
+    (ndossche)
+
+- PGSQL:
+  . Fixed INSERT/UPDATE queries building with PQescapeIdentifier() and possible
+    UB. (David Carlier)
+
+- Readline:
+  . Fixed bug GH-18139 (Memory leak when overriding some settings
+    via readline_info()). (ndossche)
+
+- SPL:
+  . Fixed bug GH-20856 (heap-use-after-free in SplDoublyLinkedList iterator
+    when modifying during iteration). (ndossche)
+
+- Standard:
+  . Fixed bug #74357 (lchown fails to change ownership of symlink with ZTS)
+    (Jakub Zelenka)
+  . Fixed bug GH-20843 (var_dump() crash with nested objects)
+    (David Carlier)
+
+15 Jan 2026, PHP 8.4.17
+
+- Core:
+  . Fix OSS-Fuzz #465488618 (Wrong assumptions when dumping function signature
+    with dynamic class const lookup default argument). (ilutov)
+  . Fixed bug GH-20695 (Assertion failure in normalize_value() when parsing
+    malformed INI input via parse_ini_string()). (ndossche)
+  . Fixed bug GH-20714 (Uncatchable exception thrown in generator). (ilutov)
+  . Fixed bug GH-20352 (UAF in php_output_handler_free via re-entrant
+    ob_start() during error deactivation). (ndossche)
+
+- Bz2:
+  . Fixed bug GH-20620 (bzcompress overflow on large source size).
+    (David Carlier)
+
+- DOM:
+  . Fixed bug GH-20722 (Null pointer dereference in DOM namespace node cloning
+    via clone on malformed objects). (ndossche)
+  . Fixed bug GH-20444 (Dom\XMLDocument::C14N() seems broken compared
+    to DOMDocument::C14N()). (ndossche)
+
+- GD:
+  . Fixed bug GH-20622 (imagestring/imagestringup overflow). (David Carlier)
+
+- Intl:
+  . Fix leak in umsg_format_helper(). (ndossche)
+
+- LDAP:
+  . Fix memory leak in ldap_set_options(). (ndossche)
+
+- Mbstring:
+  . Fixed bug GH-20674 (mb_decode_mimeheader does not handle separator).
+    (Yuya Hamada)
+
+- OpenSSL:
+  . Fixed bug GH-20802 (undefined behavior with invalid SNI_server_certs
+    options). (David Carlier)
+
+- PCNTL:
+  . Fixed bug with pcntl_getcpuaffinity() on solaris regarding invalid
+    process ids handling. (David Carlier)
+
+- Phar:
+  . Fixed bug GH-20732 (Phar::LoadPhar undefined behavior when reading fails).
+    (ndossche)
+  . Fix SplFileInfo::openFile() in write mode. (ndossche)
+  . Fix build on legacy OpenSSL 1.1.0 systems. (Giovanni Giacobbi)
+  . Fixed bug #74154 (Phar extractTo creates empty files). (ndossche)
+
+- POSIX:
+  . Fixed crash on posix groups to php array creation on macos.
+    (David Carlier)
+
+- SPL:
+  . Fixed bug GH-20678 (resource created by GlobIterator crashes with fclose()).
+    (David Carlier)
+
+- Sqlite3:
+  . Fixed bug GH-20699 (SQLite3Result fetchArray return array|false,
+    null returned). (ndossche, plusminmax)
+
+- Standard:
+  . Fix error check for proc_open() command. (ndossche)
+  . Fix memory leak in mail() when header key is numeric. (Girgias)
+  . Fixed bug GH-20582 (Heap Buffer Overflow in iptcembed). (ndossche)
+
+- Zlib:
+  . Fix OOB gzseek() causing assertion failure. (ndossche)
+
+18 Dec 2025, PHP 8.4.16
+
+- Core:
+  . Sync all boost.context files with release 1.86.0. (mvorisek)
+  . Fixed bug GH-20435 (SensitiveParameter doesn't work for named argument
+    passing to variadic parameter). (ndossche)
+  . Fixed bug GH-20286 (use-after-destroy during userland stream_close()).
+    (ndossche, David Carlier)
+
+- Bz2:
+  . Fix assertion failures resulting in crashes with stream filter
+    object parameters. (ndossche)
+
+- Date:
+  . Fix crashes when trying to instantiate uninstantiable classes via date
+    static constructors. (ndossche)
+
+- DOM:
+  . Fix memory leak when edge case is hit when registering xpath callback.
+    (ndossche)
+  . Fixed bug GH-20395 (querySelector and querySelectorAll requires elements
+    in $selectors to be lowercase). (ndossche)
+  . Fix missing NUL byte check on C14NFile(). (ndossche)
+
+- Fibers:
+  . Fixed bug GH-20483 (ASAN stack overflow with fiber.stack_size INI
+    small value). (David Carlier)
+
+- FTP:
+  . Fixed bug GH-20601 (ftp_connect overflow on timeout). (David Carlier)
+
+- GD:
+  . Fixed bug GH-20511 (imagegammacorrect out of range input/output values).
+    (David Carlier)
+  . Fixed bug GH-20602 (imagescale overflow with large height values).
+    (David Carlier)
+
+- Intl:
+  . Fixed bug GH-20426 (Spoofchecker::setRestrictionLevel() error message
+    suggests missing constants). (DanielEScherzer)
+
+- LibXML:
+  . Fix some deprecations on newer libxml versions regarding input
+    buffer/parser handling. (ndossche)
+
+- MbString:
+  . Fixed bug GH-20491 (SLES15 compile error with mbstring oniguruma).
+    (ndossche)
+  . Fixed bug GH-20492 (mbstring compile warning due to non-strings).
+    (ndossche)
+
+- mysqli:
+  . Make mysqli_begin_transaction() report errors properly. (Kamil Tekiela)
+
+- MySQLnd:
+  . Fixed bug GH-20528 (Regression breaks mysql connexion using an IPv6 address
+    enclosed in square brackets). (Remi)
+
+- Opcache:
+  . Fixed bug GH-20329 (opcache.file_cache broken with full interned string
+    buffer). (Arnaud)
+
+- PDO:
+  . Fixed GHSA-8xr5-qppj-gvwj (PDO quoting result null deref). (CVE-2025-14180)
+    (Jakub Zelenka)
+
+- Phar:
+  . Fixed bug GH-20442 (Phar does not respect case-insensitiveness of
+    __halt_compiler() when reading stub). (ndossche, TimWolla)
+  . Fix broken return value of fflush() for phar file entries. (ndossche)
+  . Fix assertion failure when fseeking a phar file out of bounds. (ndossche)
+
+- PHPDBG:
+  . Fixed ZPP type violation in phpdbg_get_executable() and phpdbg_end_oplog().
+    (Girgias)
+
+- SPL:
+  . Fixed bug GH-20614 (SplFixedArray incorrectly handles references
+    in deserialization). (ndossche)
+
+- Standard:
+  . Fix memory leak in array_diff() with custom type checks. (ndossche)
+  . Fixed bug GH-20583 (Stack overflow in http_build_query
+    via deep structures). (ndossche)
+  . Fixed GHSA-www2-q4fc-65wf (Null byte termination in dns_get_record()).
+    (ndossche)
+  . Fixed GHSA-h96m-rvf9-jgm2 (Heap buffer overflow in array_merge()).
+    (CVE-2025-14178) (ndossche)
+  . Fixed GHSA-3237-qqm7-mfv7 (Information Leak of Memory in getimagesize).
+    (CVE-2025-14177) (ndossche)
+
+- Streams:
+  . Fixed bug GH-20370 (User stream filters could violate typed property
+    constraints). (alexandre-daubois)
+
+- Tidy:
+  . Fixed bug GH-20374 (PHP with tidy and custom-tags). (ndossche)
+
+- XML:
+  . Fixed bug GH-20439 (xml_set_default_handler() does not properly handle
+    special characters in attributes when passing data to callback). (ndossche)
+
+- Zip:
+  . Fix crash in property existence test. (ndossche)
+  . Don't truncate return value of zip_fread() with user sizes. (ndossche)
+
+- Zlib:
+  . Fix assertion failures resulting in crashes with stream filter
+    object parameters. (ndossche)
+
+20 Nov 2025, PHP 8.4.15
+
+- Core:
+  . Fixed bug GH-19934 (CGI with auto_globals_jit=0 causes uouv). (ilutov)
+  . Fixed bug GH-20073 (Assertion failure in WeakMap offset operations on
+    reference). (nielsdos)
+  . Fixed bug GH-20085 (Assertion failure when combining lazy object
+    get_properties exception with foreach loop). (nielsdos)
+  . Fixed bug GH-19844 (Don't bail when closing resources on shutdown). (ilutov)
+  . Fixed bug GH-20177 (Accessing overridden private property in
+    get_object_vars() triggers assertion error). (ilutov)
+  . Fixed bug GH-20270 (Broken parent hook call with named arguments). (ilutov)
+  . Fixed bug GH-20183 (Stale EG(opline_before_exception) pointer through eval).
+    (ilutov)
+
+- DOM:
+  . Partially fixed bug GH-16317 (DOM classes do not allow
+    __debugInfo() overrides to work). (nielsdos)
+  . Fixed bug GH-20281 (\Dom\Document::getElementById() is inconsistent
+    after nodes are removed). (nielsdos)
+
+- Exif:
+  . Fix possible memory leak when tag is empty. (nielsdos)
+
+- FPM:
+  . Fixed bug GH-19974 (fpm_status_export_to_zval segfault for parallel
+    execution). (Jakub Zelenka, txuna)
+
+- FTP:
+  . Fixed bug GH-20240 (FTP with SSL: ftp_fput(): Connection timed out on
+    successful writes). (nielsdos)
+
+- GD:
+  . Fixed bug GH-20070 (Return type violation in imagefilter when an invalid
+    filter is provided). (Girgias)
+
+- Intl:
+  . Fix memory leak on error in locale_filter_matches(). (nielsdos)
+
+- LibXML:
+  . Fix not thread safe schema/relaxng calls. (SpencerMalone, nielsdos)
+
+- MySQLnd:
+  . Fixed bug GH-8978 (SSL certificate verification fails (port doubled)).
+    (nielsdos)
+  . Fixed bug GH-20122 (getColumnMeta() for JSON-column in MySQL). (nielsdos)
+
+- Opcache:
+  . Fixed bug GH-20081 (access to uninitialized vars in preload_load()).
+    (Arnaud)
+  . Fixed bug GH-20121 (JIT broken in ZTS builds on MacOS 15).
+    (Arnaud, Shivam Mathur)
+  . Fixed bug GH-19875 (JIT 1205 segfault on large file compiled in subprocess).
+    (Arnaud)
+  . Fixed bug GH-20012 (heap buffer overflow in jit). (Arnaud)
+  . Partially fixed bug GH-17733 (Avoid calling wrong function when reusing file
+    caches across differing environments). (ilutov)
+
+- PgSql:
+  . Fix memory leak when first string conversion fails. (nielsdos)
+  . Fix segfaults when attempting to fetch row into a non-instantiable class
+    name. (Girgias, nielsdos)
+
+- Phar:
+  . Fix memory leak of argument in webPhar. (nielsdos)
+  . Fix memory leak when setAlias() fails. (nielsdos)
+  . Fix a bunch of memory leaks in phar_parse_zipfile() error handling.
+    (nielsdos)
+  . Fix file descriptor/memory leak when opening central fp fails. (nielsdos)
+  . Fix memleak+UAF when opening temp stream in buildFromDirectory() fails.
+    (nielsdos)
+  . Fix potential buffer length truncation due to usage of type int instead
+    of type size_t. (Girgias)
+  . Fix memory leak when openssl polyfill returns garbage. (nielsdos)
+  . Fix file descriptor leak in phar_zip_flush() on failure. (nielsdos)
+  . Fix memory leak when opening temp file fails while trying to open
+    gzip-compressed archive. (nielsdos)
+  . Fixed bug GH-20302 (Freeing a phar alias may invalidate
+    PharFileInfo objects). (nielsdos)
+
+- Random:
+  . Fix Randomizer::__serialize() w.r.t. INDIRECTs. (nielsdos)
+
+- Reflection:
+  . Fixed bug GH-20217 (ReflectionClass::isIterable() incorrectly returns true
+    for classes with property hooks). (alexandre-daubois)
+
+- SimpleXML:
+  . Partially fixed bug GH-16317 (SimpleXML does not allow __debugInfo() overrides
+    to work). (nielsdos)
+
+- Streams:
+  . Fixed bug GH-19798: XP_SOCKET XP_SSL (Socket stream modules): Incorrect
+    condition for Win32/Win64. (Jakub Zelenka)
+
+- Tidy:
+  . Fixed GH-19021 (improved tidyOptGetCategory detection).
+    (arjendekorte, David Carlier, Peter Kokot)
+  . Fix UAF in tidy when tidySetErrorBuffer() fails. (nielsdos)
+
+- XMLReader:
+  . Fix arginfo/zpp violations when LIBXML_SCHEMAS_ENABLED is not available.
+    (nielsdos)
+
+- Windows:
+  . Fix GH-19722 (_get_osfhandle asserts in debug mode when given a socket).
+    (dktapps)
+
+09 Oct 2025, PHP 8.4.14
+
+- Core:
+  . Fixed bug GH-19765 (object_properties_load() bypasses readonly property
+    checks). (timwolla)
+  . Fixed hard_timeout with --enable-zend-max-execution-timers. (Appla)
+  . Fixed bug GH-19792 (SCCP causes UAF for return value if both warning and
+    exception are triggered). (nielsdos)
+  . Fixed bug GH-19653 (Closure named argument unpacking between temporary
+    closures can cause a crash). (nielsdos, Arnaud, Bob)
+  . Fixed bug GH-19839 (Incorrect HASH_FLAG_HAS_EMPTY_IND flag on userland
+    array). (ilutov)
+  . Fixed bug GH-19480 (error_log php.ini cannot be unset when open_basedir is
+    configured). (nielsdos)
+  . Fixed bug GH-20002 (Broken build on *BSD with MSAN). (outtersg)
+
+- CLI:
+  . Fix useless "Failed to poll event" error logs due to EAGAIN in CLI server
+    with PHP_CLI_SERVER_WORKERS. (leotaku)
+
+- Curl:
+  . Fix cloning of CURLOPT_POSTFIELDS when using the clone operator instead
+    of the curl_copy_handle() function to clone a CurlHandle. (timwolla)
+  . Fix curl build and test failures with version 8.16.
+    (nielsdos, ilutov, Jakub Zelenka)
+
+- Date:
+  . Fixed GH-17159: "P" format for ::createFromFormat swallows string literals.
+    (nielsdos)
+
+- DOM:
+  . Fix macro name clash on macOS. (Ruoyu Zhong)
+  . Fixed bug GH-20022 (docker-php-ext-install DOM failed). (nielsdos)
+
+- GD:
+  . Fixed GH-19955 (imagefttext() memory leak). (David Carlier)
+
+- MySQLnd:
+  . Fixed bug #67563 (mysqli compiled with mysqlnd does not take ipv6 adress
+    as parameter). (nielsdos)
+
+- Opcache:
+  . Fixed bug GH-19669 (assertion failure in zend_jit_trace_type_to_info_ex).
+    (Arnaud)
+  . Fixed bug GH-19831 (function JIT may not deref property value). (Arnaud)
+  . Fixed bug GH-19889 (race condition in zend_runtime_jit(),
+    zend_jit_hot_func()). (Arnaud)
+
+- Phar:
+  . Fix memory leak and invalid continuation after tar header writing fails.
+    (nielsdos)
+  . Fix memory leaks when creating temp file fails when applying zip signature.
+    (nielsdos)
+
+- SimpleXML:
+  . Fixed bug GH-19988 (zend_string_init with NULL pointer in simplexml (UB)).
+    (nielsdos)
+
+- Soap:
+  . Fixed bug GH-19784 (SoapServer memory leak). (nielsdos)
+  . Fixed bug GH-20011 (Array of SoapVar of unknown type causes crash).
+    (nielsdos)
+
+- Standard:
+  . Fixed bug GH-12265 (Cloning an object breaks serialization recursion).
+    (nielsdos)
+  . Fixed bug GH-19701 (Serialize/deserialize loses some data). (nielsdos)
+  . Fixed bug GH-19801 (leaks in var_dump() and debug_zval_dump()).
+    (alexandre-daubois)
+  . Fixed bug GH-20043 (array_unique assertion failure with RC1 array
+    causing an exception on sort). (nielsdos)
+  . Fixed bug GH-19926 (reset internal pointer earlier while splicing array
+    while COW violation flag is still set). (alexandre-daubois)
+  . Fixed bug GH-19570 (unable to fseek in /dev/zero and /dev/null).
+    (nielsdos, divinity76)
+
+- Streams:
+  . Fixed bug GH-19248 (Use strerror_r instead of strerror in main).
+    (Jakub Zelenka)
+  . Fixed bug GH-17345 (Bug #35916 was not completely fixed). (nielsdos)
+  . Fixed bug GH-19705 (segmentation when attempting to flush on non seekable
+    stream. (bukka/David Carlier)
+
+- XMLReader:
+  . Fixed bug GH-20009 (XMLReader leak on RelaxNG schema failure). (nielsdos)
+
+- Zip:
+  . Fixed bug GH-19688 (Remove pattern overflow in zip addGlob()). (nielsdos)
+  . Fixed bug GH-19932 (Memory leak in zip setEncryptionName()/setEncryptionIndex()).
+    (David Carlier)
+
+25 Sep 2025, PHP 8.4.13
+
+- Core:
+  . Fixed bug GH-18850 (Repeated inclusion of file with __halt_compiler()
+    triggers "Constant already defined" warning). (ilutov)
+  . Partially fixed bug GH-19542 (Scanning of string literals >=2GB will fail
+    due to signed int overflow). (ilutov)
+  . Fixed bug GH-19544 (GC treats ZEND_WEAKREF_TAG_MAP references as WeakMap
+    references). (Arnaud, timwolla)
+  . Fixed bug GH-19613 (Stale array iterator pointer). (ilutov)
+  . Fixed bug GH-19679 (zend_ssa_range_widening may fail to converge). (Arnaud)
+  . Fixed bug GH-19681 (PHP_EXPAND_PATH broken with bash 5.3.0). (Remi)
+  . Fixed bug GH-19720 (Assertion failure when error handler throws when
+    accessing a deprecated constant). (nielsdos)
+
+- CLI:
+  . Fixed bug GH-19461 (Improve error message on listening error with IPv6
+    address). (alexandre-daubois)
+
+- Date:
+  . Fixed date_sunrise() and date_sunset() with partial-hour UTC offset.
+    (ilutov)
+
+- DBA:
+  . Fixed bug GH-19706 (dba stream resource mismanagement). (nielsdos)
+
+- DOM:
+  . Fixed bug GH-19612 (Mitigate libxml2 tree dictionary bug). (nielsdos)
+
+- FPM:
+  . Fixed failed debug assertion when php_admin_value setting fails. (ilutov)
+
+- Intl:
+  . Fixed bug GH-11952 (Fix locale strings canonicalization for IntlDateFormatter
+    and NumberFormatter). (alexandre-daubois)
+
+- Opcache:
+  . Fixed bug GH-19493 (JIT variable not stored before YIELD). (Arnaud)
+
+- OpenSSL:
+  . Fixed bug GH-19245 (Success error message on TLS stream accept failure).
+    (Jakub Zelenka)
+
+- PGSQL:
+  . Fixed bug GH-19485 (potential use after free when using persistent pgsql
+    connections). (Mark Karpeles)
+
+- Phar:
+  . Fixed memory leaks when verifying OpenSSL signature. (Girgias)
+  . Fix memory leak in phar tar temporary file error handling code. (nielsdos)
+  . Fix metadata leak when phar convert logic fails. (nielsdos)
+  . Fix memory leak on failure in phar_convert_to_other(). (nielsdos)
+  . Fixed bug GH-19752 (Phar decompression with invalid extension
+    can cause UAF). (nielsdos)
+
+- Standard:
+  . Fixed bug GH-16649 (UAF during array_splice). (alexandre-daubois)
+  . Fixed bug GH-19577 (Avoid integer overflow when using a small offset
+    and PHP_INT_MAX with LimitIterator). (alexandre-daubois)
+
+- Streams:
+  . Remove incorrect call to zval_ptr_dtor() in user_wrapper_metadata().
+    (nielsdos)
+  . Fix OSS-Fuzz #385993744. (nielsdos)
+
+- Zip:
+  . Fix memory leak in zip when encountering empty glob result. (nielsdos)
+
+28 Aug 2025, PHP 8.4.12
+
+- Core:
+  . Fixed GH-19169 build issue with C++17 and ZEND_STATIC_ASSERT macro.
+    (psumbera)
+  . Fixed bug GH-19053 (Duplicate property slot with hooks and interface
+    property). (ilutov)
+  . Fixed bug GH-19044 (Protected properties are not scoped according to their
+    prototype). (Bob)
+  . Fixed bug GH-18581 (Coerce numeric string keys from iterators when argument
+    unpacking). (ilutov)
+  . Fixed OSS-Fuzz #434346548 (Failed assertion with throwing __toString in
+    binary const expr). (ilutov)
+  . Fixed bug GH-19305 (Operands may be being released during comparison).
+    (Arnaud)
+  . Fixed bug GH-19303 (Unpacking empty packed array into uninitialized array
+    causes assertion failure). (nielsdos)
+  . Fixed bug GH-19306 (Generator can be resumed while fetching next value from
+    delegated Generator). (Arnaud)
+  . Fixed bug GH-19326 (Calling Generator::throw() on a running generator with
+    a non-Generator delegate crashes). (Arnaud)
+  . Fixed bug GH-19280 (Stale array iterator position on rehashing). (ilutov)
+  . Fixed bug GH-18736 (Circumvented type check with return by ref + finally).
+    (ilutov)
+  . Fixed bug GH-19065 (Long match statement can segfault compiler during
+    recursive SSA renaming). (nielsdos, Arnaud)
+
+- Calendar:
+  . Fixed bug GH-19371 (integer overflow in calendar.c). (nielsdos)
+
+- FTP:
+  . Fix theoretical issues with hrtime() not being available. (nielsdos)
+
+- GD:
+  . Fix incorrect comparison with result of php_stream_can_cast(). (Girgias)
+
+- Hash:
+  . Fix crash on clone failure. (nielsdos)
+
+- Intl:
+  . Fix memleak on failure in collator_get_sort_key(). (nielsdos)
+  . Fix return value on failure for resourcebundle count handler. (Girgias)
+
+- LDAP:
+  . Fixed bug GH-18529 (additional inheriting of TLS int options).
+    (Jakub Zelenka)
+
+- LibXML:
+  . Fixed bug GH-19098 (libxml<2.13 segmentation fault caused by
+    php_libxml_node_free). (nielsdos)
+
+- MbString:
+  . Fixed bug GH-19397 (mb_list_encodings() can cause crashes on shutdown).
+    (nielsdos)
+
+- Opcache:
+  . Reset global pointers to prevent use-after-free in zend_jit_status().
+    (Florian Engelhardt)
+  . Fix issue with JIT restart and hooks. (nielsdos)
+  . Fix crash with dynamic function defs in hooks during preload. (nielsdos)
+
+- OpenSSL:
+  . Fixed bug GH-18986 (OpenSSL backend: incorrect RAND_{load,write}_file()
+    return value check). (nielsdos, botovq)
+  . Fix error return check of EVP_CIPHER_CTX_ctrl(). (nielsdos)
+  . Fixed bug GH-19428 (openssl_pkey_derive segfaults for DH derive with low
+    key_length param). (Jakub Zelenka)
+
+- PDO Pgsql:
+  . Fixed dangling pointer access on _pdo_pgsql_trim_message helper.
+    (dixyes)
+
+- SOAP:
+  . Fixed bug GH-18640 (heap-use-after-free ext/soap/php_encoding.c:299:32
+    in soap_check_zval_ref). (nielsdos)
+
+- Sockets:
+  . Fix some potential crashes on incorrect argument value. (nielsdos)
+
+- Standard:
+  . Fixed OSS Fuzz #433303828 (Leak in failed unserialize() with opcache).
+    (ilutov)
+  . Fix theoretical issues with hrtime() not being available. (nielsdos)
+  . Fixed bug GH-19300 (Nested array_multisort invocation with error breaks).
+    (nielsdos)
+
+- Windows:
+ . Free opened_path when opened_path_len >= MAXPATHLEN. (dixyes)
+
+31 Jul 2025, PHP 8.4.11
+
+- Calendar:
+  . Fixed jewishtojd overflow on year argument. (David Carlier)
+
+- Core:
+  . Fixed bug GH-18833 (Use after free with weakmaps dependent on destruction
+    order). (Daniil Gentili)
+  . Fixed bug GH-18907 (Leak when creating cycle in hook). (ilutov)
+  . Fix OSS-Fuzz #427814456. (nielsdos)
+  . Fix OSS-Fuzz #428983568 and #428760800. (nielsdos)
+
+- Curl:
+  . Fix memory leaks when returning refcounted value from curl callback.
+    (nielsdos)
+  . Remove incorrect string release. (nielsdos)
+
+- DOM:
+  . Fixed bug GH-18979 (Dom\XMLDocument::createComment() triggers undefined
+    behavior with null byte). (nielsdos)
+
+- LDAP:
+  . Fixed GH-18902 ldap_exop/ldap_exop_sync assert triggered on empty
+    request OID. (David Carlier)
+
+- MbString:
+  . Fixed bug GH-18901 (integer overflow mb_split). (nielsdos)
+
+- Opcache:
+  . Fixed bug GH-18639 (Internal class aliases can break preloading + JIT).
+    (nielsdos)
+  . Fixed bug GH-18899 (JIT function crash when emitting undefined variable
+    warning and opline is not set yet). (nielsdos)
+  . Fixed bug GH-14082 (Segmentation fault on unknown address 0x600000000018
+    in ext/opcache/jit/zend_jit.c). (nielsdos)
+  . Fixed bug GH-18898 (SEGV zend_jit_op_array_hot with property hooks
+    and preloading). (nielsdos)
+
+- OpenSSL:
+  . Fixed bug #80770 (It is not possible to get client peer certificate with
+    stream_socket_server). (Jakub Zelenka)
+
+- PCNTL:
+  . Fixed bug GH-18958 (Fatal error during shutdown after pcntl_rfork() or
+    pcntl_forkx() with zend-max-execution-timers). (Arnaud)
+
+- Phar:
+  . Fix stream double free in phar. (nielsdos, dixyes)
+  . Fix phar crash and file corruption with SplFileObject. (nielsdos)
+
+- SOAP:
+  . Fixed bug GH-18990, bug #81029, bug #47314 (SOAP HTTP socket not closing
+    on object destruction). (nielsdos)
+  . Fix memory leak when URL parsing fails in redirect. (Girgias)
+
+- SPL:
+  . Fixed bug GH-19094 (Attaching class with no Iterator implementation to
+    MultipleIterator causes crash). (nielsdos)
+
+- Standard:
+  . Fix misleading errors in printf(). (nielsdos)
+  . Fix RCN violations in array functions. (nielsdos)
+  . Fixed GH-18976 pack() overflow with h/H format and INT_MAX repeater value.
+    (David Carlier)
+
+- Streams:
+  . Fixed GH-13264 (fgets() and stream_get_line() do not return false on filter
+    fatal error). (Jakub Zelenka)
+
+- Zip:
+  . Fix leak when path is too long in ZipArchive::extractTo(). (nielsdos)
+
+03 Jul 2025, PHP 8.4.10
+
+- BcMath:
+  . Fixed bug GH-18641 (Accessing a BcMath\Number property by ref crashes).
+    (nielsdos)
+
+- Core:
+  . Fixed bugs GH-17711 and GH-18022 (Infinite recursion on deprecated attribute
+    evaluation) and GH-18464 (Recursion protection for deprecation constants not
+    released on bailout). (DanielEScherzer and ilutov)
+  . Fixed GH-18695 (zend_ast_export() - float number is not preserved).
+    (Oleg Efimov)
+  . Fix handling of references in zval_try_get_long(). (nielsdos)
+  . Do not delete main chunk in zend_gc. (danog, Arnaud)
+  . Fix compile issues with zend_alloc and some non-default options. (nielsdos)
+
+- Curl:
+  . Fix memory leak when setting a list via curl_setopt fails. (nielsdos)
+
+- Date:
+  . Fix leaks with multiple calls to DatePeriod iterator current(). (nielsdos)
+
+- DOM:
+  . Fixed bug GH-18744 (classList works not correctly if copy HTMLElement by
+    clone keyword). (nielsdos)
+
+- FPM:
+  . Fixed GH-18662 (fpm_get_status segfault). (txuna)
+
+- Hash:
+  . Fixed bug GH-14551 (PGO build fails with xxhash). (nielsdos)
+
+- Intl:
+  . Fix memory leak in intl_datetime_decompose() on failure. (nielsdos)
+  . Fix memory leak in locale lookup on failure. (nielsdos)
+
+- Opcache:
+  . Fixed bug GH-18743 (Incompatibility in Inline TLS Assembly on Alpine 3.22).
+    (nielsdos, Arnaud)
+
+- ODBC:
+  . Fix memory leak on php_odbc_fetch_hash() failure. (nielsdos)
+
+- OpenSSL:
+  . Fix memory leak of X509_STORE in php_openssl_setup_verify() on failure.
+    (nielsdos)
+  . Fixed bug #74796 (Requests through http proxy set peer name).
+    (Jakub Zelenka)
+
+- PDO ODBC:
+  . Fix memory leak if WideCharToMultiByte() fails. (nielsdos)
+
+- PDO Sqlite:
+  . Fixed memory leak with Pdo_Sqlite::createCollation when the callback
+    has an incorrect return type. (David Carlier)
+
+- Phar:
+  . Add missing filter cleanups on phar failure. (nielsdos)
+  . Fixed bug GH-18642 (Signed integer overflow in ext/phar fseek). (nielsdos)
+
+- PHPDBG:
+  . Fix 'phpdbg --help' segfault on shutdown with USE_ZEND_ALLOC=0. (nielsdos)
+
+- PGSQL:
+  . Fix warning not being emitted when failure to cancel a query with
+    pg_cancel_query(). (Girgias)
+
+- Random:
+  . Fix reference type confusion and leak in user random engine.
+    (nielsdos, timwolla)
+
+- Readline:
+  . Fix memory leak when calloc() fails in php_readline_completion_cb().
+    (nielsdos)
+
+- SimpleXML:
+  . Fixed bug GH-18597 (Heap-buffer-overflow in zend_alloc.c when assigning
+    string with UTF-8 bytes). (nielsdos)
+
+- Soap:
+  . Fix memory leaks in php_http.c when call_user_function() fails. (nielsdos)
+
+- Tidy:
+  . Fix memory leak in tidy output handler on error. (nielsdos)
+  . Fix tidyOptIsReadonly deprecation, using tidyOptGetCategory. (David Carlier)
+
+06 Jun 2025, PHP 8.4.8
+
+- Core:
+  . Fixed GH-18480 (array_splice with large values for offset/length arguments).
+    (nielsdos/David Carlier)
+  . Partially fixed GH-18572 (nested object comparisons leading to stack overflow).
+    (David Carlier)
+  . Fixed OSS-Fuzz #417078295. (nielsdos)
+  . Fixed OSS-Fuzz #418106144. (nielsdos)
+
+- Curl:
+  . Fixed GH-18460 (curl_easy_setopt with CURLOPT_USERPWD/CURLOPT_USERNAME/
+    CURLOPT_PASSWORD set the Authorization header when set to NULL).
+    (David Carlier)
+
+- Date:
+  . Fixed bug GH-18076 (Since PHP 8, the date_sun_info() function returns
+    inaccurate sunrise and sunset times, but other calculated times are
+    correct) (JiriJozif).
+  . Fixed bug GH-18481 (date_sunrise with unexpected nan value for the offset).
+    (nielsdos/David Carlier)
+
+- DOM:
+  . Backport lexbor/lexbor#274. (nielsdos, alexpeattie)
+
+- Intl:
+  . Fix various reference issues. (nielsdos)
+
+- LDAP:
+  . Fixed bug GH-18529 (ldap no longer respects TLS_CACERT from ldaprc in
+    ldap_start_tls()). (Remi)
+
+- Opcache:
+  . Fixed bug GH-18417 (Windows SHM reattachment fails when increasing
+    memory_consumption or jit_buffer_size). (nielsdos)
+  . Fixed bug GH-18297 (Exception not handled when jit guard is triggered).
+    (Arnaud)
+  . Fixed bug GH-18408 (Snapshotted poly_func / poly_this may be spilled).
+    (Arnaud)
+  . Fixed bug GH-18567 (Preloading with internal class alias triggers assertion
+    failure). (nielsdos)
+  . Fixed bug GH-18534 (FPM exit code 70 with enabled opcache and hooked
+    properties in traits). (nielsdos)
+  . Fix leak of accel_globals->key. (nielsdos)
+
+- OpenSSL:
+  . Fix missing checks against php_set_blocking() in xp_ssl.c. (nielsdos)
+
+- SPL:
+  . Fixed bug GH-18421 (Integer overflow with large numbers in LimitIterator).
+    (nielsdos)
+
+- Standard:
+  . Fixed bug GH-17403 (Potential deadlock when putenv fails). (nielsdos)
+  . Fixed bug GH-18400 (http_build_query type error is inaccurate). (nielsdos)
+  . Fixed bug GH-18509 (Dynamic calls to assert() ignore zend.assertions).
+    (timwolla)
+
+- Windows:
+  . Fix leak+crash with sapi_windows_set_ctrl_handler(). (nielsdos)
+
+- Zip:
+  . Fixed bug GH-18431 (Registering ZIP progress callback twice doesn't work).
+    (nielsdos)
+  . Fixed bug GH-18438 (Handling of empty data and errors in
+    ZipArchive::addPattern). (nielsdos)
+
+24 Apr 2025, PHP 8.4.7
+
+- Core:
+  . Fixed bug GH-18038 (Lazy proxy calls magic methods twice). (Arnaud)
+  . Fixed bug GH-18209 (Use-after-free in extract() with EXTR_REFS). (ilutov)
+  . Fixed bug GH-18268 (Segfault in array_walk() on object with added property
+    hooks). (ilutov)
+  . Fixed bug GH-18304 (Changing the properties of a DateInterval through
+    dynamic properties triggers a SegFault). (nielsdos)
+  . Fix some leaks in php_scandir. (nielsdos)
+
+- DBA:
+  . FIxed bug GH-18247 dba_popen() memory leak on invalid path. (David Carlier)
+
+- Filter:
+  . Fixed bug GH-18309 (ipv6 filter integer overflow). (nielsdos)
+
+- GD:
+  . Fixed imagecrop() overflow with rect argument with x/width y/heigh usage
+    in gdImageCrop(). (David Carlier)
+  . Fixed GH-18243 imagettftext() overflow/underflow on font size value.
+    (David Carlier)
+
+- Intl:
+  . Fix reference support for intltz_get_offset(). (nielsdos)
+
+- LDAP:
+  . Fixed bug GH-17776 (LDAP_OPT_X_TLS_* options can't be overridden). (Remi)
+  . Fix NULL deref on high modification key. (nielsdos)
+
+- libxml:
+  . Fixed custom external entity loader returning an invalid resource leading
+    to a confusing TypeError message. (Girgias)
+
+- Opcache:
+  . Fixed bug GH-18294 (assertion failure zend_jit_ir.c). (nielsdos)
+  . Fixed bug GH-18289 (Fix segfault in JIT). (Florian Engelhardt)
+  . Fixed bug GH-18136 (tracing JIT floating point register clobbering on
+    Windows and ARM64). (nielsdos)
+
+- OpenSSL:
+  . Fix memory leak in openssl_sign() when passing invalid algorithm.
+    (nielsdos)
+  . Fix potential leaks when writing to BIO fails. (nielsdos)
+
+- PDO Firebird:
+  . Fixed bug GH-18276 (persistent connection - "zend_mm_heap corrupted"
+    with setAttribute()) (SakiTakamachi).
+  . Fixed bug GH-17383 (PDOException has wrong code and message since PHP 8.4)
+    (SakiTakamachi).
+
+- PDO Sqlite:
+  . Fix memory leak on error return of collation callback. (nielsdos)
+
+- PgSql:
+  . Fix uouv in pg_put_copy_end(). (nielsdos)
+
+- SPL:
+  . Fixed bug GH-18322 (SplObjectStorage debug handler mismanages memory).
+    (nielsdos)
+
+- Standard:
+  . Fixed bug GH-18145 (php8ts crashes in php_clear_stat_cache()).
+    (Jakub Zelenka)
+  . Fix resource leak in iptcembed() on error. (nielsdos)
+
+- Tests:
+  . Address deprecated PHP 8.4 session options to prevent test failures.
+    (willvar)
+
+- Zip:
+  . Fix uouv when handling empty options in ZipArchive::addGlob(). (nielsdos)
+  . Fix memory leak when handling a too long path in ZipArchive::addGlob().
+    (nielsdos)
+
+10 Apr 2025, PHP 8.4.6
+
+- BCMath:
+  . Fixed pointer subtraction for scale. (SakiTakamachi)
+
+- Core:
+  . Fixed property hook backing value access in multi-level inheritance.
+    (ilutov)
+  . Fixed accidentally inherited default value in overridden virtual properties.
+    (ilutov)
+  . Fixed bug GH-17376 (Broken JIT polymorphism for property hooks added to
+    child class). (ilutov)
+  . Fixed bug GH-17913 (ReflectionFunction::isDeprecated() returns incorrect
+    results for closures created from magic __call()). (timwolla)
+  . Fixed bug GH-17941 (Stack-use-after-return with lazy objects and hooks).
+    (nielsdos)
+  . Fixed bug GH-17988 (Incorrect handling of hooked props without get hook in
+    get_object_vars()). (ilutov)
+  . Fixed bug GH-17998 (Skipped lazy object initialization on primed
+    SIMPLE_WRITE cache). (ilutov)
+  . Fixed bug GH-17998 (Assignment to backing value in set hook of lazy proxy
+    calls hook again). (ilutov)
+  . Fixed bug GH-17961 (use-after-free during dl()'ed module class destruction).
+    (Arnaud)
+  . Fixed bug GH-15367 (dl() of module with aliased class crashes in shutdown).
+    (Arnaud)
+  . Fixed OSS-Fuzz #403308724. (nielsdos)
+  . Fixed bug GH-13193 again (Significant performance degradation in 'foreach').
+    (nielsdos)
+
+- DBA:
+  . Fixed assertion violation when opening the same file with dba_open
+    multiple times. (chschneider)
+
+- DOM:
+  . Fixed bug GH-17991 (Assertion failure dom_attr_value_write). (nielsdos)
+  . Fix weird unpack behaviour in DOM. (nielsdos)
+  . Fixed bug GH-18090 (DOM: Svg attributes and tag names are being lowercased).
+    (nielsdos)
+  . Fix xinclude destruction of live attributes. (nielsdos)
+
+- Fuzzer:
+  . Fixed bug GH-18081 (Memory leaks in error paths of fuzzer SAPI).
+    (Lung-Alexandra)
+
+- GD:
+  . Fixed bug GH-17984 (calls with arguments as array with references).
+    (David Carlier)
+
+- LDAP:
+  . Fixed bug GH-18015 (Error messages for ldap_mod_replace are confusing).
+    (nielsdos)
+
+- Mbstring:
+  . Fixed bug GH-17989 (mb_output_handler crash with unset
+    http_output_conv_mimetypes). (nielsdos)
+
+- Opcache:
+  . Fixed bug GH-15834 (Segfault with hook "simple get" cache slot and minimal
+    JIT). (nielsdos)
+  . Fixed bug GH-17966 (Symfony JIT 1205 assertion failure). (nielsdos)
+  . Fixed bug GH-18037 (SEGV Zend/zend_execute.c). (nielsdos)
+  . Fixed bug GH-18050 (IN_ARRAY optimization in DFA pass is broken). (ilutov)
+  . Fixed bug GH-18113 (stack-buffer-overflow ext/opcache/jit/ir/ir_sccp.c).
+    (nielsdos)
+  . Fixed bug GH-18112 (NULL access with preloading and INI option). (nielsdos)
+  . Fixed bug GH-18107 (Opcache CFG jmp optimization with try-finally breaks
+    the exception table). (nielsdos)
+
+- PDO:
+  . Fix memory leak when destroying PDORow. (nielsdos)
+
+- PGSQL:
+  . Fixed bug GH-18148 (pg_copy_from() regression with explicit \n terminator
+    due to wrong offset check). (David Carlier)
+
+- Standard:
+  . Fix memory leaks in array_any() / array_all(). (nielsdos)
+
+- SOAP:
+  . Fixed bug #66049 (Typemap can break parsing in parse_packet_soap leading to
+    a segfault) . (Remi)
+
+- SPL:
+  . Fixed bug GH-18018 (RC1 data returned from offsetGet causes UAF in
+    ArrayObject). (nielsdos)
+
+- Treewide:
+  . Fixed bug GH-17736 (Assertion failure zend_reference_destroy()). (nielsdos)
+
+- Windows:
+  . Fixed bug GH-17836 (zend_vm_gen.php shouldn't break on Windows line
+    endings). (DanielEScherzer)
+
+27 Feb 2025, PHP 8.4.5
+
+- BCMath:
+  . Fixed bug GH-17398 (bcmul memory leak). (SakiTakamachi)
+
+- Core:
+  . Fixed bug GH-17623 (Broken stack overflow detection for variable
+    compilation). (ilutov)
+  . Fixed bug GH-17618 (UnhandledMatchError does not take
+    zend.exception_ignore_args=1 into account). (timwolla)
+  . Fix fallback paths in fast_long_{add,sub}_function. (nielsdos)
+  . Fixed bug OSS-Fuzz #391975641 (Crash when accessing property backing value
+    by reference). (ilutov)
+  . Fixed bug GH-17718 (Calling static methods on an interface that has
+    `__callStatic` is allowed). (timwolla)
+  . Fixed bug GH-17713 (ReflectionProperty::getRawValue() and related methods
+    may call hooks of overridden properties). (Arnaud)
+  . Fixed bug GH-17916 (Final abstract properties should error).
+    (DanielEScherzer)
+  . Fixed bug GH-17866 (zend_mm_heap corrupted error after upgrading from
+    8.4.3 to 8.4.4). (nielsdos)
+  . Fixed GHSA-rwp7-7vc6-8477 (Reference counting in php_request_shutdown
+    causes Use-After-Free). (CVE-2024-11235) (ilutov)
+
+- DOM:
+  . Fixed bug GH-17609 (Typo in error message: Dom\NO_DEFAULT_NS instead of
+    Dom\HTML_NO_DEFAULT_NS). (nielsdos)
+  . Fixed bug GH-17802 (\Dom\HTMLDocument querySelector attribute name is case
+    sensitive in HTML). (nielsdos)
+  . Fixed bug GH-17847 (xinclude destroys live node). (nielsdos)
+  . Fix using Dom\Node with Dom\XPath callbacks. (nielsdos)
+
+- FFI:
+  . Fix FFI Parsing of Pointer Declaration Lists. (davnotdev)
+
+- FPM:
+  . Fixed bug GH-17643 (FPM with httpd ProxyPass encoded PATH_INFO env).
+    (Jakub Zelenka)
+
+- GD:
+  . Fixed bug GH-17703 (imagescale with both width and height negative values
+    triggers only an Exception on width). (David Carlier)
+  . Fixed bug GH-17772 (imagepalettetotruecolor crash with memory_limit=2M).
+    (David Carlier)
+
+- LDAP:
+  . Fixed bug GH-17704 (ldap_search fails when $attributes contains a
+    non-packed array with numerical keys). (nielsdos, 7u83)
+
+- LibXML:
+  . Fixed GHSA-wg4p-4hqh-c3g9 (Reocurrence of #72714). (nielsdos)
+  . Fixed GHSA-p3x9-6h7p-cgfc (libxml streams use wrong `content-type` header
+    when requesting a redirected resource). (CVE-2025-1219) (timwolla)
+
+- MBString:
+  . Fixed bug GH-17503 (Undefined float conversion in mb_convert_variables).
+    (cmb)
+
+- Opcache:
+  . Fixed bug GH-17654 (Multiple classes using same trait causes function
+    JIT crash). (nielsdos)
+  . Fixed bug GH-17577 (JIT packed type guard crash). (nielsdos, Dmitry)
+  . Fixed bug GH-17747 (Exception on reading property in register-based
+    FETCH_OBJ_R breaks JIT). (Dmitry, nielsdos)
+  . Fixed bug GH-17715 (Null pointer deref in observer API when calling
+    cases() method on preloaded enum). (Bob)
+  . Fixed bug GH-17868 (Cannot allocate memory with tracing JIT on 8.4.4).
+    (nielsdos)
+
+- PDO_SQLite:
+  . Fixed GH-17837 ()::getColumnMeta() on unexecuted statement segfaults).
+    (cmb)
+  . Fix cycle leak in sqlite3 setAuthorizer(). (nielsdos)
+  . Fix memory leaks in pdo_sqlite callback registration. (nielsdos)
+
+- Phar:
+  . Fixed bug GH-17808: PharFileInfo refcount bug. (nielsdos)
+
+- PHPDBG:
+  . Partially fixed bug GH-17387 (Trivial crash in phpdbg lexer). (nielsdos)
+  . Fix memory leak in phpdbg calling registered function. (nielsdos)
+
+- Reflection:
+  . Fixed bug GH-15902 (Core dumped in ext/reflection/php_reflection.c).
+    (DanielEScherzer)
+  . Fixed missing final and abstract flags when dumping properties.
+    (DanielEScherzer)
+
+- Standard:
+  . Fixed bug #72666 (stat cache clearing inconsistent between file:// paths
+    and plain paths). (Jakub Zelenka)
+
+- Streams:
+  . Fixed bug GH-17650 (realloc with size 0 in user_filters.c). (nielsdos)
+  . Fix memory leak on overflow in _php_stream_scandir(). (nielsdos)
+  . Fixed GHSA-hgf5-96fm-v528 (Stream HTTP wrapper header check might omit
+    basic auth header). (CVE-2025-1736) (Jakub Zelenka)
+  . Fixed GHSA-52jp-hrpf-2jff (Stream HTTP wrapper truncate redirect location
+    to 1024 bytes). (CVE-2025-1861) (Jakub Zelenka)
+  . Fixed GHSA-pcmh-g36c-qc44 (Streams HTTP wrapper does not fail for headers
+    without colon). (CVE-2025-1734) (Jakub Zelenka)
+  . Fixed GHSA-v8xr-gpvj-cx9g (Header parser of `http` stream wrapper does not
+    handle folded headers). (CVE-2025-1217) (Jakub Zelenka)
+
+- Windows:
+  . Fixed phpize for Windows 11 (24H2). (bwoebi)
+  . Fixed GH-17855 (CURL_STATICLIB flag set even if linked with shared lib).
+    (cmb)
+
+- Zlib:
+  . Fixed bug GH-17745 (zlib extension incorrectly handles object arguments).
+    (nielsdos)
+  . Fix memory leak when encoding check fails. (nielsdos)
+  . Fix zlib support for large files. (nielsdos)
+
+13 Feb 2025, PHP 8.4.4
+
+- Core:
+  . Fixed bug GH-17234 (Numeric parent hook call fails with assertion).
+    (nielsdos)
+  . Fixed bug GH-16892 (ini_parse_quantity() fails to parse inputs starting
+    with 0x0b). (nielsdos)
+  . Fixed bug GH-16886 (ini_parse_quantity() fails to emit warning for 0x+0).
+    (nielsdos)
+  . Fixed bug GH-17222 (__PROPERTY__ magic constant does not work in all
+    constant expression contexts). (ilutov)
+  . Fixed bug GH-17214 (Relax final+private warning for trait methods with
+    inherited final). (ilutov)
+  . Fixed NULL arithmetic during system program execution on Windows. (cmb,
+    nielsdos)
+  . Fixed potential OOB when checking for trailing spaces on Windows. (cmb)
+  . Fixed bug GH-17408 (Assertion failure Zend/zend_exceptions.c).
+    (nielsdos, ilutov)
+  . Fix may_have_extra_named_args flag for ZEND_AST_UNPACK. (nielsdos)
+  . Fix NULL arithmetic in System V shared memory emulation for Windows. (cmb)
+  . Fixed bug GH-17597 (#[\Deprecated] does not work for __call() and
+    __callStatic()). (timwolla)
+
+- DOM:
+  . Fixed bug GH-17397 (Assertion failure ext/dom/php_dom.c). (nielsdos)
+  . Fixed bug GH-17486 (Incorrect error line numbers reported in
+    Dom\HTMLDocument::createFromString). (nielsdos)
+  . Fixed bug GH-17481 (UTF-8 corruption in \Dom\HTMLDocument). (nielsdos)
+  . Fixed bug GH-17500 (Segfault with requesting nodeName on nameless doctype).
+    (nielsdos)
+  . Fixed bug GH-17485 (upstream fix, Self-closing tag on void elements
+    shouldn't be a parse error/warning in \Dom\HTMLDocument). (lexborisov)
+  . Fixed bug GH-17572 (getElementsByTagName returns collections with
+    tagName-based indexing). (nielsdos)
+
+- Enchant:
+  . Fix crashes in enchant when passing null bytes. (nielsdos)
+
+- FTP:
+  . Fixed bug GH-16800 (ftp functions can abort with EINTR). (nielsdos)
+
+- GD:
+  . Fixed bug GH-17349 (Tiled truecolor filling looses single color
+    transparency). (cmb)
+  . Fixed bug GH-17373 (imagefttext() ignores clipping rect for palette
+    images). (cmb)
+  . Ported fix for libgd 223 (gdImageRotateGeneric() does not properly
+    interpolate). (cmb)
+  . Added support for reading GIFs without colormap to bundled libgd. (Andrew
+    Burley, cmb)
+
+- Gettext:
+  . Fixed bug GH-17400 (bindtextdomain SEGV on invalid domain).
+    (David Carlier)
+
+- Intl:
+  . Fixed bug GH-11874 (intl causing segfault in docker images). (nielsdos)
+
+- Opcache:
+  . Fixed bug GH-15981 (Segfault with frameless jumps and minimal JIT).
+    (nielsdos)
+  . Fixed bug GH-17307 (Internal closure causes JIT failure). (nielsdos)
+  . Fixed bug GH-17428 (Assertion failure ext/opcache/jit/zend_jit_ir.c:8940).
+    (nielsdos)
+  . Fixed bug GH-17564 (Potential UB when reading from / writing to struct
+    padding). (ilutov)
+
+- PCNTL:
+  . Fixed pcntl_setcpuaffinity exception type from ValueError to TypeError for
+    the cpu mask argument with entries type different than int/string.
+    (David Carlier)
+
+- PCRE:
+  . Fixed bug GH-17122 (memory leak in regex). (nielsdos)
+
+- PDO:
+  . Fixed a memory leak when the GC is used to free a PDOStatment. (Girgias)
+  . Fixed a crash in the PDO Firebird Statement destructor. (nielsdos)
+  . Fixed UAFs when changing default fetch class ctor args. (Girgias, nielsdos)
+
+- PgSql:
+  . Fixed build failure when the constant PGRES_TUPLES_CHUNK is not present
+    in the system. (chschneider)
+
+- Phar:
+  . Fixed bug GH-17518 (offset overflow phar extractTo()). (nielsdos)
+
+- PHPDBG:
+  . Fix crashes in function registration + test. (nielsdos, Girgias)
+
+- Session:
+  . Fix type confusion with session SID constant. (nielsdos)
+  . Fixed bug GH-17541 (ext/session NULL pointer dereferencement during
+    ID reset). (Girgias)
+
+- SimpleXML:
+  . Fixed bug GH-17409 (Assertion failure Zend/zend_hash.c:1730). (nielsdos)
+
+- SNMP:
+  . Fixed bug GH-17330 (SNMP::setSecurity segfault on closed session).
+    (David Carlier)
+
+- SPL:
+  . Fixed bug GH-15833 (Segmentation fault (access null pointer) in
+    ext/spl/spl_array.c). (nielsdos)
+  . Fixed bug GH-17516 (SplFileTempObject::getPathInfo() Undefined behavior
+    on invalid class). (David Carlier)
+
+- Standard:
+  . Fixed bug GH-17447 (Assertion failure when array popping a self addressing
+    variable). (nielsdos)
+
+- Windows:
+  . Fixed clang compiler detection. (cmb)
+
+- Zip:
+  . Fixed bug GH-17139 (Fix zip_entry_name() crash on invalid entry).
+    (nielsdos)
+
+16 Jan 2025, PHP 8.4.3
+
+- BcMath:
+  . Fixed bug GH-17049 (Correctly compare 0 and -0). (Saki Takamachi)
+  . Fixed bug GH-17061 (Now Number::round() does not remove trailing zeros).
+    (Saki Takamachi)
+  . Fixed bug GH-17064 (Correctly round rounding mode with zero edge case).
+    (Saki Takamachi)
+  . Fixed bug GH-17275 (Fixed the calculation logic of dividend scale).
+    (Saki Takamachi)
+
+- Core:
+  . Fixed bug OSS-Fuzz #382922236 (Duplicate dynamic properties in hooked object
+    iterator properties table). (ilutov)
+  . Fixed unstable get_iterator pointer for hooked classes in shm on Windows.
+    (ilutov)
+  . Fixed bug GH-17106 (ZEND_MATCH_ERROR misoptimization). (ilutov)
+  . Fixed bug GH-17162 (zend_array_try_init() with dtor can cause engine UAF).
+    (nielsdos)
+  . Fixed bug GH-17101 (AST->string does not reproduce constructor property
+    promotion correctly). (nielsdos)
+  . Fixed bug GH-17200 (Incorrect dynamic prop offset in hooked prop iterator).
+    (ilutov)
+  . Fixed bug GH-17216 (Trampoline crash on error). (nielsdos)
+
+- DBA:
+  . Skip test if inifile is disabled. (orlitzky)
+
+- DOM:
+  . Fixed bug GH-17145 (DOM memory leak). (nielsdos)
+  . Fixed bug GH-17201 (Dom\TokenList issues with interned string replace).
+    (nielsdos)
+  . Fixed bug GH-17224 (UAF in importNode). (nielsdos)
+
+- Embed:
+  . Make build command for program using embed portable. (dunglas)
+
+- FFI:
+  . Fixed bug #79075 (FFI header parser chokes on comments). (nielsdos)
+  . Fix memory leak on ZEND_FFI_TYPE_CHAR conversion failure. (nielsdos)
+  . Fixed bug GH-16013 and bug #80857 (Big endian issues). (Dmitry, nielsdos)
+
+- Fileinfo:
+  . Fixed bug GH-17039 (PHP 8.4: Incorrect MIME content type). (nielsdos)
+
+- FPM:
+  . Fixed bug GH-13437 (FPM: ERROR: scoreboard: failed to lock (already
+    locked)). (Jakub Zelenka)
+  . Fixed bug GH-17112 (Macro redefinitions). (cmb, nielsdos)
+  . Fixed bug GH-17208 (bug64539-status-json-encoding.phpt fail on 32-bits).
+    (nielsdos)
+
+- GD:
+  . Fixed bug GH-16255 (Unexpected nan value in ext/gd/libgd/gd_filter.c).
+    (nielsdos, cmb)
+  . Ported fix for libgd bug 276 (Sometimes pixels are missing when storing
+    images as BMPs). (cmb)
+
+- Gettext:
+  . Fixed bug GH-17202 (Segmentation fault ext/gettext/gettext.c
+    bindtextdomain()). (Michael Orlitzky)
+
+- Iconv:
+  . Fixed bug GH-17047 (UAF on iconv filter failure). (nielsdos)
+
+- LDAP:
+  . Fixed bug GH-17280 (ldap_search() fails when $attributes array has holes).
+    (nielsdos)
+
+- LibXML:
+  . Fixed bug GH-17223 (Memory leak in libxml encoding handling). (nielsdos)
+
+- MBString:
+  . Fixed bug GH-17112 (Macro redefinitions). (nielsdos, cmb)
+
+- Opcache:
+  . opcache_get_configuration() properly reports jit_prof_threshold. (cmb)
+  . Fixed bug GH-17140 (Assertion failure in JIT trace exit with
+    ZEND_FETCH_DIM_FUNC_ARG). (nielsdos, Dmitry)
+  . Fixed bug GH-17151 (Incorrect RC inference of op1 of FETCH_OBJ and
+    INIT_METHOD_CALL). (Dmitry, ilutov)
+  . Fixed bug GH-17246 (GC during SCCP causes segfault). (Dmitry)
+  . Fixed bug GH-17257 (UBSAN warning in ext/opcache/jit/zend_jit_vm_helpers.c).
+    (nielsdos, Dmitry)
+
+- PCNTL:
+  . Fix memory leak in cleanup code of pcntl_exec() when a non stringable
+    value is encountered past the first entry. (Girgias)
+
+- PgSql:
+  . Fixed bug GH-17158 (pg_fetch_result Shows Incorrect ArgumentCountError
+    Message when Called With 1 Argument). (nielsdos)
+  . Fixed further ArgumentCountError for calls with flexible
+    number of arguments. (David Carlier)
+
+- Phar:
+  . Fixed bug GH-17137 (Segmentation fault ext/phar/phar.c). (nielsdos)
+
+- SimpleXML:
+  . Fixed bug GH-17040 (SimpleXML's unset can break DOM objects). (nielsdos)
+  . Fixed bug GH-17153 (SimpleXML crash when using autovivification on
+    document). (nielsdos)
+
+- Sockets:
+  . Fixed bug GH-16276 (socket_strerror overflow handling with INT_MIN).
+    (David Carlier / cmb)
+  . Fixed overflow on SO_LINGER values setting, strengthening values check
+    on SO_SNDTIMEO/SO_RCVTIMEO for socket_set_option().
+    (David Carlier)
+
+- SPL:
+  . Fixed bug GH-17198 (SplFixedArray assertion failure with get_object_vars).
+    (nielsdos)
+  . Fixed bug GH-17225 (NULL deref in spl_directory.c). (nielsdos)
+
+- Streams:
+  . Fixed bug GH-17037 (UAF in user filter when adding existing filter name due
+    to incorrect error handling). (nielsdos)
+  . Fixed bug GH-16810 (overflow on fopen HTTP wrapper timeout value).
+    (David Carlier)
+  . Fixed bug GH-17067 (glob:// wrapper doesn't cater to CWD for ZTS builds).
+    (cmb)
+
+- Windows:
+  . Hardened proc_open() against cmd.exe hijacking. (cmb)
+
+- XML:
+  . Fixed bug GH-1718 (unreachable program point in zend_hash). (nielsdos)
+
+19 Dec 2024, PHP 8.4.2
+
+- BcMath:
+  . Fixed bug GH-16978 (Avoid unnecessary padding with leading zeros).
+    (Saki Takamachi)
+
+- COM:
+  . Fixed bug GH-16991 (Getting typeinfo of non DISPATCH variant segfaults).
+    (cmb)
+
+- Core:
+  . Fixed bug GH-16344 (setRawValueWithoutLazyInitialization() and
+    skipLazyInitialization() may change initialized proxy). (Arnaud)
+  . Fix is_zend_ptr() huge block comparison. (nielsdos)
+  . Fixed potential OOB read in zend_dirname() on Windows. (cmb)
+  . Fixed bug GH-15964 (printf() can strip sign of -INF). (divinity76, cmb)
+
+- Curl:
+  . Fix various memory leaks in curl mime handling. (nielsdos)
+
+- DBA:
+  . Fixed bug GH-16990 (dba_list() is now zero-indexed instead of using
+    resource ids) (kocsismate)
+
+- DOM:
+  . Fixed bug GH-16906 (Reloading document can cause UAF in iterator).
+    (nielsdos)
+
+- FPM:
+  . Fixed bug GH-16932 (wrong FPM status output). (Jakub Zelenka, James Lucas)
+
+- GMP:
+  . Fixed bug GH-16890 (array_sum() with GMP can loose precision (LLP64)).
+    (cmb)
+
+- Opcache:
+  . Fixed bug GH-16851 (JIT_G(enabled) not set correctly on other threads).
+    (dktapps)
+  . Fixed bug GH-16902 (Set of opcache tests fail zts+aarch64). (nielsdos)
+  . Fixed bug GH-16879 (JIT dead code skipping does not update call_level).
+    (nielsdos)
+
+- SAPI:
+  . Fixed bug GH-16998 (UBSAN warning in rfc1867). (nielsdos)
+
+- PHPDBG:
+  . Fixed bug GH-15208 (Segfault with breakpoint map and phpdbg_clear()).
+    (nielsdos)
+
+- Standard:
+  . Fixed bug GH-16905 (Internal iterator functions can't handle UNDEF
+    properties). (nielsdos)
+  . Fixed bug GH-16957 (Assertion failure in array_shift with
+    self-referencing array). (nielsdos)
+
+- Streams:
+  . Fixed network connect poll interuption handling. (Jakub Zelenka)
+
+- Windows:
+  . Fixed bug GH-16849 (Error dialog causes process to hang). (cmb)
+  . Windows Server 2025 is now properly reported. (cmb)
+
+21 Nov 2024, PHP 8.4.1
+
+- BcMath:
+  . [RFC] Add bcfloor, bcceil and bcround to BCMath. (Saki Takamachi)
+  . Improve performance. (Saki Takamachi, nielsdos)
+  . Adjust bcround()'s $mode parameter to only accept the RoundingMode
+    enum. (timwolla, saki)
+  . Fixed LONG_MAX in BCMath ext. (Saki Takamachi)
+  . Fixed bcdiv() div by one. (Saki Takamachi)
+  . [RFC] Support object types in BCMath. (Saki Takamachi)
+  . bcpow() performance improvement. (Jorg Sowa)
+  . ext/bcmath: Check for scale overflow. (SakiTakamachi)
+  . [RFC] ext/bcmath: Added bcdivmod. (SakiTakamachi)
+  . Fix GH-15968 (Avoid converting objects to strings in operator calculations).
+    (SakiTakamachi)
+  . Fixed bug GH-16265 (Added early return case when result is 0)
+    (Saki Takamachi).
+  . Fixed bug GH-16262 (Fixed a bug where size_t underflows) (Saki Takamachi).
+  . Fixed GH-16236 (Fixed a bug in BcMath\Number::pow() and bcpow() when
+    raising negative powers of 0) (Saki Takamachi).
+
+- Core:
+  . Added zend_call_stack_get implementation for NetBSD, DragonFlyBSD,
+    Solaris and Haiku. (David Carlier)
+  . Enabled ifunc checks on FreeBSD from the 12.x releases. (Freaky)
+  . Changed the type of PHP_DEBUG and PHP_ZTS constants to bool. (haszi)
+  . Fixed bug GH-13142 (Undefined variable name is shortened when contains \0).
+    (nielsdos)
+  . Fixed bug GH-13178 (Iterator positions incorrect when converting packed
+    array to hashed). (ilutov)
+  . Fixed zend fiber build for solaris default mode (32 bits). (David Carlier)
+  . Fixed zend call stack size for macOs/arm64. (David Carlier)
+  . Added support for Zend Max Execution Timers on FreeBSD. (Kévin Dunglas)
+  . Ensure fiber stack is not backed by THP. (crrodriguez)
+  . Implement GH-13609 (Dump wrapped object in WeakReference class). (nielsdos)
+  . Added sparc64 arch assembly support for zend fiber. (Claudio Jeker)
+  . Fixed GH-13581 no space available for TLS on NetBSD. (Paul Ripke)
+  . Added fiber Sys-V loongarch64 support. (qiangxuhui)
+  . Adjusted closure names to include the parent function's name. (timwolla)
+  . Improve randomness of uploaded file names and files created by tempnam().
+    (Arnaud)
+  . Added gc and shutdown callbacks to zend_mm custom handlers.
+    (Florian Engelhardt)
+  . Fixed bug GH-14650 (Compute the size of pages before allocating memory).
+    (Julien Voisin)
+  . Fixed bug GH-11928 (The --enable-re2c-cgoto doesn't add the -g flag).
+    (Peter Kokot)
+  . Added the #[\Deprecated] attribute. (beberlei, timwolla)
+  . Fixed GH-11389 (Allow suspending fibers in destructors). (Arnaud, trowski)
+  . Fixed bug GH-14801 (Fix build for armv7). (andypost)
+  . Implemented property hooks RFC. (ilutov)
+  . Fix GH-14978 (The xmlreader extension phpize build). (Peter Kokot)
+  . Throw Error exception when encountering recursion during comparison, rather
+    than fatal error. (ilutov)
+  . Added missing cstddef include for C++ builds. (cmb)
+  . Updated build system scripts config.guess to 2024-07-27 and config.sub to
+    2024-05-27. (Peter Kokot)
+  . Fixed bug GH-15240 (Infinite recursion in trait hook). (ilutov)
+  . Fixed bug GH-15140 (Missing variance check for abstract set with asymmetric
+    type). (ilutov)
+  . Fixed bug GH-15181 (Disabled output handler is flushed again). (cmb)
+  . Passing E_USER_ERROR to trigger_error() is now deprecated. (Girgias)
+  . Fixed bug GH-15292 (Dynamic AVX detection is broken for MSVC). (nielsdos)
+  . Using "_" as a class name is now deprecated. (Girgias)
+  . Exiting a namespace now clears seen symbols. (ilutov)
+  . The exit (and die) language constructs now behave more like a function.
+    They can be passed liked callables, are affected by the strict_types
+    declare statement, and now perform the usual type coercions instead of
+    casting any non-integer value to a string.
+    As such, passing invalid types to exit/die may now result in a TypeError
+    being thrown. (Girgias)
+  . Fixed bug GH-15438 (Hooks on constructor promoted properties without
+    visibility are ignored). (ilutov)
+  . Fixed bug GH-15419 (Missing readonly+hook incompatibility check for readonly
+    classes). (ilutov)
+  . Fixed bug GH-15187 (Various hooked object iterator issues). (ilutov)
+  . Fixed bug GH-15456 (Crash in get_class_vars() on virtual properties).
+    (ilutov)
+  . Fixed bug GH-15501 (Windows HAVE_<header>_H macros defined to 1 or
+    undefined). (Peter Kokot)
+  . Implemented asymmetric visibility for properties. (ilutov)
+  . Fixed bug GH-15644 (Asymmetric visibility doesn't work with hooks). (ilutov)
+  . Implemented lazy objects RFC. (Arnaud)
+  . Fixed bug GH-15686 (Building shared iconv with external iconv library).
+    (Peter Kokot, zeriyoshi)
+  . Fixed missing error when adding asymmetric visibility to unilateral virtual
+    property. (ilutov)
+  . Fixed bug GH-15693 (Unnecessary include in main.c bloats binary).
+    (nielsdos)
+  . Fixed bug GH-15731 (AllowDynamicProperties validation should error on
+    enums). (DanielEScherzer)
+  . Fixed bug GH-16040 (Use-after-free of object released in hook). (ilutov)
+  . Fixed bug GH-16026 (Reuse of dtor fiber during shutdown). (Arnaud)
+  . Fixed bug GH-15999 (zend_std_write_property() assertion failure with lazy
+    objects). (Arnaud)
+  . Fixed bug GH-15960 (Foreach edge cases with lazy objects). (Arnaud)
+  . Fixed bug GH-16185 (Various hooked object iterator issues). (ilutov)
+  . Fixed bug OSS-Fuzz #371445205 (Heap-use-after-free in attr_free).
+    (nielsdos)
+  . Fixed missing error when adding asymmetric visibility to static properties.
+    (ilutov)
+  . Fixed bug OSS-Fuzz #71407 (Null-dereference WRITE in
+    zend_lazy_object_clone). (Arnaud)
+  . Fixed bug GH-16574 (Incorrect error "undefined method" messages).
+    (nielsdos)
+  . Fixed bug GH-16577 (EG(strtod_state).freelist leaks with opcache.preload).
+    (nielsdos)
+  . Fixed bug GH-16615 (Assertion failure in zend_std_read_property). (Arnaud)
+  . Fixed bug GH-16342 (Added ReflectionProperty::isLazy()). (Arnaud)
+  . Fixed bug GH-16725 (Incorrect access check for non-hooked props in hooked
+    object iterator). (ilutov)
+
+- Curl:
+  . Deprecated the CURLOPT_BINARYTRANSFER constant. (divinity76)
+  . Bumped required libcurl version to 7.61.0. (Ayesh)
+  . Added feature_list key to the curl_version() return value. (Ayesh)
+  . Added constants CURL_HTTP_VERSION_3 (libcurl 7.66) and CURL_HTTP_VERSION_3ONLY
+    (libcurl 7.88) as options for CURLOPT_HTTP_VERSION (Ayesh Karunaratne)
+  . Added CURLOPT_TCP_KEEPCNT to set the number of probes to send before
+    dropping the connection. (David Carlier)
+  . Added CURLOPT_PREREQFUNCTION Curl option to set a custom callback
+    after the connection is established, but before the request is
+    performed. (Ayesh Karunaratne)
+  . Added CURLOPT_SERVER_RESPONSE_TIMEOUT, which was formerly known as
+    CURLOPT_FTP_RESPONSE_TIMEOUT. (Ayesh Karunaratne)
+  . The CURLOPT_DNS_USE_GLOBAL_CACHE option is now silently ignored. (Ayesh Karunaratne)
+  . Added CURLOPT_DEBUGFUNCTION as a Curl option. (Ayesh Karunaratne)
+  . Fixed bug GH-16359 (crash with curl_setopt* CURLOPT_WRITEFUNCTION
+    without null callback). (David Carlier)
+  . Fixed bug GH-16723 (CURLMOPT_PUSHFUNCTION issues). (cmb)
+
+- Date:
+  . Added DateTime[Immutable]::createFromTimestamp. (Marc Bennewitz)
+  . Added DateTime[Immutable]::[get|set]Microsecond. (Marc Bennewitz)
+  . Constants SUNFUNCS_RET_TIMESTAMP, SUNFUNCS_RET_STRING, and SUNFUNCS_RET_DOUBLE
+    are now deprecated. (Jorg Sowa)
+  . Fixed bug GH-13773 (DatePeriod not taking into account microseconds for end
+    date). (Mark Bennewitz, Derick)
+
+- DBA:
+  . Passing null or false to dba_key_split() is deprecated. (Grigias)
+
+- Debugging:
+  . Fixed bug GH-15923 (GDB: Python Exception <class 'TypeError'>:
+    exceptions must derive from BaseException). (nielsdos)
+
+- DOM:
+  . Added DOMNode::compareDocumentPosition(). (nielsdos)
+  . Implement #53655 (Improve speed of DOMNode::C14N() on large XML documents).
+    (nielsdos)
+  . Fix cloning attribute with namespace disappearing namespace. (nielsdos)
+  . Implement DOM HTML5 parsing and serialization RFC. (nielsdos)
+  . Fix DOMElement->prefix with empty string creates bogus prefix. (nielsdos)
+  . Handle OOM more consistently. (nielsdos)
+  . Implemented "Improve callbacks in ext/dom and ext/xsl" RFC. (nielsdos)
+  . Added DOMXPath::quote() static method. (divinity76)
+  . Implemented opt-in ext/dom spec compliance RFC. (nielsdos)
+  . Fixed bug #79701 (getElementById does not correctly work with duplicate
+    definitions). (nielsdos)
+  . Implemented "New ext-dom features in PHP 8.4" RFC. (nielsdos)
+  . Fixed GH-14698 (segfault on DOM node dereference). (David Carlier)
+  . Improve support for template elements. (nielsdos)
+  . Fix trampoline leak in xpath callables. (nielsdos)
+  . Throw instead of silently failing when creating a too long text node in
+    (DOM)ParentNode and (DOM)ChildNode. (nielsdos)
+  . Fixed bug GH-15192 (Segmentation fault in dom extension
+    (html5_serializer)). (nielsdos)
+  . Deprecated DOM_PHP_ERR constant. (nielsdos)
+  . Removed DOMImplementation::getFeature(). (nielsdos)
+  . Fixed bug GH-15331 (Element::$substitutedNodeValue test failed). (nielsdos)
+  . Fixed bug GH-15570 (Segmentation fault (access null pointer) in
+    ext/dom/html5_serializer.c). (nielsdos)
+  . Fixed bug GH-13988 (Storing DOMElement consume 4 times more memory in
+    PHP 8.1 than in PHP 8.0). (nielsdos)
+  . Fix XML serializer errata: xmlns="" serialization should be allowed.
+    (nielsdos)
+  . Fixed bug GH-15910 (Assertion failure in ext/dom/element.c). (nielsdos)
+  . Fix unsetting DOM properties. (nielsdos)
+  . Fixed bug GH-16190 (Using reflection to call Dom\Node::__construct
+    causes assertion failure). (nielsdos)
+  . Fix edge-case in DOM parsing decoding. (nielsdos)
+  . Fixed bug GH-16465 (Heap buffer overflow in DOMNode->getElementByTagName).
+    (nielsdos)
+  . Fixed bug GH-16594 (Assertion failure in DOM -> before). (nielsdos)
+
+- Fileinfo:
+  . Update to libmagic 5.45. (nielsdos)
+  . Fixed bug #65106 (PHP fails to compile ext/fileinfo). (Guillaume Outters)
+
+- FPM:
+  . Implement GH-12385 (flush headers without body when calling flush()).
+    (nielsdos)
+  . Added DragonFlyBSD system to the list which set FPM_BACKLOG_DEFAULT
+    to SOMAXCONN. (David Carlier)
+  . /dev/poll events.mechanism for Solaris/Illumos setting had been retired.
+    (David Carlier)
+  . Added memory peak to the scoreboard / status page. (Flávio Heleno)
+
+- FTP:
+  . Removed the deprecated inet_ntoa call support. (David Carlier)
+  . Fixed bug #63937 (Upload speed 10 times slower with PHP). (nielsdos)
+
+- GD:
+  . Fix parameter numbers and missing alpha check for imagecolorset().
+    (Giovanni Giacobbi)
+  . imagepng/imagejpeg/imagewep/imageavif now throw an exception on
+    invalid quality parameter. (David Carlier)
+  . Check overflow/underflow for imagescale/imagefilter. (David Carlier)
+  . Added gdImageClone to bundled libgd. (David Carlier)
+
+- Gettext:
+  . bind_textdomain_codeset, textdomain and d(*)gettext functions
+    now throw an exception on empty domain. (David Carlier)
+
+- GMP:
+  . The GMP class is now final and cannot be extended anymore. (Girgias)
+  . RFC: Change GMP bool cast behavior. (Saki Takamachi)
+
+- Hash:
+  . Changed return type of hash_update() to true. (nielsdos)
+  . Added HashContext::__debugInfo(). (timwolla)
+  . Deprecated passing incorrect data types for options to ext/hash functions.
+    (nielsdos)
+  . Added SSE2 and SHA-NI implementation of SHA-256. (timwolla, Colin Percival,
+    Graham Percival)
+  . Fix GH-15384 (Build fails on Alpine / Musl for amd64). (timwolla)
+  . Fixed bug GH-15742 (php_hash_sha.h incompatible with C++). (cmb)
+
+- IMAP:
+  . Moved to PECL. (Derick Rethans)
+
+- Intl:
+  . Added IntlDateFormatter::PATTERN constant. (David Carlier)
+  . Fixed Numberformatter::__construct when the locale is invalid, now
+    throws an exception. (David Carlier)
+  . Added NumberFormatter::ROUND_TOWARD_ZERO and ::ROUND_AWAY_FROM_ZERO as
+    aliases for ::ROUND_DOWN and ::ROUND_UP. (Jorg Sowa)
+  . Added NumberFormatter::ROUND_HALFODD. (Ayesh Karunaratne)
+  . Added PROPERTY_IDS_UNARY_OPERATOR, PROPERTY_ID_COMPAT_MATH_START and
+    PROPERTY_ID_COMPAT_MATH_CONTINUE constants. (David Carlier)
+  . Added IntlDateFormatter::getIanaID/intltz_get_iana_id method/function.
+    (David Carlier)
+  . Set to C++17 standard for icu 74 and onwards. (David Carlier)
+  . resourcebundle_get(), ResourceBundle::get(), and accessing offsets on a
+    ResourceBundle object now throw:
+    - TypeError for invalid offset types
+    - ValueError for an empty string
+    - ValueError if the integer index does not fit in a signed 32 bit integer
+  . ResourceBundle::get() now has a tentative return type of:
+    ResourceBundle|array|string|int|null
+  . Added the new Grapheme function grapheme_str_split. (youkidearitai)
+  . Added IntlDateFormatter::parseToCalendar. (David Carlier)
+  . Added SpoofChecker::setAllowedChars to set unicode chars ranges.
+    (David Carlier)
+
+- LDAP:
+  . Added LDAP_OPT_X_TLS_PROTOCOL_MAX/LDAP_OPT_X_TLS_PROTOCOL_TLS1_3
+    constants. (StephenWall)
+
+- LibXML:
+  . Added LIBXML_RECOVER constant. (nielsdos)
+  . libxml_set_streams_context() now throws immediately on an invalid context
+    instead of at the use-site. (nielsdos)
+  . Added LIBXML_NO_XXE constant. (nielsdos)
+
+- MBString:
+  . Added mb_trim, mb_ltrim and mb_rtrim. (Yuya Hamada)
+  . Added mb_ucfirst and mb_lcfirst. (Yuya Hamada)
+  . Updated Unicode data tables to Unicode 15.1. (Ayesh Karunaratne)
+  . Fixed bug GH-15824 (mb_detect_encoding(): Argument $encodings contains
+    invalid encoding "UTF8"). (Yuya Hamada)
+  . Updated Unicode data tables to Unicode 16.0. (Ayesh Karunaratne)
+
+- Mysqli:
+  . The mysqli_ping() function and mysqli::ping() method are now deprecated,
+    as the reconnect feature was removed in PHP 8.2. (Kamil Tekiela)
+  . The mysqli_kill() function and mysqli::kill() method are now deprecated.
+    If this functionality is needed a SQL "KILL" command can be used instead.
+    (Kamil Tekiela)
+  . The mysqli_refresh() function and mysqli::refresh() method are now deprecated.
+    If this functionality is needed a SQL "FLUSH" command can be used instead.
+    (Kamil Tekiela)
+  . Passing explicitly the $mode parameter to mysqli_store_result() has been
+    deprecated. As the MYSQLI_STORE_RESULT_COPY_DATA constant was only used in
+    conjunction with this function it has also been deprecated. (Girgias)
+
+- MySQLnd:
+  . Fixed bug GH-13440 (PDO quote bottleneck). (nielsdos)
+  . Fixed bug GH-10599 (Apache crash on Windows when using a self-referencing
+    anonymous function inside a class with an active mysqli connection).
+    (nielsdos)
+
+- Opcache:
+  . Added large shared segments support for FreeBSD. (David Carlier)
+  . If JIT is enabled, PHP will now exit with a fatal error on startup in case
+    of JIT startup initialization issues. (danog)
+  . Increased the maximum value of opcache.interned_strings_buffer to 32767 on
+    64bit archs. (Arnaud)
+  . Fixed bug GH-13834 (Applying non-zero offset 36 to null pointer in
+    zend_jit.c). (nielsdos)
+  . Fixed bug GH-14361 (Deep recursion in zend_cfg.c causes segfault).
+    (nielsdos)
+  . Fixed bug GH-14873 (PHP 8.4 min function fails on typed integer).
+    (nielsdos)
+  . Fixed bug GH-15490 (Building of callgraph modifies preloaded symbols).
+    (ilutov)
+  . Fixed bug GH-15178 (Assertion in tracing JIT on hooks). (ilutov)
+  . Fixed bug GH-15657 (Segmentation fault in dasm_x86.h). (nielsdos)
+  . Added opcache_jit_blacklist() function. (Bob)
+  . Fixed bug GH-16009 (Segmentation fault with frameless functions and
+    undefined CVs). (nielsdos)
+  . Fixed bug GH-16186 (Assertion failure in Zend/zend_operators.c). (Arnaud)
+  . Fixed bug GH-16572 (Incorrect result with reflection in low-trigger JIT).
+    (nielsdos)
+  . Fixed GH-16839 (Error on building Opcache JIT for Windows ARM64). (cmb)
+
+- OpenSSL:
+  . Fixed bug #80269 (OpenSSL sets Subject wrong with extraattribs parameter).
+    (Jakub Zelenka)
+  . Implement request #48520 (openssl_csr_new - allow multiple values in DN).
+    (Jakub Zelenka)
+  . Introduced new serial_hex parameter to openssl_csr_sign. (Jakub Zelenka,
+    Florian Sowade)
+  . Added X509_PURPOSE_OCSP_HELPER and X509_PURPOSE_TIMESTAMP_SIGN constants.
+    (Vincent Jardin)
+  . Bumped minimum required OpenSSL version to 1.1.1. (Ayesh Karunaratne)
+  . Added compile-time option --with-openssl-legacy-provider to enable legacy
+    provider. (Adam Saponara)
+  . Added support for Curve25519 + Curve448 based keys. (Manuel Mausz)
+  . Fixed bug GH-13343 (openssl_x509_parse should not allow omitted seconds in
+    UTCTimes). (Jakub Zelenka)
+  . Bumped minimum required OpenSSL version to 1.1.0. (cmb)
+  . Implement GH-13514 PASSWORD_ARGON2 from OpenSSL 3.2. (Remi)
+
+- Output:
+  . Clear output handler status flags during handler initialization. (haszi)
+  . Fixed bug with url_rewriter.hosts not used by output_add_rewrite_var().
+    (haszi)
+
+- PCNTL:
+  . Added pcntl_setns for Linux. (David Carlier)
+  . Added pcntl_getcpuaffinity/pcntl_setcpuaffinity. (David Carlier)
+  . Updated pcntl_get_signal_handler signal id upper limit to be
+    more in line with platforms limits. (David Carlier)
+  . Added pcntl_getcpu for Linux/FreeBSD/Solaris/Illumos. (David Carlier)
+  . Added pcntl_getqos_class/pcntl_setqos_class for macOs. (David Carlier)
+  . Added SIGCKPT/SIGCKPTEXIT constants for DragonFlyBSD. (David Carlier)
+  . Added FreeBSD's SIGTRAP handling to pcntl_siginfo_to_zval. (David Carlier)
+  . Added POSIX pcntl_waitid. (Vladimir Vrzić)
+  . Fixed bug GH-16769: (pcntl_sigwaitinfo aborts on signal value
+    as reference). (David Carlier)
+
+- PCRE:
+  . Upgrade bundled pcre2lib to version 10.43. (nielsdos)
+  . Add "/r" modifier. (Ayesh)
+  . Upgrade bundled pcre2lib to version 10.44. (Ayesh)
+  . Fixed GH-16189 (underflow on offset argument). (David Carlier)
+  . Fix UAF issues with PCRE after request shutdown. (nielsdos)
+
+- PDO:
+  . Fixed setAttribute and getAttribute. (SakiTakamachi)
+  . Implemented PDO driver-specific subclasses RFC. (danack, kocsismate)
+  . Added support for PDO driver-specific SQL parsers. (Matteo Beccati)
+  . Fixed bug GH-14792 (Compilation failure on pdo_* extensions).
+    (Peter Kokot)
+  . mysqlnd: support ER_CLIENT_INTERACTION_TIMEOUT. (Appla)
+  . The internal header php_pdo_int.h is no longer installed; it is not
+    supposed to be used by PDO drivers. (cmb)
+  . Fixed bug GH-16167 (Prevent mixing PDO sub-classes with different DSN).
+    (kocsismate)
+  . Fixed bug GH-16314 ("Pdo\Mysql object is uninitialized" when opening a
+    persistent connection). (kocsismate)
+
+- PDO_DBLIB:
+  . Fixed setAttribute and getAttribute. (SakiTakamachi)
+  . Added class Pdo\DbLib. (danack, kocsismate)
+
+- PDO_Firebird:
+  . Fixed setAttribute and getAttribute. (SakiTakamachi)
+  . Feature: Add transaction isolation level and mode settings to pdo_firebird.
+    (SakiTakamachi)
+  . Added class Pdo\Firebird. (danack, kocsismate)
+  . Added Pdo\Firebird::ATTR_API_VERSION. (SakiTakamachi)
+  . Added getApiVersion() and removed from getAttribute().
+    (SakiTakamachi)
+  . Supported Firebird 4.0 datatypes. (sim1984)
+  . Support proper formatting of time zone types. (sim1984)
+  . Fixed GH-15604 (Always make input parameters nullable). (sim1984)
+
+- PDO_MYSQL:
+  . Fixed setAttribute and getAttribute. (SakiTakamachi)
+  . Added class Pdo\Mysql. (danack, kocsismate)
+  . Added custom SQL parser. (Matteo Beccati)
+  . Fixed GH-15949 (PDO_MySQL not properly quoting PDO_PARAM_LOB binary
+    data). (mbeccati, lcobucci)
+
+- PDO_ODBC:
+  . Added class Pdo\Odbc. (danack, kocsismate)
+
+- PDO_PGSQL:
+  . Fixed GH-12423, DSN credentials being prioritized over the user/password
+    PDO constructor arguments. (SakiTakamachi)
+  . Fixed native float support with pdo_pgsql query results. (Yurunsoft)
+  . Added class Pdo\Pgsql. (danack, kocsismate)
+  . Retrieve the memory usage of the query result resource. (KentarouTakeda)
+  . Added Pdo\Pgsql::setNoticeCallBack method to receive DB notices.
+    (outtersg)
+  . Added custom SQL parser. (Matteo Beccati)
+  . Fixed GH-15986 (Double-free due to Pdo\Pgsql::setNoticeCallback()). (cmb,
+    nielsdos)
+  . Fixed GH-12940 (Using PQclosePrepared when available instead of
+    the DEALLOCATE command to free statements resources). (David Carlier)
+  . Remove PGSQL_ATTR_RESULT_MEMORY_SIZE constant as it is provided by
+    the new PDO Subclass as Pdo\Pgsql::ATTR_RESULT_MEMORY_SIZE. (Girgias)
+
+- PDO_SQLITE:
+  . Added class Pdo\Sqlite. (danack, kocsismate)
+  . Fixed bug #81227 (PDO::inTransaction reports false when in transaction).
+    (nielsdos)
+  . Added custom SQL parser. (Matteo Beccati)
+
+- PHPDBG:
+  . array out of bounds, stack overflow handled for segfault handler on windows.
+    (David Carlier)
+  . Fixed bug GH-16041 (Support stack limit in phpdbg). (Arnaud)
+
+- PGSQL:
+  . Added the possibility to have no conditions for pg_select. (OmarEmaraDev)
+  . Persistent connections support the PGSQL_CONNECT_FORCE_RENEW flag.
+    (David Carlier)
+  . Added pg_result_memory_size to get the query result memory usage.
+    (KentarouTakeda)
+  . Added pg_change_password to alter an user's password. (David Carlier)
+  . Added pg_put_copy_data/pg_put_copy_end to send COPY commands and signal
+    the end of the COPY. (David Carlier)
+  . Added pg_socket_poll to poll on the connection. (David Carlier)
+  . Added pg_jit to get infos on server JIT support. (David Carlier)
+  . Added pg_set_chunked_rows_size to fetch results per chunk. (David Carlier)
+  . pg_convert/pg_insert/pg_update/pg_delete ; regexes are now cached.
+    (David Carlier)
+
+- Phar:
+  . Fixed bug GH-12532 (PharData created from zip has incorrect timestamp).
+    (nielsdos)
+
+- POSIX:
+  . Added POSIX_SC_CHILD_MAX and POSIX_SC_CLK_TCK constants. (Jakub Zelenka)
+  . Updated posix_isatty to set the error number on file descriptors.
+    (David Carlier)
+
+- PSpell:
+  . Moved to PECL. (Derick Rethans)
+
+- Random:
+  . Fixed bug GH-15094 (php_random_default_engine() is not C++ conforming).
+    (cmb)
+  . lcg_value() is now deprecated. (timwolla)
+
+- Readline:
+  . Fixed readline_info, rl_line_buffer_length/rl_len globals on update.
+    (David Carlier)
+  . Fixed bug #51558 (Shared readline build fails). (Peter Kokot)
+  . Fixed UAF with readline_info(). (David Carlier)
+
+- Reflection:
+  . Implement GH-12908 (Show attribute name/class in ReflectionAttribute dump).
+    (nielsdos)
+  . Make ReflectionGenerator::getFunction() legal after generator termination.
+    (timwolla)
+  . Added ReflectionGenerator::isClosed(). (timwolla)
+  . Fixed bug GH-15718 (Segfault on ReflectionProperty::get{Hook,Hooks}() on
+    dynamic properties). (DanielEScherzer)
+  . Fixed bug GH-15694 (ReflectionProperty::isInitialized() is incorrect for
+    hooked properties). (ilutov)
+  . Add missing ReflectionProperty::hasHook[s]() methods. (ilutov)
+  . Add missing ReflectionProperty::isFinal() method. (ilutov)
+  . Fixed bug GH-16122 (The return value of ReflectionFunction::getNamespaceName()
+    and ReflectionFunction::inNamespace() for closures is incorrect). (timwolla)
+  . Fixed bug GH-16162 (No ReflectionProperty::IS_VIRTUAL) (DanielEScherzer)
+  . Fixed the name of the second parameter of
+    ReflectionClass::resetAsLazyGhost(). (Arnaud)
+
+- Session:
+  . INI settings session.sid_length and session.sid_bits_per_character are now
+    deprecated. (timwolla)
+  . Emit warnings for non-positive values of session.gc_divisor and negative values
+    of session.gc_probability. (Jorg Sowa)
+  . Fixed bug GH-16590 (UAF in session_encode()). (nielsdos)
+
+- SimpleXML:
+  . Fix signature of simplexml_import_dom(). (nielsdos)
+
+- SNMP:
+  . Removed the deprecated inet_ntoa call support. (David Carlier)
+
+- SOAP:
+  . Add support for clark notation for namespaces in class map. (lxShaDoWxl)
+  . Mitigate #51561 (SoapServer with a extented class and using sessions,
+    lost the setPersistence()). (nielsdos)
+  . Fixed bug #49278 (SoapClient::__getLastResponseHeaders returns NULL if
+    wsdl operation !has output). (nielsdos)
+  . Fixed bug #44383 (PHP DateTime not converted to xsd:datetime). (nielsdos)
+  . Fixed bug GH-11941 (soap with session persistence will silently fail when
+    "session" built as a shared object). (nielsdos)
+  . Passing an int to SoapServer::addFunction() is now deprecated.
+    If all PHP functions need to be provided flatten the array returned by
+    get_defined_functions(). (Girgias)
+  . The SOAP_FUNCTIONS_ALL constant is now deprecated. (Girgias)
+  . Fixed bug #61525 (SOAP functions require at least one space after HTTP
+    header colon). (nielsdos)
+  . Implement request #47317 (SoapServer::__getLastResponse()). (nielsdos)
+
+- Sockets:
+  . Removed the deprecated inet_ntoa call support. (David Carlier)
+  . Added the SO_EXECLUSIVEADDRUSE windows constant. (David Carlier)
+  . Added the SOCK_CONN_DGRAM/SOCK_DCCP netbsd constants. (David Carlier)
+  . Added multicast group support for ipv4 on FreeBSD. (jonathan@tangential.ca)
+  . Added the TCP_SYNCNT constant for Linux to set number of attempts to send
+    SYN packets from the client. (David Carlier)
+  . Added the SO_EXCLBIND constant for exclusive socket binding on illumos/solaris.
+    (David Carlier)
+  . Updated the socket_create_listen backlog argument default value to SOMAXCONN.
+    (David Carlier)
+  . Added the SO_NOSIGPIPE constant to control the generation of SIGPIPE for
+    macOs and FreeBSD. (David Carlier)
+  . Added SO_LINGER_SEC for macOs, true equivalent of SO_LINGER in other platforms.
+    (David Carlier)
+  . Add close-on-exec on socket created with socket_accept on unixes. (David Carlier)
+  . Added IP_PORTRANGE* constants for BSD systems to control ephemeral port
+    ranges. (David Carlier)
+  . Added SOCK_NONBLOCK/SOCK_CLOEXEC constants for socket_create and
+    socket_create_pair to apply O_NONBLOCK/O_CLOEXEC flags to the
+    newly created sockets. (David Carlier)
+  . Added SO_BINDTOIFINDEX to bind a socket to an interface index.
+    (David Carlier)
+
+- Sodium:
+  . Add support for AEGIS-128L and AEGIS-256. (jedisct1)
+  . Enable AES-GCM on aarch64 with the ARM crypto extensions. (jedisct1)
+
+- SPL:
+  . Implement SeekableIterator for SplObjectStorage. (nielsdos)
+  . The SplFixedArray::__wakeup() method has been deprecated as it implements
+    __serialize() and __unserialize() which need to be overwritten instead.
+    (TysonAndre)
+  . Passing a non-empty string for the $escape parameter of:
+    - SplFileObject::setCsvControl()
+    - SplFileObject::fputcsv()
+    - SplFileObject::fgetcsv()
+    is now deprecated. (Girgias)
+
+- Standard:
+  . Implement GH-12188 (Indication for the int size in phpinfo()). (timwolla)
+  . Partly fix GH-12143 (Incorrect round() result for 0.49999999999999994).
+    (timwolla)
+  . Fix GH-12252 (round(): Validate the rounding mode). (timwolla)
+  . Increase the default BCrypt cost to 12. (timwolla)
+  . Fixed bug GH-12592 (strcspn() odd behaviour with NUL bytes and empty mask).
+    (nielsdos)
+  . Removed the deprecated inet_ntoa call support. (David Carlier)
+  . Cast large floats that are within int range to int in number_format so
+    the precision is not lost. (Marc Bennewitz)
+  . Add support for 4 new rounding modes to the round() function. (Jorg Sowa)
+  . debug_zval_dump() now indicates whether an array is packed. (Max Semenik)
+  . Fix GH-12143 (Optimize round). (SakiTakamachi)
+  . Changed return type of long2ip to string from string|false. (Jorg Sowa)
+  . Fix GH-12143 (Extend the maximum precision round can handle by one digit).
+    (SakiTakamachi)
+  . Added the http_get_last_response_headers() and
+    http_clear_last_response_headers() that allows retrieving the same content
+    as the magic $http_response_header variable.
+  . Add php_base64_encode_ex() API. (Remi)
+  . Implemented "Raising zero to the power of negative number" RFC. (Jorg Sowa)
+  . Added array_find(), array_find_key(), array_all(), and array_any(). (josh)
+  . Change highlight_string() and print_r() return type to string|true. (Ayesh)
+  . Fix references in request_parse_body() options array. (nielsdos)
+  . Add RoundingMode enum. (timwolla, saki)
+  . Unserializing the uppercase 'S' tag is now deprecated. (timwolla)
+  . Enables crc32 auxiliary detection on OpenBSD. (David Carlier)
+  . Passing a non-empty string for the $escape parameter of:
+    - fputcsv()
+    - fgetcsv()
+    - str_getcsv()
+    is now deprecated. (Girgias)
+  . The str_getcsv() function now throws ValueErrors when the $separator and
+    $enclosure arguments are not one byte long, or if the $escape is not one
+    byte long or the empty string. This aligns the behaviour to be identical
+    to that of fputcsv() and fgetcsv(). (Girgias)
+  . php_uname() now throws ValueErrors on invalid inputs. (Girgias)
+  . The "allowed_classes" option for unserialize() now throws TypeErrors and
+    ValueErrors	if it is not an	array of class names. (Girgias)
+  . Implemented GH-15685 (improve proc_open error reporting on Windows). (cmb)
+  . Add support for backed enums in http_build_query(). (ilutov)
+  . Fixed bug GH-15982 (Assertion failure with array_find when references are
+    involved). (nielsdos)
+  . Fixed parameter names of fpow() to be identical to pow(). (Girgias)
+
+- Streams:
+  . Implemented GH-15155 (Stream context is lost when custom stream wrapper is
+    being filtered). (Quentin Dreyer)
+
+- Tidy:
+  . Failures in the constructor now throw exceptions rather than emitting
+    warnings and having a broken object. (nielsdos)
+  . Add tidyNode::getNextSibling() and tidyNode::getPreviousSibling().
+    (nielsdos)
+
+- Windows:
+  . Update the icon of the Windows executables, e.g. php.exe. (Ayesh,
+    Nurudin Imširović)
+  . Fixed bug GH-16199 (GREP_HEADER() is broken). (Peter Kokot)
+
+- XML:
+  . Added XML_OPTION_PARSE_HUGE parser option. (nielsdos)
+  . Fixed bug #81481 (xml_get_current_byte_index limited to 32-bit numbers on
+    64-bit builds). (nielsdos)
+  . The xml_set_object() function has been deprecated. (Girgias)
+  . Passing non-callable strings to the xml_set_*_handler() functions is now
+    deprecated. (Girgias)
+
+- XMLReader:
+  . Declares class constant types. (Ayesh)
+  . Add XMLReader::fromStream(), XMLReader::fromUri(), XMLReader::fromString(). (nielsdos)
+  . Fixed bug GH-15123 (var_dump doesn't actually work on XMLReader).
+    (nielsdos)
+
+- XMLWriter:
+  . Add XMLWriter::toStream(), XMLWriter::toUri(), XMLWriter::toMemory(). (nielsdos)
+
+- XSL:
+  . Implement request #64137 (XSLTProcessor::setParameter() should allow both
+    quotes to be used). (nielsdos)
+  . Implemented "Improve callbacks in ext/dom and ext/xsl" RFC. (nielsdos)
+  . Added XSLTProcessor::$maxTemplateDepth and XSLTProcessor::$maxTemplateVars.
+    (nielsdos)
+  . Fix trampoline leak in xpath callables. (nielsdos)
+
+- Zip:
+  . Added ZipArchive::ER_TRUNCATED_ZIP added in libzip 1.11. (Remi)
diff '--color=auto' -Naur php-8.4.18/sapi/cgi/Makefile.frag php-8.4.20RC1/sapi/cgi/Makefile.frag
--- php-8.4.18/sapi/cgi/Makefile.frag	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/sapi/cgi/Makefile.frag	2026-04-01 04:35:36.023945498 +0000
@@ -6,7 +6,7 @@
 install-cgi: $(SAPI_CGI_PATH)
 	@echo "Installing PHP CGI binary:        $(INSTALL_ROOT)$(bindir)/"
 	@$(mkinstalldirs) $(INSTALL_ROOT)$(bindir)
-	@$(INSTALL) -m 0755 $(SAPI_CGI_PATH) $(INSTALL_ROOT)$(bindir)/$(program_prefix)php-cgi$(program_suffix)$(EXEEXT)
+	@$(LIBTOOL) --mode=install $(INSTALL) -m 0755 $(SAPI_CGI_PATH) $(INSTALL_ROOT)$(bindir)/$(program_prefix)php-cgi$(program_suffix)$(EXEEXT)
 	@echo "Installing PHP CGI man page:      $(INSTALL_ROOT)$(mandir)/man1/"
 	@$(mkinstalldirs) $(INSTALL_ROOT)$(mandir)/man1
 	@$(INSTALL_DATA) sapi/cgi/php-cgi.1 $(INSTALL_ROOT)$(mandir)/man1/$(program_prefix)php-cgi$(program_suffix).1
diff '--color=auto' -Naur php-8.4.18/sapi/cli/Makefile.frag php-8.4.20RC1/sapi/cli/Makefile.frag
--- php-8.4.18/sapi/cli/Makefile.frag	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/sapi/cli/Makefile.frag	2026-04-01 04:35:36.024028806 +0000
@@ -6,7 +6,7 @@
 install-cli: $(SAPI_CLI_PATH)
 	@echo "Installing PHP CLI binary:        $(INSTALL_ROOT)$(bindir)/"
 	@$(mkinstalldirs) $(INSTALL_ROOT)$(bindir)
-	@$(INSTALL) -m 0755 $(SAPI_CLI_PATH) $(INSTALL_ROOT)$(bindir)/$(program_prefix)php$(program_suffix)$(EXEEXT)
+	@$(LIBTOOL) --mode=install $(INSTALL) -m 0755 $(SAPI_CLI_PATH) $(INSTALL_ROOT)$(bindir)/$(program_prefix)php$(program_suffix)$(EXEEXT)
 	@echo "Installing PHP CLI man page:      $(INSTALL_ROOT)$(mandir)/man1/"
 	@$(mkinstalldirs) $(INSTALL_ROOT)$(mandir)/man1
 	@$(INSTALL_DATA) sapi/cli/php.1 $(INSTALL_ROOT)$(mandir)/man1/$(program_prefix)php$(program_suffix).1
diff '--color=auto' -Naur php-8.4.18/sapi/fpm/Makefile.frag php-8.4.20RC1/sapi/fpm/Makefile.frag
--- php-8.4.18/sapi/fpm/Makefile.frag	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/sapi/fpm/Makefile.frag	2026-04-01 04:35:36.024117563 +0000
@@ -8,7 +8,7 @@
 	@$(mkinstalldirs) $(INSTALL_ROOT)$(sbindir)
 	@$(mkinstalldirs) $(INSTALL_ROOT)$(localstatedir)/log
 	@$(mkinstalldirs) $(INSTALL_ROOT)$(localstatedir)/run
-	@$(INSTALL) -m 0755 $(SAPI_FPM_PATH) $(INSTALL_ROOT)$(sbindir)/$(program_prefix)php-fpm$(program_suffix)$(EXEEXT)
+	@$(LIBTOOL) --mode=install $(INSTALL) -m 0755 $(SAPI_FPM_PATH) $(INSTALL_ROOT)$(sbindir)/$(program_prefix)php-fpm$(program_suffix)$(EXEEXT)
 
 	@if test -f "$(INSTALL_ROOT)$(sysconfdir)/php-fpm.conf"; then \
 		echo "Installing PHP FPM defconfig:     skipping"; \
diff '--color=auto' -Naur php-8.4.18/sapi/fpm/tests/bug77023-pm-dynamic-blocking-sigquit.phpt php-8.4.20RC1/sapi/fpm/tests/bug77023-pm-dynamic-blocking-sigquit.phpt
--- php-8.4.18/sapi/fpm/tests/bug77023-pm-dynamic-blocking-sigquit.phpt	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/sapi/fpm/tests/bug77023-pm-dynamic-blocking-sigquit.phpt	2026-04-01 04:35:36.024195120 +0000
@@ -6,7 +6,7 @@
 <?php
 include "skipif.inc";
 if (!function_exists('pcntl_sigprocmask')) die('skip Requires pcntl_sigprocmask()');
-if (!getenv("FPM_RUN_RESOURCE_HEAVY_TESTS")) die("skip resource heavy test");
+if (!getenv("RUN_RESOURCE_HEAVY_TESTS")) die("skip resource-heavy test");
 if (getenv('SKIP_SLOW_TESTS')) die('skip slow tests excluded by request');
 ?>
 --FILE--
diff '--color=auto' -Naur php-8.4.18/sapi/fpm/tests/proc-idle-timeout.phpt php-8.4.20RC1/sapi/fpm/tests/proc-idle-timeout.phpt
--- php-8.4.18/sapi/fpm/tests/proc-idle-timeout.phpt	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/sapi/fpm/tests/proc-idle-timeout.phpt	2026-04-01 04:35:36.024264511 +0000
@@ -3,7 +3,7 @@
 --SKIPIF--
 <?php
 include "skipif.inc";
-if (!getenv("FPM_RUN_RESOURCE_HEAVY_TESTS")) die("skip resource heavy test");
+if (!getenv("FPM_RUN_RESOURCE_HEAVY_TESTS")) die("skip FPM resource-heavy test");
 if (getenv("SKIP_SLOW_TESTS")) die("skip slow test");
 ?>
 --FILE--
diff '--color=auto' -Naur php-8.4.18/sapi/litespeed/Makefile.frag php-8.4.20RC1/sapi/litespeed/Makefile.frag
--- php-8.4.18/sapi/litespeed/Makefile.frag	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/sapi/litespeed/Makefile.frag	2026-04-01 04:35:36.024338942 +0000
@@ -6,4 +6,4 @@
 install-litespeed: $(SAPI_LITESPEED_PATH)
 	@echo "Installing PHP LiteSpeed binary:  $(INSTALL_ROOT)$(bindir)/"
 	@$(mkinstalldirs) $(INSTALL_ROOT)$(bindir)
-	@$(INSTALL) -m 0755 $(SAPI_LITESPEED_PATH) $(INSTALL_ROOT)$(bindir)/$(program_prefix)lsphp$(program_suffix)
+	@$(LIBTOOL) --mode=install $(INSTALL) -m 0755 $(SAPI_LITESPEED_PATH) $(INSTALL_ROOT)$(bindir)/$(program_prefix)lsphp$(program_suffix)
diff '--color=auto' -Naur php-8.4.18/sapi/phpdbg/Makefile.frag php-8.4.20RC1/sapi/phpdbg/Makefile.frag
--- php-8.4.18/sapi/phpdbg/Makefile.frag	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/sapi/phpdbg/Makefile.frag	2026-04-01 04:35:36.024411639 +0000
@@ -25,7 +25,7 @@
 	@$(mkinstalldirs) $(INSTALL_ROOT)$(bindir)
 	@$(mkinstalldirs) $(INSTALL_ROOT)$(localstatedir)/log
 	@$(mkinstalldirs) $(INSTALL_ROOT)$(localstatedir)/run
-	@$(INSTALL) -m 0755 $(BUILD_BINARY) $(INSTALL_ROOT)$(bindir)/$(program_prefix)phpdbg$(program_suffix)$(EXEEXT)
+	@$(LIBTOOL) --mode=install $(INSTALL) -m 0755 $(BUILD_BINARY) $(INSTALL_ROOT)$(bindir)/$(program_prefix)phpdbg$(program_suffix)$(EXEEXT)
 	@echo "Installing phpdbg man page:       $(INSTALL_ROOT)$(mandir)/man1/"
 	@$(mkinstalldirs) $(INSTALL_ROOT)$(mandir)/man1
 	@$(INSTALL_DATA) sapi/phpdbg/phpdbg.1 $(INSTALL_ROOT)$(mandir)/man1/$(program_prefix)phpdbg$(program_suffix).1
diff '--color=auto' -Naur php-8.4.18/sapi/phpdbg/phpdbg_utils.c php-8.4.20RC1/sapi/phpdbg/phpdbg_utils.c
--- php-8.4.18/sapi/phpdbg/phpdbg_utils.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/sapi/phpdbg/phpdbg_utils.c	2026-04-01 04:35:36.024539501 +0000
@@ -111,7 +111,7 @@
 
 PHPDBG_API int phpdbg_is_class_method(const char *str, size_t len, char **class, char **method) /* {{{ */
 {
-	char *sep = NULL;
+	const char *sep = NULL;
 
 	if (strstr(str, "#") != NULL)
 		return 0;
diff '--color=auto' -Naur php-8.4.18/scripts/gdb/debug_gdb_scripts_gen.php php-8.4.20RC1/scripts/gdb/debug_gdb_scripts_gen.php
--- php-8.4.18/scripts/gdb/debug_gdb_scripts_gen.php	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/scripts/gdb/debug_gdb_scripts_gen.php	2026-04-01 04:35:36.024705825 +0000
@@ -27,7 +27,7 @@
      *
      * See https://sourceware.org/gdb/current/onlinedocs/gdb.html/dotdebug_005fgdb_005fscripts-section.html#dotdebug_005fgdb_005fscripts-section
      */
-    asm(
+    __asm__(
         ".pushsection \".debug_gdb_scripts\", \"MS\",%%progbits,1\n"
         ".byte 4 /* Python Text */\n"
         ".ascii \"gdb.inlined-script\\n\"\n"
diff '--color=auto' -Naur php-8.4.18/Zend/Optimizer/sccp.c php-8.4.20RC1/Zend/Optimizer/sccp.c
--- php-8.4.18/Zend/Optimizer/sccp.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/Zend/Optimizer/sccp.c	2026-04-01 04:35:35.982880787 +0000
@@ -965,7 +965,7 @@
 					SET_RESULT(op1, &zv);
 				} else if (ct_eval_assign_dim(&zv, data, op2) == SUCCESS) {
 					/* Mark array containing partial array as partial */
-					if (IS_PARTIAL_ARRAY(data)) {
+					if (IS_PARTIAL_ARRAY(data) || IS_PARTIAL_OBJECT(data)) {
 						MAKE_PARTIAL_ARRAY(&zv);
 					}
 					SET_RESULT(result, data);
@@ -1165,7 +1165,7 @@
 						/* We can't add NEXT element into partial array (skip it) */
 						SET_RESULT(result, &zv);
 					} else if (ct_eval_add_array_elem(&zv, op1, op2) == SUCCESS) {
-						if (IS_PARTIAL_ARRAY(op1)) {
+						if (IS_PARTIAL_ARRAY(op1) || IS_PARTIAL_OBJECT(op1)) {
 							MAKE_PARTIAL_ARRAY(&zv);
 						}
 						SET_RESULT(result, &zv);
diff '--color=auto' -Naur php-8.4.18/Zend/Optimizer/zend_optimizer.c php-8.4.20RC1/Zend/Optimizer/zend_optimizer.c
--- php-8.4.18/Zend/Optimizer/zend_optimizer.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/Zend/Optimizer/zend_optimizer.c	2026-04-01 04:35:35.983065166 +0000
@@ -799,6 +799,9 @@
 	zend_class_entry *ce = Z_PTR_P(ce_zv);
 
 	if (ce->ce_flags & ZEND_ACC_PRELOADED) {
+		if (CG(compiler_options) & ZEND_COMPILE_WITH_FILE_CACHE) {
+			return true;
+		}
 		Bucket *ce_bucket = (Bucket*)((uintptr_t)ce_zv - XtOffsetOf(Bucket, val));
 		size_t offset = ce_bucket - EG(class_table)->arData;
 		if (offset < EG(persistent_classes_count)) {
@@ -817,6 +820,9 @@
 		return false;
 	} else if (fbc->type == ZEND_USER_FUNCTION) {
 		if (fbc->op_array.fn_flags & ZEND_ACC_PRELOADED) {
+			if (CG(compiler_options) & ZEND_COMPILE_WITH_FILE_CACHE) {
+				return true;
+			}
 			Bucket *fbc_bucket = (Bucket*)((uintptr_t)fbc_zv - XtOffsetOf(Bucket, val));
 			size_t offset = fbc_bucket - EG(function_table)->arData;
 			if (offset < EG(persistent_functions_count)) {
diff '--color=auto' -Naur php-8.4.18/Zend/tests/bug55509.phpt php-8.4.20RC1/Zend/tests/bug55509.phpt
--- php-8.4.18/Zend/tests/bug55509.phpt	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/Zend/tests/bug55509.phpt	2026-04-01 04:35:35.983230999 +0000
@@ -2,6 +2,7 @@
 Bug #55509 (segfault on x86_64 using more than 2G memory)
 --SKIPIF--
 <?php
+if (!getenv('RUN_RESOURCE_HEAVY_TESTS')) die('skip resource-heavy test');
 if (PHP_INT_SIZE == 4) {
   die('skip Not for 32-bits OS');
 }
diff '--color=auto' -Naur php-8.4.18/Zend/tests/bug74093.phpt php-8.4.20RC1/Zend/tests/bug74093.phpt
--- php-8.4.18/Zend/tests/bug74093.phpt	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/Zend/tests/bug74093.phpt	2026-04-01 04:35:35.983304207 +0000
@@ -1,7 +1,9 @@
 --TEST--
 Bug #74093 (Maximum execution time of n+2 seconds exceed not written in error_log)
+--FLAKY--
 --SKIPIF--
 <?php
+if (!getenv('RUN_RESOURCE_HEAVY_TESTS')) die('skip resource-heavy test');
 if (getenv("SKIP_SLOW_TESTS")) die("skip slow test");
 if (PHP_ZTS) die("skip only for no-zts build");
 if (substr(PHP_OS, 0, 3) == 'WIN') die("skip not for Windows");
@@ -12,8 +14,8 @@
 hard_timeout=1
 --FILE--
 <?php
-$a1 = range(1, 2000000);
-$a2 = range(100000, 2999999);
+$a1 = range(1, 3000000);
+$a2 = range(100000, 3999999);
 array_intersect($a1, $a2);
 ?>
 --EXPECTF--
diff '--color=auto' -Naur php-8.4.18/Zend/tests/bug78010.phpt php-8.4.20RC1/Zend/tests/bug78010.phpt
--- php-8.4.18/Zend/tests/bug78010.phpt	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/Zend/tests/bug78010.phpt	2026-04-01 04:35:35.983380571 +0000
@@ -2,6 +2,7 @@
 Bug #78010: Segmentation fault during GC
 --SKIPIF--
 <?php
+if (!getenv('RUN_RESOURCE_HEAVY_TESTS')) die('skip resource-heavy test');
 if (getenv("SKIP_SLOW_TESTS")) die('skip slow test');
 ?>
 --INI--
diff '--color=auto' -Naur php-8.4.18/Zend/tests/lazy_objects/gh20504-001.phpt php-8.4.20RC1/Zend/tests/lazy_objects/gh20504-001.phpt
--- php-8.4.18/Zend/tests/lazy_objects/gh20504-001.phpt	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/Zend/tests/lazy_objects/gh20504-001.phpt	2026-04-01 04:35:35.983491441 +0000
@@ -0,0 +1,24 @@
+--TEST--
+GH-20504: Assertion failure in zend_get_property_guard() when lazy proxy adds magic method - isset
+--CREDITS--
+vi3tL0u1s
+--FILE--
+<?php
+
+class RealInstance {
+    public $_;
+}
+class Proxy extends RealInstance {
+    public function __isset($name) {
+        return isset($this->$name['']);
+    }
+}
+$rc = new ReflectionClass(Proxy::class);
+$obj = $rc->newLazyProxy(function () {
+    return new RealInstance;
+});
+var_dump(isset($obj->name['']));
+
+?>
+--EXPECT--
+bool(false)
diff '--color=auto' -Naur php-8.4.18/Zend/tests/lazy_objects/gh20504-002.phpt php-8.4.20RC1/Zend/tests/lazy_objects/gh20504-002.phpt
--- php-8.4.18/Zend/tests/lazy_objects/gh20504-002.phpt	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/Zend/tests/lazy_objects/gh20504-002.phpt	2026-04-01 04:35:35.983562555 +0000
@@ -0,0 +1,23 @@
+--TEST--
+GH-20504: Assertion failure in zend_get_property_guard() when lazy proxy adds magic method - get
+--FILE--
+<?php
+
+class RealInstance {
+    public $_;
+}
+class Proxy extends RealInstance {
+    public function __get($name) {
+        return $this->$name;
+    }
+}
+$rc = new ReflectionClass(Proxy::class);
+$obj = $rc->newLazyProxy(function () {
+    return new RealInstance;
+});
+var_dump($obj->name);
+
+?>
+--EXPECTF--
+Warning: Undefined property: RealInstance::$name in %s on line %d
+NULL
diff '--color=auto' -Naur php-8.4.18/Zend/tests/lazy_objects/gh20504-003.phpt php-8.4.20RC1/Zend/tests/lazy_objects/gh20504-003.phpt
--- php-8.4.18/Zend/tests/lazy_objects/gh20504-003.phpt	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/Zend/tests/lazy_objects/gh20504-003.phpt	2026-04-01 04:35:35.983634261 +0000
@@ -0,0 +1,33 @@
+--TEST--
+GH-20504: Assertion failure in zend_get_property_guard() when lazy proxy adds magic method - set
+--FILE--
+<?php
+
+#[AllowDynamicProperties]
+class RealInstance {
+    public $_;
+}
+class Proxy extends RealInstance {
+    public function __set($name, $value) {
+        $this->$name = $value;
+    }
+}
+$rc = new ReflectionClass(Proxy::class);
+$obj = $rc->newLazyProxy(function () {
+    return new RealInstance;
+});
+$obj->name = 0;
+
+var_dump($obj);
+
+?>
+--EXPECTF--
+lazy proxy object(Proxy)#%d (1) {
+  ["instance"]=>
+  object(RealInstance)#%d (2) {
+    ["_"]=>
+    NULL
+    ["name"]=>
+    int(0)
+  }
+}
diff '--color=auto' -Naur php-8.4.18/Zend/tests/lazy_objects/gh20504-004.phpt php-8.4.20RC1/Zend/tests/lazy_objects/gh20504-004.phpt
--- php-8.4.18/Zend/tests/lazy_objects/gh20504-004.phpt	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/Zend/tests/lazy_objects/gh20504-004.phpt	2026-04-01 04:35:35.983709773 +0000
@@ -0,0 +1,28 @@
+--TEST--
+GH-20504: Assertion failure in zend_get_property_guard() when lazy proxy adds magic method - proxy defines __isset(), both have guards
+--FILE--
+<?php
+
+class RealInstance {
+    public $_;
+    public function __get($name) {
+        printf("%s::%s\n", static::class, __FUNCTION__);
+    }
+}
+class Proxy extends RealInstance {
+    public function __isset($name) {
+        printf("%s::%s\n", static::class, __FUNCTION__);
+        return isset($this->$name['']);
+    }
+}
+$rc = new ReflectionClass(Proxy::class);
+$obj = $rc->newLazyProxy(function () {
+    return new RealInstance;
+});
+var_dump(isset($obj->name['']));
+
+?>
+--EXPECT--
+Proxy::__isset
+Proxy::__get
+bool(false)
diff '--color=auto' -Naur php-8.4.18/Zend/tests/lazy_objects/gh20504-005.phpt php-8.4.20RC1/Zend/tests/lazy_objects/gh20504-005.phpt
--- php-8.4.18/Zend/tests/lazy_objects/gh20504-005.phpt	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/Zend/tests/lazy_objects/gh20504-005.phpt	2026-04-01 04:35:35.983795125 +0000
@@ -0,0 +1,30 @@
+--TEST--
+GH-20504: Assertion failure in zend_get_property_guard() when lazy proxy adds magic method - unset
+--FILE--
+<?php
+
+class RealInstance {
+    public $_;
+}
+class Proxy extends RealInstance {
+    public function __unset($name) {
+        unset($this->$name);
+    }
+}
+$rc = new ReflectionClass(Proxy::class);
+$obj = $rc->newLazyProxy(function () {
+    return new RealInstance;
+});
+unset($obj->name);
+
+var_dump($obj);
+
+?>
+--EXPECTF--
+lazy proxy object(Proxy)#%d (1) {
+  ["instance"]=>
+  object(RealInstance)#%d (1) {
+    ["_"]=>
+    NULL
+  }
+}
diff '--color=auto' -Naur php-8.4.18/Zend/tests/lazy_objects/gh20657-001.phpt php-8.4.20RC1/Zend/tests/lazy_objects/gh20657-001.phpt
--- php-8.4.18/Zend/tests/lazy_objects/gh20657-001.phpt	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/Zend/tests/lazy_objects/gh20657-001.phpt	2026-04-01 04:35:35.983869375 +0000
@@ -0,0 +1,32 @@
+--TEST--
+GH-20657: GC during zend_lazy_object_realize()
+--CREDITS--
+vi3tL0u1s
+--FILE--
+<?php
+
+class C {
+    public $a;
+}
+
+$reflector = new ReflectionClass(C::class);
+
+for ($i = 0; $i < 10000; $i++) {
+    $obj = $reflector->newLazyGhost(function ($obj) {});
+
+    // Add to roots
+    $obj2 = $obj;
+    unset($obj2);
+
+    // Initialize all props to mark object non-lazy. Also create a cycle.
+    $reflector->getProperty('a')->setRawValueWithoutLazyInitialization($obj, $obj);
+}
+
+var_dump($obj);
+
+?>
+--EXPECTF--
+object(C)#%d (1) {
+  ["a"]=>
+  *RECURSION*
+}
diff '--color=auto' -Naur php-8.4.18/Zend/tests/lazy_objects/gh20657-002.phpt php-8.4.20RC1/Zend/tests/lazy_objects/gh20657-002.phpt
--- php-8.4.18/Zend/tests/lazy_objects/gh20657-002.phpt	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/Zend/tests/lazy_objects/gh20657-002.phpt	2026-04-01 04:35:35.983948214 +0000
@@ -0,0 +1,43 @@
+--TEST--
+GH-20657 002: GC during zend_lazy_object_realize() - reset as lazy during realize()
+--FILE--
+<?php
+
+class C {
+    public $a;
+}
+
+class D {
+    public $self;
+    public function __construct() {
+        $this->self = $this;
+    }
+    public function __destruct() {
+        global $obj, $reflector;
+        $reflector->resetAsLazyGhost($obj, function () {});
+    }
+}
+
+new D();
+
+$reflector = new ReflectionClass(C::class);
+
+for ($i = 0; $i < 10000; $i++) {
+    $obj = $reflector->newLazyGhost(function ($obj) {});
+
+    // Add to roots
+    $obj2 = $obj;
+    unset($obj2);
+
+    // Initialize all props to mark object non-lazy. Also create a cycle.
+    $reflector->getProperty('a')->setRawValueWithoutLazyInitialization($obj, $obj);
+}
+
+var_dump($obj);
+
+?>
+--EXPECTF--
+object(C)#%d (1) {
+  ["a"]=>
+  *RECURSION*
+}
diff '--color=auto' -Naur php-8.4.18/Zend/tests/lazy_objects/gh20854.phpt php-8.4.20RC1/Zend/tests/lazy_objects/gh20854.phpt
--- php-8.4.18/Zend/tests/lazy_objects/gh20854.phpt	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/Zend/tests/lazy_objects/gh20854.phpt	2026-04-01 04:35:35.984026121 +0000
@@ -0,0 +1,22 @@
+--TEST--
+GH-20854 (Assertion in ZEND_RETURN_BY_REF with lazy proxy and return-by-ref __get)
+--FILE--
+<?php
+class C {
+    public $prop;
+
+    function &__get($name) {
+        return $this->x;
+    }
+}
+
+$rc = new ReflectionClass(C::class);
+$obj = $rc->newLazyProxy(function () {
+    return new C;
+});
+$obj->x;
+echo "Done\n";
+?>
+--EXPECTF--
+Deprecated: Creation of dynamic property C::$x is deprecated in %s on line %d
+Done
diff '--color=auto' -Naur php-8.4.18/Zend/tests/lazy_objects/gh20873.phpt php-8.4.20RC1/Zend/tests/lazy_objects/gh20873.phpt
--- php-8.4.18/Zend/tests/lazy_objects/gh20873.phpt	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/Zend/tests/lazy_objects/gh20873.phpt	2026-04-01 04:35:35.984096614 +0000
@@ -0,0 +1,30 @@
+--TEST--
+GH-20873 (Assertion failure in _zendi_try_convert_scalar_to_number with lazy proxy)
+--FILE--
+<?php
+class A {
+    public $_;
+    public function __get($n) {
+        global $obj;
+        $obj->x =& $this->_;
+        static $a = $a;
+        $e =& $this->_ - $a;
+    }
+}
+$rc = new ReflectionClass(A::class);
+$obj = $rc->newLazyProxy(fn() => new A);
+$rc->initializeLazyObject($obj);
+var_dump($obj->p);
+?>
+--EXPECTF--
+Deprecated: Creation of dynamic property A::$x is deprecated in %s on line %d
+
+Warning: Undefined variable $a in %s on line %d
+
+Notice: Indirect modification of overloaded property A::$x has no effect in %s on line %d
+
+Fatal error: Uncaught Error: Cannot assign by reference to overloaded object in %s:%d
+Stack trace:
+#0 %s(%d): A->__get('p')
+#1 {main}
+  thrown in %s on line %d
diff '--color=auto' -Naur php-8.4.18/Zend/tests/lazy_objects/gh20875.phpt php-8.4.20RC1/Zend/tests/lazy_objects/gh20875.phpt
--- php-8.4.18/Zend/tests/lazy_objects/gh20875.phpt	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/Zend/tests/lazy_objects/gh20875.phpt	2026-04-01 04:35:35.984172899 +0000
@@ -0,0 +1,49 @@
+--TEST--
+GH-20875 (Assertion failure in _get_zval_ptr_tmp with lazy proxy)
+--FILE--
+<?php
+class A {
+    public $_;
+    public function __get($name) {
+        global $obj;
+        $obj->f =& $this->b - $x > $y = new StdClass;
+        static $a = $a;
+        $t = 'x';
+        foreach (get_defined_vars() as $key => $e) {}
+        if ($v ==!1) $x = $a ?: $t = "ok";
+    }
+}
+$rc = new ReflectionClass(A::class);
+$obj = $rc->newLazyProxy(function () { return new A; });
+$real = $rc->initializeLazyObject($obj);
+var_dump($real->prop);
+?>
+--EXPECTF--
+Deprecated: Creation of dynamic property A::$b is deprecated in %s on line %d
+
+Deprecated: Creation of dynamic property A::$f is deprecated in %s on line %d
+
+Warning: Undefined variable $x in %s on line %d
+
+Notice: Object of class stdClass could not be converted to int in %s on line %d
+
+Warning: Undefined variable $a in %s on line %d
+
+Warning: Undefined variable $v in %s on line %d
+
+Notice: Indirect modification of overloaded property A::$b has no effect in %s on line %d
+
+Warning: Undefined variable $x in %s on line %d
+
+Notice: Object of class stdClass could not be converted to int in %s on line %d
+
+Warning: Undefined variable $v in %s on line %d
+
+Notice: Indirect modification of overloaded property A::$f has no effect in %s on line %d
+
+Fatal error: Uncaught Error: Cannot assign by reference to overloaded object in %s:%d
+Stack trace:
+#0 %s(%d): A->__get('b')
+#1 %s(%d): A->__get('prop')
+#2 {main}
+  thrown in %s on line %d
diff '--color=auto' -Naur php-8.4.18/Zend/tests/lazy_objects/gh20875_proxy_get_no_init.phpt php-8.4.20RC1/Zend/tests/lazy_objects/gh20875_proxy_get_no_init.phpt
--- php-8.4.18/Zend/tests/lazy_objects/gh20875_proxy_get_no_init.phpt	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/Zend/tests/lazy_objects/gh20875_proxy_get_no_init.phpt	2026-04-01 04:35:35.984249393 +0000
@@ -0,0 +1,23 @@
+--TEST--
+GH-20875 (Lazy proxy should not initialize when __get handles dynamic property access)
+--FILE--
+<?php
+
+class Foo {
+    public $_;
+
+    public function &__get($name) {
+        echo "__get\n";
+        return $name;
+    }
+}
+
+$proxy = (new ReflectionClass(Foo::class))->newLazyProxy(function () {
+    echo "init\n";
+    return new Foo();
+});
+$x = &$proxy->x;
+
+?>
+--EXPECT--
+__get
diff '--color=auto' -Naur php-8.4.18/Zend/tests/oss-fuzz-478009707.phpt php-8.4.20RC1/Zend/tests/oss-fuzz-478009707.phpt
--- php-8.4.18/Zend/tests/oss-fuzz-478009707.phpt	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/Zend/tests/oss-fuzz-478009707.phpt	2026-04-01 04:35:35.984358299 +0000
@@ -0,0 +1,27 @@
+--TEST--
+OSS-Fuzz #478009707: Assign-op/inc/dec on untyped hooked property backing value
+--FILE--
+<?php
+
+class C {
+    public $prop {
+        set {
+            $this->prop = $value;
+            $this->prop += 1;
+            $this->prop++;
+            ++$this->prop;
+        }
+    }
+}
+
+$c = new C(1);
+$c->prop = 1;
+var_dump($c->prop);
+
+$c->prop = PHP_INT_MAX;
+var_dump($c->prop);
+
+?>
+--EXPECTF--
+int(4)
+float(%s)
diff '--color=auto' -Naur php-8.4.18/Zend/zend_call_stack.h php-8.4.20RC1/Zend/zend_call_stack.h
--- php-8.4.18/Zend/zend_call_stack.h	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/Zend/zend_call_stack.h	2026-04-01 04:35:35.984654058 +0000
@@ -21,6 +21,9 @@
 
 #include "zend.h"
 #include "zend_portability.h"
+#ifdef _MSC_VER
+# include <intrin.h>
+#endif
 #ifdef __APPLE__
 # include <pthread.h>
 #endif
diff '--color=auto' -Naur php-8.4.18/Zend/zend.h php-8.4.20RC1/Zend/zend.h
--- php-8.4.18/Zend/zend.h	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/Zend/zend.h	2026-04-01 04:35:59.692545423 +0000
@@ -20,7 +20,7 @@
 #ifndef ZEND_H
 #define ZEND_H
 
-#define ZEND_VERSION "4.4.18"
+#define ZEND_VERSION "4.4.20RC1"
 
 #define ZEND_ENGINE_3
 
diff '--color=auto' -Naur php-8.4.18/Zend/zend_hash.c php-8.4.20RC1/Zend/zend_hash.c
--- php-8.4.18/Zend/zend_hash.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/Zend/zend_hash.c	2026-04-01 04:35:35.984785777 +0000
@@ -169,7 +169,7 @@
 	void *data;
 	uint32_t nSize = ht->nTableSize;
 
-	ZEND_ASSERT(HT_SIZE_TO_MASK(nSize));
+	ZEND_ASSERT(HT_SIZE_TO_MASK(nSize) != 0);
 
 	if (UNEXPECTED(GC_FLAGS(ht) & IS_ARRAY_PERSISTENT)) {
 		data = pemalloc(HT_SIZE_EX(nSize, HT_SIZE_TO_MASK(nSize)), 1);
@@ -351,7 +351,7 @@
 	uint32_t i;
 	uint32_t nSize = ht->nTableSize;
 
-	ZEND_ASSERT(HT_SIZE_TO_MASK(nSize));
+	ZEND_ASSERT(HT_SIZE_TO_MASK(nSize) != 0);
 
 	HT_ASSERT_RC1(ht);
 	// Alloc before assign to avoid inconsistencies on OOM
@@ -399,7 +399,7 @@
 
 	if (nSize == 0) return;
 
-	ZEND_ASSERT(HT_SIZE_TO_MASK(nSize));
+	ZEND_ASSERT(HT_SIZE_TO_MASK(nSize) != 0);
 
 	if (UNEXPECTED(HT_FLAGS(ht) & HASH_FLAG_UNINITIALIZED)) {
 		if (nSize > ht->nTableSize) {
@@ -1318,7 +1318,7 @@
 		uint32_t nSize = ht->nTableSize + ht->nTableSize;
 		Bucket *old_buckets = ht->arData;
 
-		ZEND_ASSERT(HT_SIZE_TO_MASK(nSize));
+		ZEND_ASSERT(HT_SIZE_TO_MASK(nSize) != 0);
 
 		new_data = pemalloc(HT_SIZE_EX(nSize, HT_SIZE_TO_MASK(nSize)), GC_FLAGS(ht) & IS_ARRAY_PERSISTENT);
 		ht->nTableSize = nSize;
diff '--color=auto' -Naur php-8.4.18/Zend/zend.h.orig php-8.4.20RC1/Zend/zend.h.orig
--- php-8.4.18/Zend/zend.h.orig	1970-01-01 00:00:00.000000000 +0000
+++ php-8.4.20RC1/Zend/zend.h.orig	2026-02-10 17:48:03.000000000 +0000
@@ -0,0 +1,456 @@
+/*
+   +----------------------------------------------------------------------+
+   | Zend Engine                                                          |
+   +----------------------------------------------------------------------+
+   | Copyright (c) Zend Technologies Ltd. (http://www.zend.com)           |
+   +----------------------------------------------------------------------+
+   | This source file is subject to version 2.00 of the Zend license,     |
+   | that is bundled with this package in the file LICENSE, and is        |
+   | available through the world-wide-web at the following url:           |
+   | http://www.zend.com/license/2_00.txt.                                |
+   | If you did not receive a copy of the Zend license and are unable to  |
+   | obtain it through the world-wide-web, please send a note to          |
+   | license@zend.com so we can mail you a copy immediately.              |
+   +----------------------------------------------------------------------+
+   | Authors: Andi Gutmans <andi@php.net>                                 |
+   |          Zeev Suraski <zeev@php.net>                                 |
+   +----------------------------------------------------------------------+
+*/
+
+#ifndef ZEND_H
+#define ZEND_H
+
+#define ZEND_VERSION "4.4.18"
+
+#define ZEND_ENGINE_3
+
+#include "zend_types.h"
+#include "zend_map_ptr.h"
+#include "zend_errors.h"
+#include "zend_alloc.h"
+#include "zend_llist.h"
+#include "zend_string.h"
+#include "zend_hash.h"
+#include "zend_ast.h"
+#include "zend_gc.h"
+#include "zend_variables.h"
+#include "zend_iterators.h"
+#include "zend_stream.h"
+#include "zend_smart_str_public.h"
+#include "zend_smart_string_public.h"
+#include "zend_signal.h"
+#include "zend_max_execution_timer.h"
+
+#define zend_sprintf sprintf
+
+#define HANDLE_BLOCK_INTERRUPTIONS()		ZEND_SIGNAL_BLOCK_INTERRUPTIONS()
+#define HANDLE_UNBLOCK_INTERRUPTIONS()		ZEND_SIGNAL_UNBLOCK_INTERRUPTIONS()
+
+#define INTERNAL_FUNCTION_PARAMETERS zend_execute_data *execute_data, zval *return_value
+#define INTERNAL_FUNCTION_PARAM_PASSTHRU execute_data, return_value
+
+#define USED_RET() \
+	(!EX(prev_execute_data) || \
+	 !ZEND_USER_CODE(EX(prev_execute_data)->func->common.type) || \
+	 (EX(prev_execute_data)->opline->result_type != IS_UNUSED))
+
+#ifdef ZEND_ENABLE_STATIC_TSRMLS_CACHE
+#define ZEND_TSRMG TSRMG_STATIC
+#define ZEND_TSRMG_FAST TSRMG_FAST_STATIC
+#define ZEND_TSRMLS_CACHE_EXTERN() TSRMLS_CACHE_EXTERN()
+#define ZEND_TSRMLS_CACHE_DEFINE() TSRMLS_CACHE_DEFINE()
+#define ZEND_TSRMLS_CACHE_UPDATE() TSRMLS_CACHE_UPDATE()
+#define ZEND_TSRMLS_CACHE TSRMLS_CACHE
+#else
+#define ZEND_TSRMG TSRMG
+#define ZEND_TSRMG_FAST TSRMG_FAST
+#define ZEND_TSRMLS_CACHE_EXTERN()
+#define ZEND_TSRMLS_CACHE_DEFINE()
+#define ZEND_TSRMLS_CACHE_UPDATE()
+#define ZEND_TSRMLS_CACHE
+#endif
+
+#ifndef ZEND_COMPILE_DL_EXT
+TSRMLS_MAIN_CACHE_EXTERN()
+#else
+ZEND_TSRMLS_CACHE_EXTERN()
+#endif
+
+struct _zend_serialize_data;
+struct _zend_unserialize_data;
+
+typedef struct _zend_serialize_data zend_serialize_data;
+typedef struct _zend_unserialize_data zend_unserialize_data;
+
+typedef struct _zend_class_name {
+	zend_string *name;
+	zend_string *lc_name;
+} zend_class_name;
+
+typedef struct _zend_trait_method_reference {
+	zend_string *method_name;
+	zend_string *class_name;
+} zend_trait_method_reference;
+
+typedef struct _zend_trait_precedence {
+	zend_trait_method_reference trait_method;
+	uint32_t num_excludes;
+	zend_string *exclude_class_names[1];
+} zend_trait_precedence;
+
+typedef struct _zend_trait_alias {
+	zend_trait_method_reference trait_method;
+
+	/**
+	* name for method to be added
+	*/
+	zend_string *alias;
+
+	/**
+	* modifiers to be set on trait method
+	*/
+	uint32_t modifiers;
+} zend_trait_alias;
+
+typedef struct _zend_class_mutable_data {
+	zval      *default_properties_table;
+	HashTable *constants_table;
+	uint32_t   ce_flags;
+	HashTable *backed_enum_table;
+} zend_class_mutable_data;
+
+typedef struct _zend_class_dependency {
+	zend_string      *name;
+	zend_class_entry *ce;
+} zend_class_dependency;
+
+typedef struct _zend_inheritance_cache_entry zend_inheritance_cache_entry;
+
+typedef struct _zend_error_info {
+	int type;
+	uint32_t lineno;
+	zend_string *filename;
+	zend_string *message;
+} zend_error_info;
+
+struct _zend_inheritance_cache_entry {
+	zend_inheritance_cache_entry *next;
+	zend_class_entry             *ce;
+	zend_class_entry             *parent;
+	zend_class_dependency        *dependencies;
+	uint32_t                      dependencies_count;
+	uint32_t                      num_warnings;
+	zend_error_info             **warnings;
+	zend_class_entry             *traits_and_interfaces[1];
+};
+
+struct _zend_class_entry {
+	char type;
+	zend_string *name;
+	/* class_entry or string depending on ZEND_ACC_LINKED */
+	union {
+		zend_class_entry *parent;
+		zend_string *parent_name;
+	};
+	int refcount;
+	uint32_t ce_flags;
+
+	int default_properties_count;
+	int default_static_members_count;
+	zval *default_properties_table;
+	zval *default_static_members_table;
+	ZEND_MAP_PTR_DEF(zval *, static_members_table);
+	HashTable function_table;
+	HashTable properties_info;
+	HashTable constants_table;
+
+	ZEND_MAP_PTR_DEF(zend_class_mutable_data*, mutable_data);
+	zend_inheritance_cache_entry *inheritance_cache;
+
+	struct _zend_property_info **properties_info_table;
+
+	zend_function *constructor;
+	zend_function *destructor;
+	zend_function *clone;
+	zend_function *__get;
+	zend_function *__set;
+	zend_function *__unset;
+	zend_function *__isset;
+	zend_function *__call;
+	zend_function *__callstatic;
+	zend_function *__tostring;
+	zend_function *__debugInfo;
+	zend_function *__serialize;
+	zend_function *__unserialize;
+
+	const zend_object_handlers *default_object_handlers;
+
+	/* allocated only if class implements Iterator or IteratorAggregate interface */
+	zend_class_iterator_funcs *iterator_funcs_ptr;
+	/* allocated only if class implements ArrayAccess interface */
+	zend_class_arrayaccess_funcs *arrayaccess_funcs_ptr;
+
+	/* handlers */
+	union {
+		zend_object* (*create_object)(zend_class_entry *class_type);
+		int (*interface_gets_implemented)(zend_class_entry *iface, zend_class_entry *class_type); /* a class implements this interface */
+	};
+	zend_object_iterator *(*get_iterator)(zend_class_entry *ce, zval *object, int by_ref);
+	zend_function *(*get_static_method)(zend_class_entry *ce, zend_string* method);
+
+	/* serializer callbacks */
+	int (*serialize)(zval *object, unsigned char **buffer, size_t *buf_len, zend_serialize_data *data);
+	int (*unserialize)(zval *object, zend_class_entry *ce, const unsigned char *buf, size_t buf_len, zend_unserialize_data *data);
+
+	uint32_t num_interfaces;
+	uint32_t num_traits;
+	uint32_t num_hooked_props;
+	uint32_t num_hooked_prop_variance_checks;
+
+	/* class_entry or string(s) depending on ZEND_ACC_LINKED */
+	union {
+		zend_class_entry **interfaces;
+		zend_class_name *interface_names;
+	};
+
+	zend_class_name *trait_names;
+	zend_trait_alias **trait_aliases;
+	zend_trait_precedence **trait_precedences;
+	HashTable *attributes;
+
+	uint32_t enum_backing_type;
+	HashTable *backed_enum_table;
+
+	zend_string *doc_comment;
+
+	union {
+		struct {
+			zend_string *filename;
+			uint32_t line_start;
+			uint32_t line_end;
+		} user;
+		struct {
+			const struct _zend_function_entry *builtin_functions;
+			struct _zend_module_entry *module;
+		} internal;
+	} info;
+};
+
+typedef union {
+	zend_max_align_t align;
+	uint64_t opaque[5];
+} zend_random_bytes_insecure_state;
+
+typedef struct _zend_utility_functions {
+	void (*error_function)(int type, zend_string *error_filename, const uint32_t error_lineno, zend_string *message);
+	size_t (*printf_function)(const char *format, ...) ZEND_ATTRIBUTE_PTR_FORMAT(printf, 1, 2);
+	size_t (*write_function)(const char *str, size_t str_length);
+	FILE *(*fopen_function)(zend_string *filename, zend_string **opened_path);
+	void (*message_handler)(zend_long message, const void *data);
+	zval *(*get_configuration_directive)(zend_string *name);
+	void (*ticks_function)(int ticks);
+	void (*on_timeout)(int seconds);
+	zend_result (*stream_open_function)(zend_file_handle *handle);
+	void (*printf_to_smart_string_function)(smart_string *buf, const char *format, va_list ap);
+	void (*printf_to_smart_str_function)(smart_str *buf, const char *format, va_list ap);
+	char *(*getenv_function)(const char *name, size_t name_len);
+	zend_string *(*resolve_path_function)(zend_string *filename);
+	zend_result (*random_bytes_function)(void *bytes, size_t size, char *errstr, size_t errstr_size);
+	void (*random_bytes_insecure_function)(zend_random_bytes_insecure_state *state, void *bytes, size_t size);
+} zend_utility_functions;
+
+typedef struct _zend_utility_values {
+	bool html_errors;
+} zend_utility_values;
+
+typedef size_t (*zend_write_func_t)(const char *str, size_t str_length);
+
+#define zend_bailout()		_zend_bailout(__FILE__, __LINE__)
+
+#define zend_try												\
+	{															\
+		JMP_BUF *__orig_bailout = EG(bailout);					\
+		JMP_BUF __bailout;										\
+																\
+		EG(bailout) = &__bailout;								\
+		if (SETJMP(__bailout)==0) {
+#define zend_catch												\
+		} else {												\
+			EG(bailout) = __orig_bailout;
+#define zend_end_try()											\
+		}														\
+		EG(bailout) = __orig_bailout;							\
+	}
+#define zend_first_try		EG(bailout)=NULL;	zend_try
+
+BEGIN_EXTERN_C()
+void zend_startup(zend_utility_functions *utility_functions);
+void zend_shutdown(void);
+void zend_register_standard_ini_entries(void);
+zend_result zend_post_startup(void);
+void zend_set_utility_values(zend_utility_values *utility_values);
+void zend_unload_modules(void);
+
+ZEND_API ZEND_COLD ZEND_NORETURN void _zend_bailout(const char *filename, uint32_t lineno);
+ZEND_API size_t zend_get_page_size(void);
+
+ZEND_API size_t zend_vspprintf(char **pbuf, size_t max_len, const char *format, va_list ap);
+ZEND_API size_t zend_spprintf(char **message, size_t max_len, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 3, 4);
+ZEND_API zend_string *zend_vstrpprintf(size_t max_len, const char *format, va_list ap);
+ZEND_API zend_string *zend_strpprintf(size_t max_len, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3);
+
+/* Same as zend_spprintf and zend_strpprintf, without checking of format validity.
+ * For use with custom printf specifiers such as %H. */
+ZEND_API size_t zend_spprintf_unchecked(char **message, size_t max_len, const char *format, ...);
+ZEND_API zend_string *zend_strpprintf_unchecked(size_t max_len, const char *format, ...);
+
+ZEND_API const char *get_zend_version(void);
+ZEND_API bool zend_make_printable_zval(zval *expr, zval *expr_copy);
+ZEND_API size_t zend_print_zval(zval *expr, int indent);
+ZEND_API void zend_print_zval_r(zval *expr, int indent);
+ZEND_API zend_string *zend_print_zval_r_to_str(zval *expr, int indent);
+ZEND_API void zend_print_flat_zval_r(zval *expr);
+void zend_print_flat_zval_r_to_buf(smart_str *str, zval *expr);
+
+static zend_always_inline size_t zend_print_variable(zval *var) {
+	return zend_print_zval(var, 0);
+}
+
+ZEND_API ZEND_COLD void zend_output_debug_string(bool trigger_break, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3);
+
+ZEND_API void zend_activate(void);
+ZEND_API void zend_deactivate(void);
+ZEND_API void zend_call_destructors(void);
+ZEND_API void zend_activate_modules(void);
+ZEND_API void zend_deactivate_modules(void);
+ZEND_API void zend_post_deactivate_modules(void);
+
+ZEND_API void free_estring(char **str_p);
+
+END_EXTERN_C()
+
+/* output support */
+#define ZEND_WRITE(str, str_len)		zend_write((str), (str_len))
+#define ZEND_WRITE_EX(str, str_len)		write_func((str), (str_len))
+#define ZEND_PUTS(str)					zend_write((str), strlen((str)))
+#define ZEND_PUTS_EX(str)				write_func((str), strlen((str)))
+#define ZEND_PUTC(c)					zend_write(&(c), 1)
+
+BEGIN_EXTERN_C()
+extern ZEND_API size_t (*zend_printf)(const char *format, ...) ZEND_ATTRIBUTE_PTR_FORMAT(printf, 1, 2);
+extern ZEND_API zend_write_func_t zend_write;
+extern ZEND_API FILE *(*zend_fopen)(zend_string *filename, zend_string **opened_path);
+extern ZEND_API void (*zend_ticks_function)(int ticks);
+
+/* Called by the VM in certain places like at the loop header, user function
+ * entry, and after internal function calls, if EG(vm_interrupt) has been set.
+ *
+ * If this is used to switch the EG(current_execute_data), such as implementing
+ * a coroutine scheduler, then it needs to check the top frame to see if it's
+ * an internal function. If an internal function is on top, then the frame
+ * shouldn't be switched away.
+ *
+ * Prior to PHP 8.0, this check was not necessary. In PHP 8.0,
+ * zend_call_function started calling zend_interrupt_function, and in 8.4 the
+ * DO_*CALL* opcodes started calling the zend_interrupt_function while the
+ * internal frame is still on top.
+ */
+extern ZEND_API void (*zend_interrupt_function)(zend_execute_data *execute_data);
+
+extern ZEND_API void (*zend_error_cb)(int type, zend_string *error_filename, const uint32_t error_lineno, zend_string *message);
+extern ZEND_API void (*zend_on_timeout)(int seconds);
+extern ZEND_API zend_result (*zend_stream_open_function)(zend_file_handle *handle);
+extern void (*zend_printf_to_smart_string)(smart_string *buf, const char *format, va_list ap);
+extern void (*zend_printf_to_smart_str)(smart_str *buf, const char *format, va_list ap);
+extern ZEND_API char *(*zend_getenv)(const char *name, size_t name_len);
+extern ZEND_API zend_string *(*zend_resolve_path)(zend_string *filename);
+/* Generate 'size' random bytes into 'bytes' with the OS CSPRNG. */
+extern ZEND_ATTRIBUTE_NONNULL ZEND_API zend_result (*zend_random_bytes)(
+		void *bytes, size_t size, char *errstr, size_t errstr_size);
+/* Generate 'size' random bytes into 'bytes' with a general purpose PRNG (not
+ * crypto safe). 'state' must be zeroed before the first call and can be reused.
+ */
+extern ZEND_ATTRIBUTE_NONNULL ZEND_API void (*zend_random_bytes_insecure)(
+		zend_random_bytes_insecure_state *state, void *bytes, size_t size);
+
+/* These two callbacks are especially for opcache */
+extern ZEND_API zend_result (*zend_post_startup_cb)(void);
+extern ZEND_API void (*zend_post_shutdown_cb)(void);
+
+extern ZEND_API void (*zend_accel_schedule_restart_hook)(int reason);
+
+ZEND_API ZEND_COLD void zend_error(int type, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3);
+ZEND_API ZEND_COLD ZEND_NORETURN void zend_error_noreturn(int type, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3);
+ZEND_API ZEND_COLD ZEND_NORETURN void zend_error_noreturn_unchecked(int type, const char *format, ...);
+/* For custom format specifiers like H */
+ZEND_API ZEND_COLD void zend_error_unchecked(int type, const char *format, ...);
+/* If filename is NULL the default filename is used. */
+ZEND_API ZEND_COLD void zend_error_at(int type, zend_string *filename, uint32_t lineno, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 4, 5);
+ZEND_API ZEND_COLD ZEND_NORETURN void zend_error_at_noreturn(int type, zend_string *filename, uint32_t lineno, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 4, 5);
+ZEND_API ZEND_COLD void zend_error_zstr(int type, zend_string *message);
+ZEND_API ZEND_COLD void zend_error_zstr_at(int type, zend_string *filename, uint32_t lineno, zend_string *message);
+
+ZEND_API ZEND_COLD void zend_throw_error(zend_class_entry *exception_ce, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3);
+ZEND_API ZEND_COLD void zend_type_error(const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 1, 2);
+ZEND_API ZEND_COLD void zend_argument_count_error(const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 1, 2);
+ZEND_API ZEND_COLD void zend_value_error(const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 1, 2);
+/* type should be one of the BP_VAR_* constants, only special messages happen for isset/empty and unset */
+ZEND_API ZEND_COLD void zend_illegal_container_offset(const zend_string *container, const zval *offset, int type);
+
+ZEND_COLD void zenderror(const char *error);
+
+/* For internal C errors */
+ZEND_API ZEND_COLD ZEND_NORETURN void zend_strerror_noreturn(int type, int errn, const char *message);
+
+/* The following #define is used for code duality in PHP for Engine 1 & 2 */
+#define ZEND_STANDARD_CLASS_DEF_PTR zend_standard_class_def
+extern ZEND_API zend_class_entry *zend_standard_class_def;
+extern ZEND_API zend_utility_values zend_uv;
+
+/* If DTrace is available and enabled */
+extern ZEND_API bool zend_dtrace_enabled;
+END_EXTERN_C()
+
+#define ZEND_UV(name) (zend_uv.name)
+
+BEGIN_EXTERN_C()
+ZEND_API void zend_message_dispatcher(zend_long message, const void *data);
+
+ZEND_API zval *zend_get_configuration_directive(zend_string *name);
+END_EXTERN_C()
+
+/* Messages for applications of Zend */
+#define ZMSG_FAILED_INCLUDE_FOPEN		1L
+#define ZMSG_FAILED_REQUIRE_FOPEN		2L
+#define ZMSG_FAILED_HIGHLIGHT_FOPEN		3L
+#define ZMSG_MEMORY_LEAK_DETECTED		4L
+#define ZMSG_MEMORY_LEAK_REPEATED		5L
+#define ZMSG_LOG_SCRIPT_NAME			6L
+#define ZMSG_MEMORY_LEAKS_GRAND_TOTAL	7L
+
+typedef enum {
+	EH_NORMAL = 0,
+	EH_THROW
+} zend_error_handling_t;
+
+typedef struct {
+	zend_error_handling_t  handling;
+	zend_class_entry       *exception;
+} zend_error_handling;
+
+BEGIN_EXTERN_C()
+ZEND_API void zend_save_error_handling(zend_error_handling *current);
+ZEND_API void zend_replace_error_handling(zend_error_handling_t error_handling, zend_class_entry *exception_class, zend_error_handling *current);
+ZEND_API void zend_restore_error_handling(zend_error_handling *saved);
+ZEND_API void zend_begin_record_errors(void);
+ZEND_API void zend_emit_recorded_errors(void);
+ZEND_API void zend_free_recorded_errors(void);
+END_EXTERN_C()
+
+#define DEBUG_BACKTRACE_PROVIDE_OBJECT (1<<0)
+#define DEBUG_BACKTRACE_IGNORE_ARGS    (1<<1)
+
+#include "zend_object_handlers.h"
+#include "zend_operators.h"
+
+#endif /* ZEND_H */
diff '--color=auto' -Naur php-8.4.18/Zend/zend_lazy_objects.c php-8.4.20RC1/Zend/zend_lazy_objects.c
--- php-8.4.18/Zend/zend_lazy_objects.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/Zend/zend_lazy_objects.c	2026-04-01 04:35:35.984980484 +0000
@@ -678,8 +678,6 @@
 	ZEND_ASSERT(zend_object_is_lazy(obj));
 	ZEND_ASSERT(!zend_lazy_object_initialized(obj));
 
-	zend_lazy_object_del_info(obj);
-
 #if ZEND_DEBUG
 	for (int i = 0; i < obj->ce->default_properties_count; i++) {
 		ZEND_ASSERT(!(Z_PROP_FLAG_P(&obj->properties_table[i]) & IS_PROP_LAZY));
@@ -687,6 +685,7 @@
 #endif
 
 	OBJ_EXTRA_FLAGS(obj) &= ~(IS_OBJ_LAZY_UNINITIALIZED | IS_OBJ_LAZY_PROXY);
+	zend_lazy_object_del_info(obj);
 }
 
 ZEND_API HashTable *zend_lazy_object_get_properties(zend_object *object)
diff '--color=auto' -Naur php-8.4.18/Zend/zend_multiply.h php-8.4.20RC1/Zend/zend_multiply.h
--- php-8.4.18/Zend/zend_multiply.h	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/Zend/zend_multiply.h	2026-04-01 04:35:35.985082387 +0000
@@ -267,7 +267,8 @@
 		: "=&r"(res), "=&r"(m_overflow)
 		: "r"(nmemb),
 		  "r"(size),
-		  "r"(offset));
+		  "r"(offset)
+		: "cc");
 
 	if (UNEXPECTED(m_overflow)) {
 		*overflow = 1;
@@ -291,7 +292,8 @@
              : "=&r"(res), "=&r"(m_overflow)
              : "r"(nmemb),
                "r"(size),
-               "r"(offset));
+               "r"(offset)
+             : "xer");
 
         if (UNEXPECTED(m_overflow)) {
                 *overflow = 1;
diff '--color=auto' -Naur php-8.4.18/Zend/zend_object_handlers.c php-8.4.20RC1/Zend/zend_object_handlers.c
--- php-8.4.18/Zend/zend_object_handlers.c	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/Zend/zend_object_handlers.c	2026-04-01 04:35:35.985227661 +0000
@@ -956,25 +956,27 @@
 uninit_error:
 	if (UNEXPECTED(zend_lazy_object_must_init(zobj))) {
 		if (!prop_info || (Z_PROP_FLAG_P(retval) & IS_PROP_LAZY)) {
-			zobj = zend_lazy_object_init(zobj);
-			if (!zobj) {
+			zend_object *instance = zend_lazy_object_init(zobj);
+			if (!instance) {
 				retval = &EG(uninitialized_zval);
 				goto exit;
 			}
 
-			if (UNEXPECTED(guard)) {
+			if (UNEXPECTED(guard && (instance->ce->ce_flags & ZEND_ACC_USE_GUARDS))) {
+				/* Find which guard was used on zobj, so we can set the same
+				 * guard on instance. */
 				uint32_t guard_type = (type == BP_VAR_IS) && zobj->ce->__isset
 					? IN_ISSET : IN_GET;
-				guard = zend_get_property_guard(zobj, name);
+				guard = zend_get_property_guard(instance, name);
 				if (!((*guard) & guard_type)) {
 					(*guard) |= guard_type;
-					retval = zend_std_read_property(zobj, name, type, cache_slot, rv);
+					retval = zend_std_read_property(instance, name, type, cache_slot, rv);
 					(*guard) &= ~guard_type;
 					return retval;
 				}
 			}
 
-			return zend_std_read_property(zobj, name, type, cache_slot, rv);
+			return zend_std_read_property(instance, name, type, cache_slot, rv);
 		}
 	}
 	if (type != BP_VAR_IS) {
@@ -1013,7 +1015,7 @@
 		return &EG(error_zval);
 	}
 
-	if (UNEXPECTED(guarded)) {
+	if (UNEXPECTED(guarded && (instance->ce->ce_flags & ZEND_ACC_USE_GUARDS))) {
 		uint32_t *guard = zend_get_property_guard(instance, name);
 		if (!((*guard) & IN_SET)) {
 			(*guard) |= IN_SET;
@@ -1399,12 +1401,24 @@
 			    UNEXPECTED((*zend_get_property_guard(zobj, name)) & IN_GET) ||
 			    UNEXPECTED(prop_info && (Z_PROP_FLAG_P(retval) & IS_PROP_UNINIT))) {
 				if (UNEXPECTED(zend_lazy_object_must_init(zobj) && (Z_PROP_FLAG_P(retval) & IS_PROP_LAZY))) {
-					zobj = zend_lazy_object_init(zobj);
-					if (!zobj) {
+					bool guarded = zobj->ce->__get
+						&& (*zend_get_property_guard(zobj, name) & IN_GET);
+					zend_object *instance = zend_lazy_object_init(zobj);
+					if (!instance) {
 						return &EG(error_zval);
 					}
 
-					return zend_std_get_property_ptr_ptr(zobj, name, type, cache_slot);
+					if (guarded && (instance->ce->ce_flags & ZEND_ACC_USE_GUARDS)) {
+						uint32_t *guard = zend_get_property_guard(instance, name);
+						if (!(*guard & IN_GET)) {
+							(*guard) |= IN_GET;
+							retval = zend_std_get_property_ptr_ptr(instance, name, type, cache_slot);
+							(*guard) &= ~IN_GET;
+							return retval;
+						}
+					}
+
+					return zend_std_get_property_ptr_ptr(instance, name, type, cache_slot);
 				}
 				if (UNEXPECTED(type == BP_VAR_RW || type == BP_VAR_R)) {
 					if (prop_info) {
@@ -1447,6 +1461,25 @@
 		}
 		if (EXPECTED(!zobj->ce->__get) ||
 		    UNEXPECTED((*zend_get_property_guard(zobj, name)) & IN_GET)) {
+			if (UNEXPECTED(zend_lazy_object_must_init(zobj))) {
+				bool guarded = (zobj->ce->__get != NULL);
+				zend_object *instance = zend_lazy_object_init(zobj);
+				if (!instance) {
+					return &EG(error_zval);
+				}
+
+				if (guarded && (instance->ce->ce_flags & ZEND_ACC_USE_GUARDS)) {
+					uint32_t *guard = zend_get_property_guard(instance, name);
+					if (!(*guard & IN_GET)) {
+						(*guard) |= IN_GET;
+						retval = zend_std_get_property_ptr_ptr(instance, name, type, cache_slot);
+						(*guard) &= ~IN_GET;
+						return retval;
+					}
+				}
+
+				return zend_std_get_property_ptr_ptr(instance, name, type, cache_slot);
+			}
 			if (UNEXPECTED(zobj->ce->ce_flags & ZEND_ACC_NO_DYNAMIC_PROPERTIES)) {
 				zend_forbidden_dynamic_property(zobj->ce, name);
 				return &EG(error_zval);
@@ -1456,14 +1489,6 @@
 					return &EG(error_zval);
 				}
 			}
-			if (UNEXPECTED(zend_lazy_object_must_init(zobj))) {
-				zobj = zend_lazy_object_init(zobj);
-				if (!zobj) {
-					return &EG(error_zval);
-				}
-
-				return zend_std_get_property_ptr_ptr(zobj, name, type, cache_slot);
-			}
 			if (UNEXPECTED(!zobj->properties)) {
 				rebuild_object_properties_internal(zobj);
 			}
@@ -1597,7 +1622,7 @@
 			return;
 		}
 
-		if (UNEXPECTED(guard)) {
+		if (UNEXPECTED(guard && zobj->ce->ce_flags & ZEND_ACC_USE_GUARDS)) {
 			guard = zend_get_property_guard(zobj, name);
 			if (!((*guard) & IN_UNSET)) {
 				(*guard) |= IN_UNSET;
diff '--color=auto' -Naur php-8.4.18/Zend/zend_vm_def.h php-8.4.20RC1/Zend/zend_vm_def.h
--- php-8.4.18/Zend/zend_vm_def.h	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/Zend/zend_vm_def.h	2026-04-01 04:35:35.985779264 +0000
@@ -1070,7 +1070,7 @@
 					}
 
 					prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2);
-					if (prop_info) {
+					if (prop_info && ZEND_TYPE_IS_SET(prop_info->type)) {
 						/* special case for typed properties */
 						zend_binary_assign_op_typed_prop(prop_info, zptr, value OPLINE_CC EXECUTE_DATA_CC);
 					} else {
@@ -1326,7 +1326,8 @@
 				}
 			} else {
 				prop_info = (zend_property_info *) CACHED_PTR_EX(cache_slot + 2);
-				zend_pre_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC);
+				zend_pre_incdec_property_zval(zptr,
+					prop_info && ZEND_TYPE_IS_SET(prop_info->type) ? prop_info : NULL OPLINE_CC EXECUTE_DATA_CC);
 			}
 		} else {
 			zend_pre_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC);
@@ -1394,7 +1395,8 @@
 				ZVAL_NULL(EX_VAR(opline->result.var));
 			} else {
 				prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2);
-				zend_post_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC);
+				zend_post_incdec_property_zval(zptr,
+					prop_info && ZEND_TYPE_IS_SET(prop_info->type) ? prop_info : NULL OPLINE_CC EXECUTE_DATA_CC);
 			}
 		} else {
 			zend_post_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC);
diff '--color=auto' -Naur php-8.4.18/Zend/zend_vm_execute.h php-8.4.20RC1/Zend/zend_vm_execute.h
--- php-8.4.18/Zend/zend_vm_execute.h	2026-02-10 17:48:03.000000000 +0000
+++ php-8.4.20RC1/Zend/zend_vm_execute.h	2026-04-01 04:35:35.989935998 +0000
@@ -23590,7 +23590,7 @@
 					}
 
 					prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2);
-					if (prop_info) {
+					if (prop_info && ZEND_TYPE_IS_SET(prop_info->type)) {
 						/* special case for typed properties */
 						zend_binary_assign_op_typed_prop(prop_info, zptr, value OPLINE_CC EXECUTE_DATA_CC);
 					} else {
@@ -23798,7 +23798,8 @@
 				}
 			} else {
 				prop_info = (zend_property_info *) CACHED_PTR_EX(cache_slot + 2);
-				zend_pre_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC);
+				zend_pre_incdec_property_zval(zptr,
+					prop_info && ZEND_TYPE_IS_SET(prop_info->type) ? prop_info : NULL OPLINE_CC EXECUTE_DATA_CC);
 			}
 		} else {
 			zend_pre_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC);
@@ -23860,7 +23861,8 @@
 				ZVAL_NULL(EX_VAR(opline->result.var));
 			} else {
 				prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2);
-				zend_post_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC);
+				zend_post_incdec_property_zval(zptr,
+					prop_info && ZEND_TYPE_IS_SET(prop_info->type) ? prop_info : NULL OPLINE_CC EXECUTE_DATA_CC);
 			}
 		} else {
 			zend_post_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC);
@@ -26591,7 +26593,7 @@
 					}
 
 					prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2);
-					if (prop_info) {
+					if (prop_info && ZEND_TYPE_IS_SET(prop_info->type)) {
 						/* special case for typed properties */
 						zend_binary_assign_op_typed_prop(prop_info, zptr, value OPLINE_CC EXECUTE_DATA_CC);
 					} else {
@@ -26801,7 +26803,8 @@
 				}
 			} else {
 				prop_info = (zend_property_info *) CACHED_PTR_EX(cache_slot + 2);
-				zend_pre_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC);
+				zend_pre_incdec_property_zval(zptr,
+					prop_info && ZEND_TYPE_IS_SET(prop_info->type) ? prop_info : NULL OPLINE_CC EXECUTE_DATA_CC);
 			}
 		} else {
 			zend_pre_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC);
@@ -26864,7 +26867,8 @@
 				ZVAL_NULL(EX_VAR(opline->result.var));
 			} else {
 				prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2);
-				zend_post_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC);
+				zend_post_incdec_property_zval(zptr,
+					prop_info && ZEND_TYPE_IS_SET(prop_info->type) ? prop_info : NULL OPLINE_CC EXECUTE_DATA_CC);
 			}
 		} else {
 			zend_post_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC);
@@ -30951,7 +30955,7 @@
 					}
 
 					prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2);
-					if (prop_info) {
+					if (prop_info && ZEND_TYPE_IS_SET(prop_info->type)) {
 						/* special case for typed properties */
 						zend_binary_assign_op_typed_prop(prop_info, zptr, value OPLINE_CC EXECUTE_DATA_CC);
 					} else {
@@ -31159,7 +31163,8 @@
 				}
 			} else {
 				prop_info = (zend_property_info *) CACHED_PTR_EX(cache_slot + 2);
-				zend_pre_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC);
+				zend_pre_incdec_property_zval(zptr,
+					prop_info && ZEND_TYPE_IS_SET(prop_info->type) ? prop_info : NULL OPLINE_CC EXECUTE_DATA_CC);
 			}
 		} else {
 			zend_pre_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC);
@@ -31221,7 +31226,8 @@
 				ZVAL_NULL(EX_VAR(opline->result.var));
 			} else {
 				prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2);
-				zend_post_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC);
+				zend_post_incdec_property_zval(zptr,
+					prop_info && ZEND_TYPE_IS_SET(prop_info->type) ? prop_info : NULL OPLINE_CC EXECUTE_DATA_CC);
 			}
 		} else {
 			zend_post_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC);
@@ -33621,7 +33627,7 @@
 					}
 
 					prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2);
-					if (prop_info) {
+					if (prop_info && ZEND_TYPE_IS_SET(prop_info->type)) {
 						/* special case for typed properties */
 						zend_binary_assign_op_typed_prop(prop_info, zptr, value OPLINE_CC EXECUTE_DATA_CC);
 					} else {
@@ -33699,7 +33705,8 @@
 				}
 			} else {
 				prop_info = (zend_property_info *) CACHED_PTR_EX(cache_slot + 2);
-				zend_pre_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC);
+				zend_pre_incdec_property_zval(zptr,
+					prop_info && ZEND_TYPE_IS_SET(prop_info->type) ? prop_info : NULL OPLINE_CC EXECUTE_DATA_CC);
 			}
 		} else {
 			zend_pre_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC);
@@ -33761,7 +33768,8 @@
 				ZVAL_NULL(EX_VAR(opline->result.var));
 			} else {
 				prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2);
-				zend_post_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC);
+				zend_post_incdec_property_zval(zptr,
+					prop_info && ZEND_TYPE_IS_SET(prop_info->type) ? prop_info : NULL OPLINE_CC EXECUTE_DATA_CC);
 			}
 		} else {
 			zend_post_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC);
@@ -35807,7 +35815,7 @@
 					}
 
 					prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2);
-					if (prop_info) {
+					if (prop_info && ZEND_TYPE_IS_SET(prop_info->type)) {
 						/* special case for typed properties */
 						zend_binary_assign_op_typed_prop(prop_info, zptr, value OPLINE_CC EXECUTE_DATA_CC);
 					} else {
@@ -35885,7 +35893,8 @@
 				}
 			} else {
 				prop_info = (zend_property_info *) CACHED_PTR_EX(cache_slot + 2);
-				zend_pre_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC);
+				zend_pre_incdec_property_zval(zptr,
+					prop_info && ZEND_TYPE_IS_SET(prop_info->type) ? prop_info : NULL OPLINE_CC EXECUTE_DATA_CC);
 			}
 		} else {
 			zend_pre_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC);
@@ -35948,7 +35957,8 @@
 				ZVAL_NULL(EX_VAR(opline->result.var));
 			} else {
 				prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2);
-				zend_post_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC);
+				zend_post_incdec_property_zval(zptr,
+					prop_info && ZEND_TYPE_IS_SET(prop_info->type) ? prop_info : NULL OPLINE_CC EXECUTE_DATA_CC);
 			}
 		} else {
 			zend_post_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC);
@@ -38457,7 +38467,7 @@
 					}
 
 					prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2);
-					if (prop_info) {
+					if (prop_info && ZEND_TYPE_IS_SET(prop_info->type)) {
 						/* special case for typed properties */
 						zend_binary_assign_op_typed_prop(prop_info, zptr, value OPLINE_CC EXECUTE_DATA_CC);
 					} else {
@@ -38535,7 +38545,8 @@
 				}
 			} else {
 				prop_info = (zend_property_info *) CACHED_PTR_EX(cache_slot + 2);
-				zend_pre_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC);
+				zend_pre_incdec_property_zval(zptr,
+					prop_info && ZEND_TYPE_IS_SET(prop_info->type) ? prop_info : NULL OPLINE_CC EXECUTE_DATA_CC);
 			}
 		} else {
 			zend_pre_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC);
@@ -38597,7 +38608,8 @@
 				ZVAL_NULL(EX_VAR(opline->result.var));
 			} else {
 				prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2);
-				zend_post_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC);
+				zend_post_incdec_property_zval(zptr,
+					prop_info && ZEND_TYPE_IS_SET(prop_info->type) ? prop_info : NULL OPLINE_CC EXECUTE_DATA_CC);
 			}
 		} else {
 			zend_post_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC);
@@ -42612,7 +42624,7 @@
 					}
 
 					prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2);
-					if (prop_info) {
+					if (prop_info && ZEND_TYPE_IS_SET(prop_info->type)) {
 						/* special case for typed properties */
 						zend_binary_assign_op_typed_prop(prop_info, zptr, value OPLINE_CC EXECUTE_DATA_CC);
 					} else {
@@ -42820,7 +42832,8 @@
 				}
 			} else {
 				prop_info = (zend_property_info *) CACHED_PTR_EX(cache_slot + 2);
-				zend_pre_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC);
+				zend_pre_incdec_property_zval(zptr,
+					prop_info && ZEND_TYPE_IS_SET(prop_info->type) ? prop_info : NULL OPLINE_CC EXECUTE_DATA_CC);
 			}
 		} else {
 			zend_pre_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC);
@@ -42882,7 +42895,8 @@
 				ZVAL_NULL(EX_VAR(opline->result.var));
 			} else {
 				prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2);
-				zend_post_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC);
+				zend_post_incdec_property_zval(zptr,
+					prop_info && ZEND_TYPE_IS_SET(prop_info->type) ? prop_info : NULL OPLINE_CC EXECUTE_DATA_CC);
 			}
 		} else {
 			zend_post_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC);
@@ -46566,7 +46580,7 @@
 					}
 
 					prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2);
-					if (prop_info) {
+					if (prop_info && ZEND_TYPE_IS_SET(prop_info->type)) {
 						/* special case for typed properties */
 						zend_binary_assign_op_typed_prop(prop_info, zptr, value OPLINE_CC EXECUTE_DATA_CC);
 					} else {
@@ -46776,7 +46790,8 @@
 				}
 			} else {
 				prop_info = (zend_property_info *) CACHED_PTR_EX(cache_slot + 2);
-				zend_pre_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC);
+				zend_pre_incdec_property_zval(zptr,
+					prop_info && ZEND_TYPE_IS_SET(prop_info->type) ? prop_info : NULL OPLINE_CC EXECUTE_DATA_CC);
 			}
 		} else {
 			zend_pre_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC);
@@ -46839,7 +46854,8 @@
 				ZVAL_NULL(EX_VAR(opline->result.var));
 			} else {
 				prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2);
-				zend_post_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC);
+				zend_post_incdec_property_zval(zptr,
+					prop_info && ZEND_TYPE_IS_SET(prop_info->type) ? prop_info : NULL OPLINE_CC EXECUTE_DATA_CC);
 			}
 		} else {
 			zend_post_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC);
@@ -52071,7 +52087,7 @@
 					}
 
 					prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2);
-					if (prop_info) {
+					if (prop_info && ZEND_TYPE_IS_SET(prop_info->type)) {
 						/* special case for typed properties */
 						zend_binary_assign_op_typed_prop(prop_info, zptr, value OPLINE_CC EXECUTE_DATA_CC);
 					} else {
@@ -52279,7 +52295,8 @@
 				}
 			} else {
 				prop_info = (zend_property_info *) CACHED_PTR_EX(cache_slot + 2);
-				zend_pre_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC);
+				zend_pre_incdec_property_zval(zptr,
+					prop_info && ZEND_TYPE_IS_SET(prop_info->type) ? prop_info : NULL OPLINE_CC EXECUTE_DATA_CC);
 			}
 		} else {
 			zend_pre_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC);
@@ -52341,7 +52358,8 @@
 				ZVAL_NULL(EX_VAR(opline->result.var));
 			} else {
 				prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2);
-				zend_post_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC);
+				zend_post_incdec_property_zval(zptr,
+					prop_info && ZEND_TYPE_IS_SET(prop_info->type) ? prop_info : NULL OPLINE_CC EXECUTE_DATA_CC);
 			}
 		} else {
 			zend_post_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC);
