From a43f82d480aa039c3518fe3c2b3364fda353dbd2 Mon Sep 17 00:00:00 2001 From: Rick Lam Date: Thu, 22 Oct 2026 03:33:16 +0100 Subject: [PATCH 1/6] Add the Alpine 3.15 php7 aports recipe Verbatim copy of community/php7 from aports 3.15-stable (php 7.4.33-r1), fetched from git.alpinelinux.org. Every file matches the sha512sums in the APKBUILD. The next commit adds the CVE fix on top, so its diff shows only our changes. Refs #46 Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01Uugex1w8qZoTbBRbcFwkcp --- 7.4/aports/community/php7/APKBUILD | 730 ++++++++++++++++++ .../community/php7/CVE-2023-0567-1.patch | 144 ++++ .../community/php7/CVE-2023-0567-2.patch | 39 + 7.4/aports/community/php7/CVE-2023-0568.patch | 64 ++ .../community/php7/CVE-2023-0662-1.patch | 27 + .../community/php7/CVE-2023-0662-2.patch | 413 ++++++++++ 7.4/aports/community/php7/disabled-tests.list | 219 ++++++ 7.4/aports/community/php7/enchant-2.patch | 76 ++ .../community/php7/fix-curl-7.83-test.patch | 25 + .../community/php7/fix-fpm-syntax.patch | 33 + 7.4/aports/community/php7/fix-fpm-tests.patch | 58 ++ .../community/php7/fix-tests-devserver.patch | 23 + 7.4/aports/community/php7/includedir.patch | 41 + 7.4/aports/community/php7/install-pear.patch | 14 + .../php7/php7-fpm-version-suffix.patch | 79 ++ 7.4/aports/community/php7/php7-fpm.initd | 93 +++ 7.4/aports/community/php7/php7-fpm.logrotate | 13 + 7.4/aports/community/php7/php7-module.conf | 13 + 7.4/aports/community/php7/sharedir.patch | 11 + .../php7/xfail-openssl-1.1-test.patch | 13 + 20 files changed, 2128 insertions(+) create mode 100644 7.4/aports/community/php7/APKBUILD create mode 100644 7.4/aports/community/php7/CVE-2023-0567-1.patch create mode 100644 7.4/aports/community/php7/CVE-2023-0567-2.patch create mode 100644 7.4/aports/community/php7/CVE-2023-0568.patch create mode 100644 7.4/aports/community/php7/CVE-2023-0662-1.patch create mode 100644 7.4/aports/community/php7/CVE-2023-0662-2.patch create mode 100644 7.4/aports/community/php7/disabled-tests.list create mode 100644 7.4/aports/community/php7/enchant-2.patch create mode 100644 7.4/aports/community/php7/fix-curl-7.83-test.patch create mode 100644 7.4/aports/community/php7/fix-fpm-syntax.patch create mode 100644 7.4/aports/community/php7/fix-fpm-tests.patch create mode 100644 7.4/aports/community/php7/fix-tests-devserver.patch create mode 100644 7.4/aports/community/php7/includedir.patch create mode 100644 7.4/aports/community/php7/install-pear.patch create mode 100644 7.4/aports/community/php7/php7-fpm-version-suffix.patch create mode 100644 7.4/aports/community/php7/php7-fpm.initd create mode 100644 7.4/aports/community/php7/php7-fpm.logrotate create mode 100644 7.4/aports/community/php7/php7-module.conf create mode 100644 7.4/aports/community/php7/sharedir.patch create mode 100644 7.4/aports/community/php7/xfail-openssl-1.1-test.patch diff --git a/7.4/aports/community/php7/APKBUILD b/7.4/aports/community/php7/APKBUILD new file mode 100644 index 0000000..e069330 --- /dev/null +++ b/7.4/aports/community/php7/APKBUILD @@ -0,0 +1,730 @@ +# Contributor: Valery Kartel +# Contributor: Jakub Jirutka +# Maintainer: Valery Kartel + +# Bundled libraries +# +# Name | License | Location | State +# ----------+---------------------+------------------------+--------- +# bcmath | LGPL-2.1-or-later | ext/bcmath/libbcmath | used +# date | MIT | ext/date/lib | used +# fileinfo | BSD-2-Clause | ext/fileinfo/libmagic | used +# gd | BSD | ext/gd/libgd | used +# hash | CC0-1.0 | ext/hash/sha3 | used +# libmbfl | LGPL-2.1-only | ext/mbstring/libmbfl | used +# pcre | BSD-3-Clause | ext/pcre/pcrelib | not used +# sqlite3 | Public | ext/sqlite3/libsqlite | not used +# libXMLRPC | BSD-3-Clause | ext/xmlrpc/libxmlrpc | used +# libzip | BSD-3-Clause | ext/zip/lib | not used + +# Static extensions +# +# Name | Reason +# ----------+-------------------------------------------- +# zlib | https://bugs.alpinelinux.org/issues/8299 + +pkgname=php7 +_pkgreal=php +pkgver=7.4.33 +pkgrel=1 +_apiver=20190902 +_suffix=${pkgname#php} +# Is this package the default (latest) PHP version? +_default_php="yes" +pkgdesc="The PHP$_suffix language runtime engine" +url="https://www.php.net/" +arch="all" +license="PHP-3.01 BSD-3-Clause LGPL-2.0-or-later MIT Zend-2.0" +depends="$pkgname-common" +depends_dev="$pkgname=$pkgver-r$pkgrel autoconf pcre2-dev re2c" +# Most dependencies between extensions is auto-discovered (see _extension()). +_depends_mysqlnd="$pkgname-openssl" +_depends_pdo_mysql="$pkgname-pdo $pkgname-mysqlnd" +_depends_phar="$pkgname" +# openssl is actually transitive dependency here, but we need to because of +# load index based on number of dependencies. +_depends_mysqli="$pkgname-mysqlnd $pkgname-openssl" +makedepends=" + $depends_dev + apache2-dev + argon2-dev + aspell-dev + bison + bzip2-dev + curl-dev + enchant2-dev + freetds-dev + freetype-dev + gdbm-dev + gettext-dev + gmp-dev + icu-dev + imap-dev + krb5-dev + libedit-dev + libical-dev + libjpeg-turbo-dev + libpng-dev + libpq-dev + lmdb-dev + oniguruma-dev + libsodium-dev + libwebp-dev + libxml2-dev + libxpm-dev + libxslt-dev + libzip-dev + net-snmp-dev + openldap-dev + sqlite-dev + tidyhtml-dev + unixodbc-dev + zlib-dev + " +provides="$pkgname-cli php-cli php" # for backward compatibility +provider_priority=100 +subpackages="$pkgname-dbg $pkgname-dev $pkgname-doc + $pkgname-phpdbg $pkgname-apache2 + $pkgname-embed $pkgname-cgi $pkgname-fpm + $pkgname-pear::noarch + " +source="https://php.net/distributions/$_pkgreal-$pkgver.tar.xz + $pkgname-fpm.initd + $pkgname-fpm.logrotate + $pkgname-module.conf + disabled-tests.list + install-pear.patch + includedir.patch + sharedir.patch + php7-fpm-version-suffix.patch + fix-tests-devserver.patch + enchant-2.patch + xfail-openssl-1.1-test.patch + CVE-2023-0567-1.patch + CVE-2023-0567-2.patch + CVE-2023-0568.patch + CVE-2023-0662-1.patch + CVE-2023-0662-2.patch + fix-fpm-tests.patch + fix-fpm-syntax.patch + fix-curl-7.83-test.patch + " +builddir="$srcdir/$_pkgreal-$pkgver" + +_libdir="/usr/lib/$pkgname" +_extension_dir="$_libdir/modules" +_extension_confd="/etc/$pkgname/conf.d" + +_extensions=" + bcmath + bz2 + calendar + ctype + curl + dba + dom + enchant + exif + ffi + fileinfo + ftp + gd + gettext + gmp + iconv + imap + intl + json + ldap + mbstring + mysqli + mysqlnd + odbc + opcache + openssl + pcntl + pdo + pdo_dblib + pdo_mysql + pdo_odbc + pdo_pgsql + pdo_sqlite + pgsql + phar + posix + pspell + session + shmop + simplexml + snmp + soap + sodium + sockets + sqlite3 + sysvmsg + sysvsem + sysvshm + tidy + tokenizer + xml + xmlreader + xmlrpc + xmlwriter + xsl + zip + " +for _ext in $_extensions; do + case "$_ext" in + phar) subpackages="$subpackages $pkgname-$_ext:$_ext";; + *) subpackages="$subpackages $pkgname-$_ext:_extension";; + esac +done +subpackages="$subpackages $pkgname-common::noarch" + +# see https://gitlab.alpinelinux.org/alpine/aports/-/issues/12775 +[ "$CARCH" != "riscv64" ] && subpackages="$subpackages $pkgname-litespeed" + +# secfixes: +# 7.4.33-r1: +# - CVE-2023-0567 +# - CVE-2023-0568 +# - CVE-2023-0662 +# 7.4.33-r0: +# - CVE-2022-31630 +# - CVE-2022-37454 +# 7.4.32-r0: +# - CVE-2022-31628 +# - CVE-2022-31629 +# - CVE-2022-31625 +# - CVE-2022-31626 +# 7.4.28-r0: +# - CVE-2021-21708 +# 7.4.26-r0: +# - CVE-2021-21707 +# 7.4.25-r0: +# - CVE-2021-21703 +# 7.4.24-r0: +# - CVE-2021-21706 +# 7.4.21-r0: +# - CVE-2021-21705 +# 7.4.15-r0: +# - CVE-2021-21702 +# 7.4.14-r0: +# - CVE-2020-7071 +# 7.4.11-r0: +# - CVE-2020-7069 +# - CVE-2020-7070 +# 7.3.18-r0: +# - CVE-2019-11048 +# 7.3.17-r0: +# - CVE-2020-7067 +# 7.3.16-r0: +# - CVE-2020-7064 +# - CVE-2020-7065 +# - CVE-2020-7066 +# 7.3.15-r0: +# - CVE-2020-7061 +# - CVE-2020-7062 +# - CVE-2020-7063 +# 7.3.14-r0: +# - CVE-2020-7059 +# - CVE-2020-7060 +# 7.3.13-r0: +# - CVE-2019-11045 +# - CVE-2019-11047 +# - CVE-2019-11050 +# 7.3.11-r0: +# - CVE-2019-11043 +# 7.3.9-r0: +# - CVE-2019-13224 +# 7.3.8-r0: +# - CVE-2019-11041 +# - CVE-2019-11042 +# 7.2.19-r0: +# - CVE-2019-11039 +# - CVE-2019-11040 +# 7.2.18-r0: +# - CVE-2019-11036 +# 7.2.17-r0: +# - CVE-2019-11034 +# - CVE-2019-11035 +# 7.2.16-r0: +# - CVE-2019-9641 +# - CVE-2019-9640 +# - CVE-2019-9639 +# - CVE-2019-9638 +# - CVE-2019-9637 +# 7.2.14-r0: +# - CVE-2019-9024 +# - CVE-2019-9023 +# - CVE-2019-9022 +# - CVE-2019-9021 +# - CVE-2019-9020 +# 7.2.13-r0: +# - CVE-2018-20783 +# 7.2.8-r0: +# - CVE-2015-9253 +# - CVE-2018-12882 +# - CVE-2018-12883 +# - CVE-2018-14851 +# 7.2.5-r0: +# - CVE-2018-5712 +# - CVE-2018-10546 +# - CVE-2018-10547 +# - CVE-2018-10548 +# - CVE-2018-10549 + +prepare() { + default_prepare + + local vapi=$(sed -n '/#define PHP_API_VERSION/{s/.* //;p}' main/php.h) + if [ "$vapi" != "$_apiver" ]; then + error "Upstream API version is now $vapi. Expecting $_apiver" + error "After updating _apiver, all 3rd-party extensions must be rebuilt." + return 1 + fi + + # https://bugs.php.net/63362 - Not needed but installed headers. + # Drop some Windows specific headers to avoid installation, + # before build to ensure they are really not needed. + rm -f TSRM/tsrm_win32.h \ + TSRM/tsrm_config.w32.h \ + Zend/zend_config.w32.h \ + ext/mysqlnd/config-win.h \ + ext/standard/winver.h + + # Fix some bogus permissions. + find . -name '*.[ch]' -exec chmod 644 {} \; + + # XXX: Delete failing tests. + sed -n '/^[^#]/p' "$srcdir"/disabled-tests.list | while read -r item; do + rm -r $item # do it in this way to apply globbing... + done + + autoconf +} + +# Notes: +# * gd-jis-conv breaks any non-latin font rendering (vakartel). +# * libxml cannot be build as shared. +# * -D_LARGEFILE_SOURCE and -D_FILE_OFFSET_BITS=64 (https://www.php.net/manual/en/intro.filesystem.php andypost) +# * -O2 optimize for apps usage (andypost) +_build() { + local common_flags="-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64" + export CFLAGS="${CFLAGS/-Os/-O2} $common_flags" + export CXXFLAGS="${CXXFLAGS/-Os/-O2} $common_flags" + + local without_pcre_jit + [ "$CARCH" = "s390x" ] && without_pcre_jit="--without-pcre-jit" + + EXTENSION_DIR=$_extension_dir ./configure \ + --build=$CBUILD \ + --host=$CHOST \ + --prefix=/usr \ + --program-suffix=$_suffix \ + --libdir=$_libdir \ + --datadir=/usr/share/$pkgname \ + --sysconfdir=/etc/$pkgname \ + --localstatedir=/var \ + --with-layout=GNU \ + --with-pic \ + --with-config-file-path=/etc/$pkgname \ + --with-config-file-scan-dir=$_extension_confd \ + --disable-short-tags \ + \ + --enable-bcmath=shared \ + --with-bz2=shared \ + --enable-calendar=shared \ + --enable-ctype=shared \ + --with-curl=shared \ + --enable-dba=shared \ + --with-dbmaker=shared \ + --with-gdbm \ + --with-lmdb \ + --enable-dom=shared \ + --with-enchant=shared \ + --enable-exif=shared \ + --with-ffi=shared \ + --enable-fileinfo=shared \ + --enable-ftp=shared \ + --enable-gd=shared \ + --with-freetype \ + --with-jpeg \ + --with-webp \ + --with-xpm \ + --disable-gd-jis-conv \ + --with-gettext=shared \ + --with-gmp=shared \ + --with-iconv=shared \ + --with-imap=shared \ + --with-imap-ssl \ + --enable-intl=shared \ + --enable-json=shared \ + --with-ldap=shared \ + --with-ldap-sasl \ + --with-libedit \ + --with-libxml \ + --enable-mbstring=shared \ + --with-mysqli=shared,mysqlnd \ + --with-mysql-sock=/run/mysqld/mysqld.sock \ + --enable-mysqlnd=shared \ + --enable-opcache=shared \ + --with-openssl=shared \ + --with-kerberos \ + --with-system-ciphers \ + --with-password-argon2 \ + --enable-pcntl=shared \ + --with-external-pcre \ + $without_pcre_jit \ + --enable-pdo=shared \ + --with-pdo-dblib=shared \ + --with-pdo-mysql=shared,mysqlnd \ + --with-pdo-odbc=shared,unixODBC,/usr \ + --with-pdo-pgsql=shared \ + --with-pdo-sqlite=shared \ + --with-pgsql=shared \ + --enable-phar=shared \ + --enable-posix=shared \ + --with-pspell=shared \ + --without-readline \ + --enable-session=shared \ + --enable-shmop=shared \ + --enable-simplexml=shared \ + --with-snmp=shared \ + --enable-soap=shared \ + --with-sodium=shared \ + --enable-sockets=shared \ + --with-sqlite3=shared \ + --enable-sysvmsg=shared \ + --enable-sysvsem=shared \ + --enable-sysvshm=shared \ + --with-tidy=shared \ + --enable-tokenizer=shared \ + --with-unixODBC=shared,/usr \ + --enable-xml=shared \ + --enable-xmlreader=shared \ + --with-xmlrpc=shared \ + --enable-xmlwriter=shared \ + --with-xsl=shared \ + --with-zip=shared \ + --with-zlib \ + "$@" + make +} + +build() { + # apache2 SAPIs because not fixed https://bugs.php.net/bug.php?id=52419 + _build --disable-phpdbg \ + --disable-cli \ + --with-apxs2 + mv libs/libphp$_suffix.so sapi/apache2handler/mod_php$_suffix.so + + local enable_litespeed + [ -z ${subpackages##*-litespeed*} ] && enable_litespeed=--enable-litespeed + # cgi, cli, fpm, embed, pear, litespeed + _build --enable-phpdbg \ + --enable-phpdbg-webhelper \ + --with-pear=/usr/share/$pkgname \ + --enable-fpm \ + $enable_litespeed \ + --enable-embed +} + +check() { + # PHP is so stupid that it's not able to resolve dependencies + # between extensions and load them in correct order, so we must + # help it... + # opcache is Zend extension, it's handled specially in Makefile + local php_modules=$(_extensions_by_load_order \ + | grep -vx opcache \ + | xargs -n 1 printf "'$builddir/modules/%s.la' ") + sed -i "/^PHP_TEST_SHARED_EXTENSIONS/,/extension=/ \ + s|in \$(PHP_MODULES)\"*|in $php_modules|" Makefile + + # XXX: Few tests fail on the named platforms. + # Ignore it for now and continue build even on test failures. + local allow_fail='no' + case "$CARCH" in + x86 | s390x | mips*) allow_fail='yes' + esac + + TESTS="${TESTS:- --show-diff}" NO_INTERACTION=1 REPORT_EXIT_STATUS=1 \ + SKIP_SLOW_TESTS=1 SKIP_ONLINE_TESTS=1 TEST_TIMEOUT=10 \ + TZ='' LANG='' LC_ALL='' \ + TRAVIS=true SKIP_IO_CAPTURE_TESTS=1 \ + make test || [ "$allow_fail" = yes ] + + echo 'NOTE: We have skipped quite a lot tests, see disabled-tests.list.' +} + +package() { + make -j1 INSTALL_ROOT="$pkgdir" install + + install -Dm644 php.ini-production "$pkgdir"/etc/$pkgname/php.ini + + local file; for file in pear peardev pecl; do + sed -i -e "s|/usr/bin/php|/usr/bin/php$_suffix|g" \ + -e "s|PHP=php|PHP=php$_suffix|" \ + "$pkgdir"/usr/bin/$file + done + + find "$pkgdir" -name '.*' -print0 | xargs -0 rm -rf + rmdir "$pkgdir"/var/run + + if [ "$_default_php" = yes ]; then + ln -s php$_suffix "$pkgdir"/usr/bin/php + fi +} + +dev() { + default_dev + replaces="php-dev" + + cd "$pkgdir" + + _mv usr/bin/php-config$_suffix \ + usr/bin/phpize$_suffix \ + "$subpkgdir"/usr/bin/ + + _mv ./$_libdir/build "$subpkgdir"/$_libdir/ + + if [ "$_default_php" = yes ]; then + ln -s phpize$_suffix "$subpkgdir"/usr/bin/phpize + ln -s php-config$_suffix "$subpkgdir"/usr/bin/php-config + fi +} + +doc() { + default_doc + + cd "$builddir" + + mkdir -p "$subpkgdir"/usr/share/doc/$pkgname + cp CODING_STANDARDS.md EXTENSIONS LICENSE NEWS \ + README* UPGRADING* \ + "$subpkgdir"/usr/share/doc/$pkgname/ +} + +apache2() { + pkgdesc="PHP$_suffix Module for Apache2" + depends="$depends apache2" + provides="php-apache2" + + install -D -m 755 "$builddir"/sapi/apache2handler/mod_php$_suffix.so \ + "$subpkgdir"/usr/lib/apache2/mod_php$_suffix.so + + install -D -m 644 "$srcdir"/php$_suffix-module.conf \ + "$subpkgdir"/etc/apache2/conf.d/php$_suffix-module.conf +} + +phpdbg() { + pkgdesc="Interactive PHP$_suffix debugger" + provides="php-phpdbg" + + amove usr/bin/phpdbg$_suffix + + if [ "$_default_php" = yes ]; then + ln -s phpdbg$_suffix "$subpkgdir"/usr/bin/phpdbg + fi +} + +embed() { + pkgdesc="PHP$_suffix Embedded Library" + provides="php-embed" + + _mv "$pkgdir"/usr/lib/libphp*.so "$subpkgdir"/usr/lib/ +} + +litespeed() { + pkgdesc="PHP$_suffix LiteSpeed SAPI" + provides="php-lightspeed" + + mkdir -p "$subpkgdir"/usr/bin + mv "$pkgdir"/usr/bin/lsphp$_suffix "$subpkgdir"/usr/bin + + if [ "$_default_php" = yes ]; then + ln -s lsphp$_suffix "$subpkgdir"/usr/bin/lsphp + fi +} + +cgi() { + pkgdesc="PHP$_suffix Common Gateway Interface" + provides="php-cgi" + + _mv "$pkgdir"/usr/bin/php-cgi$_suffix "$subpkgdir"/usr/bin/ + + if [ "$_default_php" = yes ]; then + ln -s php-cgi$_suffix "$subpkgdir"/usr/bin/php-cgi + fi +} + +fpm() { + pkgdesc="PHP$_suffix FastCGI Process Manager" + provides="php-fpm" + + cd "$pkgdir" + + _mv var "$subpkgdir"/ + _mv usr/share/$pkgname/fpm "$subpkgdir"/var/lib/$pkgname/ + _mv usr/sbin "$subpkgdir"/usr/ + _mv etc/$pkgname/php-fpm* "$subpkgdir"/etc/$pkgname/ + + local file; for file in php-fpm.conf php-fpm.d/www.conf; do + mv "$subpkgdir"/etc/$pkgname/$file.default \ + "$subpkgdir"/etc/$pkgname/$file + done + + install -D -m 755 "$srcdir"/$pkgname-fpm.initd \ + "$subpkgdir"/etc/init.d/php-fpm$_suffix + + install -D -m 644 "$srcdir"/$pkgname-fpm.logrotate \ + "$subpkgdir"/etc/logrotate.d/php-fpm$_suffix + + mkdir -p "$subpkgdir"/var/log/$pkgname +} + +pear() { + pkgdesc="PHP$_suffix Extension and Application Repository" + depends="$pkgname $pkgname-xml" + provides="php-pear" + + cd "$pkgdir" + + mkdir -p "$subpkgdir"/usr/bin + local file; for file in pecl pear peardev; do + mv usr/bin/$file "$subpkgdir"/usr/bin/$file$_suffix + if [ "$_default_php" = yes ]; then + ln -s $file$_suffix "$subpkgdir"/usr/bin/$file + fi + done + + _mv etc/$pkgname/pear.conf "$subpkgdir"/etc/$pkgname/ + _mv usr/share "$subpkgdir"/usr/ +} + +common() { + pkgdesc="$pkgdesc (common config)" + provides="php-common $pkgname-zlib php-zlib" # for backward compatibility + depends="" + + cd "$pkgdir" + + _mv usr/lib "$subpkgdir"/usr/ + _mv etc "$subpkgdir"/ + mkdir -p "$subpkgdir"/$_extension_confd +} + +phar() { + _extension + + cd "$pkgdir" + + mkdir -p "$subpkgdir"/usr/bin + rm usr/bin/phar$_suffix + mv usr/bin/phar$_suffix.phar "$subpkgdir"/usr/bin/phar$_suffix.phar + ln -s phar$_suffix.phar "$subpkgdir"/usr/bin/phar$_suffix + ln -s phar$_suffix.phar "$subpkgdir"/usr/bin/phar.phar$_suffix + + if [ "$_default_php" = yes ]; then + ln -s phar$_suffix.phar "$subpkgdir"/usr/bin/phar.phar + ln -s phar$_suffix.phar "$subpkgdir"/usr/bin/phar + fi +} + +_extension() { + local extname="${subpkgname#$pkgname-}" + local extdepends="$(eval "echo \$_depends_$extname")" + local extdesc="$(head -n1 "$builddir"/ext/$extname/CREDITS 2>/dev/null ||:)" + pkgdesc="PHP$_suffix extension: ${extdesc:-$extname}" + provides="php-$extname" + + : ${extdepends:=$(_resolve_extension_deps "$extname")} + depends="$depends $extdepends" + + local load_order=$(_extension_load_order "$extname") + + # extension prefix + local prefix= + [ "$extname" != "opcache" ] || prefix="zend_" + + _mv "$pkgdir"/$_extension_dir/$extname.so \ + "$subpkgdir"/$_extension_dir/ + + mkdir -p "$subpkgdir"/$_extension_confd + echo "${prefix}extension=$extname.so" \ + > "$subpkgdir"/$_extension_confd/"$(printf %02d $load_order)"_$extname.ini +} + +# Resolves dependencies of the given extension name (without $pkgname- prefix) +# on other extensions in $_extensions and prints them with $pkgname- prefix. +_resolve_extension_deps() { + local name="$1" + + # We use config.w32 just because it's more accurate than config.m4. + local config="$builddir/ext/$name/config.w32" + [ -f "$config" ] || return 0 + + cat "$config" \ + | sed -En "s/.*ADD_EXTENSION_DEP\('$name', ([^)]+)\).*/\1/p" \ + | tr -d "'," | tr ' ' '\n' \ + | sort -u \ + | while read -r dep; do + if echo "$_extensions" | grep -qw "$dep"; then + echo "$pkgname-$dep" + fi + done +} + +# Prints a load order (0-based integer) for the given extension name. Extension +# with lower load order should be loaded before exts with higher load order. +# It's based on number of dependencies of the extension (with exception for +# "imap"), which is flawed, but simple and good enough for now. +_extension_load_order() { + local name="$1" + local deps=$(eval "echo \$_depends_$name") + + case "$name" in + # XXX: This must be loaded after recode, even though it does + # not depend on it. So we must use this hack... + *) echo "${deps:=$(_resolve_extension_deps $name)}" | wc -w;; + esac +} + +# Prints $_extensions sorted by load order and name. +_extensions_by_load_order() { + local deps list name + + for name in $_extensions; do + list="$list $(_extension_load_order $name);$name" + done + printf '%s\n' $list | sort -t ';' -k 1 | sed -E 's/\d+;//' +} + +_mv() { + local dest; for dest; do true; done # get last argument + mkdir -p "$dest" + mv "$@" +} + +sha512sums=" +499b63b99e5d8e8082ff89d3a91b4cb9a593ea7553b96e48863414c13d2e50275904ed29070e2232e529ee91160f505e6060a4d129cb5bf098aa5b6ea0928d3d php-7.4.33.tar.xz +1c708de82d1086f272f484faf6cf6d087af7c31750cc2550b0b94ed723961b363f28a947b015b2dfc0765caea185a75f5d2c2f2b099c948b65c290924f606e4f php7-fpm.initd +cacce7bf789467ff40647b7319e3760c6c587218720538516e8d400baa75651f72165c4e28056cd0c1dc89efecb4d00d0d7823bed80b29136262c825ce816691 php7-fpm.logrotate +274bd7b0b2b7002fa84c779640af37b59258bb37b05cb7dd5c89452977d71807f628d91b523b5039608376d1f760f3425d165242ca75ee5129b2730e71c4e198 php7-module.conf +ee221c1cf94783ef15780007eab8a9d5e38a8f939f9e25168687438c558e673a4c3b321d96017571cbe569756585003f750382981d0f02cf0a634d951b850f98 disabled-tests.list +a4130d29c7fee2b8cb561b116baf603bdc3a7b5b4985ec3c9918f253d1851197539dfad72c6b36d9f7008f85982904731184c79e4cee4415c1a1b88016639225 install-pear.patch +ebf571c5e595221b9944d7e840807ebb68c1be38bf117186e19a3bd1070310ece5918bcaa5f941679f3371a2108ad57bf179c3f90e612a5a2b982db941172859 includedir.patch +965b52893affb666af64e00d09e0208dcd41b17ce2864cf05616c6d05a05c0121694c0b209d403b8c0c55d18e6f1528c4aba1a4fcdce7b282a13304d12cd0f9d sharedir.patch +16399fbf6a966f9beffe00f659f9551ef8e52285bca116da5bd5b15ec99a2b0bd5fa03be0faa6c893802aa44c100d634083343a9ac0cd2467812865df66dd572 php7-fpm-version-suffix.patch +3bfeea79f9acfaa7be5bab85cd3d02713abb569e54024a22bb2c747c06d97f83ac2c63dcd75c7c409426ac03f8bc2ccc01bcd66bc39a767930d32542349123f9 fix-tests-devserver.patch +7c8c3cac9efce81d525cb5a70e1402e393881b83ef4c7b5d39d3565803d21cd283daf3d74e9a8b059ecac66cf339756acc63608ffcb83d960dba86583bd45108 enchant-2.patch +996b9a542858b0385a300265194afc57eddb72b9d7e4dcdf63b4f1ba7d3588e67309030acc73f00af1717168becd50b1d3582fcb88605e9892fd683a33cae023 xfail-openssl-1.1-test.patch +8dd578f264edaf372a6e787d65e2f8d45ea1af88036cc0d62251b6796aef327b8bd0a4df90eecdbd9e8a8c0e7501f90813a3af745e262151b7f7fe995c7a8c1b CVE-2023-0567-1.patch +35c9c4bdc8b4091d68ad65732c016dd33a0e3e92b3669dfbda7a107ca7c22d72955fecd73add0338873faf8344721838d72c0aa637fefdb6cdae7a1d310d570b CVE-2023-0567-2.patch +5fe3a0e9e1cf2e069d3b97c74a12d6f1c05faf694be7527a40a358afc1ee2dd6004f6ce0027c483eda7f6e835dc384258760b098c03d2af04950b58ac0e83cc8 CVE-2023-0568.patch +f7e87369658e333247896cb3cc6d56a54e2041453c0dc78180d7d31ac5008f98837039c215beda24e12b78ac183d70b7488e3d2978b159e565fc6517ed023cb1 CVE-2023-0662-1.patch +22c8f8b31b76832a0ccd45e0df808ba07e2cab67c7e6ca94d5cc124ad185fd0494a11ed1573b4ac03094c21979de40ecb4ee76cf8e63cd27f716aff189e9b28d CVE-2023-0662-2.patch +81fe1bc37129c8902c572d63f9c4c266cabf61c1217d8b079b020dd60ad49e725426dc201b4c0d044d8a6793b15a2a58eac6595ceb1f8a91aa9b2ea9728adfd6 fix-fpm-tests.patch +5582cbf13dcc9c536c6a9881183fedd40d35497c527e20e9e8e3288ce6219d9218dd16d9f43cc4412fd471b84df786076141f8409f950578b50d1540244f29f2 fix-fpm-syntax.patch +be6a57063414bd255def54d5f6e42cbdc3baec55c8eaf9c8ca6e96d0cb3fec942ebb1868806850859d34c5c45d03a2abfec3fecd1aef04524da8eda01d9041ed fix-curl-7.83-test.patch +" diff --git a/7.4/aports/community/php7/CVE-2023-0567-1.patch b/7.4/aports/community/php7/CVE-2023-0567-1.patch new file mode 100644 index 0000000..2863840 --- /dev/null +++ b/7.4/aports/community/php7/CVE-2023-0567-1.patch @@ -0,0 +1,144 @@ +Patch-Source: https://github.com/php/php-src/commit/c840f71524067aa474c00c3eacfb83bd860bfc8a + +From c840f71524067aa474c00c3eacfb83bd860bfc8a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= +Date: Mon, 23 Jan 2023 21:15:24 +0100 +Subject: [PATCH] crypt: Fix validation of malformed BCrypt hashes +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +PHP’s implementation of crypt_blowfish differs from the upstream Openwall +version by adding a “PHP Hack”, which allows one to cut short the BCrypt salt +by including a `$` character within the characters that represent the salt. + +Hashes that are affected by the “PHP Hack” may erroneously validate any +password as valid when used with `password_verify` and when comparing the +return value of `crypt()` against the input. + +The PHP Hack exists since the first version of PHP’s own crypt_blowfish +implementation that was added in 1e820eca02dcf322b41fd2fe4ed2a6b8309f8ab5. + +No clear reason is given for the PHP Hack’s existence. This commit removes it, +because BCrypt hashes containing a `$` character in their salt are not valid +BCrypt hashes. +--- + ext/standard/crypt_blowfish.c | 8 -- + .../tests/crypt/bcrypt_salt_dollar.phpt | 82 +++++++++++++++++++ + 2 files changed, 82 insertions(+), 8 deletions(-) + create mode 100644 ext/standard/tests/crypt/bcrypt_salt_dollar.phpt + +diff --git a/ext/standard/crypt_blowfish.c b/ext/standard/crypt_blowfish.c +index 3806a290aee4..351d40308089 100644 +--- a/ext/standard/crypt_blowfish.c ++++ b/ext/standard/crypt_blowfish.c +@@ -371,7 +371,6 @@ static const unsigned char BF_atoi64[0x60] = { + #define BF_safe_atoi64(dst, src) \ + { \ + tmp = (unsigned char)(src); \ +- if (tmp == '$') break; /* PHP hack */ \ + if ((unsigned int)(tmp -= 0x20) >= 0x60) return -1; \ + tmp = BF_atoi64[tmp]; \ + if (tmp > 63) return -1; \ +@@ -399,13 +398,6 @@ static int BF_decode(BF_word *dst, const char *src, int size) + *dptr++ = ((c3 & 0x03) << 6) | c4; + } while (dptr < end); + +- if (end - dptr == size) { +- return -1; +- } +- +- while (dptr < end) /* PHP hack */ +- *dptr++ = 0; +- + return 0; + } + +diff --git a/ext/standard/tests/crypt/bcrypt_salt_dollar.phpt b/ext/standard/tests/crypt/bcrypt_salt_dollar.phpt +new file mode 100644 +index 000000000000..32e335f4b087 +--- /dev/null ++++ b/ext/standard/tests/crypt/bcrypt_salt_dollar.phpt +@@ -0,0 +1,82 @@ ++--TEST-- ++bcrypt correctly rejects salts containing $ ++--FILE-- ++ ++--EXPECT-- ++string(8) "$2y$04$$" ++string(1) "*" ++bool(false) ++string(9) "$2y$04$0$" ++string(1) "*" ++bool(false) ++string(10) "$2y$04$00$" ++string(1) "*" ++bool(false) ++string(11) "$2y$04$000$" ++string(1) "*" ++bool(false) ++string(12) "$2y$04$0000$" ++string(1) "*" ++bool(false) ++string(13) "$2y$04$00000$" ++string(1) "*" ++bool(false) ++string(14) "$2y$04$000000$" ++string(1) "*" ++bool(false) ++string(15) "$2y$04$0000000$" ++string(1) "*" ++bool(false) ++string(16) "$2y$04$00000000$" ++string(1) "*" ++bool(false) ++string(17) "$2y$04$000000000$" ++string(1) "*" ++bool(false) ++string(18) "$2y$04$0000000000$" ++string(1) "*" ++bool(false) ++string(19) "$2y$04$00000000000$" ++string(1) "*" ++bool(false) ++string(20) "$2y$04$000000000000$" ++string(1) "*" ++bool(false) ++string(21) "$2y$04$0000000000000$" ++string(1) "*" ++bool(false) ++string(22) "$2y$04$00000000000000$" ++string(1) "*" ++bool(false) ++string(23) "$2y$04$000000000000000$" ++string(1) "*" ++bool(false) ++string(24) "$2y$04$0000000000000000$" ++string(1) "*" ++bool(false) ++string(25) "$2y$04$00000000000000000$" ++string(1) "*" ++bool(false) ++string(26) "$2y$04$000000000000000000$" ++string(1) "*" ++bool(false) ++string(27) "$2y$04$0000000000000000000$" ++string(1) "*" ++bool(false) ++string(28) "$2y$04$00000000000000000000$" ++string(1) "*" ++bool(false) ++string(29) "$2y$04$000000000000000000000$" ++string(1) "*" ++bool(false) ++string(30) "$2y$04$0000000000000000000000$" ++string(60) "$2y$04$000000000000000000000u2a2UpVexIt9k3FMJeAVr3c04F5tcI8K" ++bool(false) diff --git a/7.4/aports/community/php7/CVE-2023-0567-2.patch b/7.4/aports/community/php7/CVE-2023-0567-2.patch new file mode 100644 index 0000000..9141a9a --- /dev/null +++ b/7.4/aports/community/php7/CVE-2023-0567-2.patch @@ -0,0 +1,39 @@ +Patch-Source: https://github.com/php/php-src/commit/a92acbad873a05470af1a47cb785a18eadd827b5 + +From a92acbad873a05470af1a47cb785a18eadd827b5 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= +Date: Mon, 23 Jan 2023 22:13:57 +0100 +Subject: [PATCH] crypt: Fix possible buffer overread in php_crypt() + +--- + ext/standard/crypt.c | 1 + + ext/standard/tests/password/password_bcrypt_short.phpt | 8 ++++++++ + 2 files changed, 9 insertions(+) + create mode 100644 ext/standard/tests/password/password_bcrypt_short.phpt + +diff --git a/ext/standard/crypt.c b/ext/standard/crypt.c +index 8c105cf910e8..8316c8b96063 100644 +--- a/ext/standard/crypt.c ++++ b/ext/standard/crypt.c +@@ -135,6 +135,7 @@ PHPAPI zend_string *php_crypt(const char *password, const int pass_len, const ch + } else if ( + salt[0] == '$' && + salt[1] == '2' && ++ salt[2] != 0 && + salt[3] == '$') { + char output[PHP_MAX_SALT_LEN + 1]; + +diff --git a/ext/standard/tests/password/password_bcrypt_short.phpt b/ext/standard/tests/password/password_bcrypt_short.phpt +new file mode 100644 +index 000000000000..085bc8a23904 +--- /dev/null ++++ b/ext/standard/tests/password/password_bcrypt_short.phpt +@@ -0,0 +1,8 @@ ++--TEST-- ++Test that password_hash() does not overread buffers when a short hash is passed ++--FILE-- ++ ++--EXPECT-- ++bool(false) diff --git a/7.4/aports/community/php7/CVE-2023-0568.patch b/7.4/aports/community/php7/CVE-2023-0568.patch new file mode 100644 index 0000000..510fb6d --- /dev/null +++ b/7.4/aports/community/php7/CVE-2023-0568.patch @@ -0,0 +1,64 @@ +Patch-Source: https://github.com/php/php-src/commit/ec10b28d64decbc54aa1e585dce580f0bd7a5953 + +From ec10b28d64decbc54aa1e585dce580f0bd7a5953 Mon Sep 17 00:00:00 2001 +From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> +Date: Fri, 27 Jan 2023 19:28:27 +0100 +Subject: [PATCH] Fix array overrun when appending slash to paths + +Fix it by extending the array sizes by one character. As the input is +limited to the maximum path length, there will always be place to append +the slash. As the php_check_specific_open_basedir() simply uses the +strings to compare against each other, no new failures related to too +long paths are introduced. +We'll let the DOM and XML case handle a potentially too long path in the +library code. +--- + ext/dom/document.c | 2 +- + ext/xmlreader/php_xmlreader.c | 2 +- + main/fopen_wrappers.c | 6 +++--- + 3 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/ext/dom/document.c b/ext/dom/document.c +index dbbabb8bffde..fa6a6377ad5c 100644 +--- a/ext/dom/document.c ++++ b/ext/dom/document.c +@@ -1174,7 +1174,7 @@ static xmlDocPtr dom_document_parser(zval *id, int mode, char *source, size_t so + int validate, recover, resolve_externals, keep_blanks, substitute_ent; + int resolved_path_len; + int old_error_reporting = 0; +- char *directory=NULL, resolved_path[MAXPATHLEN]; ++ char *directory=NULL, resolved_path[MAXPATHLEN + 1]; + + if (id != NULL) { + intern = Z_DOMOBJ_P(id); +diff --git a/ext/xmlreader/php_xmlreader.c b/ext/xmlreader/php_xmlreader.c +index ecc52aa1d6f4..d8f8105010c7 100644 +--- a/ext/xmlreader/php_xmlreader.c ++++ b/ext/xmlreader/php_xmlreader.c +@@ -1024,7 +1024,7 @@ PHP_METHOD(XMLReader, XML) + xmlreader_object *intern = NULL; + char *source, *uri = NULL, *encoding = NULL; + int resolved_path_len, ret = 0; +- char *directory=NULL, resolved_path[MAXPATHLEN]; ++ char *directory=NULL, resolved_path[MAXPATHLEN + 1]; + xmlParserInputBufferPtr inputbfr; + xmlTextReaderPtr reader; + +diff --git a/main/fopen_wrappers.c b/main/fopen_wrappers.c +index 39a9c82d5984..5e4a619c8fe7 100644 +--- a/main/fopen_wrappers.c ++++ b/main/fopen_wrappers.c +@@ -129,10 +129,10 @@ PHPAPI ZEND_INI_MH(OnUpdateBaseDir) + */ + PHPAPI int php_check_specific_open_basedir(const char *basedir, const char *path) + { +- char resolved_name[MAXPATHLEN]; +- char resolved_basedir[MAXPATHLEN]; ++ char resolved_name[MAXPATHLEN + 1]; ++ char resolved_basedir[MAXPATHLEN + 1]; + char local_open_basedir[MAXPATHLEN]; +- char path_tmp[MAXPATHLEN]; ++ char path_tmp[MAXPATHLEN + 1]; + char *path_file; + size_t resolved_basedir_len; + size_t resolved_name_len; diff --git a/7.4/aports/community/php7/CVE-2023-0662-1.patch b/7.4/aports/community/php7/CVE-2023-0662-1.patch new file mode 100644 index 0000000..df7cf26 --- /dev/null +++ b/7.4/aports/community/php7/CVE-2023-0662-1.patch @@ -0,0 +1,27 @@ +Patch-Source: https://github.com/php/php-src/commit/e45850c195dcd5534394cf357a3f776d4916b655 + +From e45850c195dcd5534394cf357a3f776d4916b655 Mon Sep 17 00:00:00 2001 +From: Jakub Zelenka +Date: Thu, 19 Jan 2023 14:11:18 +0000 +Subject: [PATCH] Fix repeated warning for file uploads limit exceeding + +--- + main/rfc1867.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/main/rfc1867.c b/main/rfc1867.c +index c2f606c64aa1..b43cfae5a1e2 100644 +--- a/main/rfc1867.c ++++ b/main/rfc1867.c +@@ -911,7 +911,10 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) /* {{{ */ + skip_upload = 1; + } else if (upload_cnt <= 0) { + skip_upload = 1; +- sapi_module.sapi_error(E_WARNING, "Maximum number of allowable file uploads has been exceeded"); ++ if (upload_cnt == 0) { ++ --upload_cnt; ++ sapi_module.sapi_error(E_WARNING, "Maximum number of allowable file uploads has been exceeded"); ++ } + } + + /* Return with an error if the posted data is garbled */ diff --git a/7.4/aports/community/php7/CVE-2023-0662-2.patch b/7.4/aports/community/php7/CVE-2023-0662-2.patch new file mode 100644 index 0000000..360f86d --- /dev/null +++ b/7.4/aports/community/php7/CVE-2023-0662-2.patch @@ -0,0 +1,413 @@ +Patch-Source: https://github.com/php/php-src/commit/716de0cff539f46294ef70fe75d548cd66766370 + +From 716de0cff539f46294ef70fe75d548cd66766370 Mon Sep 17 00:00:00 2001 +From: Jakub Zelenka +Date: Thu, 19 Jan 2023 14:31:25 +0000 +Subject: [PATCH] Introduce max_multipart_body_parts INI + +This fixes GHSA-54hq-v5wp-fqgv DOS vulnerabality by limitting number of +parsed multipart body parts as currently all parts were always parsed. +--- + main/main.c | 1 + + main/rfc1867.c | 11 ++ + ...-54hq-v5wp-fqgv-max-body-parts-custom.phpt | 53 +++++++++ + ...54hq-v5wp-fqgv-max-body-parts-default.phpt | 54 +++++++++ + .../ghsa-54hq-v5wp-fqgv-max-file-uploads.phpt | 52 +++++++++ + sapi/fpm/tests/tester.inc | 106 +++++++++++++++--- + 6 files changed, 262 insertions(+), 15 deletions(-) + create mode 100644 sapi/fpm/tests/ghsa-54hq-v5wp-fqgv-max-body-parts-custom.phpt + create mode 100644 sapi/fpm/tests/ghsa-54hq-v5wp-fqgv-max-body-parts-default.phpt + create mode 100644 sapi/fpm/tests/ghsa-54hq-v5wp-fqgv-max-file-uploads.phpt + +diff --git a/main/main.c b/main/main.c +index 40684f32dc14..c58ea58bf5ac 100644 +--- a/main/main.c ++++ b/main/main.c +@@ -751,6 +751,7 @@ PHP_INI_BEGIN() + PHP_INI_ENTRY("disable_functions", "", PHP_INI_SYSTEM, NULL) + PHP_INI_ENTRY("disable_classes", "", PHP_INI_SYSTEM, NULL) + PHP_INI_ENTRY("max_file_uploads", "20", PHP_INI_SYSTEM|PHP_INI_PERDIR, NULL) ++ PHP_INI_ENTRY("max_multipart_body_parts", "-1", PHP_INI_SYSTEM|PHP_INI_PERDIR, NULL) + + STD_PHP_INI_BOOLEAN("allow_url_fopen", "1", PHP_INI_SYSTEM, OnUpdateBool, allow_url_fopen, php_core_globals, core_globals) + STD_PHP_INI_BOOLEAN("allow_url_include", "0", PHP_INI_SYSTEM, OnUpdateBool, allow_url_include, php_core_globals, core_globals) +diff --git a/main/rfc1867.c b/main/rfc1867.c +index b43cfae5a1e2..3086e8da3dbe 100644 +--- a/main/rfc1867.c ++++ b/main/rfc1867.c +@@ -687,6 +687,7 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) /* {{{ */ + void *event_extra_data = NULL; + unsigned int llen = 0; + int upload_cnt = INI_INT("max_file_uploads"); ++ int body_parts_cnt = INI_INT("max_multipart_body_parts"); + const zend_encoding *internal_encoding = zend_multibyte_get_internal_encoding(); + php_rfc1867_getword_t getword; + php_rfc1867_getword_conf_t getword_conf; +@@ -708,6 +709,11 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) /* {{{ */ + return; + } + ++ if (body_parts_cnt < 0) { ++ body_parts_cnt = PG(max_input_vars) + upload_cnt; ++ } ++ int body_parts_limit = body_parts_cnt; ++ + /* Get the boundary */ + boundary = strstr(content_type_dup, "boundary"); + if (!boundary) { +@@ -792,6 +798,11 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) /* {{{ */ + char *pair = NULL; + int end = 0; + ++ if (--body_parts_cnt < 0) { ++ php_error_docref(NULL, E_WARNING, "Multipart body parts limit exceeded %d. To increase the limit change max_multipart_body_parts in php.ini.", body_parts_limit); ++ goto fileupload_done; ++ } ++ + while (isspace(*cd)) { + ++cd; + } +diff --git a/sapi/fpm/tests/ghsa-54hq-v5wp-fqgv-max-body-parts-custom.phpt b/sapi/fpm/tests/ghsa-54hq-v5wp-fqgv-max-body-parts-custom.phpt +new file mode 100644 +index 000000000000..d2239ac3c410 +--- /dev/null ++++ b/sapi/fpm/tests/ghsa-54hq-v5wp-fqgv-max-body-parts-custom.phpt +@@ -0,0 +1,53 @@ ++--TEST-- ++FPM: GHSA-54hq-v5wp-fqgv - max_multipart_body_parts ini custom value ++--SKIPIF-- ++ ++--FILE-- ++start(); ++$tester->expectLogStartNotices(); ++echo $tester ++ ->request(stdin: [ ++ 'parts' => [ ++ 'count' => 30, ++ ] ++ ]) ++ ->getBody(); ++$tester->terminate(); ++$tester->close(); ++ ++?> ++--EXPECT-- ++Warning: Unknown: Multipart body parts limit exceeded 10. To increase the limit change max_multipart_body_parts in php.ini. in Unknown on line 0 ++int(10) ++--CLEAN-- ++ +diff --git a/sapi/fpm/tests/ghsa-54hq-v5wp-fqgv-max-body-parts-default.phpt b/sapi/fpm/tests/ghsa-54hq-v5wp-fqgv-max-body-parts-default.phpt +new file mode 100644 +index 000000000000..42b5afbf9ee7 +--- /dev/null ++++ b/sapi/fpm/tests/ghsa-54hq-v5wp-fqgv-max-body-parts-default.phpt +@@ -0,0 +1,54 @@ ++--TEST-- ++FPM: GHSA-54hq-v5wp-fqgv - max_multipart_body_parts ini default ++--SKIPIF-- ++ ++--FILE-- ++start(); ++$tester->expectLogStartNotices(); ++echo $tester ++ ->request(stdin: [ ++ 'parts' => [ ++ 'count' => 30, ++ ] ++ ]) ++ ->getBody(); ++$tester->terminate(); ++$tester->close(); ++ ++?> ++--EXPECT-- ++Warning: Unknown: Input variables exceeded 20. To increase the limit change max_input_vars in php.ini. in Unknown on line 0 ++ ++Warning: Unknown: Multipart body parts limit exceeded 25. To increase the limit change max_multipart_body_parts in php.ini. in Unknown on line 0 ++int(20) ++--CLEAN-- ++ +diff --git a/sapi/fpm/tests/ghsa-54hq-v5wp-fqgv-max-file-uploads.phpt b/sapi/fpm/tests/ghsa-54hq-v5wp-fqgv-max-file-uploads.phpt +new file mode 100644 +index 000000000000..da81174c7280 +--- /dev/null ++++ b/sapi/fpm/tests/ghsa-54hq-v5wp-fqgv-max-file-uploads.phpt +@@ -0,0 +1,52 @@ ++--TEST-- ++FPM: GHSA-54hq-v5wp-fqgv - exceeding max_file_uploads ++--SKIPIF-- ++ ++--FILE-- ++start(); ++$tester->expectLogStartNotices(); ++echo $tester ++ ->request(stdin: [ ++ 'parts' => [ ++ 'count' => 10, ++ 'param' => 'filename' ++ ] ++ ]) ++ ->getBody(); ++$tester->terminate(); ++$tester->close(); ++ ++?> ++--EXPECT-- ++Warning: Maximum number of allowable file uploads has been exceeded in Unknown on line 0 ++int(5) ++--CLEAN-- ++ +diff --git a/sapi/fpm/tests/tester.inc b/sapi/fpm/tests/tester.inc +index 6197cdba53f5..e51aa0f69143 100644 +--- a/sapi/fpm/tests/tester.inc ++++ b/sapi/fpm/tests/tester.inc +@@ -527,16 +527,16 @@ + * @param string $query + * @param array $headers + * @param string|null $uri +- * @param string|null $address +- * @param string|null $successMessage +- * @param string|null $errorMessage +- * @param bool $connKeepAlive ++ * @param string|null $scriptFilename ++ * @param string|null $stdin + * @return array + */ + private function getRequestParams( + string $query = '', + array $headers = [], +- string $uri = null ++ string $uri = null, ++ string $scriptFilename = null, ++ string $stdin = null + ) { + if (is_null($uri)) { + $uri = $this->makeSourceFile(); +@@ -545,8 +545,8 @@ + $params = array_merge( + [ + 'GATEWAY_INTERFACE' => 'FastCGI/1.0', +- 'REQUEST_METHOD' => 'GET', +- 'SCRIPT_FILENAME' => $uri, ++ 'REQUEST_METHOD' => is_null($stdin) ? 'GET' : 'POST', ++ 'SCRIPT_FILENAME' => $scriptFilename ?: $uri, + 'SCRIPT_NAME' => $uri, + 'QUERY_STRING' => $query, + 'REQUEST_URI' => $uri . ($query ? '?'.$query : ""), +@@ -560,7 +560,7 @@ + 'SERVER_PROTOCOL' => 'HTTP/1.1', + 'DOCUMENT_ROOT' => __DIR__, + 'CONTENT_TYPE' => '', +- 'CONTENT_LENGTH' => 0 ++ 'CONTENT_LENGTH' => strlen($stdin ?? "") // Default to 0 + ], + $headers + ); +@@ -571,16 +571,85 @@ + } + + /** +- * Execute request. ++ * Parse stdin and generate data for multipart config. + * +- * @param string $query ++ * @param array $stdin + * @param array $headers +- * @param string|null $uri +- * @param string|null $address +- * @param string|null $successMessage +- * @param string|null $errorMessage +- * @param bool $connKeepAlive ++ * ++ * @return void ++ * @throws \Exception ++ */ ++ private function parseStdin(array $stdin, array &$headers) ++ { ++ $parts = $stdin['parts'] ?? null; ++ if (empty($parts)) { ++ throw new \Exception('The stdin array needs to contain parts'); ++ } ++ $boundary = $stdin['boundary'] ?? 'AaB03x'; ++ if ( ! isset($headers['CONTENT_TYPE'])) { ++ $headers['CONTENT_TYPE'] = 'multipart/form-data; boundary=' . $boundary; ++ } ++ $count = $parts['count'] ?? null; ++ if ( ! is_null($count)) { ++ $dispositionType = $parts['disposition'] ?? 'form-data'; ++ $dispositionParam = $parts['param'] ?? 'name'; ++ $namePrefix = $parts['prefix'] ?? 'f'; ++ $nameSuffix = $parts['suffix'] ?? ''; ++ $value = $parts['value'] ?? 'test'; ++ $parts = []; ++ for ($i = 0; $i < $count; $i++) { ++ $parts[] = [ ++ 'disposition' => $dispositionType, ++ 'param' => $dispositionParam, ++ 'name' => "$namePrefix$i$nameSuffix", ++ 'value' => $value ++ ]; ++ } ++ } ++ $out = ''; ++ $nl = "\r\n"; ++ foreach ($parts as $part) { ++ if (!is_array($part)) { ++ $part = ['name' => $part]; ++ } elseif ( ! isset($part['name'])) { ++ throw new \Exception('Each part has to have a name'); ++ } ++ $name = $part['name']; ++ $dispositionType = $part['disposition'] ?? 'form-data'; ++ $dispositionParam = $part['param'] ?? 'name'; ++ $value = $part['value'] ?? 'test'; ++ $partHeaders = $part['headers'] ?? []; ++ ++ $out .= "--$boundary$nl"; ++ $out .= "Content-disposition: $dispositionType; $dispositionParam=\"$name\"$nl"; ++ foreach ($partHeaders as $headerName => $headerValue) { ++ $out .= "$headerName: $headerValue$nl"; ++ } ++ $out .= $nl; ++ $out .= "$value$nl"; ++ } ++ $out .= "--$boundary--$nl"; ++ ++ return $out; ++ } ++ ++ /** ++ * Execute request. ++ * ++ * @param string $query ++ * @param array $headers ++ * @param string|null $uri ++ * @param string|null $address ++ * @param string|null $successMessage ++ * @param string|null $errorMessage ++ * @param bool $connKeepAlive ++ * @param string|null $scriptFilename = null ++ * @param string|array|null $stdin = null ++ * @param bool $expectError ++ * @param int $readLimit ++ * + * @return Response ++ * @throws \Exception + */ + public function request( + string $query = '', +@@ -589,17 +658,24 @@ + string $address = null, + string $successMessage = null, + string $errorMessage = null, +- bool $connKeepAlive = false ++ bool $connKeepAlive = false, ++ string $scriptFilename = null, ++ $stdin = null, ++ bool $expectError = false, ++ int $readLimit = -1 + ) { + if ($this->hasError()) { + return new Response(null, true); + } + +- $params = $this->getRequestParams($query, $headers, $uri); ++ if (is_array($stdin)) { ++ $stdin = $this->parseStdin($stdin, $headers); ++ } + ++ $params = $this->getRequestParams($query, $headers, $uri, $scriptFilename, $stdin); + try { + $this->response = new Response( +- $this->getClient($address, $connKeepAlive)->request_data($params, false) ++ $this->getClient($address, $connKeepAlive)->request_data($params, $stdin, $readLimit) + ); + $this->message($successMessage); + } catch (\Exception $exception) { diff --git a/7.4/aports/community/php7/disabled-tests.list b/7.4/aports/community/php7/disabled-tests.list new file mode 100644 index 0000000..cbfd896 --- /dev/null +++ b/7.4/aports/community/php7/disabled-tests.list @@ -0,0 +1,219 @@ +# +# Tests that we don't need to run +# + +# These are mostly unit or regression tests, we care about integration tests. +tests/classes/* +Zend/tests/* + +# Windows tests +ext/standard/tests/file/windows_mb_path/* +ext/standard/tests/file/*win32*.phpt +ext/standard/tests/dir/*win32*.phpt + +# Require database or slow as dblib +ext/mysqli/tests/* +ext/odbc/tests/* +ext/pdo/tests/*.phpt +ext/pdo_dblib/tests/* +ext/pdo_mysql/tests/* +ext/pdo_odbc/tests/* +ext/pdo_pgsql/tests/* +ext/pgsql/tests/* + +# +# Tests that fail and probably should not... +# + +# Too many tests fail! Some of them bogus, some not. +# THIS SHOULD BE REALLY FIXED! +ext/openssl/tests/bug46127.phpt +ext/openssl/tests/bug48182.phpt +ext/openssl/tests/bug54992.phpt +ext/openssl/tests/bug65538_001.phpt +ext/openssl/tests/bug65538_003.phpt +ext/openssl/tests/bug65729.phpt +ext/openssl/tests/bug68265.phpt +ext/openssl/tests/bug68879.phpt +ext/openssl/tests/bug68920.phpt +ext/openssl/tests/bug69215.phpt +ext/openssl/tests/bug72333.phpt +ext/openssl/tests/bug74159.phpt +ext/openssl/tests/bug76705.phpt +ext/openssl/tests/bug77390.phpt +ext/openssl/tests/capture_peer_cert_001.phpt +ext/openssl/tests/openssl_peer_fingerprint_basic.phpt +ext/openssl/tests/peer_verification.phpt +ext/openssl/tests/san_peer_matching.phpt +ext/openssl/tests/session_meta_capture.phpt +ext/openssl/tests/session_meta_capture_tlsv13.phpt +ext/openssl/tests/sni_server.phpt +ext/openssl/tests/sni_server_key_cert.phpt +ext/openssl/tests/stream_crypto_flags_001.phpt +ext/openssl/tests/stream_crypto_flags_002.phpt +ext/openssl/tests/stream_crypto_flags_003.phpt +ext/openssl/tests/stream_crypto_flags_004.phpt +ext/openssl/tests/stream_security_level.phpt +ext/openssl/tests/stream_verify_peer_name_001.phpt +ext/openssl/tests/stream_verify_peer_name_002.phpt +ext/openssl/tests/stream_verify_peer_name_003.phpt +ext/openssl/tests/streams_crypto_method.phpt +ext/openssl/tests/tls_min_v1.0_max_v1.1_wrapper.phpt +ext/openssl/tests/tls_wrapper.phpt +ext/openssl/tests/tls_wrapper_with_tls_v1.3.phpt +ext/openssl/tests/tlsv1.0_wrapper.phpt +ext/openssl/tests/tlsv1.1_wrapper.phpt +ext/openssl/tests/tlsv1.2_wrapper.phpt +ext/openssl/tests/tlsv1.3_wrapper.phpt + +# Needs to open tls socket +ext/openssl/tests/bug62890.phpt + +# Broken tests, missing config. +sapi/fpm/tests/socket-ipv4-fallback.phpt + +# Fails in chroot (on Travis). +sapi/cli/tests/cli_process_title_unix.phpt + +# Error messages in different order. +sapi/cgi/tests/005.phpt + +# Fails on ppc64le. +sapi/phpdbg/tests/watch_006.phpt + +# Missing timezone in date. +ext/date/tests/bug27780.phpt +ext/date/tests/bug32555.phpt +ext/date/tests/bug33532.phpt + +# Number overflow!? +ext/date/tests/bug53437_var5.phpt +ext/date/tests/bug53437_var6.phpt +# fails on 32 bits +ext/date/tests/bug53437_var3.phpt + +# Incompatible version of enchant library? +ext/enchant/tests/broker_list_dicts.phpt +ext/enchant/tests/bug13181.phpt +# no warning but expected +ext/enchant/tests/bug53070.phpt + +# Wrong charset, conversion from `UTF-8' to `ASCII//TRANSLIT' is not allowed. +ext/iconv/tests/iconv_basic_001.phpt + +# Wrong charset, conversion from `UTF-8' to `UTF-8//IGNORE' is not allowed. +ext/iconv/tests/bug48147.phpt + +# stream_filter_append(): unable to create or locate filter "convert.iconv.ucs-2/utf-8//IGNORE" +ext/iconv/tests/bug76249.phpt + +# for ICU <= 57.1 +ext/intl/tests/spoofchecker_001.phpt +ext/intl/tests/timezone_IDforWindowsID_basic.phpt +ext/intl/tests/timezone_windowsID_basic.phpt + +# Class 'Phar' not found. +ext/opcache/tests/issue0115.phpt +ext/opcache/tests/issue0149.phpt + +# Fails in CI - Insufficient privileges. https://gitlab.alpinelinux.org/alpine/aports/-/issues/12692#note_169663 +ext/pcntl/tests/pcntl_unshare_01.phpt +ext/pcntl/tests/pcntl_unshare_02.phpt + +# Randomly fails. +ext/pcntl/tests/002.phpt +# Randomly fails on arm7 +ext/standard/tests/file/bug60120.phpt + +# Call to undefined function session_start(). +ext/session/tests/session_regenerate_id_cookie.phpt + +# Class 'SoapServer' not found. +ext/soap/tests/bug73037.phpt + +# Incorrect results. +ext/soap/tests/server009.phpt + +# Incorrect results. +ext/standard/tests/crypt/bcrypt_invalid_algorithm.phpt +ext/standard/tests/crypt/bcrypt_invalid_cost.phpt +ext/standard/tests/crypt/des_fallback_invalid_salt.phpt +ext/standard/tests/strings/crypt_blowfish.phpt +ext/standard/tests/strings/crypt_blowfish_variation1.phpt +ext/standard/tests/strings/crypt_blowfish_variation2.phpt + +# Incorrect results. +ext/standard/tests/strings/bug51059.phpt +ext/standard/tests/strings/bug79986.phpt + +# Failing tests related to locale and/or iconv. +ext/date/tests/009.phpt +ext/iconv/tests/bug52211.phpt +ext/intl/tests/bug67052.phpt +ext/json/tests/bug41403.phpt +ext/pcre/tests/ctype_back_to_c.phpt +ext/pcre/tests/locales.phpt +ext/soap/tests/bugs/bug39815.phpt +ext/standard/tests/array/locale_sort.phpt +ext/standard/tests/strings/htmlentities02.phpt +ext/standard/tests/strings/htmlentities03.phpt +ext/standard/tests/strings/moneyformat.phpt +ext/standard/tests/strings/setlocale_basic1.phpt +ext/standard/tests/strings/setlocale_basic2.phpt +ext/standard/tests/strings/setlocale_basic3.phpt +ext/standard/tests/strings/setlocale_error.phpt +ext/standard/tests/strings/setlocale_variation1.phpt +ext/standard/tests/strings/setlocale_variation2.phpt +ext/standard/tests/strings/setlocale_variation3.phpt +ext/standard/tests/strings/setlocale_variation4.phpt +ext/standard/tests/strings/setlocale_variation5.phpt +ext/standard/tests/strings/sprintf_f_3.phpt +ext/standard/tests/strings/strtoupper.phpt +ext/standard/tests/time/strptime_basic.phpt +ext/standard/tests/time/strptime_parts.phpt +tests/lang/034.phpt +tests/lang/bug30638.phpt + +# setlocale() does not affect result of nl_langinfo(CODESET) always returns UTF-8 +ext/fileinfo/tests/bug74170.phpt + +# no xml header displayed +ext/tidy/tests/020.phpt + +# +# Tests that fail for known reason and/or we don't need to worry about them +# + +# Fails due to unsupported JP charsets. +ext/iconv/tests/eucjp2iso2022jp.phpt +ext/iconv/tests/iconv_mime_encode.phpt +ext/standard/tests/strings/htmlentities04.phpt +ext/standard/tests/strings/htmlentities15.phpt + +# Requires running SNMP server. +ext/snmp/tests/* + +# Different wording of socket error messages (due to different libc). +ext/sockets/tests/socket_strerror.phpt + +# Expects permissions on /etc to be 40755 +ext/standard/tests/file/006_error.phpt + +# Fails probably due to differencies in musl. +ext/standard/tests/file/popen_pclose_error.phpt + +# Fails probably due to differencies in musl. +ext/sockets/tests/socket_create_pair-wrongparams.phpt + +# Fail due to libxml2 upgrade to 2.9.12 +# See: https://gitlab.alpinelinux.org/alpine/aports/-/issues/12692 +ext/dom/tests/DOMDocument_loadXML_error1.phpt +ext/dom/tests/DOMDocument_load_error1.phpt +ext/dom/tests/bug43364.phpt +ext/dom/tests/bug80268.phpt +ext/libxml/tests/bug61367-read.phpt +ext/libxml/tests/libxml_disable_entity_loader.phpt +sapi/fpm/tests/bug68391-conf-include-order.phpt + +# compilation failed https://gitlab.alpinelinux.org/alpine/aports/-/issues/13116 +ext/pcre/tests/bug70345.phpt diff --git a/7.4/aports/community/php7/enchant-2.patch b/7.4/aports/community/php7/enchant-2.patch new file mode 100644 index 0000000..9d421c3 --- /dev/null +++ b/7.4/aports/community/php7/enchant-2.patch @@ -0,0 +1,76 @@ +--- php-7.4.4/ext/enchant/config.m4 2020-03-17 10:40:22.000000000 +0000 ++++ php-7.4.4/ext/enchant/config.m4 2020-03-27 21:25:27.754470703 +0000 +@@ -4,21 +4,21 @@ PHP_ARG_WITH([enchant], + [Include Enchant support])]) + + if test "$PHP_ENCHANT" != "no"; then +- PKG_CHECK_MODULES([ENCHANT], [enchant]) ++ PKG_CHECK_MODULES([ENCHANT], [enchant-2]) + + PHP_EVAL_INCLINE($ENCHANT_CFLAGS) + PHP_EVAL_LIBLINE($ENCHANT_LIBS, ENCHANT_SHARED_LIBADD) + + AC_DEFINE(HAVE_ENCHANT, 1, [ ]) + +- PHP_CHECK_LIBRARY(enchant, enchant_get_version, ++ PHP_CHECK_LIBRARY(enchant-2, enchant_get_version, + [ + AC_DEFINE(HAVE_ENCHANT_GET_VERSION, 1, [ ]) + ], [ ], [ + $ENCHANT_LIBS + ]) + +- PHP_CHECK_LIBRARY(enchant, enchant_broker_set_param, ++ PHP_CHECK_LIBRARY(enchant-2, enchant_broker_set_param, + [ + AC_DEFINE(HAVE_ENCHANT_BROKER_SET_PARAM, 1, [ ]) + ], [ ], [ +--- a/ext/enchant/enchant.c.orig ++++ b/ext/enchant/enchant.c +@@ -738,7 +738,7 @@ + for (i = 0; i < n_sugg; i++) { + add_next_index_string(sugg, suggs[i]); + } +- enchant_dict_free_suggestions(pdict->pdict, suggs); ++ enchant_dict_free_string_list(pdict->pdict, suggs); + } + + +@@ -793,7 +793,7 @@ + add_next_index_string(return_value, suggs[i]); + } + +- enchant_dict_free_suggestions(pdict->pdict, suggs); ++ enchant_dict_free_string_list(pdict->pdict, suggs); + } + } + /* }}} */ +@@ -813,7 +813,7 @@ + + PHP_ENCHANT_GET_DICT; + +- enchant_dict_add_to_personal(pdict->pdict, word, wordlen); ++ enchant_dict_add(pdict->pdict, word, wordlen); + } + /* }}} */ + +@@ -851,7 +851,7 @@ + + PHP_ENCHANT_GET_DICT; + +- RETURN_BOOL(enchant_dict_is_in_session(pdict->pdict, word, wordlen)); ++ RETURN_BOOL(enchant_dict_is_added(pdict->pdict, word, wordlen)); + } + /* }}} */ + +--- php-7.4.4/build/php.m4 2020-03-17 06:40:21.000000000 -0400 ++++ php-7.4.4/build/php.m4 2020-04-05 09:27:14.634620646 -0400 +@@ -1541,7 +1541,7 @@ AC_DEFUN([PHP_CHECK_LIBRARY], [ + ],[ + LDFLAGS=$save_old_LDFLAGS + ext_shared=$save_ext_shared +- unset ac_cv_lib_$1[]_$2 ++ unset ac_cv_lib_[]translit($1, -, _)_$2 + $4 + ])dnl + ]) diff --git a/7.4/aports/community/php7/fix-curl-7.83-test.patch b/7.4/aports/community/php7/fix-curl-7.83-test.patch new file mode 100644 index 0000000..b087acf --- /dev/null +++ b/7.4/aports/community/php7/fix-curl-7.83-test.patch @@ -0,0 +1,25 @@ +From a4179e4c92b6365d39e09cb9cd63c476848013af Mon Sep 17 00:00:00 2001 +From: "Christoph M. Becker" +Date: Wed, 27 Apr 2022 12:37:39 +0200 +Subject: [PATCH] Fix test for curl 7.83.0 +Patch-Source: https://github.com/php/php-src/commit/a4179e4c92b6365d39e09cb9cd63c476848013af + +libcurl 7.83.0 removed some trailing exclamation marks from error +messages[1]; we have to cater to that. + +[1] +--- + ext/curl/tests/curl_basic_007.phpt | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ext/curl/tests/curl_basic_007.phpt b/ext/curl/tests/curl_basic_007.phpt +index 3b53658d6a7e..3834e4674f82 100644 +--- a/ext/curl/tests/curl_basic_007.phpt ++++ b/ext/curl/tests/curl_basic_007.phpt +@@ -20,5 +20,5 @@ curl_close($ch); + + ?> + --EXPECTF-- +-string(%d) "No URL set!%w" ++string(%d) "No URL set%A" + int(3) diff --git a/7.4/aports/community/php7/fix-fpm-syntax.patch b/7.4/aports/community/php7/fix-fpm-syntax.patch new file mode 100644 index 0000000..d6cd0bd --- /dev/null +++ b/7.4/aports/community/php7/fix-fpm-syntax.patch @@ -0,0 +1,33 @@ +--- a/sapi/fpm/tests/ghsa-54hq-v5wp-fqgv-max-body-parts-custom.phpt ++++ b/sapi/fpm/tests/ghsa-54hq-v5wp-fqgv-max-body-parts-custom.phpt +@@ -35,7 +35,7 @@ + $tester->start(); + $tester->expectLogStartNotices(); + echo $tester +- ->request(stdin: [ ++ ->request('', [], null, null, null, null, false, null, [ + 'parts' => [ + 'count' => 30, + ] +--- a/sapi/fpm/tests/ghsa-54hq-v5wp-fqgv-max-body-parts-default.phpt ++++ b/sapi/fpm/tests/ghsa-54hq-v5wp-fqgv-max-body-parts-default.phpt +@@ -34,7 +34,7 @@ + $tester->start(); + $tester->expectLogStartNotices(); + echo $tester +- ->request(stdin: [ ++ ->request('', [], null, null, null, null, false, null, [ + 'parts' => [ + 'count' => 30, + ] +--- a/sapi/fpm/tests/ghsa-54hq-v5wp-fqgv-max-file-uploads.phpt ++++ b/sapi/fpm/tests/ghsa-54hq-v5wp-fqgv-max-file-uploads.phpt +@@ -33,7 +33,7 @@ + $tester->start(); + $tester->expectLogStartNotices(); + echo $tester +- ->request(stdin: [ ++ ->request('', [], null, null, null, null, false, null, [ + 'parts' => [ + 'count' => 10, + 'param' => 'filename' diff --git a/7.4/aports/community/php7/fix-fpm-tests.patch b/7.4/aports/community/php7/fix-fpm-tests.patch new file mode 100644 index 0000000..a0d375e --- /dev/null +++ b/7.4/aports/community/php7/fix-fpm-tests.patch @@ -0,0 +1,58 @@ +Patch-Source: https://github.com/php/php-src/commit/e86d8704b44dde164e36b5364036e1988ac566fe + +From e86d8704b44dde164e36b5364036e1988ac566fe Mon Sep 17 00:00:00 2001 +From: Remi Collet +Date: Tue, 14 Feb 2023 14:13:40 +0100 +Subject: [PATCH] more config for new FPM tests + +--- + sapi/fpm/tests/ghsa-54hq-v5wp-fqgv-max-body-parts-custom.phpt | 4 +++- + .../fpm/tests/ghsa-54hq-v5wp-fqgv-max-body-parts-default.phpt | 4 +++- + sapi/fpm/tests/ghsa-54hq-v5wp-fqgv-max-file-uploads.phpt | 4 +++- + 3 files changed, 9 insertions(+), 3 deletions(-) + +diff --git a/sapi/fpm/tests/ghsa-54hq-v5wp-fqgv-max-body-parts-custom.phpt b/sapi/fpm/tests/ghsa-54hq-v5wp-fqgv-max-body-parts-custom.phpt +index d2239ac3c410..d5c4c4d46987 100644 +--- a/sapi/fpm/tests/ghsa-54hq-v5wp-fqgv-max-body-parts-custom.phpt ++++ b/sapi/fpm/tests/ghsa-54hq-v5wp-fqgv-max-body-parts-custom.phpt +@@ -21,7 +21,9 @@ php_admin_value[html_errors] = false + php_admin_value[max_input_vars] = 20 + php_admin_value[max_file_uploads] = 5 + php_admin_value[max_multipart_body_parts] = 10 +-php_flag[display_errors] = On ++php_admin_flag[display_errors] = On ++php_admin_flag[display_startup_errors] = On ++php_admin_flag[log_errors] = On + EOT; + + $code = << +Date: Mon, 01 May 2017 01:33:00 +0200 +Subject: [PATCH] Fix tests failing due to extra message from built-in web server + +Remove messages like: + + PHP 7.1.4 Development Server started at Mon May 1 00:42:39 2017 + +from test outputs, because tests do not expect them. I have no clue what +happens here... + +--- a/run-tests.php ++++ b/run-tests.php +@@ -2503,6 +2503,9 @@ + // Does the output match what is expected? + $output = preg_replace("/\r\n/", "\n", trim($out)); + ++ // Remove message from built-in development server. ++ $output = preg_replace("/^PHP [0-9.]+ Development Server started at .*\n\n?/m", "", $output); ++ + /* when using CGI, strip the headers from the output */ + $headers = array(); + diff --git a/7.4/aports/community/php7/includedir.patch b/7.4/aports/community/php7/includedir.patch new file mode 100644 index 0000000..c8874df --- /dev/null +++ b/7.4/aports/community/php7/includedir.patch @@ -0,0 +1,41 @@ +--- a/scripts/Makefile.frag ++++ b/scripts/Makefile.frag +@@ -2,7 +2,7 @@ + # Build environment install + # + +-phpincludedir = $(includedir)/php ++phpincludedir = $(includedir)/php7 + phpbuilddir = $(libdir)/build + + BUILD_FILES = \ +--- a/ext/pdo/Makefile.frag ++++ b/ext/pdo/Makefile.frag +@@ -1,4 +1,4 @@ +-phpincludedir=$(prefix)/include/php ++phpincludedir=$(prefix)/include/php7 + + PDO_HEADER_FILES= \ + php_pdo.h \ +--- a/scripts/php-config.in ++++ b/scripts/php-config.in +@@ -6,7 +6,7 @@ + exec_prefix="@exec_prefix@" + version="@PHP_VERSION@" + vernum="@PHP_VERSION_ID@" +-include_dir="@includedir@/php" ++include_dir="@includedir@/php7" + includes="-I$include_dir -I$include_dir/main -I$include_dir/TSRM -I$include_dir/Zend -I$include_dir/ext -I$include_dir/ext/date/lib" + ldflags="@PHP_LDFLAGS@" + libs="@EXTRA_LIBS@" +--- a/scripts/phpize.in ++++ b/scripts/phpize.in +@@ -5,7 +5,7 @@ + datarootdir='@datarootdir@' + exec_prefix="`eval echo @exec_prefix@`" + phpdir="`eval echo @libdir@`/build" +-includedir="`eval echo @includedir@`/php" ++includedir="`eval echo @includedir@`/php7" + builddir="`pwd`" + SED="@SED@" + diff --git a/7.4/aports/community/php7/install-pear.patch b/7.4/aports/community/php7/install-pear.patch new file mode 100644 index 0000000..831f60a --- /dev/null +++ b/7.4/aports/community/php7/install-pear.patch @@ -0,0 +1,14 @@ +--- ./pear/Makefile.frag.orig 2013-04-12 07:02:27.041602514 +0000 ++++ ./pear/Makefile.frag 2013-04-12 07:04:09.065836822 +0000 +@@ -1,7 +1,10 @@ + peardir=$(PEAR_INSTALLDIR) + ++# help the built php to find xml extension so we can install pear ++PEAR_INSTALL_XML_FLAGS = -d extension_dir="$(top_builddir)/modules" -d extension=xml.so ++ + # Skip all php.ini files altogether +-PEAR_INSTALL_FLAGS = -n -dshort_open_tag=0 -dopen_basedir= -derror_reporting=1803 -dmemory_limit=-1 -ddetect_unicode=0 ++PEAR_INSTALL_FLAGS = -n -dshort_open_tag=0 -dopen_basedir= -derror_reporting=1803 -dmemory_limit=-1 -ddetect_unicode=0 $(PEAR_INSTALL_XML_FLAGS) + + WGET = `which wget 2>/dev/null` + FETCH = `which fetch 2>/dev/null` diff --git a/7.4/aports/community/php7/php7-fpm-version-suffix.patch b/7.4/aports/community/php7/php7-fpm-version-suffix.patch new file mode 100644 index 0000000..d480f7a --- /dev/null +++ b/7.4/aports/community/php7/php7-fpm-version-suffix.patch @@ -0,0 +1,79 @@ +--- a/sapi/fpm/fpm/fpm_conf.c ++++ b/sapi/fpm/fpm/fpm_conf.c +@@ -1212,7 +1212,7 @@ + } + + if (!fpm_global_config.error_log) { +- fpm_global_config.error_log = strdup("log/php-fpm.log"); ++ fpm_global_config.error_log = strdup("log/php7/error.log"); + } + + #ifdef HAVE_SYSTEMD +@@ -1223,7 +1223,7 @@ + + #ifdef HAVE_SYSLOG_H + if (!fpm_global_config.syslog_ident) { +- fpm_global_config.syslog_ident = strdup("php-fpm"); ++ fpm_global_config.syslog_ident = strdup("php-fpm7"); + } + + if (fpm_global_config.syslog_facility < 0) { +@@ -1722,7 +1722,7 @@ + if (fpm_globals.prefix == NULL) { + spprintf(&tmp, 0, "%s/php-fpm.conf", PHP_SYSCONFDIR); + } else { +- spprintf(&tmp, 0, "%s/etc/php-fpm.conf", fpm_globals.prefix); ++ spprintf(&tmp, 0, "%s/etc/php7/php-fpm.conf", fpm_globals.prefix); + } + + if (!tmp) { + +--- a/sapi/fpm/php-fpm.conf.in ++++ b/sapi/fpm/php-fpm.conf.in +@@ -16,3 +16,3 @@ + ; Default Value: none +-;pid = run/php-fpm.pid ++;pid = run/php-fpm7.pid + +@@ -22,4 +22,4 @@ + ; Note: the default prefix is @EXPANDED_LOCALSTATEDIR@ +-; Default Value: log/php-fpm.log +-;error_log = log/php-fpm.log ++; Default Value: log/php7/error.log ++;error_log = log/php7/error.log + +@@ -35,4 +35,4 @@ + ; which must suit common needs. +-; Default Value: php-fpm +-;syslog.ident = php-fpm ++; Default Value: php-fpm7 ++;syslog.ident = php-fpm7 + +--- a/sapi/fpm/www.conf.in ++++ b/sapi/fpm/www.conf.in +@@ -257,7 +257,7 @@ + + ; The access log file + ; Default: not set +-;access.log = log/$pool.access.log ++;access.log = log/php7/$pool.access.log + + ; The access log format. + ; The following syntax is allowed +@@ -321,7 +321,7 @@ + ; The log file for slow requests + ; Default Value: not set + ; Note: slowlog is mandatory if request_slowlog_timeout is set +-;slowlog = log/$pool.log.slow ++;slowlog = log/php7/$pool.slow.log + + ; The timeout for serving a single request after which a PHP backtrace will be + ; dumped to the 'slowlog' file. A value of '0s' means 'off'. +@@ -434,6 +434,6 @@ + ; specified at startup with the -d argument + ;php_admin_value[sendmail_path] = /usr/sbin/sendmail -t -i -f www@my.domain.com + ;php_flag[display_errors] = off +-;php_admin_value[error_log] = /var/log/fpm-php.www.log ++;php_admin_value[error_log] = /var/log/php7/$pool.error.log + ;php_admin_flag[log_errors] = on + ;php_admin_value[memory_limit] = 32M diff --git a/7.4/aports/community/php7/php7-fpm.initd b/7.4/aports/community/php7/php7-fpm.initd new file mode 100644 index 0000000..f56fdb5 --- /dev/null +++ b/7.4/aports/community/php7/php7-fpm.initd @@ -0,0 +1,93 @@ +#!/sbin/openrc-run + +# If you want to run separate master process per pool, then create a symlink +# to this runscript for each pool. In that mode, the php-fpm daemon is started +# as nobody by default. You can override the user (and group) by declaring +# variable "user" and optionally "group" in conf.d file, or in the $fpm_config +# file (the former has precedence). + +: ${name:="PHP FastCGI Process Manager"} + +command="/usr/sbin/php-fpm7" +command_background="yes" +start_stop_daemon_args="--quiet" +pidfile="/run/$RC_SVCNAME/php-fpm.pid" +retry="SIGTERM/20" + +# configtest is here only for backward compatibility +extra_commands="checkconfig configtest" +extra_started_commands="reload reopen" +description_checkconfig="Run php-fpm config check" +description_reload="Gracefully reload workers and config" +description_reopen="Reopen log files" + +required_files="$fpm_config" + +depend() { + need net + use apache2 lighttpd nginx +} + +init_vars() { + # Defaults for single master process with multiple pools + if [ "$RC_SVCNAME" = "php-fpm7" ]; then + : ${fpm_config:="/etc/php7/php-fpm.conf"} + : ${user:="root"} + # Defaults for master process per pool + else + : ${fpm_config="/etc/php7/php-fpm.d/${RC_SVCNAME#php-fpm7.}.conf"} + : ${user:="$(conf_get user)"} + : ${user:="nobody"} + : ${group:="$(conf_get group)"} + fi + command_args="--nodaemonize --fpm-config $fpm_config" + start_stop_daemon_args="$start_stop_daemon_args + --user $user ${group:+"--group $group"}" +} + +start_pre() { + checkconfig || return 1 + + # If unix socket is used (instead of TCP/IP), then ensure that the + # directory exists and has correct privileges. + local listen="$(conf_get listen)" + if [ "${listen:0:1}" = "/" ]; then + checkpath -d -o $user:$group "$(dirname "$listen")" + fi + + checkpath -d "$(dirname "$pidfile")" +} + +reload() { + ebegin "Reloading $name" + start-stop-daemon --signal USR2 --pidfile "$pidfile" + eend $? +} + +reopen() { + ebegin "Reopening $name log files" + start-stop-daemon --signal USR1 --pidfile "$pidfile" + eend $? +} + +checkconfig() { + init_vars + ebegin "Checking $fpm_config" + + local out + out="$(su -s /bin/sh -c "$command --test --fpm-config $fpm_config" $user 2>&1)" || { + printf "%s\n" "$out" + eend 1 "failed, please correct errors above" + return 1 + } +} + +configtest() { + ewarn "configtest is deprecated, use checkconfig instead" + checkconfig +} + +conf_get() { + local key="$1" + sed -nE "s/^${key}\s*=\s*\"?([^\";]+).*/\1/p" "$fpm_config" | head -n 1 +} diff --git a/7.4/aports/community/php7/php7-fpm.logrotate b/7.4/aports/community/php7/php7-fpm.logrotate new file mode 100644 index 0000000..10e53e4 --- /dev/null +++ b/7.4/aports/community/php7/php7-fpm.logrotate @@ -0,0 +1,13 @@ +/var/log/php7/*.log { + rotate 7 + daily + missingok + notifempty + delaycompress + compress + dateext + sharedscripts + postrotate + /etc/init.d/php-fpm7 --ifstarted --quiet reopen + endscript +} diff --git a/7.4/aports/community/php7/php7-module.conf b/7.4/aports/community/php7/php7-module.conf new file mode 100644 index 0000000..4c26b8f --- /dev/null +++ b/7.4/aports/community/php7/php7-module.conf @@ -0,0 +1,13 @@ +LoadModule php7_module modules/mod_php7.so + +DirectoryIndex index.php index.html + + + SetHandler application/x-httpd-php + + +# Uncomment the following to allow .phps files to be handled by the php source filter, +# and displayed as syntax-highlighted source code +# +# SetHandler application/x-httpd-php-source +# diff --git a/7.4/aports/community/php7/sharedir.patch b/7.4/aports/community/php7/sharedir.patch new file mode 100644 index 0000000..2963e89 --- /dev/null +++ b/7.4/aports/community/php7/sharedir.patch @@ -0,0 +1,11 @@ +--- a/php.ini-production 2018-07-28 18:05:51.737130931 +0300 ++++ b/php.ini-production 2018-07-28 18:06:45.177774666 +0300 +@@ -733,7 +733,7 @@ + ;;;;;;;;;;;;;;;;;;;;;;;;; + + ; UNIX: "/path1:/path2" +-;include_path = ".:/php/includes" ++include_path = ".:/usr/share/php7" + ; + ; Windows: "\path1;\path2" + ;include_path = ".;c:\php\includes" diff --git a/7.4/aports/community/php7/xfail-openssl-1.1-test.patch b/7.4/aports/community/php7/xfail-openssl-1.1-test.patch new file mode 100644 index 0000000..f607cc1 --- /dev/null +++ b/7.4/aports/community/php7/xfail-openssl-1.1-test.patch @@ -0,0 +1,13 @@ +diff --git a/ext/openssl/tests/openssl_error_string_basic.phpt b/ext/openssl/tests/openssl_error_string_basic.phpt +index e4ea264b3b..fd1f7ef9d3 100644 +--- a/ext/openssl/tests/openssl_error_string_basic.phpt ++++ b/ext/openssl/tests/openssl_error_string_basic.phpt +@@ -2,6 +2,8 @@ + openssl_error_string() tests + --SKIPIF-- + ++--XFAIL-- ++Somehow unstable + --FILE-- + Date: Thu, 22 Oct 2026 03:34:05 +0100 Subject: [PATCH 2/6] Patch php7 for CVE-2026-109618 and CVE-2026-109619 Adds the upstream EOL fix (php-src 712e60f, "Avoid state corruption via bailout") to the Alpine 3.15 php7 recipe and bumps pkgrel to r2 so apk prefers our build over Alpine's r1. The upstream branch is based on plain 7.4.33, so its fix also introduces max_multipart_body_parts (CVE-2023-0662). Alpine already carries that in CVE-2023-0662-2.patch, so those four hunks are dropped and every Alpine patch is kept. The result applies cleanly on top of all 15 Alpine patches and its added lines are identical to ppa:ondrej/php 7.4.33-31, which ships the same fix. Refs #46 Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01Uugex1w8qZoTbBRbcFwkcp --- 7.4/aports/community/php7/APKBUILD | 4 +- .../php7/CVE-2026-109618-109619.patch | 932 ++++++++++++++++++ 2 files changed, 935 insertions(+), 1 deletion(-) create mode 100644 7.4/aports/community/php7/CVE-2026-109618-109619.patch diff --git a/7.4/aports/community/php7/APKBUILD b/7.4/aports/community/php7/APKBUILD index e069330..19851d7 100644 --- a/7.4/aports/community/php7/APKBUILD +++ b/7.4/aports/community/php7/APKBUILD @@ -26,7 +26,7 @@ pkgname=php7 _pkgreal=php pkgver=7.4.33 -pkgrel=1 +pkgrel=2 _apiver=20190902 _suffix=${pkgname#php} # Is this package the default (latest) PHP version? @@ -108,6 +108,7 @@ source="https://php.net/distributions/$_pkgreal-$pkgver.tar.xz fix-fpm-tests.patch fix-fpm-syntax.patch fix-curl-7.83-test.patch + CVE-2026-109618-109619.patch " builddir="$srcdir/$_pkgreal-$pkgver" @@ -727,4 +728,5 @@ f7e87369658e333247896cb3cc6d56a54e2041453c0dc78180d7d31ac5008f98837039c215beda24 81fe1bc37129c8902c572d63f9c4c266cabf61c1217d8b079b020dd60ad49e725426dc201b4c0d044d8a6793b15a2a58eac6595ceb1f8a91aa9b2ea9728adfd6 fix-fpm-tests.patch 5582cbf13dcc9c536c6a9881183fedd40d35497c527e20e9e8e3288ce6219d9218dd16d9f43cc4412fd471b84df786076141f8409f950578b50d1540244f29f2 fix-fpm-syntax.patch be6a57063414bd255def54d5f6e42cbdc3baec55c8eaf9c8ca6e96d0cb3fec942ebb1868806850859d34c5c45d03a2abfec3fecd1aef04524da8eda01d9041ed fix-curl-7.83-test.patch +1f73855623c03ce6202610500989a6f08eb3a7cd4a80d007fd078644b142b8e51aab28fefab876c03c935f112c7162d696d42cb983961f6cb6c3c4586513bb49 CVE-2026-109618-109619.patch " diff --git a/7.4/aports/community/php7/CVE-2026-109618-109619.patch b/7.4/aports/community/php7/CVE-2026-109618-109619.patch new file mode 100644 index 0000000..e6d2734 --- /dev/null +++ b/7.4/aports/community/php7/CVE-2026-109618-109619.patch @@ -0,0 +1,932 @@ +From 712e60f9edfd03f0960fc4fc3c2c375f42b90aa2 Mon Sep 17 00:00:00 2001 +From: Arnaud Le Blanc +Date: Sun, 18 Oct 2026 20:09:54 +0200 +Subject: [PATCH] Avoid state corruption via bailout + +Minimal mitigation for EOL version. + +Fix GHSA-w8hw-w9fx-j79w (CVE-2026-109618) +Fix GHSA-6wmf-4rv5-p3rp (CVE-2026-109619) + +Co-authored-by: Ilija Tovilo +--- + Zend/zend_API.h | 1 + + Zend/zend_alloc.c | 68 ++++++++++++++++++++--------- + Zend/zend_alloc.h | 2 + + Zend/zend_execute_API.c | 13 ++++++ + Zend/zend_hash.c | 13 ++++-- + Zend/zend_hash.h | 1 + + Zend/zend_llist.c | 2 + + Zend/zend_multiply.h | 4 +- + Zend/zend_strtod.c | 4 +- + Zend/zend_types.h | 26 +++++++----- + Zend/zend_vm_def.h | 11 ++++- + Zend/zend_vm_execute.h | 94 +++++++++++++++++++++++++++++++++++++---- + ext/session/session.c | 2 +- + main/SAPI.c | 5 +++ + main/main.c | 6 +++ + main/php_variables.c | 8 ++-- + main/rfc1867.c | 39 ++++++++++++++--- + 17 files changed, 240 insertions(+), 59 deletions(-) +diff --git a/Zend/zend_API.h b/Zend/zend_API.h +index 2a3b582902f3..26f7726bd8cc 100644 +--- a/Zend/zend_API.h ++++ b/Zend/zend_API.h +@@ -380,6 +380,7 @@ ZEND_API char *zend_get_type_by_const(int type); + + #define array_init(arg) ZVAL_ARR((arg), zend_new_array(0)) + #define array_init_size(arg, size) ZVAL_ARR((arg), zend_new_array(size)) ++#define array_init_singleton(arg) ZVAL_ARR((arg), zend_new_array_singleton()) + ZEND_API int object_init(zval *arg); + ZEND_API int object_init_ex(zval *arg, zend_class_entry *ce); + ZEND_API int object_and_properties_init(zval *arg, zend_class_entry *ce, HashTable *properties); +diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c +index 3a33e5441c70..be9b975426be 100644 +--- a/Zend/zend_alloc.c ++++ b/Zend/zend_alloc.c +@@ -57,6 +57,7 @@ + #include "zend_operators.h" + #include "zend_multiply.h" + #include "zend_bitset.h" ++#include "zend_execute.h" + #include + + #ifdef HAVE_UNISTD_H +@@ -363,7 +364,42 @@ static ZEND_COLD ZEND_NORETURN void zend_mm_panic(const char *message) + #if ZEND_DEBUG && defined(HAVE_KILL) && defined(HAVE_GETPID) + kill(getpid(), SIGSEGV); + #endif +- exit(1); ++ _exit(1); ++} ++ ++ZEND_API ZEND_COLD ZEND_NORETURN void zend_mm_safe_error_ex(const char *format, ...) ++{ ++ zend_string *script_filename = NULL; ++ uint32_t script_lineno = 0; ++ ++ if (zend_is_executing()) { ++ script_filename = zend_get_executed_filename_ex(); ++ script_lineno = zend_get_executed_lineno(); ++ } else if (zend_is_compiling()) { ++ script_filename = zend_get_compiled_filename(); ++ script_lineno = zend_get_compiled_lineno(); ++ } ++ ++ va_list args; ++ va_start(args, format); ++ ++ char buf[1024]; ++ vsnprintf(buf, sizeof(buf), format, args); ++ ++ va_end(args); ++ ++ fprintf(stderr, ++ "\nFatal error: %s in %s on line %d\n", ++ buf, ++ script_filename ? ZSTR_VAL(script_filename) : "Unknown", ++ script_lineno); ++ ++ /* See http://support.microsoft.com/kb/190351 */ ++# ifdef ZEND_WIN32 ++ fflush(stderr); ++# endif ++ ++ _exit(1); + } + + static ZEND_COLD ZEND_NORETURN void zend_mm_safe_error(zend_mm_heap *heap, +@@ -375,22 +411,14 @@ static ZEND_COLD ZEND_NORETURN void zend_mm_safe_error(zend_mm_heap *heap, + #endif + size_t size) + { ++ (void) heap; + +- heap->overflow = 1; +- zend_try { +- zend_error_noreturn(E_ERROR, +- format, +- limit, ++ zend_mm_safe_error_ex(format, limit, + #if ZEND_DEBUG +- filename, +- lineno, ++ filename, ++ lineno, + #endif +- size); +- } zend_catch { +- } zend_end_try(); +- heap->overflow = 0; +- zend_bailout(); +- exit(1); ++ size); + } + + #ifdef _WIN32 +@@ -1318,7 +1346,7 @@ static zend_always_inline void *zend_mm_alloc_heap(zend_mm_heap *heap, size_t si + size = MAX(size, 1); + size = ZEND_MM_ALIGNED_SIZE(size) + ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_debug_info)); + if (UNEXPECTED(size < real_size)) { +- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu + %zu)", ZEND_MM_ALIGNED_SIZE(real_size), ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_debug_info))); ++ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (%zu + %zu)", ZEND_MM_ALIGNED_SIZE(real_size), ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_debug_info))); + return NULL; + } + #endif +@@ -1762,7 +1790,7 @@ static void *zend_mm_alloc_huge(zend_mm_heap *heap, size_t size ZEND_FILE_LINE_D + void *ptr; + + if (UNEXPECTED(new_size < size)) { +- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu + %zu)", size, alignment); ++ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (%zu + %zu)", size, alignment); + } + + #if ZEND_MM_LIMIT +@@ -2617,7 +2645,7 @@ ZEND_API char* ZEND_FASTCALL _estrdup(const char *s ZEND_FILE_LINE_DC ZEND_FILE_ + + length = strlen(s); + if (UNEXPECTED(length + 1 == 0)) { +- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (1 * %zu + 1)", length); ++ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (1 * %zu + 1)", length); + } + p = (char *) _emalloc(length + 1 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); + memcpy(p, s, length+1); +@@ -2629,7 +2657,7 @@ ZEND_API char* ZEND_FASTCALL _estrndup(const char *s, size_t length ZEND_FILE_LI + char *p; + + if (UNEXPECTED(length + 1 == 0)) { +- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (1 * %zu + 1)", length); ++ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (1 * %zu + 1)", length); + } + p = (char *) _emalloc(length + 1 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); + memcpy(p, s, length); +@@ -2643,7 +2671,7 @@ ZEND_API char* ZEND_FASTCALL zend_strndup(const char *s, size_t length) + char *p; + + if (UNEXPECTED(length + 1 == 0)) { +- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (1 * %zu + 1)", length); ++ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (1 * %zu + 1)", length); + } + p = (char *) malloc(length + 1); + if (UNEXPECTED(p == NULL)) { +@@ -2974,7 +3002,7 @@ ZEND_API zend_mm_heap *zend_mm_startup_ex(const zend_mm_handlers *handlers, void + static ZEND_COLD ZEND_NORETURN void zend_out_of_memory(void) + { + fprintf(stderr, "Out of memory\n"); +- exit(1); ++ _exit(1); + } + + ZEND_API void * __zend_malloc(size_t len) +diff --git a/Zend/zend_alloc.h b/Zend/zend_alloc.h +index 8bb854328dbd..2ed2ed8b3adf 100644 +--- a/Zend/zend_alloc.h ++++ b/Zend/zend_alloc.h +@@ -402,6 +402,8 @@ static void apc_init_heap(void) + size_t zend_mm_globals_size(void); + #endif + ++ZEND_API ZEND_COLD ZEND_NORETURN void zend_mm_safe_error_ex(const char *format, ...); ++ + END_EXTERN_C() + + #endif +diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c +index f4f0fa14f1d3..724b6e5cc414 100644 +--- a/Zend/zend_execute_API.c ++++ b/Zend/zend_execute_API.c +@@ -337,10 +337,21 @@ void shutdown_executor(void) /* {{{ */ + gc_collect_cycles(); + } + #endif ++ } else { ++ /* may be used by zend_error_zstr_at before init_executor */ ++ ZVAL_UNDEF(&EG(user_error_handler)); ++ ZVAL_UNDEF(&EG(user_exception_handler)); ++ memset(&EG(user_error_handlers_error_reporting), 0, sizeof(EG(user_error_handlers_error_reporting))); ++ memset(&EG(user_error_handlers), 0, sizeof(EG(user_error_handlers))); ++ memset(&EG(user_exception_handlers), 0, sizeof(EG(user_exception_handlers))); + } + + zend_objects_store_free_object_storage(&EG(objects_store), fast_shutdown); + ++ /* may be used by zend_error_zstr_at before init_executor */ ++ EG(error_handling) = EH_NORMAL; ++ EG(exception) = NULL; ++ + zend_weakrefs_shutdown(); + + zend_try { +@@ -357,6 +368,8 @@ void shutdown_executor(void) /* {{{ */ + zend_hash_discard(EG(function_table), EG(persistent_functions_count)); + zend_hash_discard(EG(class_table), EG(persistent_classes_count)); + zend_cleanup_internal_classes(); ++ EG(objects_store).object_buckets = NULL; ++ EG(objects_store).top = 1; + } else { + zend_vm_stack_destroy(); + +diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c +index da150bd7984c..ef3d301db15e 100644 +--- a/Zend/zend_hash.c ++++ b/Zend/zend_hash.c +@@ -97,7 +97,7 @@ static zend_always_inline uint32_t zend_hash_check_size(uint32_t nSize) + if (nSize <= HT_MIN_SIZE) { + return HT_MIN_SIZE; + } else if (UNEXPECTED(nSize >= HT_MAX_SIZE)) { +- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%u * %zu + %zu)", nSize, sizeof(Bucket), sizeof(Bucket)); ++ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (%u * %zu + %zu)", nSize, sizeof(Bucket), sizeof(Bucket)); + } + + #if defined(ZEND_WIN32) +@@ -251,6 +251,13 @@ ZEND_API HashTable* ZEND_FASTCALL _zend_new_array_0(void) + return ht; + } + ++ZEND_API HashTable* ZEND_FASTCALL zend_new_array_singleton(void) ++{ ++ HashTable *ht = _zend_new_array_0(); ++ ht->nTableSize = 1; ++ return ht; ++} ++ + ZEND_API HashTable* ZEND_FASTCALL _zend_new_array(uint32_t nSize) + { + HashTable *ht = emalloc(sizeof(HashTable)); +@@ -282,7 +289,7 @@ static void ZEND_FASTCALL zend_hash_packed_grow(HashTable *ht) + { + HT_ASSERT_RC1(ht); + if (ht->nTableSize >= HT_MAX_SIZE) { +- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%u * %zu + %zu)", ht->nTableSize * 2, sizeof(Bucket), sizeof(Bucket)); ++ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (%u * %zu + %zu)", ht->nTableSize * 2, sizeof(Bucket), sizeof(Bucket)); + } + ht->nTableSize += ht->nTableSize; + HT_SET_DATA_ADDR(ht, perealloc2(HT_GET_DATA_ADDR(ht), HT_SIZE_EX(ht->nTableSize, HT_MIN_MASK), HT_USED_SIZE(ht), GC_FLAGS(ht) & IS_ARRAY_PERSISTENT)); +@@ -1164,7 +1171,7 @@ static void ZEND_FASTCALL zend_hash_do_resize(HashTable *ht) + pefree(old_data, GC_FLAGS(ht) & IS_ARRAY_PERSISTENT); + zend_hash_rehash(ht); + } else { +- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%u * %zu + %zu)", ht->nTableSize * 2, sizeof(Bucket) + sizeof(uint32_t), sizeof(Bucket)); ++ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (%u * %zu + %zu)", ht->nTableSize * 2, sizeof(Bucket) + sizeof(uint32_t), sizeof(Bucket)); + } + } + +diff --git a/Zend/zend_hash.h b/Zend/zend_hash.h +index f1e2d34685d5..b833479eaa10 100644 +--- a/Zend/zend_hash.h ++++ b/Zend/zend_hash.h +@@ -296,6 +296,7 @@ ZEND_API int ZEND_FASTCALL zend_hash_rehash(HashTable *ht); + #endif + + ZEND_API HashTable* ZEND_FASTCALL _zend_new_array_0(void); ++ZEND_API HashTable* ZEND_FASTCALL zend_new_array_singleton(void); + ZEND_API HashTable* ZEND_FASTCALL _zend_new_array(uint32_t size); + ZEND_API HashTable* ZEND_FASTCALL zend_new_pair(zval *val1, zval *val2); + ZEND_API uint32_t zend_array_count(HashTable *ht); +diff --git a/Zend/zend_llist.c b/Zend/zend_llist.c +index 4a2c22e63212..0955e953aa3e 100644 +--- a/Zend/zend_llist.c ++++ b/Zend/zend_llist.c +@@ -112,6 +112,8 @@ ZEND_API void zend_llist_destroy(zend_llist *l) + current = next; + } + ++ l->head = NULL; ++ l->tail = NULL; + l->count = 0; + } + +diff --git a/Zend/zend_multiply.h b/Zend/zend_multiply.h +index a3827d25d128..a9bbda553847 100644 +--- a/Zend/zend_multiply.h ++++ b/Zend/zend_multiply.h +@@ -321,7 +321,7 @@ static zend_always_inline size_t zend_safe_address_guarded(size_t nmemb, size_t + size_t ret = zend_safe_address(nmemb, size, offset, &overflow); + + if (UNEXPECTED(overflow)) { +- zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset); ++ zend_mm_safe_error_ex("Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset); + return 0; + } + return ret; +@@ -334,7 +334,7 @@ static zend_always_inline size_t zend_safe_addmult(size_t nmemb, size_t size, si + size_t ret = zend_safe_address(nmemb, size, offset, &overflow); + + if (UNEXPECTED(overflow)) { +- zend_error_noreturn(E_ERROR, "Possible integer overflow in %s (%zu * %zu + %zu)", message, nmemb, size, offset); ++ zend_mm_safe_error_ex("Possible integer overflow in %s (%zu * %zu + %zu)", message, nmemb, size, offset); + return 0; + } + return ret; +diff --git a/Zend/zend_strtod.c b/Zend/zend_strtod.c +index 2228e2262cf1..ad8df201af46 100644 +--- a/Zend/zend_strtod.c ++++ b/Zend/zend_strtod.c +@@ -603,7 +603,7 @@ Balloc + rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(ULong)); + if (!rv) { + FREE_DTOA_LOCK(0); +- zend_error_noreturn(E_ERROR, "Balloc() failed to allocate memory"); ++ zend_mm_safe_error_ex("Balloc() failed to allocate memory"); + } + #else + len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1) +@@ -616,7 +616,7 @@ Balloc + rv = (Bigint*)MALLOC(len*sizeof(double)); + if (!rv) { + FREE_DTOA_LOCK(0); +- zend_error_noreturn(E_ERROR, "Balloc() failed to allocate memory"); ++ zend_mm_safe_error_ex("Balloc() failed to allocate memory"); + } + #endif + rv->k = k; +diff --git a/Zend/zend_types.h b/Zend/zend_types.h +index 7b8c079c458d..f7828eb6d373 100644 +--- a/Zend/zend_types.h ++++ b/Zend/zend_types.h +@@ -330,17 +330,21 @@ struct _zend_array { + # define HT_HASH_RESET(ht) do { \ + char *p = (char*)&HT_HASH(ht, (ht)->nTableMask); \ + size_t size = HT_HASH_SIZE((ht)->nTableMask); \ +- __m128i xmm0 = _mm_setzero_si128(); \ +- xmm0 = _mm_cmpeq_epi8(xmm0, xmm0); \ +- ZEND_ASSERT(size >= 64 && ((size & 0x3f) == 0)); \ +- do { \ +- _mm_storeu_si128((__m128i*)p, xmm0); \ +- _mm_storeu_si128((__m128i*)(p+16), xmm0); \ +- _mm_storeu_si128((__m128i*)(p+32), xmm0); \ +- _mm_storeu_si128((__m128i*)(p+48), xmm0); \ +- p += 64; \ +- size -= 64; \ +- } while (size != 0); \ ++ if (UNEXPECTED(size < 64)) { \ ++ memset(p, HT_INVALID_IDX, size); \ ++ } else { \ ++ __m128i xmm0 = _mm_setzero_si128(); \ ++ xmm0 = _mm_cmpeq_epi8(xmm0, xmm0); \ ++ ZEND_ASSERT(size >= 64 && ((size & 0x3f) == 0)); \ ++ do { \ ++ _mm_storeu_si128((__m128i*)p, xmm0); \ ++ _mm_storeu_si128((__m128i*)(p+16), xmm0); \ ++ _mm_storeu_si128((__m128i*)(p+32), xmm0); \ ++ _mm_storeu_si128((__m128i*)(p+48), xmm0); \ ++ p += 64; \ ++ size -= 64; \ ++ } while (size != 0); \ ++ } \ + } while (0) + #else + # define HT_HASH_RESET(ht) \ +diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h +index d362b0164321..3af90d705b52 100644 +--- a/Zend/zend_vm_def.h ++++ b/Zend/zend_vm_def.h +@@ -417,7 +417,7 @@ ZEND_VM_HANDLER(8, ZEND_CONCAT, CONST|TMPVAR|CV, CONST|TMPVAR|CV, SPEC(NO_CONST_ + size_t len = ZSTR_LEN(op1_str); + + if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { +- zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation"); ++ zend_mm_safe_error_ex("Integer overflow in memory allocation"); + } + str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); +@@ -426,6 +426,9 @@ ZEND_VM_HANDLER(8, ZEND_CONCAT, CONST|TMPVAR|CV, CONST|TMPVAR|CV, SPEC(NO_CONST_ + zend_string_release_ex(op2_str, 0); + } + } else { ++ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { ++ zend_mm_safe_error_ex("Integer overflow in memory allocation"); ++ } + str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); + memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); +@@ -3210,6 +3213,9 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(53, ZEND_FAST_CONCAT, CONST|TMPVAR|CV, CONST|TMP + !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { + size_t len = ZSTR_LEN(op1_str); + ++ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { ++ zend_mm_safe_error_ex("Integer overflow in memory allocation"); ++ } + str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); +@@ -3217,6 +3223,9 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(53, ZEND_FAST_CONCAT, CONST|TMPVAR|CV, CONST|TMP + zend_string_release_ex(op2_str, 0); + } + } else { ++ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { ++ zend_mm_safe_error_ex("Integer overflow in memory allocation"); ++ } + str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); + memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); +diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h +index 2875fd37404a..8701e77ea8d2 100644 +--- a/Zend/zend_vm_execute.h ++++ b/Zend/zend_vm_execute.h +@@ -5631,6 +5631,9 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_ + !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { + size_t len = ZSTR_LEN(op1_str); + ++ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { ++ zend_mm_safe_error_ex("Integer overflow in memory allocation"); ++ } + str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); +@@ -5638,6 +5641,9 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_ + zend_string_release_ex(op2_str, 0); + } + } else { ++ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { ++ zend_mm_safe_error_ex("Integer overflow in memory allocation"); ++ } + str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); + memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); +@@ -7491,6 +7497,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_TMPVAR_HANDL + !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { + size_t len = ZSTR_LEN(op1_str); + ++ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { ++ zend_mm_safe_error_ex("Integer overflow in memory allocation"); ++ } + str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); +@@ -7498,6 +7507,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_TMPVAR_HANDL + zend_string_release_ex(op2_str, 0); + } + } else { ++ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { ++ zend_mm_safe_error_ex("Integer overflow in memory allocation"); ++ } + str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); + memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); +@@ -7900,7 +7912,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CONST_TMPVAR_ + size_t len = ZSTR_LEN(op1_str); + + if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { +- zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation"); ++ zend_mm_safe_error_ex("Integer overflow in memory allocation"); + } + str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); +@@ -7909,6 +7921,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CONST_TMPVAR_ + zend_string_release_ex(op2_str, 0); + } + } else { ++ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { ++ zend_mm_safe_error_ex("Integer overflow in memory allocation"); ++ } + str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); + memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); +@@ -9952,6 +9967,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_CV_HANDLER(Z + !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { + size_t len = ZSTR_LEN(op1_str); + ++ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { ++ zend_mm_safe_error_ex("Integer overflow in memory allocation"); ++ } + str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); +@@ -9959,6 +9977,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_CV_HANDLER(Z + zend_string_release_ex(op2_str, 0); + } + } else { ++ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { ++ zend_mm_safe_error_ex("Integer overflow in memory allocation"); ++ } + str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); + memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); +@@ -10361,7 +10382,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CONST_CV_HAND + size_t len = ZSTR_LEN(op1_str); + + if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { +- zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation"); ++ zend_mm_safe_error_ex("Integer overflow in memory allocation"); + } + str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); +@@ -10370,6 +10391,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CONST_CV_HAND + zend_string_release_ex(op2_str, 0); + } + } else { ++ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { ++ zend_mm_safe_error_ex("Integer overflow in memory allocation"); ++ } + str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); + memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); +@@ -13928,6 +13952,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CONST_HANDL + !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { + size_t len = ZSTR_LEN(op1_str); + ++ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { ++ zend_mm_safe_error_ex("Integer overflow in memory allocation"); ++ } + str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); +@@ -13935,6 +13962,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CONST_HANDL + zend_string_release_ex(op2_str, 0); + } + } else { ++ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { ++ zend_mm_safe_error_ex("Integer overflow in memory allocation"); ++ } + str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); + memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); +@@ -14681,7 +14711,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CONST_ + size_t len = ZSTR_LEN(op1_str); + + if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { +- zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation"); ++ zend_mm_safe_error_ex("Integer overflow in memory allocation"); + } + str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); +@@ -14690,6 +14720,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CONST_ + zend_string_release_ex(op2_str, 0); + } + } else { ++ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { ++ zend_mm_safe_error_ex("Integer overflow in memory allocation"); ++ } + str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); + memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); +@@ -15353,7 +15386,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_TMPVAR_HAND + size_t len = ZSTR_LEN(op1_str); + + if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { +- zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation"); ++ zend_mm_safe_error_ex("Integer overflow in memory allocation"); + } + str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); +@@ -15362,6 +15395,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_TMPVAR_HAND + zend_string_release_ex(op2_str, 0); + } + } else { ++ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { ++ zend_mm_safe_error_ex("Integer overflow in memory allocation"); ++ } + str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); + memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); +@@ -16107,6 +16143,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_TMPVAR + !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { + size_t len = ZSTR_LEN(op1_str); + ++ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { ++ zend_mm_safe_error_ex("Integer overflow in memory allocation"); ++ } + str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); +@@ -16114,6 +16153,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_TMPVAR + zend_string_release_ex(op2_str, 0); + } + } else { ++ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { ++ zend_mm_safe_error_ex("Integer overflow in memory allocation"); ++ } + str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); + memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); +@@ -17040,7 +17082,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CV_HANDLER( + size_t len = ZSTR_LEN(op1_str); + + if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { +- zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation"); ++ zend_mm_safe_error_ex("Integer overflow in memory allocation"); + } + str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); +@@ -17049,6 +17091,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CV_HANDLER( + zend_string_release_ex(op2_str, 0); + } + } else { ++ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { ++ zend_mm_safe_error_ex("Integer overflow in memory allocation"); ++ } + str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); + memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); +@@ -17401,6 +17446,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CV_HAN + !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { + size_t len = ZSTR_LEN(op1_str); + ++ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { ++ zend_mm_safe_error_ex("Integer overflow in memory allocation"); ++ } + str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); +@@ -17408,6 +17456,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CV_HAN + zend_string_release_ex(op2_str, 0); + } + } else { ++ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { ++ zend_mm_safe_error_ex("Integer overflow in memory allocation"); ++ } + str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); + memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); +@@ -38348,7 +38399,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CONST_HANDLER(Z + size_t len = ZSTR_LEN(op1_str); + + if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { +- zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation"); ++ zend_mm_safe_error_ex("Integer overflow in memory allocation"); + } + str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); +@@ -38357,6 +38408,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CONST_HANDLER(Z + zend_string_release_ex(op2_str, 0); + } + } else { ++ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { ++ zend_mm_safe_error_ex("Integer overflow in memory allocation"); ++ } + str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); + memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); +@@ -40727,7 +40781,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_CONST_HAND + size_t len = ZSTR_LEN(op1_str); + + if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { +- zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation"); ++ zend_mm_safe_error_ex("Integer overflow in memory allocation"); + } + str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); +@@ -40736,6 +40790,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_CONST_HAND + zend_string_release_ex(op2_str, 0); + } + } else { ++ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { ++ zend_mm_safe_error_ex("Integer overflow in memory allocation"); ++ } + str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); + memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); +@@ -41849,6 +41906,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_TMPVAR_HANDLER( + !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { + size_t len = ZSTR_LEN(op1_str); + ++ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { ++ zend_mm_safe_error_ex("Integer overflow in memory allocation"); ++ } + str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); +@@ -41856,6 +41916,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_TMPVAR_HANDLER( + zend_string_release_ex(op2_str, 0); + } + } else { ++ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { ++ zend_mm_safe_error_ex("Integer overflow in memory allocation"); ++ } + str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); + memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); +@@ -44132,6 +44195,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_TMPVAR_HAN + !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { + size_t len = ZSTR_LEN(op1_str); + ++ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { ++ zend_mm_safe_error_ex("Integer overflow in memory allocation"); ++ } + str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); +@@ -44139,6 +44205,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_TMPVAR_HAN + zend_string_release_ex(op2_str, 0); + } + } else { ++ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { ++ zend_mm_safe_error_ex("Integer overflow in memory allocation"); ++ } + str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); + memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); +@@ -46857,7 +46926,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CV_HANDLER(ZEND + size_t len = ZSTR_LEN(op1_str); + + if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { +- zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation"); ++ zend_mm_safe_error_ex("Integer overflow in memory allocation"); + } + str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); +@@ -46866,6 +46935,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CV_HANDLER(ZEND + zend_string_release_ex(op2_str, 0); + } + } else { ++ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { ++ zend_mm_safe_error_ex("Integer overflow in memory allocation"); ++ } + str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); + memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); +@@ -49268,6 +49340,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_CV_HANDLER + !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { + size_t len = ZSTR_LEN(op1_str); + ++ if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { ++ zend_mm_safe_error_ex("Integer overflow in memory allocation"); ++ } + str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); +@@ -49275,6 +49350,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_CV_HANDLER + zend_string_release_ex(op2_str, 0); + } + } else { ++ if (UNEXPECTED(ZSTR_LEN(op1_str) > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { ++ zend_mm_safe_error_ex("Integer overflow in memory allocation"); ++ } + str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); + memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); +diff --git a/ext/session/session.c b/ext/session/session.c +index 8fb6dd2cd5d2..89a7400a9ca9 100644 +--- a/ext/session/session.c ++++ b/ext/session/session.c +@@ -3174,7 +3174,7 @@ static int php_session_rfc1867_callback(unsigned int event, void *event_data, vo + if (php_session_rfc1867_orig_callback) { + retval = php_session_rfc1867_orig_callback(event, event_data, extra); + } +- if (!PS(rfc1867_enabled)) { ++ if (!PS(rfc1867_enabled) || true) { + return retval; + } + +diff --git a/main/SAPI.c b/main/SAPI.c +index a5a68f8c680e..1c320f6e3fa3 100644 +--- a/main/SAPI.c ++++ b/main/SAPI.c +@@ -509,18 +509,23 @@ SAPI_API void sapi_deactivate(void) + } + if (SG(request_info).auth_user) { + efree(SG(request_info).auth_user); ++ SG(request_info).auth_user = NULL; + } + if (SG(request_info).auth_password) { + efree(SG(request_info).auth_password); ++ SG(request_info).auth_password = NULL; + } + if (SG(request_info).auth_digest) { + efree(SG(request_info).auth_digest); ++ SG(request_info).auth_digest = NULL; + } + if (SG(request_info).content_type_dup) { + efree(SG(request_info).content_type_dup); ++ SG(request_info).content_type_dup = NULL; + } + if (SG(request_info).current_user) { + efree(SG(request_info).current_user); ++ SG(request_info).current_user = NULL; + } + if (sapi_module.deactivate) { + sapi_module.deactivate(); +diff --git a/main/main.c b/main/main.c +index 0b33b2b56c9a..bb8501f97362 100644 +--- a/main/main.c ++++ b/main/main.c +@@ -1960,6 +1961,8 @@ void php_request_shutdown(void *dummy) + + for (i=0; i Date: Thu, 22 Oct 2026 04:11:44 +0100 Subject: [PATCH 3/6] Adjust the php7 test suite for the CVE fix A full test run with and without the fix (same recipe, non-root, arm64) differs by exactly nine tests, all caused by the fix on purpose: - tests/lang/bug45392.phpt: out-of-memory errors are now written straight to stderr before _exit(1), which adds a blank line before "Fatal error". The expected output now allows it, so the test still checks that buffered output is not leaked when memory runs out. - ext/session/tests/rfc1867*.phpt (8 tests): the fix turns session upload progress off entirely, so these tests check a feature that is gone. Disabled. Four more fail with and without the fix when built in Docker (curl_basic_009, date bug73837, streams opendir-003 and opendir-004), so they are disabled too. Refs #46 Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01Uugex1w8qZoTbBRbcFwkcp --- 7.4/aports/community/php7/APKBUILD | 4 +++- .../php7/CVE-2026-109618-109619-tests.patch | 8 ++++++++ 7.4/aports/community/php7/disabled-tests.list | 16 ++++++++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 7.4/aports/community/php7/CVE-2026-109618-109619-tests.patch diff --git a/7.4/aports/community/php7/APKBUILD b/7.4/aports/community/php7/APKBUILD index 19851d7..f500453 100644 --- a/7.4/aports/community/php7/APKBUILD +++ b/7.4/aports/community/php7/APKBUILD @@ -109,6 +109,7 @@ source="https://php.net/distributions/$_pkgreal-$pkgver.tar.xz fix-fpm-syntax.patch fix-curl-7.83-test.patch CVE-2026-109618-109619.patch + CVE-2026-109618-109619-tests.patch " builddir="$srcdir/$_pkgreal-$pkgver" @@ -712,7 +713,7 @@ sha512sums=" 1c708de82d1086f272f484faf6cf6d087af7c31750cc2550b0b94ed723961b363f28a947b015b2dfc0765caea185a75f5d2c2f2b099c948b65c290924f606e4f php7-fpm.initd cacce7bf789467ff40647b7319e3760c6c587218720538516e8d400baa75651f72165c4e28056cd0c1dc89efecb4d00d0d7823bed80b29136262c825ce816691 php7-fpm.logrotate 274bd7b0b2b7002fa84c779640af37b59258bb37b05cb7dd5c89452977d71807f628d91b523b5039608376d1f760f3425d165242ca75ee5129b2730e71c4e198 php7-module.conf -ee221c1cf94783ef15780007eab8a9d5e38a8f939f9e25168687438c558e673a4c3b321d96017571cbe569756585003f750382981d0f02cf0a634d951b850f98 disabled-tests.list +cfc219aef8b3da67ceb66cd4af01eb8f273342d8bd638013adec9408cc516c73a49f5f32fcca0e6e39fc5fa04643046ff75ce0c217be9795786528eebf07e11f disabled-tests.list a4130d29c7fee2b8cb561b116baf603bdc3a7b5b4985ec3c9918f253d1851197539dfad72c6b36d9f7008f85982904731184c79e4cee4415c1a1b88016639225 install-pear.patch ebf571c5e595221b9944d7e840807ebb68c1be38bf117186e19a3bd1070310ece5918bcaa5f941679f3371a2108ad57bf179c3f90e612a5a2b982db941172859 includedir.patch 965b52893affb666af64e00d09e0208dcd41b17ce2864cf05616c6d05a05c0121694c0b209d403b8c0c55d18e6f1528c4aba1a4fcdce7b282a13304d12cd0f9d sharedir.patch @@ -729,4 +730,5 @@ f7e87369658e333247896cb3cc6d56a54e2041453c0dc78180d7d31ac5008f98837039c215beda24 5582cbf13dcc9c536c6a9881183fedd40d35497c527e20e9e8e3288ce6219d9218dd16d9f43cc4412fd471b84df786076141f8409f950578b50d1540244f29f2 fix-fpm-syntax.patch be6a57063414bd255def54d5f6e42cbdc3baec55c8eaf9c8ca6e96d0cb3fec942ebb1868806850859d34c5c45d03a2abfec3fecd1aef04524da8eda01d9041ed fix-curl-7.83-test.patch 1f73855623c03ce6202610500989a6f08eb3a7cd4a80d007fd078644b142b8e51aab28fefab876c03c935f112c7162d696d42cb983961f6cb6c3c4586513bb49 CVE-2026-109618-109619.patch +4e077c3818e395eed735d450971c5bde250fecbf32c258c3e7b56c54cb7e59350e211b48ea2ac870f15eefc8b860e5aa7d824b12d2e9ab7333fe6231e17e55d7 CVE-2026-109618-109619-tests.patch " diff --git a/7.4/aports/community/php7/CVE-2026-109618-109619-tests.patch b/7.4/aports/community/php7/CVE-2026-109618-109619-tests.patch new file mode 100644 index 0000000..0f66f08 --- /dev/null +++ b/7.4/aports/community/php7/CVE-2026-109618-109619-tests.patch @@ -0,0 +1,8 @@ +--- a/tests/lang/bug45392.phpt ++++ b/tests/lang/bug45392.phpt +@@ -20,4 +20,5 @@ + ?> + --EXPECTF-- + 2 ++ + Fatal error: Allowed memory size of %d bytes exhausted%s diff --git a/7.4/aports/community/php7/disabled-tests.list b/7.4/aports/community/php7/disabled-tests.list index cbfd896..a276e91 100644 --- a/7.4/aports/community/php7/disabled-tests.list +++ b/7.4/aports/community/php7/disabled-tests.list @@ -217,3 +217,19 @@ sapi/fpm/tests/bug68391-conf-include-order.phpt # compilation failed https://gitlab.alpinelinux.org/alpine/aports/-/issues/13116 ext/pcre/tests/bug70345.phpt + +# Session upload progress is turned off by the CVE-2026-109618/109619 fix +ext/session/tests/rfc1867.phpt +ext/session/tests/rfc1867_inter.phpt +ext/session/tests/rfc1867_sid_cookie.phpt +ext/session/tests/rfc1867_sid_get.phpt +ext/session/tests/rfc1867_sid_get_2.phpt +ext/session/tests/rfc1867_sid_invalid.phpt +ext/session/tests/rfc1867_sid_only_cookie.phpt +ext/session/tests/rfc1867_sid_post.phpt + +# Fail with and without the CVE-2026-109618/109619 fix when built in Docker +ext/curl/tests/curl_basic_009.phpt +ext/date/tests/bug73837.phpt +ext/standard/tests/streams/opendir-003.phpt +ext/standard/tests/streams/opendir-004.phpt From fff63b3c01cac66a8d0e6e794781bcb8ff5a65a6 Mon Sep 17 00:00:00 2001 From: Rick Lam Date: Thu, 22 Oct 2026 04:23:43 +0100 Subject: [PATCH 4/6] Build the 7.4 image on Alpine 3.15 with the patched php7 A builder stage builds the patched php7 recipe as a non-root user (running abuild as root makes the opcache preloading tests fail) with Alpine's test suite enabled. The image then moves to alpine:3.15 and keeps the signed packages as a local repo in /opt/php7-apk, listed first, so images built on top get the patched 7.4.33-r2 too, for example php7-apache2 in graze/new-php. /opt rather than /srv because new-php declares /srv as a volume. gnu-libiconv 1.16 on Alpine 3.15 no longer ships preloadable_libiconv.so, so the LD_PRELOAD fix stopped working and iconv //TRANSLIT returned false (Utils::slugify would produce empty slugs). It is pinned to 1.15-r3 from the v3.13 repo, the same package the current image uses. Two new tests check that php7 is the r2 build and that php7-apache2 added later resolves to r2. Both fail against the current graze/php-alpine:7.4 and pass here, as do all 19 bats tests. Refs #46 Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01Uugex1w8qZoTbBRbcFwkcp --- 7.4/Dockerfile | 29 ++++++++++++++++++++++++++--- 7.4/php.bats | 16 ++++++++++++++++ 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/7.4/Dockerfile b/7.4/Dockerfile index 0ad2b6a..919ad6f 100644 --- a/7.4/Dockerfile +++ b/7.4/Dockerfile @@ -1,4 +1,22 @@ -FROM alpine:3.13 +FROM alpine:3.15 AS php7-build + +ENV PACKAGER="graze " + +RUN apk add --no-cache alpine-sdk \ + && apk update \ + && adduser -D builder \ + && addgroup builder abuild + +USER builder + +COPY --chown=builder aports/community/php7 /home/builder/community/php7 + +WORKDIR /home/builder/community/php7 + +RUN abuild-keygen -a -n \ + && abuild -r + +FROM alpine:3.15 LABEL maintainer="developers@graze.com" \ license="MIT" \ @@ -8,12 +26,17 @@ LABEL maintainer="developers@graze.com" \ org.label-schema.description="small php image based on alpine" \ org.label-schema.vcs-url="https://github.com/graze/docker-php-alpine" +COPY --from=php7-build /home/builder/.abuild/*.rsa.pub /etc/apk/keys/ +COPY --from=php7-build /home/builder/packages/community /opt/php7-apk + RUN set -xe \ - && echo "@php http://dl-cdn.alpinelinux.org/alpine/v3.13/community" >> /etc/apk/repositories \ + && sed -i '1i /opt/php7-apk' /etc/apk/repositories \ + && echo "@php http://dl-cdn.alpinelinux.org/alpine/v3.15/community" >> /etc/apk/repositories \ + && echo "@alpine313 http://dl-cdn.alpinelinux.org/alpine/v3.13/community" >> /etc/apk/repositories \ && apk add --update --no-cache \ ca-certificates \ curl \ - gnu-libiconv \ + gnu-libiconv@alpine313=1.15-r3 \ openssh-client \ libmemcached-libs \ libevent \ diff --git a/7.4/php.bats b/7.4/php.bats index 0d674ef..871015a 100755 --- a/7.4/php.bats +++ b/7.4/php.bats @@ -62,3 +62,19 @@ [[ "${output}" == *"zip"* ]] [[ "${output}" == *"zlib"* ]] } + +@test "php7 is the build patched for CVE-2026-109618 and CVE-2026-109619" { + run docker run --rm ${container} sh -c "apk info -v 2>/dev/null | grep '^php7-common-'" + echo 'status:' $status + echo 'output:' $output + [ "$status" -eq 0 ] + [[ "${output}" == *"php7-common-7.4.33-r2"* ]] +} + +@test "php7 packages added later come from the patched build" { + run docker run --rm ${container} apk add --no-cache --simulate php7-apache2 + echo 'status:' $status + echo 'output:' $output + [ "$status" -eq 0 ] + [[ "${output}" == *"php7-apache2 (7.4.33-r2)"* ]] +} From d1a6c7ea9ce018635849463fb5011d4b8b16dd55 Mon Sep 17 00:00:00 2001 From: Rick Lam Date: Thu, 22 Oct 2026 04:27:49 +0100 Subject: [PATCH 5/6] Pin gnu-libiconv without a repository tag A tagged repository (@alpine313) put "gnu-libiconv@alpine313" in the apk world file. Images keep no package indexes, so any later apk call without --no-cache could not see the tag and refused to commit. The dispatch image hit this at "apk del .imagick-build-deps". Installing gnu-libiconv=1.15-r3 with a one-off --repository leaves a plain version pin that apk satisfies from the installed package. Checked by building graze/new-php:7.4 (cli and apache) and the dispatch php74 image on top: imagick 3.8.0 compiles and renders, iconv //TRANSLIT works, mod_php loads, and the dispatch health check returns 200. All 19 bats tests pass. Refs #46 Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01Uugex1w8qZoTbBRbcFwkcp --- 7.4/Dockerfile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/7.4/Dockerfile b/7.4/Dockerfile index 919ad6f..d195a5a 100644 --- a/7.4/Dockerfile +++ b/7.4/Dockerfile @@ -32,11 +32,10 @@ COPY --from=php7-build /home/builder/packages/community /opt/php7-apk RUN set -xe \ && sed -i '1i /opt/php7-apk' /etc/apk/repositories \ && echo "@php http://dl-cdn.alpinelinux.org/alpine/v3.15/community" >> /etc/apk/repositories \ - && echo "@alpine313 http://dl-cdn.alpinelinux.org/alpine/v3.13/community" >> /etc/apk/repositories \ + && apk add --no-cache --repository http://dl-cdn.alpinelinux.org/alpine/v3.13/community gnu-libiconv=1.15-r3 \ && apk add --update --no-cache \ ca-certificates \ curl \ - gnu-libiconv@alpine313=1.15-r3 \ openssh-client \ libmemcached-libs \ libevent \ From adc0e36feea06560e521fa0d4b65ebed6c69638f Mon Sep 17 00:00:00 2001 From: Rick Lam Date: Thu, 22 Oct 2026 05:09:03 +0100 Subject: [PATCH 6/6] Delete the private APK signing key in the same layer The master build exports every layer to the registry build cache (mode=max), so the builder layer would have carried the private key used to sign the php7 packages. Anyone pulling the cache could then sign packages and indexes that the images trust. The key is now removed in the same RUN that generates and uses it, so no layer contains it. The public key stays for the runtime image. Checked locally: none of the five builder-stage layers contains a private .rsa (a control tar with one is detected), and all 19 bats tests pass. Refs #46 Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01Uugex1w8qZoTbBRbcFwkcp --- 7.4/Dockerfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/7.4/Dockerfile b/7.4/Dockerfile index d195a5a..fe8bbef 100644 --- a/7.4/Dockerfile +++ b/7.4/Dockerfile @@ -14,7 +14,8 @@ COPY --chown=builder aports/community/php7 /home/builder/community/php7 WORKDIR /home/builder/community/php7 RUN abuild-keygen -a -n \ - && abuild -r + && abuild -r \ + && rm -f /home/builder/.abuild/*.rsa FROM alpine:3.15