diff options
-rw-r--r-- | failed.txt | 16 | ||||
-rw-r--r-- | macros.php | 4 | ||||
-rw-r--r-- | php-7.2.0-oci8conf.patch | 24 | ||||
-rw-r--r-- | php-7.2.16-systzdata-v17.patch | 2 | ||||
-rw-r--r-- | php-bug81726.patch | 92 | ||||
-rw-r--r-- | php-bug81738.patch | 129 | ||||
-rw-r--r-- | php-bug81740.patch | 87 | ||||
-rw-r--r-- | php-bug81744.patch | 190 | ||||
-rw-r--r-- | php-bug81746.patch | 100 | ||||
-rw-r--r-- | php-cve-2023-0662.patch | 148 | ||||
-rw-r--r-- | php-cve-2023-3247.patch | 152 | ||||
-rw-r--r-- | php-cve-2023-3823.patch | 91 | ||||
-rw-r--r-- | php-cve-2023-3824.patch | 714 | ||||
-rw-r--r-- | php-cve-2024-11233.patch | 158 | ||||
-rw-r--r-- | php-cve-2024-11234.patch | 97 | ||||
-rw-r--r-- | php-cve-2024-11236.patch | 150 | ||||
-rw-r--r-- | php-cve-2024-2756.patch | 197 | ||||
-rw-r--r-- | php-cve-2024-3096.patch | 85 | ||||
-rw-r--r-- | php-cve-2024-5458.patch | 184 | ||||
-rw-r--r-- | php-cve-2024-8925.patch | 236 | ||||
-rw-r--r-- | php-cve-2024-8926.patch | 204 | ||||
-rw-r--r-- | php-cve-2024-8927.patch | 98 | ||||
-rw-r--r-- | php-cve-2024-8932.patch | 141 | ||||
-rw-r--r-- | php-ghsa-4w77-75f9-2c8w.patch | 139 | ||||
-rw-r--r-- | php.spec | 230 |
25 files changed, 3581 insertions, 87 deletions
@@ -1,18 +1,13 @@ -===== 7.2.34-12 (2022-09-29) +===== 7.2.34-25 (2024-11-26) $ grep -ar 'Tests failed' /var/lib/mock/*/build.log -/var/lib/mock/scl72el7x/build.log:Tests failed : 0 -/var/lib/mock/scl72el8x/build.log:Tests failed : 18 -/var/lib/mock/scl72fc35x/build.log:Tests failed : 18 +/var/lib/mock/scl72el8a/build.log:Tests failed : 22 +/var/lib/mock/scl72el8x/build.log:Tests failed : 22 -el8x - 4 Bug #48097 (date_timezone_set function produces wrong datetime result) [ext/date/tests/bug48097.phpt] -el8x, fc33x, fc34x: - 3 buildroot issue with strict openssl policy (fixed in 7.4) -fc33x, fc34x, fc35x - 4 Bug #33415 [2] (Possibly invalid non-one-hour DST or timezone shifts) [ext/date/tests/bug33415-2.phpt] +el8: + 3 buildroot issue with strict openssl policy (fixed in 7.4) and tzdata (1) proc_open give erratic test results :( @@ -20,4 +15,3 @@ fc33x, fc34x, fc35x (3) known issue (4) tzdata related (5) need investigation - @@ -14,3 +14,7 @@ %@SCL@__php @BINDIR@/php +%@SCL@__phpize @BINDIR@/phpize + +%@SCL@__phpconfig @BINDIR@/php-config + diff --git a/php-7.2.0-oci8conf.patch b/php-7.2.0-oci8conf.patch index 0ad16a1..d026575 100644 --- a/php-7.2.0-oci8conf.patch +++ b/php-7.2.0-oci8conf.patch @@ -10,26 +10,4 @@ diff -up ./ext/ldap/php_ldap.h.remi-oci8 ./ext/ldap/php_ldap.h extern zend_module_entry ldap_module_entry; #define ldap_module_ptr &ldap_module_entry -diff -up ./ext/oci8/config.m4.remi-oci8 ./ext/oci8/config.m4 ---- ./ext/oci8/config.m4.remi-oci8 2017-06-20 15:45:39.000000000 +0200 -+++ ./ext/oci8/config.m4 2017-06-20 16:55:01.640203868 +0200 -@@ -372,6 +372,7 @@ if test "$PHP_OCI8" != "no"; then - - dnl Header directory for Instant Client SDK RPM install - OCISDKRPMINC=`echo "$PHP_OCI8_INSTANT_CLIENT" | $PHP_OCI8_SED -e 's!^/usr/lib/oracle/\(.*\)/client\('${PHP_OCI8_IC_LIBDIR_SUFFIX}'\)*/lib[/]*$!/usr/include/oracle/\1/client\2!'` -+ OCISDKRPMINC=`echo "$PHP_OCI8_INSTANT_CLIENT" | $PHP_OCI8_SED -e 's!^/usr/\(lib64\|lib\)/oracle/\(.*\)/\(client64\|client\)/lib[/]*$!/usr/include/oracle/\2/\3!'` - - dnl Header directory for Instant Client SDK zip file install - OCISDKZIPINC=$PHP_OCI8_INSTANT_CLIENT/sdk/include -diff -up ./ext/pdo_oci/config.m4.remi-oci8 ./ext/pdo_oci/config.m4 ---- ./ext/pdo_oci/config.m4.remi-oci8 2017-06-20 16:55:01.640203868 +0200 -+++ ./ext/pdo_oci/config.m4 2017-06-20 17:16:03.053538358 +0200 -@@ -93,7 +93,7 @@ if test "$PHP_PDO_OCI" != "no"; then - - AC_MSG_CHECKING([for oci.h]) - dnl Header directory for Instant Client SDK RPM install -- OCISDKRPMINC=`echo "$PDO_OCI_LIB_DIR" | $PHP_PDO_OCI_SED -e 's!^\(.*\)/lib/oracle/\(.*\)/\('${PDO_OCI_CLIENT_DIR}'\)/lib[/]*$!\1/include/oracle/\2/\3!'` -+ OCISDKRPMINC=`echo "$PDO_OCI_LIB_DIR" | $PHP_PDO_OCI_SED -e 's!^\(.*\)/\(lib64\|lib\)/oracle/\(.*\)/\('${PDO_OCI_CLIENT_DIR}'\)/lib[/]*$!\1/include/oracle/\3/\4!'` - - dnl Header directory for manual installation - OCISDKMANINC=`echo "$PDO_OCI_LIB_DIR" | $PHP_PDO_OCI_SED -e 's!^\(.*\)/lib[/]*$!\1/include!'` + diff --git a/php-7.2.16-systzdata-v17.patch b/php-7.2.16-systzdata-v17.patch index 640bff2..e8ae8b2 100644 --- a/php-7.2.16-systzdata-v17.patch +++ b/php-7.2.16-systzdata-v17.patch @@ -410,7 +410,7 @@ diff -up php-7.2.16RC1/ext/date/lib/parse_tz.c.systzdata php-7.2.16RC1/ext/date/ + size_t n; + char *data, *p; + -+ data = malloc(3 * sysdb->index_size + 7); ++ data = malloc(3 * sysdb->index_size + sizeof(FAKE_HEADER) - 1); + + p = mempcpy(data, FAKE_HEADER, sizeof(FAKE_HEADER) - 1); + diff --git a/php-bug81726.patch b/php-bug81726.patch index 53dcde3..847ebff 100644 --- a/php-bug81726.patch +++ b/php-bug81726.patch @@ -86,3 +86,95 @@ index ba76a9b0e0..52c973d7c4 100644 continue; } +From 8fad7bf40e1b5bf74f308eb882b1d72987ef539c Mon Sep 17 00:00:00 2001 +From: "Christoph M. Becker" <cmbecker69@gmx.de> +Date: Tue, 27 Sep 2022 17:43:40 +0200 +Subject: [PATCH] Fix regression introduced by fixing bug 81726 + +When a tar phar is created, `phar_open_from_fp()` is also called, but +since the file has just been created, none of the format checks can +succeed, so we continue to loop, but must not check again for the +format. Therefore, we bring back the old `test` variable. + +Closes GH-9620. + +(cherry picked from commit 432bf196d59bcb661fcf9cb7029cea9b43f490af) +--- + ext/phar/phar.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/ext/phar/phar.c b/ext/phar/phar.c +index 52c973d7c4..534af318f4 100644 +--- a/ext/phar/phar.c ++++ b/ext/phar/phar.c +@@ -1575,7 +1575,7 @@ static int phar_open_from_fp(php_stream* fp, char *fname, int fname_len, char *a + const char zip_magic[] = "PK\x03\x04"; + const char gz_magic[] = "\x1f\x8b\x08"; + const char bz_magic[] = "BZh"; +- char *pos; ++ char *pos, test = '\0'; + int recursion_count = 3; // arbitrary limit to avoid too deep or even infinite recursion + const int window_size = 1024; + char buffer[1024 + sizeof(token)]; /* a 1024 byte window + the size of the halt_compiler token (moving window) */ +@@ -1604,7 +1604,8 @@ static int phar_open_from_fp(php_stream* fp, char *fname, int fname_len, char *a + MAPPHAR_ALLOC_FAIL("internal corruption of phar \"%s\" (truncated entry)") + } + +- if (recursion_count) { ++ if (!test && recursion_count) { ++ test = '\1'; + pos = buffer+tokenlen; + if (!memcmp(pos, gz_magic, 3)) { + char err = 0; +@@ -1664,6 +1665,7 @@ static int phar_open_from_fp(php_stream* fp, char *fname, int fname_len, char *a + compression = PHAR_FILE_COMPRESSED_GZ; + + /* now, start over */ ++ test = '\0'; + if (!--recursion_count) { + MAPPHAR_ALLOC_FAIL("unable to decompress gzipped phar archive \"%s\""); + break; +@@ -1705,6 +1707,7 @@ static int phar_open_from_fp(php_stream* fp, char *fname, int fname_len, char *a + compression = PHAR_FILE_COMPRESSED_BZ2; + + /* now, start over */ ++ test = '\0'; + if (!--recursion_count) { + MAPPHAR_ALLOC_FAIL("unable to decompress bzipped phar archive \"%s\""); + break; +-- +2.37.3 + +From 9d32d284b25f5df75780911a47b3c23cbaac1761 Mon Sep 17 00:00:00 2001 +From: Remi Collet <remi@remirepo.net> +Date: Fri, 30 Sep 2022 09:22:14 +0200 +Subject: [PATCH] fix NEWS + +--- + NEWS | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/NEWS b/NEWS +index fe4cb9c484..b7a19aea19 100644 +--- a/NEWS ++++ b/NEWS +@@ -1,14 +1,16 @@ + PHP NEWS + ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| + +-Backported from 7.4.31 ++Backported from 7.4.32 + + - Core: +- . Fixed bug #81726: phar wrapper: DOS when using quine gzip file. +- (CVE-2022-31628). (cmb) + . Fixed bug #81727: Don't mangle HTTP variable names that clash with ones + that have a specific semantic meaning. (CVE-2022-31629). (Derick) + ++- Phar: ++ . Fixed bug #81726: phar wrapper: DOS when using quine gzip file. ++ (CVE-2022-31628). (cmb) ++ + Backported from 7.4.30 + + - mysqlnd: diff --git a/php-bug81738.patch b/php-bug81738.patch new file mode 100644 index 0000000..6fceeab --- /dev/null +++ b/php-bug81738.patch @@ -0,0 +1,129 @@ +From 4b1f3b84336a26db9649c5175e29984fa1b54950 Mon Sep 17 00:00:00 2001 +From: Stanislav Malyshev <smalyshev@gmail.com> +Date: Thu, 20 Oct 2022 23:57:35 -0600 +Subject: [PATCH] Fix bug #81738 (buffer overflow in hash_update() on long + parameter) + +(cherry picked from commit de4517ad607df8d4cb3735228b39e4a48f95556c) +--- + NEWS | 6 ++++++ + ext/hash/sha3/generic32lc/KeccakSponge.inc | 14 ++++++++------ + ext/hash/sha3/generic64lc/KeccakSponge.inc | 14 ++++++++------ + 3 files changed, 22 insertions(+), 12 deletions(-) + +diff --git a/NEWS b/NEWS +index e31f007ad0..b6e3c4fe6c 100644 +--- a/NEWS ++++ b/NEWS +@@ -1,6 +1,12 @@ + PHP NEWS + ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| + ++Backported from 7.4.33 ++ ++- Hash: ++ . Fixed bug #81738: buffer overflow in hash_update() on long parameter. ++ (CVE-2022-37454) (nicky at mouha dot be) ++ + Backported from 7.4.32 + + - Core: +diff --git a/ext/hash/sha3/generic32lc/KeccakSponge.inc b/ext/hash/sha3/generic32lc/KeccakSponge.inc +index 42a15aac6d..f8c42ff788 100644 +--- a/ext/hash/sha3/generic32lc/KeccakSponge.inc ++++ b/ext/hash/sha3/generic32lc/KeccakSponge.inc +@@ -160,7 +160,7 @@ int SpongeAbsorb(SpongeInstance *instance, const unsigned char *data, size_t dat + i = 0; + curData = data; + while(i < dataByteLen) { +- if ((instance->byteIOIndex == 0) && (dataByteLen >= (i + rateInBytes))) { ++ if ((instance->byteIOIndex == 0) && (dataByteLen-i >= rateInBytes)) { + #ifdef SnP_FastLoop_Absorb + /* processing full blocks first */ + if ((rateInBytes % (SnP_width/200)) == 0) { +@@ -186,9 +186,10 @@ int SpongeAbsorb(SpongeInstance *instance, const unsigned char *data, size_t dat + } + else { + /* normal lane: using the message queue */ +- partialBlock = (unsigned int)(dataByteLen - i); +- if (partialBlock+instance->byteIOIndex > rateInBytes) ++ if (dataByteLen-i > rateInBytes-instance->byteIOIndex) + partialBlock = rateInBytes-instance->byteIOIndex; ++ else ++ partialBlock = (unsigned int)(dataByteLen - i); + #ifdef KeccakReference + displayBytes(1, "Block to be absorbed (part)", curData, partialBlock); + #endif +@@ -263,7 +264,7 @@ int SpongeSqueeze(SpongeInstance *instance, unsigned char *data, size_t dataByte + i = 0; + curData = data; + while(i < dataByteLen) { +- if ((instance->byteIOIndex == rateInBytes) && (dataByteLen >= (i + rateInBytes))) { ++ if ((instance->byteIOIndex == rateInBytes) && (dataByteLen-i >= rateInBytes)) { + for(j=dataByteLen-i; j>=rateInBytes; j-=rateInBytes) { + SnP_Permute(instance->state); + SnP_ExtractBytes(instance->state, curData, 0, rateInBytes); +@@ -280,9 +281,10 @@ int SpongeSqueeze(SpongeInstance *instance, unsigned char *data, size_t dataByte + SnP_Permute(instance->state); + instance->byteIOIndex = 0; + } +- partialBlock = (unsigned int)(dataByteLen - i); +- if (partialBlock+instance->byteIOIndex > rateInBytes) ++ if (dataByteLen-i > rateInBytes-instance->byteIOIndex) + partialBlock = rateInBytes-instance->byteIOIndex; ++ else ++ partialBlock = (unsigned int)(dataByteLen - i); + i += partialBlock; + + SnP_ExtractBytes(instance->state, curData, instance->byteIOIndex, partialBlock); +diff --git a/ext/hash/sha3/generic64lc/KeccakSponge.inc b/ext/hash/sha3/generic64lc/KeccakSponge.inc +index 42a15aac6d..f8c42ff788 100644 +--- a/ext/hash/sha3/generic64lc/KeccakSponge.inc ++++ b/ext/hash/sha3/generic64lc/KeccakSponge.inc +@@ -160,7 +160,7 @@ int SpongeAbsorb(SpongeInstance *instance, const unsigned char *data, size_t dat + i = 0; + curData = data; + while(i < dataByteLen) { +- if ((instance->byteIOIndex == 0) && (dataByteLen >= (i + rateInBytes))) { ++ if ((instance->byteIOIndex == 0) && (dataByteLen-i >= rateInBytes)) { + #ifdef SnP_FastLoop_Absorb + /* processing full blocks first */ + if ((rateInBytes % (SnP_width/200)) == 0) { +@@ -186,9 +186,10 @@ int SpongeAbsorb(SpongeInstance *instance, const unsigned char *data, size_t dat + } + else { + /* normal lane: using the message queue */ +- partialBlock = (unsigned int)(dataByteLen - i); +- if (partialBlock+instance->byteIOIndex > rateInBytes) ++ if (dataByteLen-i > rateInBytes-instance->byteIOIndex) + partialBlock = rateInBytes-instance->byteIOIndex; ++ else ++ partialBlock = (unsigned int)(dataByteLen - i); + #ifdef KeccakReference + displayBytes(1, "Block to be absorbed (part)", curData, partialBlock); + #endif +@@ -263,7 +264,7 @@ int SpongeSqueeze(SpongeInstance *instance, unsigned char *data, size_t dataByte + i = 0; + curData = data; + while(i < dataByteLen) { +- if ((instance->byteIOIndex == rateInBytes) && (dataByteLen >= (i + rateInBytes))) { ++ if ((instance->byteIOIndex == rateInBytes) && (dataByteLen-i >= rateInBytes)) { + for(j=dataByteLen-i; j>=rateInBytes; j-=rateInBytes) { + SnP_Permute(instance->state); + SnP_ExtractBytes(instance->state, curData, 0, rateInBytes); +@@ -280,9 +281,10 @@ int SpongeSqueeze(SpongeInstance *instance, unsigned char *data, size_t dataByte + SnP_Permute(instance->state); + instance->byteIOIndex = 0; + } +- partialBlock = (unsigned int)(dataByteLen - i); +- if (partialBlock+instance->byteIOIndex > rateInBytes) ++ if (dataByteLen-i > rateInBytes-instance->byteIOIndex) + partialBlock = rateInBytes-instance->byteIOIndex; ++ else ++ partialBlock = (unsigned int)(dataByteLen - i); + i += partialBlock; + + SnP_ExtractBytes(instance->state, curData, instance->byteIOIndex, partialBlock); +-- +2.37.3 + diff --git a/php-bug81740.patch b/php-bug81740.patch new file mode 100644 index 0000000..de24046 --- /dev/null +++ b/php-bug81740.patch @@ -0,0 +1,87 @@ +From 67ef55c661506875d04e58bc9d1293a919eb798e Mon Sep 17 00:00:00 2001 +From: "Christoph M. Becker" <cmbecker69@gmx.de> +Date: Mon, 31 Oct 2022 17:20:23 +0100 +Subject: [PATCH 1/2] Fix #81740: PDO::quote() may return unquoted string + +`sqlite3_snprintf()` expects its first parameter to be `int`; we need +to avoid overflow. + +(cherry picked from commit 921b6813da3237a83e908998483f46ae3d8bacba) +(cherry picked from commit 7cb160efe19d3dfb8b92629805733ea186b55050) +--- + ext/pdo_sqlite/sqlite_driver.c | 3 +++ + ext/pdo_sqlite/tests/bug81740.phpt | 17 +++++++++++++++++ + 2 files changed, 20 insertions(+) + create mode 100644 ext/pdo_sqlite/tests/bug81740.phpt + +diff --git a/ext/pdo_sqlite/sqlite_driver.c b/ext/pdo_sqlite/sqlite_driver.c +index 2bf452a88a..4bd844e2b5 100644 +--- a/ext/pdo_sqlite/sqlite_driver.c ++++ b/ext/pdo_sqlite/sqlite_driver.c +@@ -236,6 +236,9 @@ static char *pdo_sqlite_last_insert_id(pdo_dbh_t *dbh, const char *name, size_t + /* NB: doesn't handle binary strings... use prepared stmts for that */ + static int sqlite_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, size_t unquotedlen, char **quoted, size_t *quotedlen, enum pdo_param_type paramtype ) + { ++ if (unquotedlen > (INT_MAX - 3) / 2) { ++ return 0; ++ } + *quoted = safe_emalloc(2, unquotedlen, 3); + sqlite3_snprintf(2*unquotedlen + 3, *quoted, "'%q'", unquoted); + *quotedlen = strlen(*quoted); +diff --git a/ext/pdo_sqlite/tests/bug81740.phpt b/ext/pdo_sqlite/tests/bug81740.phpt +new file mode 100644 +index 0000000000..99fb07c304 +--- /dev/null ++++ b/ext/pdo_sqlite/tests/bug81740.phpt +@@ -0,0 +1,17 @@ ++--TEST-- ++Bug #81740 (PDO::quote() may return unquoted string) ++--SKIPIF-- ++<?php ++if (!extension_loaded('pdo_sqlite')) print 'skip not loaded'; ++if (getenv("SKIP_SLOW_TESTS")) die("skip slow test"); ++?> ++--INI-- ++memory_limit=-1 ++--FILE-- ++<?php ++$pdo = new PDO("sqlite::memory:"); ++$string = str_repeat("a", 0x80000000); ++var_dump($pdo->quote($string)); ++?> ++--EXPECT-- ++bool(false) +-- +2.38.1 + +From 09d73edbbcdb419611e341bec46bf083c708d864 Mon Sep 17 00:00:00 2001 +From: Remi Collet <remi@remirepo.net> +Date: Mon, 19 Dec 2022 09:24:02 +0100 +Subject: [PATCH 2/2] NEWS + +(cherry picked from commit 7328f3a0344806b846bd05657bdce96e47810bf0) +(cherry picked from commit 144d79977c7e2a410a705f550dbc8ee754dd1cb3) +--- + NEWS | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/NEWS b/NEWS +index b6e3c4fe6c..1c00ef6357 100644 +--- a/NEWS ++++ b/NEWS +@@ -1,6 +1,12 @@ + PHP NEWS + ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| + ++Backported from 8.0.27 ++ ++- PDO/SQLite: ++ . Fixed bug #81740 (PDO::quote() may return unquoted string). ++ (CVE-2022-31631) (cmb) ++ + Backported from 7.4.33 + + - Hash: +-- +2.38.1 + diff --git a/php-bug81744.patch b/php-bug81744.patch new file mode 100644 index 0000000..2864136 --- /dev/null +++ b/php-bug81744.patch @@ -0,0 +1,190 @@ +From 77e6dd89b92c3c7b3191e53508b1cd1744a89208 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= <tim@bastelstu.be> +Date: Mon, 23 Jan 2023 21:15:24 +0100 +Subject: [PATCH 1/8] 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. + +(cherry picked from commit c840f71524067aa474c00c3eacfb83bd860bfc8a) +(cherry picked from commit 7437aaae38cf4b3357e7580f9e22fd4a403b6c23) +--- + 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 5cf306715f..e923b55ed0 100644 +--- a/ext/standard/crypt_blowfish.c ++++ b/ext/standard/crypt_blowfish.c +@@ -377,7 +377,6 @@ static 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; \ +@@ -405,13 +404,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 0000000000..32e335f4b0 +--- /dev/null ++++ b/ext/standard/tests/crypt/bcrypt_salt_dollar.phpt +@@ -0,0 +1,82 @@ ++--TEST-- ++bcrypt correctly rejects salts containing $ ++--FILE-- ++<?php ++for ($i = 0; $i < 23; $i++) { ++ $salt = '$2y$04$' . str_repeat('0', $i) . '$'; ++ $result = crypt("foo", $salt); ++ var_dump($salt); ++ var_dump($result); ++ var_dump($result === $salt); ++} ++?> ++--EXPECT-- ++string(8) "$2y$04$$" ++string(2) "*0" ++bool(false) ++string(9) "$2y$04$0$" ++string(2) "*0" ++bool(false) ++string(10) "$2y$04$00$" ++string(2) "*0" ++bool(false) ++string(11) "$2y$04$000$" ++string(2) "*0" ++bool(false) ++string(12) "$2y$04$0000$" ++string(2) "*0" ++bool(false) ++string(13) "$2y$04$00000$" ++string(2) "*0" ++bool(false) ++string(14) "$2y$04$000000$" ++string(2) "*0" ++bool(false) ++string(15) "$2y$04$0000000$" ++string(2) "*0" ++bool(false) ++string(16) "$2y$04$00000000$" ++string(2) "*0" ++bool(false) ++string(17) "$2y$04$000000000$" ++string(2) "*0" ++bool(false) ++string(18) "$2y$04$0000000000$" ++string(2) "*0" ++bool(false) ++string(19) "$2y$04$00000000000$" ++string(2) "*0" ++bool(false) ++string(20) "$2y$04$000000000000$" ++string(2) "*0" ++bool(false) ++string(21) "$2y$04$0000000000000$" ++string(2) "*0" ++bool(false) ++string(22) "$2y$04$00000000000000$" ++string(2) "*0" ++bool(false) ++string(23) "$2y$04$000000000000000$" ++string(2) "*0" ++bool(false) ++string(24) "$2y$04$0000000000000000$" ++string(2) "*0" ++bool(false) ++string(25) "$2y$04$00000000000000000$" ++string(2) "*0" ++bool(false) ++string(26) "$2y$04$000000000000000000$" ++string(2) "*0" ++bool(false) ++string(27) "$2y$04$0000000000000000000$" ++string(2) "*0" ++bool(false) ++string(28) "$2y$04$00000000000000000000$" ++string(2) "*0" ++bool(false) ++string(29) "$2y$04$000000000000000000000$" ++string(2) "*0" ++bool(false) ++string(30) "$2y$04$0000000000000000000000$" ++string(60) "$2y$04$000000000000000000000u2a2UpVexIt9k3FMJeAVr3c04F5tcI8K" ++bool(false) +-- +2.39.1 + +From c57400002961b6df74960c52777ad0fb3dbeabea Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= <tim@bastelstu.be> +Date: Mon, 23 Jan 2023 22:13:57 +0100 +Subject: [PATCH 2/8] crypt: Fix possible buffer overread in php_crypt() + +(cherry picked from commit a92acbad873a05470af1a47cb785a18eadd827b5) +(cherry picked from commit ed0281b588a6840cb95f3134a4e68847a3be5bb7) +--- + 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 e873ca7946..c391cfd3f6 100644 +--- a/ext/standard/crypt.c ++++ b/ext/standard/crypt.c +@@ -156,6 +156,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 0000000000..085bc8a239 +--- /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-- ++<?php ++var_dump(password_verify("foo", '$2')); ++?> ++--EXPECT-- ++bool(false) +-- +2.39.1 + diff --git a/php-bug81746.patch b/php-bug81746.patch new file mode 100644 index 0000000..c654709 --- /dev/null +++ b/php-bug81746.patch @@ -0,0 +1,100 @@ +From 3640e9897928d5b5607270c20593a0c04a455e1e 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 3/8] 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. + +(cherry picked from commit ec10b28d64decbc54aa1e585dce580f0bd7a5953) +(cherry picked from commit 887cd0710ad856a0d22c329b6ea6c71ebd8621ae) +--- + 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 11ef4aa818..c212faa695 100644 +--- a/ext/dom/document.c ++++ b/ext/dom/document.c +@@ -1359,7 +1359,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 6c1da2761d..0f2b62ae20 100644 +--- a/ext/xmlreader/php_xmlreader.c ++++ b/ext/xmlreader/php_xmlreader.c +@@ -1040,7 +1040,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 520edfadbb..33047bb160 100644 +--- a/main/fopen_wrappers.c ++++ b/main/fopen_wrappers.c +@@ -135,10 +135,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; +-- +2.39.1 + +From 2b9c9a8cb00914c08e34ee242d4aa3ba4aa74ef4 Mon Sep 17 00:00:00 2001 +From: Remi Collet <remi@remirepo.net> +Date: Mon, 13 Feb 2023 11:46:47 +0100 +Subject: [PATCH 4/8] NEWS + +(cherry picked from commit 614468ce4056c0ef93aae09532dcffdf65b594b5) +--- + NEWS | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/NEWS b/NEWS +index 1c00ef6357..ad57c5ccd5 100644 +--- a/NEWS ++++ b/NEWS +@@ -1,6 +1,14 @@ + PHP NEWS + ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| + ++Backported from 8.0.28 ++ ++- Core: ++ . Fixed bug #81744 (Password_verify() always return true with some hash). ++ (CVE-2023-0567). (Tim Düsterhus) ++ . Fixed bug #81746 (1-byte array overrun in common path resolve code). ++ (CVE-2023-0568). (Niels Dossche) ++ + Backported from 8.0.27 + + - PDO/SQLite: +-- +2.39.1 + diff --git a/php-cve-2023-0662.patch b/php-cve-2023-0662.patch new file mode 100644 index 0000000..07361d1 --- /dev/null +++ b/php-cve-2023-0662.patch @@ -0,0 +1,148 @@ +From 1548e88ea16f68d15a71040c7fb6bff3874c5e32 Mon Sep 17 00:00:00 2001 +From: Jakub Zelenka <bukka@php.net> +Date: Thu, 19 Jan 2023 14:11:18 +0000 +Subject: [PATCH 5/8] Fix repeated warning for file uploads limit exceeding + +(cherry picked from commit 3a2fdef1ae38881110006616ee1f0534b082ca45) +--- + main/rfc1867.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/main/rfc1867.c b/main/rfc1867.c +index 27718e72a4..3f7a0c76f9 100644 +--- a/main/rfc1867.c ++++ b/main/rfc1867.c +@@ -932,7 +932,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 */ +-- +2.39.1 + +From 7d196fe1295491e624edf263525148c8c3bfd902 Mon Sep 17 00:00:00 2001 +From: Jakub Zelenka <bukka@php.net> +Date: Thu, 19 Jan 2023 14:31:25 +0000 +Subject: [PATCH 6/8] 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. + +(cherry picked from commit 8ec78d28d20c82c75c4747f44c52601cfdb22516) +--- + main/main.c | 1 + + main/rfc1867.c | 11 +++++++++++ + 2 files changed, 12 insertions(+) + +diff --git a/main/main.c b/main/main.c +index a3fc980b17..0cfdb91368 100644 +--- a/main/main.c ++++ b/main/main.c +@@ -621,6 +621,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 3f7a0c76f9..14813a300c 100644 +--- a/main/rfc1867.c ++++ b/main/rfc1867.c +@@ -704,6 +704,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; +@@ -725,6 +726,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) { +@@ -809,6 +815,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; + } +-- +2.39.1 + +From 7900df2bfa37eaf0217fd2d62f3418b0be096cba Mon Sep 17 00:00:00 2001 +From: Remi Collet <remi@remirepo.net> +Date: Tue, 14 Feb 2023 09:14:47 +0100 +Subject: [PATCH 7/8] NEWS + +(cherry picked from commit 472db3ee3a00ac00d36019eee0b3b7362334481c) +--- + NEWS | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/NEWS b/NEWS +index ad57c5ccd5..e59c43300a 100644 +--- a/NEWS ++++ b/NEWS +@@ -9,6 +9,10 @@ Backported from 8.0.28 + . Fixed bug #81746 (1-byte array overrun in common path resolve code). + (CVE-2023-0568). (Niels Dossche) + ++- FPM: ++ . Fixed bug GHSA-54hq-v5wp-fqgv (DOS vulnerability when parsing multipart ++ request body). (CVE-2023-0662) (Jakub Zelenka) ++ + Backported from 8.0.27 + + - PDO/SQLite: +-- +2.39.1 + +From 27d1f29635717f619267b5e2ebf87ec43faa18f0 Mon Sep 17 00:00:00 2001 +From: Remi Collet <remi@remirepo.net> +Date: Tue, 14 Feb 2023 11:47:22 +0100 +Subject: [PATCH 8/8] fix NEWS, not FPM specific + +(cherry picked from commit c04f310440a906fc4ca885f4ecf6e3e4cd36edc7) +--- + NEWS | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/NEWS b/NEWS +index e59c43300a..47e9f89a64 100644 +--- a/NEWS ++++ b/NEWS +@@ -8,8 +8,6 @@ Backported from 8.0.28 + (CVE-2023-0567). (Tim Düsterhus) + . Fixed bug #81746 (1-byte array overrun in common path resolve code). + (CVE-2023-0568). (Niels Dossche) +- +-- FPM: + . Fixed bug GHSA-54hq-v5wp-fqgv (DOS vulnerability when parsing multipart + request body). (CVE-2023-0662) (Jakub Zelenka) + +-- +2.39.1 + diff --git a/php-cve-2023-3247.patch b/php-cve-2023-3247.patch new file mode 100644 index 0000000..54e8592 --- /dev/null +++ b/php-cve-2023-3247.patch @@ -0,0 +1,152 @@ +From a8cd8000fe5814302758a26f4ad4fd9d392c91e0 Mon Sep 17 00:00:00 2001 +From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> +Date: Sun, 16 Apr 2023 15:05:03 +0200 +Subject: [PATCH] Fix missing randomness check and insufficient random bytes + for SOAP HTTP Digest +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +If php_random_bytes_throw fails, the nonce will be uninitialized, but +still sent to the server. The client nonce is intended to protect +against a malicious server. See section 5.10 and 5.12 of RFC 7616 [1], +and bullet point 2 below. + +Tim pointed out that even though it's the MD5 of the nonce that gets sent, +enumerating 31 bits is trivial. So we have still a stack information leak +of 31 bits. + +Furthermore, Tim found the following issues: +* The small size of cnonce might cause the server to erroneously reject + a request due to a repeated (cnonce, nc) pair. As per the birthday + problem 31 bits of randomness will return a duplication with 50% + chance after less than 55000 requests and nc always starts counting at 1. +* The cnonce is intended to protect the client and password against a + malicious server that returns a constant server nonce where the server + precomputed a rainbow table between passwords and correct client response. + As storage is fairly cheap, a server could precompute the client responses + for (a subset of) client nonces and still have a chance of reversing the + client response with the same probability as the cnonce duplication. + + Precomputing the rainbow table for all 2^31 cnonces increases the rainbow + table size by factor 2 billion, which is infeasible. But precomputing it + for 2^14 cnonces only increases the table size by factor 16k and the server + would still have a 10% chance of successfully reversing a password with a + single client request. + +This patch fixes the issues by increasing the nonce size, and checking +the return value of php_random_bytes_throw(). In the process we also get +rid of the MD5 hashing of the nonce. + +[1] RFC 7616: https://www.rfc-editor.org/rfc/rfc7616 + +Co-authored-by: Tim Düsterhus <timwolla@php.net> +(cherry picked from commit 126d517ce240e9f638d9a5eaa509eaca49ef562a) +(cherry picked from commit 0cfca9aa1395271833848daec0bace51d965531d) +--- + NEWS | 6 ++++++ + ext/soap/php_http.c | 21 +++++++++++++-------- + 2 files changed, 19 insertions(+), 8 deletions(-) + +diff --git a/NEWS b/NEWS +index 47e9f89a646..ae5101b368e 100644 +--- a/NEWS ++++ b/NEWS +@@ -1,6 +1,12 @@ + PHP NEWS + ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| + ++Backported from 8.0.29 ++ ++- Soap: ++ . Fixed bug GHSA-76gg-c692-v2mw (Missing error check and insufficient random ++ bytes in HTTP Digest authentication for SOAP). (nielsdos, timwolla) ++ + Backported from 8.0.28 + + - Core: +diff --git a/ext/soap/php_http.c b/ext/soap/php_http.c +index 57754021b77..15b086e21c4 100644 +--- a/ext/soap/php_http.c ++++ b/ext/soap/php_http.c +@@ -665,18 +665,23 @@ int make_http_soap_request(zval *this_ptr, + if ((digest = zend_hash_str_find(Z_OBJPROP_P(this_ptr), "_digest", sizeof("_digest")-1)) != NULL) { + if (Z_TYPE_P(digest) == IS_ARRAY) { + char HA1[33], HA2[33], response[33], cnonce[33], nc[9]; +- zend_long nonce; ++ unsigned char nonce[16]; + PHP_MD5_CTX md5ctx; + unsigned char hash[16]; + +- php_random_bytes_throw(&nonce, sizeof(nonce)); +- nonce &= 0x7fffffff; ++ if (UNEXPECTED(php_random_bytes_throw(&nonce, sizeof(nonce)) != SUCCESS)) { ++ ZEND_ASSERT(EG(exception)); ++ php_stream_close(stream); ++ zend_hash_str_del(Z_OBJPROP_P(this_ptr), "httpurl", sizeof("httpurl")-1); ++ zend_hash_str_del(Z_OBJPROP_P(this_ptr), "httpsocket", sizeof("httpsocket")-1); ++ zend_hash_str_del(Z_OBJPROP_P(this_ptr), "_use_proxy", sizeof("_use_proxy")-1); ++ smart_str_free(&soap_headers_z); ++ smart_str_free(&soap_headers); ++ return FALSE; ++ } + +- PHP_MD5Init(&md5ctx); +- snprintf(cnonce, sizeof(cnonce), ZEND_LONG_FMT, nonce); +- PHP_MD5Update(&md5ctx, (unsigned char*)cnonce, strlen(cnonce)); +- PHP_MD5Final(hash, &md5ctx); +- make_digest(cnonce, hash); ++ php_hash_bin2hex(cnonce, nonce, sizeof(nonce)); ++ cnonce[32] = 0; + + if ((tmp = zend_hash_str_find(Z_ARRVAL_P(digest), "nc", sizeof("nc")-1)) != NULL && + Z_TYPE_P(tmp) == IS_LONG) { +From 1563873cd3f1fbd2464d3521b699f14efce1db13 Mon Sep 17 00:00:00 2001 +From: Remi Collet <remi@remirepo.net> +Date: Tue, 6 Jun 2023 18:05:22 +0200 +Subject: [PATCH] Fix GH-11382 add missing hash header for bin2hex + +(cherry picked from commit 40439039c224bb8cdebd1b7b3d03b8cc11e7cce7) +--- + ext/soap/php_http.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/ext/soap/php_http.c b/ext/soap/php_http.c +index 15b086e21c..6903a3b9c9 100644 +--- a/ext/soap/php_http.c ++++ b/ext/soap/php_http.c +@@ -23,6 +23,7 @@ + #include "ext/standard/base64.h" + #include "ext/standard/md5.h" + #include "ext/standard/php_random.h" ++#include "ext/hash/php_hash.h" + + static char *get_http_header_value(char *headers, char *type); + static zend_string *get_http_body(php_stream *socketd, int close, char *headers); +From 24d822d4e70431cc6dc795f7ff5193960f385c2f Mon Sep 17 00:00:00 2001 +From: Remi Collet <remi@remirepo.net> +Date: Thu, 15 Jun 2023 08:47:55 +0200 +Subject: [PATCH] add cve + +(cherry picked from commit f3021d66d7bb42d2578530cc94f9bde47e58eb10) +--- + NEWS | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/NEWS b/NEWS +index ae5101b368..5f49a7ee04 100644 +--- a/NEWS ++++ b/NEWS +@@ -5,7 +5,8 @@ Backported from 8.0.29 + + - Soap: + . Fixed bug GHSA-76gg-c692-v2mw (Missing error check and insufficient random +- bytes in HTTP Digest authentication for SOAP). (nielsdos, timwolla) ++ bytes in HTTP Digest authentication for SOAP). ++ (CVE-2023-3247) (nielsdos, timwolla) + + Backported from 8.0.28 + +-- +2.40.1 + diff --git a/php-cve-2023-3823.patch b/php-cve-2023-3823.patch new file mode 100644 index 0000000..70829bf --- /dev/null +++ b/php-cve-2023-3823.patch @@ -0,0 +1,91 @@ +From f8f433d0d8eaac21af4f4532496d33f9c2b381d6 Mon Sep 17 00:00:00 2001 +From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> +Date: Mon, 10 Jul 2023 13:25:34 +0200 +Subject: [PATCH 1/5] Fix buffer mismanagement in phar_dir_read() + +Fixes GHSA-jqcx-ccgc-xwhv. + +(cherry picked from commit 80316123f3e9dcce8ac419bd9dd43546e2ccb5ef) +(cherry picked from commit c398fe98c044c8e7c23135acdc38d4ef7bedc983) +(cherry picked from commit 3f14261065e4c0552afa9cb16411475050a41c2c) +--- + ext/phar/dirstream.c | 15 ++++++++------ + ext/phar/tests/GHSA-jqcx-ccgc-xwhv.phpt | 27 +++++++++++++++++++++++++ + 2 files changed, 36 insertions(+), 6 deletions(-) + create mode 100644 ext/phar/tests/GHSA-jqcx-ccgc-xwhv.phpt + +diff --git a/ext/phar/dirstream.c b/ext/phar/dirstream.c +index 1ee886ec2f..66931b652c 100644 +--- a/ext/phar/dirstream.c ++++ b/ext/phar/dirstream.c +@@ -92,25 +92,28 @@ static int phar_dir_seek(php_stream *stream, zend_off_t offset, int whence, zend + */ + static size_t phar_dir_read(php_stream *stream, char *buf, size_t count) /* {{{ */ + { +- size_t to_read; + HashTable *data = (HashTable *)stream->abstract; + zend_string *str_key; + zend_ulong unused; + ++ if (count != sizeof(php_stream_dirent)) { ++ return -1; ++ } ++ + if (HASH_KEY_NON_EXISTENT == zend_hash_get_current_key(data, &str_key, &unused)) { + return 0; + } + + zend_hash_move_forward(data); +- to_read = MIN(ZSTR_LEN(str_key), count); + +- if (to_read == 0 || count < ZSTR_LEN(str_key)) { ++ php_stream_dirent *dirent = (php_stream_dirent *) buf; ++ ++ if (sizeof(dirent->d_name) <= ZSTR_LEN(str_key)) { + return 0; + } + +- memset(buf, 0, sizeof(php_stream_dirent)); +- memcpy(((php_stream_dirent *) buf)->d_name, ZSTR_VAL(str_key), to_read); +- ((php_stream_dirent *) buf)->d_name[to_read + 1] = '\0'; ++ memset(dirent, 0, sizeof(php_stream_dirent)); ++ PHP_STRLCPY(dirent->d_name, ZSTR_VAL(str_key), sizeof(dirent->d_name), ZSTR_LEN(str_key)); + + return sizeof(php_stream_dirent); + } +diff --git a/ext/phar/tests/GHSA-jqcx-ccgc-xwhv.phpt b/ext/phar/tests/GHSA-jqcx-ccgc-xwhv.phpt +new file mode 100644 +index 0000000000..4e12f05fb6 +--- /dev/null ++++ b/ext/phar/tests/GHSA-jqcx-ccgc-xwhv.phpt +@@ -0,0 +1,27 @@ ++--TEST-- ++GHSA-jqcx-ccgc-xwhv (Buffer overflow and overread in phar_dir_read()) ++--SKIPIF-- ++<?php if (!extension_loaded("phar")) die("skip"); ?> ++--INI-- ++phar.readonly=0 ++--FILE-- ++<?php ++$phar = new Phar(__DIR__. '/GHSA-jqcx-ccgc-xwhv.phar'); ++$phar->startBuffering(); ++$phar->addFromString(str_repeat('A', PHP_MAXPATHLEN - 1), 'This is the content of file 1.'); ++$phar->addFromString(str_repeat('B', PHP_MAXPATHLEN - 1).'C', 'This is the content of file 2.'); ++$phar->stopBuffering(); ++ ++$handle = opendir('phar://' . __DIR__ . '/GHSA-jqcx-ccgc-xwhv.phar'); ++var_dump(strlen(readdir($handle))); ++// Must not be a string of length PHP_MAXPATHLEN+1 ++var_dump(readdir($handle)); ++closedir($handle); ++?> ++--CLEAN-- ++<?php ++unlink(__DIR__. '/GHSA-jqcx-ccgc-xwhv.phar'); ++?> ++--EXPECTF-- ++int(%d) ++bool(false) +-- +2.41.0 + diff --git a/php-cve-2023-3824.patch b/php-cve-2023-3824.patch new file mode 100644 index 0000000..e807dd6 --- /dev/null +++ b/php-cve-2023-3824.patch @@ -0,0 +1,714 @@ +From d7de6908dfc8774e86a54100ad4e2ee810426001 Mon Sep 17 00:00:00 2001 +From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> +Date: Sat, 15 Jul 2023 17:33:52 +0200 +Subject: [PATCH 2/5] Sanitize libxml2 globals before parsing + +Fixes GHSA-3qrf-m4j2-pcrr. + +To parse a document with libxml2, you first need to create a parsing context. +The parsing context contains parsing options (e.g. XML_NOENT to substitute +entities) that the application (in this case PHP) can set. +Unfortunately, libxml2 also supports providing default set options. +For example, if you call xmlSubstituteEntitiesDefault(1) then the XML_NOENT +option will be added to the parsing options every time you create a parsing +context **even if the application never requested XML_NOENT**. + +Third party extensions can override these globals, in particular the +substitute entity global. This causes entity substitution to be +unexpectedly active. + +Fix it by setting the parsing options to a sane known value. +For API calls that depend on global state we introduce +PHP_LIBXML_SANITIZE_GLOBALS() and PHP_LIBXML_RESTORE_GLOBALS(). +For other APIs that work directly with a context we introduce +php_libxml_sanitize_parse_ctxt_options(). + +(cherry picked from commit c283c3ab0ba45d21b2b8745c1f9c7cbfe771c975) +(cherry picked from commit b3758bd21223b97c042cae7bd26a66cde081ea98) +(cherry picked from commit 4fb61f06b1aff89a4d7e548c37ffa5bf573270c3) +--- + ext/dom/document.c | 15 ++++++++ + ext/dom/documentfragment.c | 2 ++ + ...xml_global_state_entity_loader_bypass.phpt | 36 +++++++++++++++++++ + ext/libxml/php_libxml.h | 36 +++++++++++++++++++ + ext/simplexml/simplexml.c | 6 ++++ + ...xml_global_state_entity_loader_bypass.phpt | 36 +++++++++++++++++++ + ext/soap/php_xml.c | 2 ++ + ext/xml/compat.c | 2 ++ + ext/xmlreader/php_xmlreader.c | 9 +++++ + ...xml_global_state_entity_loader_bypass.phpt | 35 ++++++++++++++++++ + ext/xsl/xsltprocessor.c | 9 +++-- + 11 files changed, 183 insertions(+), 5 deletions(-) + create mode 100644 ext/dom/tests/libxml_global_state_entity_loader_bypass.phpt + create mode 100644 ext/simplexml/tests/libxml_global_state_entity_loader_bypass.phpt + create mode 100644 ext/xmlreader/tests/libxml_global_state_entity_loader_bypass.phpt + +diff --git a/ext/dom/document.c b/ext/dom/document.c +index c212faa695..b0eed5820b 100644 +--- a/ext/dom/document.c ++++ b/ext/dom/document.c +@@ -1438,6 +1438,7 @@ static xmlDocPtr dom_document_parser(zval *id, int mode, char *source, size_t so + options |= XML_PARSE_NOBLANKS; + } + ++ php_libxml_sanitize_parse_ctxt_options(ctxt); + xmlCtxtUseOptions(ctxt, options); + + ctxt->recovery = recover; +@@ -1735,7 +1736,9 @@ PHP_FUNCTION(dom_document_xinclude) + + DOM_GET_OBJ(docp, id, xmlDocPtr, intern); + ++ PHP_LIBXML_SANITIZE_GLOBALS(xinclude); + err = xmlXIncludeProcessFlags(docp, (int)flags); ++ PHP_LIBXML_RESTORE_GLOBALS(xinclude); + + /* XML_XINCLUDE_START and XML_XINCLUDE_END nodes need to be removed as these + are added via xmlXIncludeProcess to mark beginning and ending of xincluded document +@@ -1774,6 +1777,7 @@ PHP_FUNCTION(dom_document_validate) + + DOM_GET_OBJ(docp, id, xmlDocPtr, intern); + ++ PHP_LIBXML_SANITIZE_GLOBALS(validate); + cvp = xmlNewValidCtxt(); + + cvp->userData = NULL; +@@ -1785,6 +1789,7 @@ PHP_FUNCTION(dom_document_validate) + } else { + RETVAL_FALSE; + } ++ PHP_LIBXML_RESTORE_GLOBALS(validate); + + xmlFreeValidCtxt(cvp); + +@@ -1818,14 +1823,18 @@ static void _dom_document_schema_validate(INTERNAL_FUNCTION_PARAMETERS, int type + + DOM_GET_OBJ(docp, id, xmlDocPtr, intern); + ++ PHP_LIBXML_SANITIZE_GLOBALS(new_parser_ctxt); ++ + switch (type) { + case DOM_LOAD_FILE: + if (CHECK_NULL_PATH(source, source_len)) { ++ PHP_LIBXML_RESTORE_GLOBALS(new_parser_ctxt); + php_error_docref(NULL, E_WARNING, "Invalid Schema file source"); + RETURN_FALSE; + } + valid_file = _dom_get_valid_file_path(source, resolved_path, MAXPATHLEN); + if (!valid_file) { ++ PHP_LIBXML_RESTORE_GLOBALS(new_parser_ctxt); + php_error_docref(NULL, E_WARNING, "Invalid Schema file source"); + RETURN_FALSE; + } +@@ -1846,6 +1855,7 @@ static void _dom_document_schema_validate(INTERNAL_FUNCTION_PARAMETERS, int type + parser); + sptr = xmlSchemaParse(parser); + xmlSchemaFreeParserCtxt(parser); ++ PHP_LIBXML_RESTORE_GLOBALS(new_parser_ctxt); + if (!sptr) { + php_error_docref(NULL, E_WARNING, "Invalid Schema"); + RETURN_FALSE; +@@ -1866,11 +1876,13 @@ static void _dom_document_schema_validate(INTERNAL_FUNCTION_PARAMETERS, int type + } + #endif + ++ PHP_LIBXML_SANITIZE_GLOBALS(validate); + xmlSchemaSetValidOptions(vptr, valid_opts); + xmlSchemaSetValidErrors(vptr, php_libxml_error_handler, php_libxml_error_handler, vptr); + is_valid = xmlSchemaValidateDoc(vptr, docp); + xmlSchemaFree(sptr); + xmlSchemaFreeValidCtxt(vptr); ++ PHP_LIBXML_RESTORE_GLOBALS(validate); + + if (is_valid == 0) { + RETURN_TRUE; +@@ -1940,12 +1952,14 @@ static void _dom_document_relaxNG_validate(INTERNAL_FUNCTION_PARAMETERS, int typ + return; + } + ++ PHP_LIBXML_SANITIZE_GLOBALS(parse); + xmlRelaxNGSetParserErrors(parser, + (xmlRelaxNGValidityErrorFunc) php_libxml_error_handler, + (xmlRelaxNGValidityWarningFunc) php_libxml_error_handler, + parser); + sptr = xmlRelaxNGParse(parser); + xmlRelaxNGFreeParserCtxt(parser); ++ PHP_LIBXML_RESTORE_GLOBALS(parse); + if (!sptr) { + php_error_docref(NULL, E_WARNING, "Invalid RelaxNG"); + RETURN_FALSE; +@@ -2045,6 +2059,7 @@ static void dom_load_html(INTERNAL_FUNCTION_PARAMETERS, int mode) /* {{{ */ + ctxt->sax->error = php_libxml_ctx_error; + ctxt->sax->warning = php_libxml_ctx_warning; + } ++ php_libxml_sanitize_parse_ctxt_options(ctxt); + if (options) { + htmlCtxtUseOptions(ctxt, (int)options); + } +diff --git a/ext/dom/documentfragment.c b/ext/dom/documentfragment.c +index 87cb691501..b7ecfdc14b 100644 +--- a/ext/dom/documentfragment.c ++++ b/ext/dom/documentfragment.c +@@ -134,7 +134,9 @@ PHP_METHOD(domdocumentfragment, appendXML) { + } + + if (data) { ++ PHP_LIBXML_SANITIZE_GLOBALS(parse); + err = xmlParseBalancedChunkMemory(nodep->doc, NULL, NULL, 0, (xmlChar *) data, &lst); ++ PHP_LIBXML_RESTORE_GLOBALS(parse); + if (err != 0) { + RETURN_FALSE; + } +diff --git a/ext/dom/tests/libxml_global_state_entity_loader_bypass.phpt b/ext/dom/tests/libxml_global_state_entity_loader_bypass.phpt +new file mode 100644 +index 0000000000..b28afd4694 +--- /dev/null ++++ b/ext/dom/tests/libxml_global_state_entity_loader_bypass.phpt +@@ -0,0 +1,36 @@ ++--TEST-- ++GHSA-3qrf-m4j2-pcrr (libxml global state entity loader bypass) ++--SKIPIF-- ++<?php ++if (!extension_loaded('libxml')) die('skip libxml extension not available'); ++if (!extension_loaded('dom')) die('skip dom extension not available'); ++if (!extension_loaded('zend-test')) die('skip zend-test extension not available'); ++?> ++--FILE-- ++<?php ++ ++$xml = "<?xml version='1.0'?><!DOCTYPE root [<!ENTITY % bork SYSTEM \"php://nope\"> %bork;]><nothing/>"; ++ ++libxml_use_internal_errors(true); ++ ++function parseXML($xml) { ++ $doc = new DOMDocument(); ++ @$doc->loadXML($xml); ++ $doc->createDocumentFragment()->appendXML("&bork;"); ++ foreach (libxml_get_errors() as $error) { ++ var_dump(trim($error->message)); ++ } ++} ++ ++parseXML($xml); ++zend_test_override_libxml_global_state(); ++parseXML($xml); ++ ++echo "Done\n"; ++ ++?> ++--EXPECT-- ++string(25) "Entity 'bork' not defined" ++string(25) "Entity 'bork' not defined" ++string(25) "Entity 'bork' not defined" ++Done +diff --git a/ext/libxml/php_libxml.h b/ext/libxml/php_libxml.h +index f7aa726d88..371b4eecc5 100644 +--- a/ext/libxml/php_libxml.h ++++ b/ext/libxml/php_libxml.h +@@ -122,6 +122,42 @@ PHP_LIBXML_API void php_libxml_shutdown(void); + ZEND_TSRMLS_CACHE_EXTERN() + #endif + ++/* Other extension may override the global state options, these global options ++ * are copied initially to ctxt->options. Set the options to a known good value. ++ * See libxml2 globals.c and parserInternals.c. ++ * The unique_name argument allows multiple sanitizes and restores within the ++ * same function, even nested is necessary. */ ++#define PHP_LIBXML_SANITIZE_GLOBALS(unique_name) \ ++ int xml_old_loadsubset_##unique_name = xmlLoadExtDtdDefaultValue; \ ++ xmlLoadExtDtdDefaultValue = 0; \ ++ int xml_old_validate_##unique_name = xmlDoValidityCheckingDefaultValue; \ ++ xmlDoValidityCheckingDefaultValue = 0; \ ++ int xml_old_pedantic_##unique_name = xmlPedanticParserDefault(0); \ ++ int xml_old_substitute_##unique_name = xmlSubstituteEntitiesDefault(0); \ ++ int xml_old_linenrs_##unique_name = xmlLineNumbersDefault(0); \ ++ int xml_old_blanks_##unique_name = xmlKeepBlanksDefault(1); ++ ++#define PHP_LIBXML_RESTORE_GLOBALS(unique_name) \ ++ xmlLoadExtDtdDefaultValue = xml_old_loadsubset_##unique_name; \ ++ xmlDoValidityCheckingDefaultValue = xml_old_validate_##unique_name; \ ++ (void) xmlPedanticParserDefault(xml_old_pedantic_##unique_name); \ ++ (void) xmlSubstituteEntitiesDefault(xml_old_substitute_##unique_name); \ ++ (void) xmlLineNumbersDefault(xml_old_linenrs_##unique_name); \ ++ (void) xmlKeepBlanksDefault(xml_old_blanks_##unique_name); ++ ++/* Alternative for above, working directly on the context and not setting globals. ++ * Generally faster because no locking is involved, and this has the advantage that it sets the options to a known good value. */ ++static zend_always_inline void php_libxml_sanitize_parse_ctxt_options(xmlParserCtxtPtr ctxt) ++{ ++ ctxt->loadsubset = 0; ++ ctxt->validate = 0; ++ ctxt->pedantic = 0; ++ ctxt->replaceEntities = 0; ++ ctxt->linenumbers = 0; ++ ctxt->keepBlanks = 1; ++ ctxt->options = 0; ++} ++ + #else /* HAVE_LIBXML */ + #define libxml_module_ptr NULL + #endif +diff --git a/ext/simplexml/simplexml.c b/ext/simplexml/simplexml.c +index 341daed0ee..c2b0230e19 100644 +--- a/ext/simplexml/simplexml.c ++++ b/ext/simplexml/simplexml.c +@@ -2217,7 +2217,9 @@ PHP_FUNCTION(simplexml_load_file) + RETURN_FALSE; + } + ++ PHP_LIBXML_SANITIZE_GLOBALS(read_file); + docp = xmlReadFile(filename, NULL, (int)options); ++ PHP_LIBXML_RESTORE_GLOBALS(read_file); + + if (!docp) { + RETURN_FALSE; +@@ -2271,7 +2273,9 @@ PHP_FUNCTION(simplexml_load_string) + RETURN_FALSE; + } + ++ PHP_LIBXML_SANITIZE_GLOBALS(read_memory); + docp = xmlReadMemory(data, (int)data_len, NULL, NULL, (int)options); ++ PHP_LIBXML_RESTORE_GLOBALS(read_memory); + + if (!docp) { + RETURN_FALSE; +@@ -2321,7 +2325,9 @@ SXE_METHOD(__construct) + return; + } + ++ PHP_LIBXML_SANITIZE_GLOBALS(read_file_or_memory); + docp = is_url ? xmlReadFile(data, NULL, (int)options) : xmlReadMemory(data, (int)data_len, NULL, NULL, (int)options); ++ PHP_LIBXML_RESTORE_GLOBALS(read_file_or_memory); + + if (!docp) { + ((php_libxml_node_object *)sxe)->document = NULL; +diff --git a/ext/simplexml/tests/libxml_global_state_entity_loader_bypass.phpt b/ext/simplexml/tests/libxml_global_state_entity_loader_bypass.phpt +new file mode 100644 +index 0000000000..2152e01232 +--- /dev/null ++++ b/ext/simplexml/tests/libxml_global_state_entity_loader_bypass.phpt +@@ -0,0 +1,36 @@ ++--TEST-- ++GHSA-3qrf-m4j2-pcrr (libxml global state entity loader bypass) ++--SKIPIF-- ++<?php ++if (!extension_loaded('libxml')) die('skip libxml extension not available'); ++if (!extension_loaded('simplexml')) die('skip simplexml extension not available'); ++if (!extension_loaded('zend-test')) die('skip zend-test extension not available'); ++?> ++--FILE-- ++<?php ++ ++$xml = "<?xml version='1.0'?><!DOCTYPE root [<!ENTITY % bork SYSTEM \"php://nope\"> %bork;]><nothing/>"; ++ ++libxml_use_internal_errors(true); ++zend_test_override_libxml_global_state(); ++ ++echo "--- String test ---\n"; ++simplexml_load_string($xml); ++echo "--- Constructor test ---\n"; ++new SimpleXMLElement($xml); ++echo "--- File test ---\n"; ++file_put_contents("libxml_global_state_entity_loader_bypass.tmp", $xml); ++simplexml_load_file("libxml_global_state_entity_loader_bypass.tmp"); ++ ++echo "Done\n"; ++ ++?> ++--CLEAN-- ++<?php ++@unlink("libxml_global_state_entity_loader_bypass.tmp"); ++?> ++--EXPECT-- ++--- String test --- ++--- Constructor test --- ++--- File test --- ++Done +diff --git a/ext/soap/php_xml.c b/ext/soap/php_xml.c +index 1ac684eb81..053960c559 100644 +--- a/ext/soap/php_xml.c ++++ b/ext/soap/php_xml.c +@@ -94,6 +94,7 @@ xmlDocPtr soap_xmlParseFile(const char *filename) + if (ctxt) { + zend_bool old; + ++ php_libxml_sanitize_parse_ctxt_options(ctxt); + ctxt->keepBlanks = 0; + ctxt->sax->ignorableWhitespace = soap_ignorableWhitespace; + ctxt->sax->comment = soap_Comment; +@@ -144,6 +145,7 @@ xmlDocPtr soap_xmlParseMemory(const void *buf, size_t buf_size) + if (ctxt) { + zend_bool old; + ++ php_libxml_sanitize_parse_ctxt_options(ctxt); + ctxt->sax->ignorableWhitespace = soap_ignorableWhitespace; + ctxt->sax->comment = soap_Comment; + ctxt->sax->warning = NULL; +diff --git a/ext/xml/compat.c b/ext/xml/compat.c +index ef83485722..c55047215b 100644 +--- a/ext/xml/compat.c ++++ b/ext/xml/compat.c +@@ -19,6 +19,7 @@ + #include "php.h" + #if defined(HAVE_LIBXML) && (defined(HAVE_XML) || defined(HAVE_XMLRPC)) && !defined(HAVE_LIBEXPAT) + #include "expat_compat.h" ++#include "ext/libxml/php_libxml.h" + + typedef struct _php_xml_ns { + xmlNsPtr nsptr; +@@ -473,6 +474,7 @@ XML_ParserCreate_MM(const XML_Char *encoding, const XML_Memory_Handling_Suite *m + parser->parser->charset = XML_CHAR_ENCODING_NONE; + #endif + ++ php_libxml_sanitize_parse_ctxt_options(parser->parser); + #if LIBXML_VERSION >= 20703 + xmlCtxtUseOptions(parser->parser, XML_PARSE_OLDSAX); + #endif +diff --git a/ext/xmlreader/php_xmlreader.c b/ext/xmlreader/php_xmlreader.c +index 0f2b62ae20..f0fd013ff9 100644 +--- a/ext/xmlreader/php_xmlreader.c ++++ b/ext/xmlreader/php_xmlreader.c +@@ -301,6 +301,7 @@ static xmlRelaxNGPtr _xmlreader_get_relaxNG(char *source, size_t source_len, siz + return NULL; + } + ++ PHP_LIBXML_SANITIZE_GLOBALS(parse); + if (error_func || warn_func) { + xmlRelaxNGSetParserErrors(parser, + (xmlRelaxNGValidityErrorFunc) error_func, +@@ -309,6 +310,7 @@ static xmlRelaxNGPtr _xmlreader_get_relaxNG(char *source, size_t source_len, siz + } + sptr = xmlRelaxNGParse(parser); + xmlRelaxNGFreeParserCtxt(parser); ++ PHP_LIBXML_RESTORE_GLOBALS(parse); + + return sptr; + } +@@ -881,7 +883,9 @@ PHP_METHOD(xmlreader, open) + valid_file = _xmlreader_get_valid_file_path(source, resolved_path, MAXPATHLEN ); + + if (valid_file) { ++ PHP_LIBXML_SANITIZE_GLOBALS(reader_for_file); + reader = xmlReaderForFile(valid_file, encoding, options); ++ PHP_LIBXML_RESTORE_GLOBALS(reader_for_file); + } + + if (reader == NULL) { +@@ -959,7 +963,9 @@ PHP_METHOD(xmlreader, setSchema) + + intern = Z_XMLREADER_P(id); + if (intern && intern->ptr) { ++ PHP_LIBXML_SANITIZE_GLOBALS(schema); + retval = xmlTextReaderSchemaValidate(intern->ptr, source); ++ PHP_LIBXML_RESTORE_GLOBALS(schema); + + if (retval == 0) { + RETURN_TRUE; +@@ -1079,6 +1085,7 @@ PHP_METHOD(xmlreader, XML) + } + uri = (char *) xmlCanonicPath((const xmlChar *) resolved_path); + } ++ PHP_LIBXML_SANITIZE_GLOBALS(text_reader); + reader = xmlNewTextReader(inputbfr, uri); + + if (reader != NULL) { +@@ -1099,9 +1106,11 @@ PHP_METHOD(xmlreader, XML) + xmlFree(uri); + } + ++ PHP_LIBXML_RESTORE_GLOBALS(text_reader); + return; + } + } ++ PHP_LIBXML_RESTORE_GLOBALS(text_reader); + } + + if (uri) { +diff --git a/ext/xmlreader/tests/libxml_global_state_entity_loader_bypass.phpt b/ext/xmlreader/tests/libxml_global_state_entity_loader_bypass.phpt +new file mode 100644 +index 0000000000..e9ffb04c2b +--- /dev/null ++++ b/ext/xmlreader/tests/libxml_global_state_entity_loader_bypass.phpt +@@ -0,0 +1,35 @@ ++--TEST-- ++GHSA-3qrf-m4j2-pcrr (libxml global state entity loader bypass) ++--SKIPIF-- ++<?php ++if (!extension_loaded('libxml')) die('skip libxml extension not available'); ++if (!extension_loaded('xmlreader')) die('skip xmlreader extension not available'); ++if (!extension_loaded('zend-test')) die('skip zend-test extension not available'); ++?> ++--FILE-- ++<?php ++ ++$xml = "<?xml version='1.0'?><!DOCTYPE root [<!ENTITY % bork SYSTEM \"php://nope\"> %bork;]><nothing/>"; ++ ++libxml_use_internal_errors(true); ++zend_test_override_libxml_global_state(); ++ ++echo "--- String test ---\n"; ++$reader = XMLReader::xml($xml); ++$reader->read(); ++echo "--- File test ---\n"; ++file_put_contents("libxml_global_state_entity_loader_bypass.tmp", $xml); ++$reader = XMLReader::open("libxml_global_state_entity_loader_bypass.tmp"); ++$reader->read(); ++ ++echo "Done\n"; ++ ++?> ++--CLEAN-- ++<?php ++@unlink("libxml_global_state_entity_loader_bypass.tmp"); ++?> ++--EXPECT-- ++--- String test --- ++--- File test --- ++Done +diff --git a/ext/xsl/xsltprocessor.c b/ext/xsl/xsltprocessor.c +index 9948d6f0b3..7bbe640a5c 100644 +--- a/ext/xsl/xsltprocessor.c ++++ b/ext/xsl/xsltprocessor.c +@@ -396,7 +396,7 @@ PHP_FUNCTION(xsl_xsltprocessor_import_stylesheet) + xmlDoc *doc = NULL, *newdoc = NULL; + xsltStylesheetPtr sheetp, oldsheetp; + xsl_object *intern; +- int prevSubstValue, prevExtDtdValue, clone_docu = 0; ++ int clone_docu = 0; + xmlNode *nodep = NULL; + zend_object_handlers *std_hnd; + zval *cloneDocu, member, rv; +@@ -419,13 +419,12 @@ PHP_FUNCTION(xsl_xsltprocessor_import_stylesheet) + stylesheet document otherwise the node proxies will be a mess */ + newdoc = xmlCopyDoc(doc, 1); + xmlNodeSetBase((xmlNodePtr) newdoc, (xmlChar *)doc->URL); +- prevSubstValue = xmlSubstituteEntitiesDefault(1); +- prevExtDtdValue = xmlLoadExtDtdDefaultValue; ++ PHP_LIBXML_SANITIZE_GLOBALS(parse); ++ xmlSubstituteEntitiesDefault(1); + xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS; + + sheetp = xsltParseStylesheetDoc(newdoc); +- xmlSubstituteEntitiesDefault(prevSubstValue); +- xmlLoadExtDtdDefaultValue = prevExtDtdValue; ++ PHP_LIBXML_RESTORE_GLOBALS(parse); + + if (!sheetp) { + xmlFreeDoc(newdoc); +-- +2.41.0 + +From 3535016313ece1e12ffd5d9fc2f39478941be3d8 Mon Sep 17 00:00:00 2001 +From: Remi Collet <remi@remirepo.net> +Date: Tue, 1 Aug 2023 07:37:25 +0200 +Subject: [PATCH 3/5] backport zend_test changes + (zend_test_override_libxml_global_state) + +(cherry picked from commit 24e669e790e6aebd219c9a9fa19017455c8646b4) +(cherry picked from commit 79a97d0e2b93c40c3728d587046266989c5acc42) +--- + ...xml_global_state_entity_loader_bypass.phpt | 1 + + ...xml_global_state_entity_loader_bypass.phpt | 1 + + ...xml_global_state_entity_loader_bypass.phpt | 5 +++-- + ext/zend_test/test.c | 22 +++++++++++++++++++ + 4 files changed, 27 insertions(+), 2 deletions(-) + +diff --git a/ext/dom/tests/libxml_global_state_entity_loader_bypass.phpt b/ext/dom/tests/libxml_global_state_entity_loader_bypass.phpt +index b28afd4694..7fc2a249ac 100644 +--- a/ext/dom/tests/libxml_global_state_entity_loader_bypass.phpt ++++ b/ext/dom/tests/libxml_global_state_entity_loader_bypass.phpt +@@ -5,6 +5,7 @@ GHSA-3qrf-m4j2-pcrr (libxml global state entity loader bypass) + if (!extension_loaded('libxml')) die('skip libxml extension not available'); + if (!extension_loaded('dom')) die('skip dom extension not available'); + if (!extension_loaded('zend-test')) die('skip zend-test extension not available'); ++if (!function_exists('zend_test_override_libxml_global_state')) die('skip not for Windows'); + ?> + --FILE-- + <?php +diff --git a/ext/simplexml/tests/libxml_global_state_entity_loader_bypass.phpt b/ext/simplexml/tests/libxml_global_state_entity_loader_bypass.phpt +index 2152e01232..54f9d4941e 100644 +--- a/ext/simplexml/tests/libxml_global_state_entity_loader_bypass.phpt ++++ b/ext/simplexml/tests/libxml_global_state_entity_loader_bypass.phpt +@@ -5,6 +5,7 @@ GHSA-3qrf-m4j2-pcrr (libxml global state entity loader bypass) + if (!extension_loaded('libxml')) die('skip libxml extension not available'); + if (!extension_loaded('simplexml')) die('skip simplexml extension not available'); + if (!extension_loaded('zend-test')) die('skip zend-test extension not available'); ++if (!function_exists('zend_test_override_libxml_global_state')) die('skip not for Windows'); + ?> + --FILE-- + <?php +diff --git a/ext/xmlreader/tests/libxml_global_state_entity_loader_bypass.phpt b/ext/xmlreader/tests/libxml_global_state_entity_loader_bypass.phpt +index e9ffb04c2b..b0120b325e 100644 +--- a/ext/xmlreader/tests/libxml_global_state_entity_loader_bypass.phpt ++++ b/ext/xmlreader/tests/libxml_global_state_entity_loader_bypass.phpt +@@ -5,6 +5,7 @@ GHSA-3qrf-m4j2-pcrr (libxml global state entity loader bypass) + if (!extension_loaded('libxml')) die('skip libxml extension not available'); + if (!extension_loaded('xmlreader')) die('skip xmlreader extension not available'); + if (!extension_loaded('zend-test')) die('skip zend-test extension not available'); ++if (!function_exists('zend_test_override_libxml_global_state')) die('skip not for Windows'); + ?> + --FILE-- + <?php +@@ -15,11 +16,11 @@ libxml_use_internal_errors(true); + zend_test_override_libxml_global_state(); + + echo "--- String test ---\n"; +-$reader = XMLReader::xml($xml); ++$reader = @XMLReader::xml($xml); + $reader->read(); + echo "--- File test ---\n"; + file_put_contents("libxml_global_state_entity_loader_bypass.tmp", $xml); +-$reader = XMLReader::open("libxml_global_state_entity_loader_bypass.tmp"); ++$reader = @XMLReader::open("libxml_global_state_entity_loader_bypass.tmp"); + $reader->read(); + + echo "Done\n"; +diff --git a/ext/zend_test/test.c b/ext/zend_test/test.c +index 4a7fe540fb..611bc9b68c 100644 +--- a/ext/zend_test/test.c ++++ b/ext/zend_test/test.c +@@ -25,6 +25,11 @@ + #include "ext/standard/info.h" + #include "php_test.h" + ++#if defined(HAVE_LIBXML) && !defined(PHP_WIN32) ++# include <libxml/globals.h> ++# include <libxml/parser.h> ++#endif ++ + static zend_class_entry *zend_test_interface; + static zend_class_entry *zend_test_class; + static zend_class_entry *zend_test_trait; +@@ -44,6 +49,20 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_zend_leak_variable, 0, 0, 1) + ZEND_ARG_INFO(0, variable) + ZEND_END_ARG_INFO() + ++#if defined(HAVE_LIBXML) && !defined(PHP_WIN32) ++static ZEND_FUNCTION(zend_test_override_libxml_global_state) ++{ ++ ZEND_PARSE_PARAMETERS_NONE(); ++ ++ xmlLoadExtDtdDefaultValue = 1; ++ xmlDoValidityCheckingDefaultValue = 1; ++ (void) xmlPedanticParserDefault(1); ++ (void) xmlSubstituteEntitiesDefault(1); ++ (void) xmlLineNumbersDefault(1); ++ (void) xmlKeepBlanksDefault(0); ++} ++#endif ++ + ZEND_FUNCTION(zend_test_func) + { + /* dummy */ +@@ -251,6 +270,9 @@ const zend_function_entry zend_test_functions[] = { + ZEND_FE(zend_terminate_string, arginfo_zend_terminate_string) + ZEND_FE(zend_leak_bytes, NULL) + ZEND_FE(zend_leak_variable, arginfo_zend_leak_variable) ++#if defined(HAVE_LIBXML) && !defined(PHP_WIN32) ++ ZEND_FE(zend_test_override_libxml_global_state, NULL) ++#endif + ZEND_FE_END + }; + +-- +2.41.0 + +From 26d70866843598f4a2ed94b01999b38e1d7c0e97 Mon Sep 17 00:00:00 2001 +From: Remi Collet <remi@remirepo.net> +Date: Tue, 1 Aug 2023 15:45:24 +0200 +Subject: [PATCH 4/5] adapt to 7.2 + +--- + ext/dom/tests/libxml_global_state_entity_loader_bypass.phpt | 1 - + .../tests/libxml_global_state_entity_loader_bypass.phpt | 1 - + .../tests/libxml_global_state_entity_loader_bypass.phpt | 1 - + ext/zend_test/test.c | 2 -- + 4 files changed, 5 deletions(-) + +diff --git a/ext/dom/tests/libxml_global_state_entity_loader_bypass.phpt b/ext/dom/tests/libxml_global_state_entity_loader_bypass.phpt +index 7fc2a249ac..25499006d9 100644 +--- a/ext/dom/tests/libxml_global_state_entity_loader_bypass.phpt ++++ b/ext/dom/tests/libxml_global_state_entity_loader_bypass.phpt +@@ -4,7 +4,6 @@ GHSA-3qrf-m4j2-pcrr (libxml global state entity loader bypass) + <?php + if (!extension_loaded('libxml')) die('skip libxml extension not available'); + if (!extension_loaded('dom')) die('skip dom extension not available'); +-if (!extension_loaded('zend-test')) die('skip zend-test extension not available'); + if (!function_exists('zend_test_override_libxml_global_state')) die('skip not for Windows'); + ?> + --FILE-- +diff --git a/ext/simplexml/tests/libxml_global_state_entity_loader_bypass.phpt b/ext/simplexml/tests/libxml_global_state_entity_loader_bypass.phpt +index 54f9d4941e..e09ecb5d72 100644 +--- a/ext/simplexml/tests/libxml_global_state_entity_loader_bypass.phpt ++++ b/ext/simplexml/tests/libxml_global_state_entity_loader_bypass.phpt +@@ -4,7 +4,6 @@ GHSA-3qrf-m4j2-pcrr (libxml global state entity loader bypass) + <?php + if (!extension_loaded('libxml')) die('skip libxml extension not available'); + if (!extension_loaded('simplexml')) die('skip simplexml extension not available'); +-if (!extension_loaded('zend-test')) die('skip zend-test extension not available'); + if (!function_exists('zend_test_override_libxml_global_state')) die('skip not for Windows'); + ?> + --FILE-- +diff --git a/ext/xmlreader/tests/libxml_global_state_entity_loader_bypass.phpt b/ext/xmlreader/tests/libxml_global_state_entity_loader_bypass.phpt +index b0120b325e..9824e10603 100644 +--- a/ext/xmlreader/tests/libxml_global_state_entity_loader_bypass.phpt ++++ b/ext/xmlreader/tests/libxml_global_state_entity_loader_bypass.phpt +@@ -4,7 +4,6 @@ GHSA-3qrf-m4j2-pcrr (libxml global state entity loader bypass) + <?php + if (!extension_loaded('libxml')) die('skip libxml extension not available'); + if (!extension_loaded('xmlreader')) die('skip xmlreader extension not available'); +-if (!extension_loaded('zend-test')) die('skip zend-test extension not available'); + if (!function_exists('zend_test_override_libxml_global_state')) die('skip not for Windows'); + ?> + --FILE-- +diff --git a/ext/zend_test/test.c b/ext/zend_test/test.c +index 611bc9b68c..51818083d9 100644 +--- a/ext/zend_test/test.c ++++ b/ext/zend_test/test.c +@@ -52,8 +52,6 @@ ZEND_END_ARG_INFO() + #if defined(HAVE_LIBXML) && !defined(PHP_WIN32) + static ZEND_FUNCTION(zend_test_override_libxml_global_state) + { +- ZEND_PARSE_PARAMETERS_NONE(); +- + xmlLoadExtDtdDefaultValue = 1; + xmlDoValidityCheckingDefaultValue = 1; + (void) xmlPedanticParserDefault(1); +-- +2.41.0 + +From 79c0bf87711036b83f8ee1723c034ccc839d847b Mon Sep 17 00:00:00 2001 +From: Remi Collet <remi@remirepo.net> +Date: Tue, 1 Aug 2023 07:22:33 +0200 +Subject: [PATCH 5/5] NEWS + +(cherry picked from commit ef1d507acf7be23d7624dc3c891683b2218feb51) +(cherry picked from commit 3cf7c2b10e577136b267f2d90bfdff6743271c5c) +--- + NEWS | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/NEWS b/NEWS +index 5f49a7ee04..286f3df0f4 100644 +--- a/NEWS ++++ b/NEWS +@@ -1,6 +1,16 @@ + PHP NEWS + ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| + ++Backported from 8.0.30 ++ ++- Libxml: ++ . Fixed bug GHSA-3qrf-m4j2-pcrr (Security issue with external entity loading ++ in XML without enabling it). (CVE-2023-3823) (nielsdos, ilutov) ++ ++- Phar: ++ . Fixed bug GHSA-jqcx-ccgc-xwhv (Buffer mismanagement in phar_dir_read()). ++ (CVE-2023-3824) (nielsdos) ++ + Backported from 8.0.29 + + - Soap: +-- +2.41.0 + diff --git a/php-cve-2024-11233.patch b/php-cve-2024-11233.patch new file mode 100644 index 0000000..119dc2e --- /dev/null +++ b/php-cve-2024-11233.patch @@ -0,0 +1,158 @@ +From 0a651c02701268532a9754542f629af85e28ae02 Mon Sep 17 00:00:00 2001 +From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> +Date: Fri, 8 Nov 2024 22:04:21 +0100 +Subject: [PATCH 6/9] Fix GHSA-r977-prxv-hc43 + +Move the bound check upwards. Since this doesn't generate output we can +check the bound first. + +(cherry picked from commit 81030c9bbb5cd2e740b8398bb7212df9709f0274) +(cherry picked from commit 2cee10a1206f5bc7724232d3988be2cfcb0bc9df) +(cherry picked from commit 44a5975f83a02eb8169d12af912e6222b28216d0) +(cherry picked from commit 7065fa31a468139f07b40f7036ce4761037dafd2) +--- + ext/standard/filters.c | 7 ++++--- + ext/standard/tests/filters/ghsa-r977-prxv-hc43.phpt | 12 ++++++++++++ + 2 files changed, 16 insertions(+), 3 deletions(-) + create mode 100644 ext/standard/tests/filters/ghsa-r977-prxv-hc43.phpt + +diff --git a/ext/standard/filters.c b/ext/standard/filters.c +index 03e5e11df8..26850c46a8 100644 +--- a/ext/standard/filters.c ++++ b/ext/standard/filters.c +@@ -1122,6 +1122,9 @@ static php_conv_err_t php_conv_qprint_decode_convert(php_conv_qprint_decode *ins + } break; + + case 5: { ++ if (icnt == 0) { ++ goto out; ++ } + if (!inst->lbchars && lb_cnt == 1 && *ps == '\n') { + /* auto-detect soft line breaks, found network line break */ + lb_cnt = lb_ptr = 0; +@@ -1135,15 +1138,13 @@ static php_conv_err_t php_conv_qprint_decode_convert(php_conv_qprint_decode *ins + /* soft line break */ + lb_cnt = lb_ptr = 0; + scan_stat = 0; +- } else if (icnt > 0) { ++ } else { + if (*ps == (unsigned char)inst->lbchars[lb_cnt]) { + lb_cnt++; + ps++, icnt--; + } else { + scan_stat = 6; /* no break for short-cut */ + } +- } else { +- goto out; + } + } break; + +diff --git a/ext/standard/tests/filters/ghsa-r977-prxv-hc43.phpt b/ext/standard/tests/filters/ghsa-r977-prxv-hc43.phpt +new file mode 100644 +index 0000000000..8fdcce8ff2 +--- /dev/null ++++ b/ext/standard/tests/filters/ghsa-r977-prxv-hc43.phpt +@@ -0,0 +1,12 @@ ++--TEST-- ++GHSA-r977-prxv-hc43: Single byte overread with convert.quoted-printable-decode filter ++--FILE-- ++<?php ++ ++$input_data = str_repeat('A', 8189)."X=\r"; ++$filter_url = "php://filter/convert.quoted-printable-decode/resource=data:," . urlencode($input_data); ++var_dump(file_get_contents($filter_url)); ++ ++?> ++--EXPECT-- ++string(8190) "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAX" +-- +2.47.0 + +From d149a44b005e0d24208b0bd0f7179dfbbfffefb1 Mon Sep 17 00:00:00 2001 +From: "Christoph M. Becker" <cmbecker69@gmx.de> +Date: Mon, 8 Jun 2020 23:19:43 +0200 +Subject: [PATCH 7/9] Fix #74267: segfault with streams and invalid data + +If the current character is a line break character, it cannot be a tab +or space character, so we would always fail with an invalid sequence +error. Obviously, these `scan_stat == 4` conditions are meant to be +exclusive. + +Furthermore, if `in_pp == NULL || in_left_p == NULL` is true, we hit a +segfault if we are not returning right away. Obviously, the additional +constraints don't make sense, so we remove them. + +(cherry picked from commit 12c59f6660706321f9d42c55421ff6864439c8b7) +--- + ext/standard/filters.c | 7 +++---- + ext/standard/tests/filters/bug74267.phpt | 26 ++++++++++++++++++++++++ + 2 files changed, 29 insertions(+), 4 deletions(-) + create mode 100644 ext/standard/tests/filters/bug74267.phpt + +diff --git a/ext/standard/filters.c b/ext/standard/filters.c +index 26850c46a8..2b58c65ea5 100644 +--- a/ext/standard/filters.c ++++ b/ext/standard/filters.c +@@ -788,7 +788,7 @@ static php_conv_err_t php_conv_qprint_encode_convert(php_conv_qprint_encode *ins + lb_ptr = inst->lb_ptr; + lb_cnt = inst->lb_cnt; + +- if ((in_pp == NULL || in_left_p == NULL) && (lb_ptr >=lb_cnt)) { ++ if (in_pp == NULL || in_left_p == NULL) { + return PHP_CONV_ERR_SUCCESS; + } + +@@ -1016,7 +1016,7 @@ static php_conv_err_t php_conv_qprint_decode_convert(php_conv_qprint_decode *ins + lb_ptr = inst->lb_ptr; + lb_cnt = inst->lb_cnt; + +- if ((in_pp == NULL || in_left_p == NULL) && lb_cnt == lb_ptr) { ++ if (in_pp == NULL || in_left_p == NULL) { + if (inst->scan_stat != 0) { + return PHP_CONV_ERR_UNEXPECTED_EOS; + } +@@ -1113,8 +1113,7 @@ static php_conv_err_t php_conv_qprint_decode_convert(php_conv_qprint_decode *ins + *ps == (unsigned char)inst->lbchars[lb_cnt]) { + lb_cnt++; + scan_stat = 5; +- } +- if (*ps != '\t' && *ps != ' ') { ++ } else if (*ps != '\t' && *ps != ' ') { + err = PHP_CONV_ERR_INVALID_SEQ; + goto out; + } +diff --git a/ext/standard/tests/filters/bug74267.phpt b/ext/standard/tests/filters/bug74267.phpt +new file mode 100644 +index 0000000000..17d7996b7f +--- /dev/null ++++ b/ext/standard/tests/filters/bug74267.phpt +@@ -0,0 +1,26 @@ ++--TEST-- ++Bug #74267 (segfault with streams and invalid data) ++--FILE-- ++<?php ++$stream = fopen('php://memory', 'w'); ++stream_filter_append($stream, 'convert.quoted-printable-decode', STREAM_FILTER_WRITE, ['line-break-chars' => "\r\n"]); ++ ++$lines = [ ++ "\r\n", ++ " -=()\r\n", ++ " -=\r\n", ++ "\r\n" ++ ]; ++ ++foreach ($lines as $line) { ++ fwrite($stream, $line); ++} ++ ++fclose($stream); ++echo "done\n"; ++?> ++--EXPECTF-- ++Warning: fwrite(): stream filter (convert.quoted-printable-decode): invalid byte sequence in %s on line %d ++ ++Warning: fwrite(): stream filter (convert.quoted-printable-decode): invalid byte sequence in %s on line %d ++done +-- +2.47.0 + diff --git a/php-cve-2024-11234.patch b/php-cve-2024-11234.patch new file mode 100644 index 0000000..7106136 --- /dev/null +++ b/php-cve-2024-11234.patch @@ -0,0 +1,97 @@ +From 11787051a17d2fcea427cd66c3fcc5e99ab94a03 Mon Sep 17 00:00:00 2001 +From: Jakub Zelenka <bukka@php.net> +Date: Fri, 8 Nov 2024 23:43:47 +0100 +Subject: [PATCH 4/9] Fix GHSA-c5f2-jwm7-mmq2: stream HTTP fulluri CRLF + injection + +(cherry picked from commit 426a6d4539ebee34879ac5de857036bb6ff0e732) +(cherry picked from commit bc1f192102dd8cbda028e40aa31604c4885d387c) +(cherry picked from commit 8d130e16fbfda7d154fedfa0f1ff1d5ad5e26815) +(cherry picked from commit 494de65139592da0e5e5b6fdf198c2f9c762f4d6) +(cherry picked from commit dcb89ed9d0217510f3906ce0c517f704e6bd80dc) +--- + ext/standard/http_fopen_wrapper.c | 18 ++++++++---- + .../tests/http/ghsa-c5f2-jwm7-mmq2.phpt | 28 +++++++++++++++++++ + 2 files changed, 40 insertions(+), 6 deletions(-) + create mode 100644 ext/standard/tests/http/ghsa-c5f2-jwm7-mmq2.phpt + +diff --git a/ext/standard/http_fopen_wrapper.c b/ext/standard/http_fopen_wrapper.c +index be23679d2d..e125364923 100644 +--- a/ext/standard/http_fopen_wrapper.c ++++ b/ext/standard/http_fopen_wrapper.c +@@ -176,6 +176,11 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, + return NULL; + } + ++ /* Should we send the entire path in the request line, default to no. */ ++ if (context && (tmpzval = php_stream_context_get_option(context, "http", "request_fulluri")) != NULL) { ++ request_fulluri = zend_is_true(tmpzval); ++ } ++ + use_ssl = resource->scheme && (strlen(resource->scheme) > 4) && resource->scheme[4] == 's'; + /* choose default ports */ + if (use_ssl && resource->port == 0) +@@ -195,6 +200,13 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, + } + } + ++ if (request_fulluri && (strchr(path, '\n') != NULL || strchr(path, '\r') != NULL)) { ++ php_stream_wrapper_log_error(wrapper, options, "HTTP wrapper full URI path does not allow CR or LF characters"); ++ php_url_free(resource); ++ efree(transport_string); ++ return NULL; ++ } ++ + if (context && (tmpzval = php_stream_context_get_option(context, wrapper->wops->label, "timeout")) != NULL) { + double d = zval_get_double(tmpzval); + #ifndef PHP_WIN32 +@@ -375,12 +387,6 @@ finish: + smart_str_appends(&req_buf, "GET "); + } + +- /* Should we send the entire path in the request line, default to no. */ +- if (!request_fulluri && context && +- (tmpzval = php_stream_context_get_option(context, "http", "request_fulluri")) != NULL) { +- request_fulluri = zend_is_true(tmpzval); +- } +- + if (request_fulluri) { + /* Ask for everything */ + smart_str_appends(&req_buf, path); +diff --git a/ext/standard/tests/http/ghsa-c5f2-jwm7-mmq2.phpt b/ext/standard/tests/http/ghsa-c5f2-jwm7-mmq2.phpt +new file mode 100644 +index 0000000000..6e68f67654 +--- /dev/null ++++ b/ext/standard/tests/http/ghsa-c5f2-jwm7-mmq2.phpt +@@ -0,0 +1,28 @@ ++--TEST-- ++GHSA-c5f2-jwm7-mmq2 (Configuring a proxy in a stream context might allow for CRLF injection in URIs) ++--INI-- ++allow_url_fopen=1 ++--CONFLICTS-- ++server ++--FILE-- ++<?php ++$serverCode = <<<'CODE' ++echo $_SERVER['REQUEST_URI']; ++CODE; ++ ++include __DIR__."/../../../../sapi/cli/tests/php_cli_server.inc"; ++php_cli_server_start($serverCode, null); ++ ++$host = PHP_CLI_SERVER_ADDRESS; ++$userinput = "index.php HTTP/1.1\r\nHost: $host\r\n\r\nGET /index2.php HTTP/1.1\r\nHost: $host\r\n\r\nGET /index.php"; ++$context = stream_context_create(['http' => ['proxy' => 'tcp://' . $host, 'request_fulluri' => true]]); ++echo file_get_contents("http://$host/$userinput", false, $context); ++?> ++--EXPECTF-- ++Warning: file_get_contents(http://localhost:%d/index.php HTTP/1.1 ++Host: localhost:%d ++ ++GET /index2.php HTTP/1.1 ++Host: localhost:%d ++ ++GET /index.php): failed to open stream: HTTP wrapper full URI path does not allow CR or LF characters in %s on line %d +-- +2.47.0 + diff --git a/php-cve-2024-11236.patch b/php-cve-2024-11236.patch new file mode 100644 index 0000000..1122989 --- /dev/null +++ b/php-cve-2024-11236.patch @@ -0,0 +1,150 @@ +From c6ee9a7d0385e4cd6cf9dcd0104dd6714e2a968d Mon Sep 17 00:00:00 2001 +From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> +Date: Thu, 24 Oct 2024 22:02:17 +0200 +Subject: [PATCH 1/9] Fix GHSA-5hqh-c84r-qjcv: Integer overflow in the dblib + quoter causing OOB writes + +(cherry picked from commit d9baa9fed8c3ba692a36b388c0c7762e5102e2e0) +(cherry picked from commit 5d9e54065ed18c51e4f25d8900635f90810c7394) +(cherry picked from commit 97546df8d6900b115536c17af9213f1da837b82e) +(cherry picked from commit 5e7cd3e7ed7c894550ca35514708ffe1874a31ad) +--- + ext/pdo_dblib/dblib_driver.c | 8 ++++++- + ext/pdo_dblib/tests/GHSA-5hqh-c84r-qjcv.phpt | 24 ++++++++++++++++++++ + 2 files changed, 31 insertions(+), 1 deletion(-) + create mode 100644 ext/pdo_dblib/tests/GHSA-5hqh-c84r-qjcv.phpt + +diff --git a/ext/pdo_dblib/dblib_driver.c b/ext/pdo_dblib/dblib_driver.c +index 13526092ea..6fa650e4da 100644 +--- a/ext/pdo_dblib/dblib_driver.c ++++ b/ext/pdo_dblib/dblib_driver.c +@@ -156,6 +156,7 @@ static int dblib_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, size_t unqu + + size_t i; + char * q; ++ size_t extralen = 0; + *quotedlen = 0; + + if (H->assume_national_character_set_strings) { +@@ -170,7 +171,7 @@ static int dblib_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, size_t unqu + + /* Detect quoted length, adding extra char for doubled single quotes */ + for (i = 0; i < unquotedlen; i++) { +- if (unquoted[i] == '\'') ++*quotedlen; ++ if (unquoted[i] == '\'') ++extralen; + ++*quotedlen; + } + +@@ -178,6 +179,11 @@ static int dblib_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, size_t unqu + if (use_national_character_set) { + ++*quotedlen; /* N prefix */ + } ++ if (UNEXPECTED(*quotedlen > ZSTR_MAX_LEN - extralen)) { ++ return 0; ++ } ++ ++ *quotedlen += extralen; + q = *quoted = emalloc(*quotedlen + 1); /* Add byte for terminal null */ + if (use_national_character_set) { + *q++ = 'N'; +diff --git a/ext/pdo_dblib/tests/GHSA-5hqh-c84r-qjcv.phpt b/ext/pdo_dblib/tests/GHSA-5hqh-c84r-qjcv.phpt +new file mode 100644 +index 0000000000..431c61951e +--- /dev/null ++++ b/ext/pdo_dblib/tests/GHSA-5hqh-c84r-qjcv.phpt +@@ -0,0 +1,24 @@ ++--TEST-- ++GHSA-5hqh-c84r-qjcv (Integer overflow in the dblib quoter causing OOB writes) ++--EXTENSIONS-- ++pdo_dblib ++--SKIPIF-- ++<?php ++if (PHP_INT_SIZE != 4) die("skip for 32bit platforms only"); ++if (PHP_OS_FAMILY === "Windows") die("skip not for Windows because the virtual address space for application is only 2GiB"); ++if (getenv("SKIP_SLOW_TESTS")) die("skip slow test"); ++require __DIR__ . '/config.inc'; ++getDbConnection(); ++?> ++--INI-- ++memory_limit=-1 ++--FILE-- ++<?php ++ ++require __DIR__ . '/config.inc'; ++$db = getDbConnection(); ++var_dump($db->quote(str_repeat("'", 2147483646))); ++ ++?> ++--EXPECT-- ++bool(false) +-- +2.47.0 + +From 8a4f389396493a43f9de9ba48920b6a82b6d1370 Mon Sep 17 00:00:00 2001 +From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> +Date: Thu, 24 Oct 2024 22:02:36 +0200 +Subject: [PATCH 2/9] Fix GHSA-5hqh-c84r-qjcv: Integer overflow in the firebird + quoter causing OOB writes + +(cherry picked from commit 69c5f68fdc3deed9ebce2cc44b4bf5e0c47cd28f) +(cherry picked from commit b4f73be75dbdde970a18cc7a636898b10400fb3f) +(cherry picked from commit 0530cbfe5c3044537de52d8382eba5d69dbac726) +(cherry picked from commit 72d4c4e435544c2d87d634188d480099345b601b) +--- + ext/pdo_firebird/firebird_driver.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/ext/pdo_firebird/firebird_driver.c b/ext/pdo_firebird/firebird_driver.c +index 1e2e7746fa..b238ea630e 100644 +--- a/ext/pdo_firebird/firebird_driver.c ++++ b/ext/pdo_firebird/firebird_driver.c +@@ -243,7 +243,7 @@ free_statement: + static int firebird_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, size_t unquotedlen, /* {{{ */ + char **quoted, size_t *quotedlen, enum pdo_param_type paramtype) + { +- int qcount = 0; ++ size_t qcount = 0; + char const *co, *l, *r; + char *c; + +@@ -258,6 +258,10 @@ static int firebird_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, size_t u + /* count the number of ' characters */ + for (co = unquoted; (co = strchr(co,'\'')); qcount++, co++); + ++ if (UNEXPECTED(unquotedlen + 2 > ZSTR_MAX_LEN - qcount)) { ++ return 0; ++ } ++ + *quotedlen = unquotedlen + qcount + 2; + *quoted = c = emalloc(*quotedlen+1); + *c++ = '\''; +-- +2.47.0 + +From ff868946218d6d1661a0c35757e2058cb3ed23ec Mon Sep 17 00:00:00 2001 +From: Remi Collet <remi@remirepo.net> +Date: Fri, 22 Nov 2024 15:24:16 +0100 +Subject: [PATCH 3/9] backport ZSTR_MAX_LEN + +(cherry picked from commit 37056ad634d9c44bac0d6c8e730eafaec1344840) +--- + Zend/zend_string.h | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/Zend/zend_string.h b/Zend/zend_string.h +index 784b88ea6a..5f7a9ea2b3 100644 +--- a/Zend/zend_string.h ++++ b/Zend/zend_string.h +@@ -74,6 +74,9 @@ END_EXTERN_C() + + #define _ZSTR_STRUCT_SIZE(len) (_ZSTR_HEADER_SIZE + len + 1) + ++#define ZSTR_MAX_OVERHEAD (ZEND_MM_ALIGNED_SIZE(_ZSTR_HEADER_SIZE + 1)) ++#define ZSTR_MAX_LEN (SIZE_MAX - ZSTR_MAX_OVERHEAD) ++ + #define ZSTR_ALLOCA_ALLOC(str, _len, use_heap) do { \ + (str) = (zend_string *)do_alloca(ZEND_MM_ALIGNED_SIZE_EX(_ZSTR_STRUCT_SIZE(_len), 8), (use_heap)); \ + GC_REFCOUNT(str) = 1; \ +-- +2.47.0 + diff --git a/php-cve-2024-2756.patch b/php-cve-2024-2756.patch new file mode 100644 index 0000000..6e13a30 --- /dev/null +++ b/php-cve-2024-2756.patch @@ -0,0 +1,197 @@ +From c213de619a532d35e8f7abe4a245433dbf21c960 Mon Sep 17 00:00:00 2001 +From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> +Date: Sun, 17 Mar 2024 21:04:47 +0100 +Subject: [PATCH 1/4] Fix GHSA-wpj3-hf5j-x4v4: __Host-/__Secure- cookie bypass + due to partial CVE-2022-31629 fix + +The check happened too early as later code paths may perform more +mangling rules. Move the check downwards right before adding the actual +variable. + +(cherry picked from commit 093c08af25fb323efa0c8e6154aa9fdeae3d3b53) +(cherry picked from commit 2e07a3acd7a6b53c55325b94bed97748d7697b53) +(cherry picked from commit a6c1c62a25ac23b08a86af11d68f0e2eaafc102b) +(cherry picked from commit 46b570a1e4aeb4a414898fcc09503ac388d16256) +--- + ext/standard/tests/ghsa-wpj3-hf5j-x4v4.phpt | 63 +++++++++++++++++++++ + main/php_variables.c | 41 +++++++++----- + 2 files changed, 90 insertions(+), 14 deletions(-) + create mode 100644 ext/standard/tests/ghsa-wpj3-hf5j-x4v4.phpt + +diff --git a/ext/standard/tests/ghsa-wpj3-hf5j-x4v4.phpt b/ext/standard/tests/ghsa-wpj3-hf5j-x4v4.phpt +new file mode 100644 +index 0000000000..77fcb68089 +--- /dev/null ++++ b/ext/standard/tests/ghsa-wpj3-hf5j-x4v4.phpt +@@ -0,0 +1,63 @@ ++--TEST-- ++ghsa-wpj3-hf5j-x4v4 (__Host-/__Secure- cookie bypass due to partial CVE-2022-31629 fix) ++--COOKIE-- ++..Host-test=ignore_1; ++._Host-test=ignore_2; ++.[Host-test=ignore_3; ++_.Host-test=ignore_4; ++__Host-test=ignore_5; ++_[Host-test=ignore_6; ++[.Host-test=ignore_7; ++[_Host-test=ignore_8; ++[[Host-test=ignore_9; ++..Host-test[]=ignore_10; ++._Host-test[]=ignore_11; ++.[Host-test[]=ignore_12; ++_.Host-test[]=ignore_13; ++__Host-test[]=legitimate_14; ++_[Host-test[]=legitimate_15; ++[.Host-test[]=ignore_16; ++[_Host-test[]=ignore_17; ++[[Host-test[]=ignore_18; ++..Secure-test=ignore_1; ++._Secure-test=ignore_2; ++.[Secure-test=ignore_3; ++_.Secure-test=ignore_4; ++__Secure-test=ignore_5; ++_[Secure-test=ignore_6; ++[.Secure-test=ignore_7; ++[_Secure-test=ignore_8; ++[[Secure-test=ignore_9; ++..Secure-test[]=ignore_10; ++._Secure-test[]=ignore_11; ++.[Secure-test[]=ignore_12; ++_.Secure-test[]=ignore_13; ++__Secure-test[]=legitimate_14; ++_[Secure-test[]=legitimate_15; ++[.Secure-test[]=ignore_16; ++[_Secure-test[]=ignore_17; ++[[Secure-test[]=ignore_18; ++--FILE-- ++<?php ++var_dump($_COOKIE); ++?> ++--EXPECT-- ++array(3) { ++ ["__Host-test"]=> ++ array(1) { ++ [0]=> ++ string(13) "legitimate_14" ++ } ++ ["_"]=> ++ array(2) { ++ ["Host-test["]=> ++ string(13) "legitimate_15" ++ ["Secure-test["]=> ++ string(13) "legitimate_15" ++ } ++ ["__Secure-test"]=> ++ array(1) { ++ [0]=> ++ string(13) "legitimate_14" ++ } ++} +diff --git a/main/php_variables.c b/main/php_variables.c +index bd59134fc9..3e0e8d767e 100644 +--- a/main/php_variables.c ++++ b/main/php_variables.c +@@ -59,6 +59,21 @@ PHPAPI void php_register_variable_safe(char *var, char *strval, size_t str_len, + php_register_variable_ex(var, &new_entry, track_vars_array); + } + ++/* Discard variable if mangling made it start with __Host-, where pre-mangling it did not start with __Host- ++ * Discard variable if mangling made it start with __Secure-, where pre-mangling it did not start with __Secure- */ ++static zend_bool php_is_forbidden_variable_name(const char *mangled_name, size_t mangled_name_len, const char *pre_mangled_name) ++{ ++ if (mangled_name_len >= sizeof("__Host-")-1 && strncmp(mangled_name, "__Host-", sizeof("__Host-")-1) == 0 && strncmp(pre_mangled_name, "__Host-", sizeof("__Host-")-1) != 0) { ++ return 1; ++ } ++ ++ if (mangled_name_len >= sizeof("__Secure-")-1 && strncmp(mangled_name, "__Secure-", sizeof("__Secure-")-1) == 0 && strncmp(pre_mangled_name, "__Secure-", sizeof("__Secure-")-1) != 0) { ++ return 1; ++ } ++ ++ return 0; ++} ++ + PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars_array) + { + char *p = NULL; +@@ -109,20 +124,6 @@ PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars + } + var_len = p - var; + +- /* Discard variable if mangling made it start with __Host-, where pre-mangling it did not start with __Host- */ +- if (strncmp(var, "__Host-", sizeof("__Host-")-1) == 0 && strncmp(var_name, "__Host-", sizeof("__Host-")-1) != 0) { +- zval_ptr_dtor_nogc(val); +- free_alloca(var_orig, use_heap); +- return; +- } +- +- /* Discard variable if mangling made it start with __Secure-, where pre-mangling it did not start with __Secure- */ +- if (strncmp(var, "__Secure-", sizeof("__Secure-")-1) == 0 && strncmp(var_name, "__Secure-", sizeof("__Secure-")-1) != 0) { +- zval_ptr_dtor_nogc(val); +- free_alloca(var_orig, use_heap); +- return; +- } +- + if (var_len==0) { /* empty variable name, or variable name with a space in it */ + zval_dtor(val); + free_alloca(var_orig, use_heap); +@@ -220,6 +221,12 @@ PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars + return; + } + } else { ++ if (php_is_forbidden_variable_name(index, index_len, var_name)) { ++ zval_ptr_dtor_nogc(val); ++ free_alloca(var_orig, use_heap); ++ return; ++ } ++ + gpc_element_p = zend_symtable_str_find(symtable1, index, index_len); + if (!gpc_element_p) { + zval tmp; +@@ -258,6 +265,12 @@ plain_var: + zval_ptr_dtor(&gpc_element); + } + } else { ++ if (php_is_forbidden_variable_name(index, index_len, var_name)) { ++ zval_ptr_dtor_nogc(val); ++ free_alloca(var_orig, use_heap); ++ return; ++ } ++ + /* + * According to rfc2965, more specific paths are listed above the less specific ones. + * If we encounter a duplicate cookie name, we should skip it, since it is not possible +-- +2.44.0 + +From ee591001f7a3db7405b4fa027659768c2355df6d Mon Sep 17 00:00:00 2001 +From: Remi Collet <remi@remirepo.net> +Date: Wed, 10 Apr 2024 08:59:32 +0200 +Subject: [PATCH 2/4] NEWS + +(cherry picked from commit 366cc249b7d54707572beb7096e8f6c65ee79719) +(cherry picked from commit dcdd49ef3bfbd8ccc778850d6a0f9b98adf625d4) +(cherry picked from commit 8642473b624f809b768180b104c013f74e3a99a0) +--- + NEWS | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/NEWS b/NEWS +index 286f3df0f4..e55195bc56 100644 +--- a/NEWS ++++ b/NEWS +@@ -1,6 +1,12 @@ + PHP NEWS + ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| + ++Backported from 8.1.28 ++ ++- Standard: ++ . Fixed bug GHSA-wpj3-hf5j-x4v4 (__Host-/__Secure- cookie bypass due to ++ partial CVE-2022-31629 fix). (CVE-2024-2756) (nielsdos) ++ + Backported from 8.0.30 + + - Libxml: +-- +2.44.0 + diff --git a/php-cve-2024-3096.patch b/php-cve-2024-3096.patch new file mode 100644 index 0000000..ca137c6 --- /dev/null +++ b/php-cve-2024-3096.patch @@ -0,0 +1,85 @@ +From d22d9ebb29dce86edd622205dd1196a2796c08c7 Mon Sep 17 00:00:00 2001 +From: Jakub Zelenka <bukka@php.net> +Date: Fri, 29 Mar 2024 15:27:59 +0000 +Subject: [PATCH 3/4] Fix bug GHSA-q6x7-frmf-grcw: password_verify can + erroneously return true + +Disallow null character in bcrypt password + +(cherry picked from commit 0ba5229a3f7572846e91c8f5382e87785f543826) +(cherry picked from commit 81794c73068d9a44bf109bbcc9793e7b56a1c051) +(cherry picked from commit 4a7ceb9d6427f8d368f1a8739267b1f8310ec201) +(cherry picked from commit 747100905eceffb1f67096b437001e42900eb6bb) +--- + ext/standard/password.c | 5 +++++ + ext/standard/tests/password/password_bcrypt_errors.phpt | 6 ++++++ + 2 files changed, 11 insertions(+) + +diff --git a/ext/standard/password.c b/ext/standard/password.c +index c92925b903..4944369ba8 100644 +--- a/ext/standard/password.c ++++ b/ext/standard/password.c +@@ -438,6 +438,11 @@ PHP_FUNCTION(password_hash) + cost = zval_get_long(option_buffer); + } + ++ if (memchr(ZSTR_VAL(password), '\0', ZSTR_LEN(password))) { ++ php_error_docref(NULL, E_WARNING, "Bcrypt password must not contain null character"); ++ RETURN_NULL(); ++ } ++ + if (cost < 4 || cost > 31) { + php_error_docref(NULL, E_WARNING, "Invalid bcrypt cost parameter specified: " ZEND_LONG_FMT, cost); + RETURN_NULL(); +diff --git a/ext/standard/tests/password/password_bcrypt_errors.phpt b/ext/standard/tests/password/password_bcrypt_errors.phpt +index a0826080e6..f95b72670a 100644 +--- a/ext/standard/tests/password/password_bcrypt_errors.phpt ++++ b/ext/standard/tests/password/password_bcrypt_errors.phpt +@@ -16,6 +16,8 @@ var_dump(password_hash("foo", PASSWORD_BCRYPT, array("salt" => 123))); + + var_dump(password_hash("foo", PASSWORD_BCRYPT, array("cost" => "foo"))); + ++var_dump(password_hash("null\0password", PASSWORD_BCRYPT)); ++ + ?> + --EXPECTF-- + Warning: password_hash(): Invalid bcrypt cost parameter specified: 3 in %s on line %d +@@ -41,3 +43,7 @@ NULL + + Warning: password_hash(): Invalid bcrypt cost parameter specified: 0 in %s on line %d + NULL ++ ++Warning: password_hash(): Bcrypt password must not contain null character in %s on line %d ++NULL ++ +-- +2.44.0 + +From be830600a8e4c33a25e965d0782903e885e91c6d Mon Sep 17 00:00:00 2001 +From: Remi Collet <remi@remirepo.net> +Date: Wed, 10 Apr 2024 09:01:09 +0200 +Subject: [PATCH 4/4] NEWS + +(cherry picked from commit 24f77904ee2259d722559f129f96a1f145a2367b) +(cherry picked from commit 027bdbc636632be49ecfad8d4191509faacb34ac) +(cherry picked from commit fbeed182bb0b0c4c453e064198b5cc3814a10de0) +--- + NEWS | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/NEWS b/NEWS +index e55195bc56..7d99fb7d60 100644 +--- a/NEWS ++++ b/NEWS +@@ -6,6 +6,8 @@ Backported from 8.1.28 + - Standard: + . Fixed bug GHSA-wpj3-hf5j-x4v4 (__Host-/__Secure- cookie bypass due to + partial CVE-2022-31629 fix). (CVE-2024-2756) (nielsdos) ++ . Fixed bug GHSA-h746-cjrr-wfmr (password_verify can erroneously return true, ++ opening ATO risk). (CVE-2024-3096) (Jakub Zelenka) + + Backported from 8.0.30 + +-- +2.44.0 + diff --git a/php-cve-2024-5458.patch b/php-cve-2024-5458.patch new file mode 100644 index 0000000..d64bccd --- /dev/null +++ b/php-cve-2024-5458.patch @@ -0,0 +1,184 @@ +From 87a7b8dab75e221a1fcd74cf34dc650f7253c12c Mon Sep 17 00:00:00 2001 +From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> +Date: Wed, 22 May 2024 22:25:02 +0200 +Subject: [PATCH 1/2] Fix GHSA-w8qr-v226-r27w + +We should not early-out with success status if we found an ipv6 +hostname, we should keep checking the rest of the conditions. +Because integrating the if-check of the ipv6 hostname in the +"Validate domain" if-check made the code hard to read, I extracted the +condition out to a separate function. This also required to make +a few pointers const in order to have some clean code. + +(cherry picked from commit 4066610b47e22c24cbee91be434a94357056a479) +(cherry picked from commit 08be64e40197fc12dca5f802d16748d9c3cb4cb4) +(cherry picked from commit 76362f9526afbd5565003d981f9507aaf62337f2) +--- + ext/filter/logical_filters.c | 35 ++++++++++--------- + ext/filter/tests/ghsa-w8qr-v226-r27w.phpt | 41 +++++++++++++++++++++++ + 2 files changed, 61 insertions(+), 15 deletions(-) + create mode 100644 ext/filter/tests/ghsa-w8qr-v226-r27w.phpt + +diff --git a/ext/filter/logical_filters.c b/ext/filter/logical_filters.c +index 6894fa2551..f91aa12da4 100644 +--- a/ext/filter/logical_filters.c ++++ b/ext/filter/logical_filters.c +@@ -81,7 +81,7 @@ + #define FORMAT_IPV4 4 + #define FORMAT_IPV6 6 + +-static int _php_filter_validate_ipv6(char *str, size_t str_len); ++static int _php_filter_validate_ipv6(const char *str, size_t str_len); + + static int php_filter_parse_int(const char *str, size_t str_len, zend_long *ret) { /* {{{ */ + zend_long ctx_value; +@@ -532,6 +532,14 @@ static int is_userinfo_valid(char *str) + return 1; + } + ++static zend_bool php_filter_is_valid_ipv6_hostname(const char *s, size_t l) ++{ ++ const char *e = s + l; ++ const char *t = e - 1; ++ ++ return *s == '[' && *t == ']' && _php_filter_validate_ipv6(s + 1, l - 2); ++} ++ + void php_filter_validate_url(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ + { + php_url *url; +@@ -551,7 +559,7 @@ void php_filter_validate_url(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ + } + + if (url->scheme != NULL && (!strcasecmp(url->scheme, "http") || !strcasecmp(url->scheme, "https"))) { +- char *e, *s, *t; ++ const char *s; + size_t l; + + if (url->host == NULL) { +@@ -560,17 +568,14 @@ void php_filter_validate_url(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ + + s = url->host; + l = strlen(s); +- e = url->host + l; +- t = e - 1; +- +- /* An IPv6 enclosed by square brackets is a valid hostname */ +- if (*s == '[' && *t == ']' && _php_filter_validate_ipv6((s + 1), l - 2)) { +- php_url_free(url); +- return; +- } + +- // Validate domain +- if (!_php_filter_validate_domain(url->host, l, FILTER_FLAG_HOSTNAME)) { ++ if ( ++ /* An IPv6 enclosed by square brackets is a valid hostname.*/ ++ !php_filter_is_valid_ipv6_hostname(s, l) && ++ /* Validate domain. ++ * This includes a loose check for an IPv4 address. */ ++ !_php_filter_validate_domain(url->host, l, FILTER_FLAG_HOSTNAME) ++ ) { + php_url_free(url); + RETURN_VALIDATION_FAILED + } +@@ -701,15 +706,15 @@ static int _php_filter_validate_ipv4(char *str, size_t str_len, int *ip) /* {{{ + } + /* }}} */ + +-static int _php_filter_validate_ipv6(char *str, size_t str_len) /* {{{ */ ++static int _php_filter_validate_ipv6(const char *str, size_t str_len) /* {{{ */ + { + int compressed = 0; + int blocks = 0; + int n; + char *ipv4; +- char *end; ++ const char *end; + int ip4elm[4]; +- char *s = str; ++ const char *s = str; + + if (!memchr(str, ':', str_len)) { + return 0; +diff --git a/ext/filter/tests/ghsa-w8qr-v226-r27w.phpt b/ext/filter/tests/ghsa-w8qr-v226-r27w.phpt +new file mode 100644 +index 0000000000..0092408ee5 +--- /dev/null ++++ b/ext/filter/tests/ghsa-w8qr-v226-r27w.phpt +@@ -0,0 +1,41 @@ ++--TEST-- ++GHSA-w8qr-v226-r27w ++--EXTENSIONS-- ++filter ++--FILE-- ++<?php ++ ++function test(string $input) { ++ var_dump(filter_var($input, FILTER_VALIDATE_URL)); ++} ++ ++echo "--- These ones should fail ---\n"; ++test("http://t[est@127.0.0.1"); ++test("http://t[est@[::1]"); ++test("http://t[est@[::1"); ++test("http://t[est@::1]"); ++test("http://php.net\\@aliyun.com/aaa.do"); ++test("http://test[@2001:db8:3333:4444:5555:6666:1.2.3.4]"); ++test("http://te[st@2001:db8:3333:4444:5555:6666:1.2.3.4]"); ++test("http://te[st@2001:db8:3333:4444:5555:6666:1.2.3.4"); ++ ++echo "--- These ones should work ---\n"; ++test("http://test@127.0.0.1"); ++test("http://test@[2001:db8:3333:4444:5555:6666:1.2.3.4]"); ++test("http://test@[::1]"); ++ ++?> ++--EXPECT-- ++--- These ones should fail --- ++bool(false) ++bool(false) ++bool(false) ++bool(false) ++bool(false) ++bool(false) ++bool(false) ++bool(false) ++--- These ones should work --- ++string(21) "http://test@127.0.0.1" ++string(50) "http://test@[2001:db8:3333:4444:5555:6666:1.2.3.4]" ++string(17) "http://test@[::1]" +-- +2.45.1 + +From 6b6444a1b72d6249cfa592f20395efe67ca55f73 Mon Sep 17 00:00:00 2001 +From: Remi Collet <remi@remirepo.net> +Date: Tue, 4 Jun 2024 16:48:08 +0200 +Subject: [PATCH 2/2] NEWS + +(cherry picked from commit a1ff81b786bd519597e770795be114f5171f0648) +(cherry picked from commit ec1d5e6468479e64acc7fb8cb955f053b64ea9a0) +(cherry picked from commit cfe1b1acead13b6af163f3ce947d3a1dbded82a0) +--- + NEWS | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/NEWS b/NEWS +index 7d99fb7d60..3bb175ea25 100644 +--- a/NEWS ++++ b/NEWS +@@ -1,6 +1,12 @@ + PHP NEWS + ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| + ++Backported from 8.1.29 ++ ++- Filter: ++ . Fixed bug GHSA-w8qr-v226-r27w (Filter bypass in filter_var FILTER_VALIDATE_URL). ++ (CVE-2024-5458) (nielsdos) ++ + Backported from 8.1.28 + + - Standard: +-- +2.45.1 + diff --git a/php-cve-2024-8925.patch b/php-cve-2024-8925.patch new file mode 100644 index 0000000..031bfc3 --- /dev/null +++ b/php-cve-2024-8925.patch @@ -0,0 +1,236 @@ +From 5731a40507feea683591addf3599d210cd7a1fd9 Mon Sep 17 00:00:00 2001 +From: Arnaud Le Blanc <arnaud.lb@gmail.com> +Date: Mon, 9 Sep 2024 15:22:07 +0200 +Subject: [PATCH 3/8] Fix GHSA-9pqp-7h25-4f32 + +multipart/form-data boundaries larger than the read buffer result in erroneous +parsing, which violates data integrity. + +Limit boundary size, as allowed by RFC 1521: + + Encapsulation boundaries [...] must be no longer than 70 characters, not + counting the two leading hyphens. + +We correctly parse payloads with boundaries of length up to +FILLUNIT-strlen("\r\n--") bytes, so allow this for BC. + +(cherry picked from commit 19b49258d0c5a61398d395d8afde1123e8d161e0) +(cherry picked from commit 2b0daf421c162376892832588eccdfa9a286ed09) +(cherry picked from commit a24ac172f52e75101913f3946cfa5515f723c99f) +(cherry picked from commit 08f0adf0700f8bbaa4fd75b7a694bbd9ae45300d) +--- + main/rfc1867.c | 7 ++ + tests/basic/GHSA-9pqp-7h25-4f32.inc | 3 + + tests/basic/GHSA-9pqp-7h25-4f32.phpt | 100 +++++++++++++++++++++++++++ + 3 files changed, 110 insertions(+) + create mode 100644 tests/basic/GHSA-9pqp-7h25-4f32.inc + create mode 100644 tests/basic/GHSA-9pqp-7h25-4f32.phpt + +diff --git a/main/rfc1867.c b/main/rfc1867.c +index 14813a300c..43b94c056a 100644 +--- a/main/rfc1867.c ++++ b/main/rfc1867.c +@@ -769,6 +769,13 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) /* {{{ */ + boundary_len = boundary_end-boundary; + } + ++ /* Boundaries larger than FILLUNIT-strlen("\r\n--") characters lead to ++ * erroneous parsing */ ++ if (boundary_len > FILLUNIT-strlen("\r\n--")) { ++ sapi_module.sapi_error(E_WARNING, "Boundary too large in multipart/form-data POST data"); ++ return; ++ } ++ + /* Initialize the buffer */ + if (!(mbuff = multipart_buffer_new(boundary, boundary_len))) { + sapi_module.sapi_error(E_WARNING, "Unable to initialize the input buffer"); +diff --git a/tests/basic/GHSA-9pqp-7h25-4f32.inc b/tests/basic/GHSA-9pqp-7h25-4f32.inc +new file mode 100644 +index 0000000000..adf72a361a +--- /dev/null ++++ b/tests/basic/GHSA-9pqp-7h25-4f32.inc +@@ -0,0 +1,3 @@ ++<?php ++print "Hello world\n"; ++var_dump($_POST); +diff --git a/tests/basic/GHSA-9pqp-7h25-4f32.phpt b/tests/basic/GHSA-9pqp-7h25-4f32.phpt +new file mode 100644 +index 0000000000..af81916370 +--- /dev/null ++++ b/tests/basic/GHSA-9pqp-7h25-4f32.phpt +@@ -0,0 +1,100 @@ ++--TEST-- ++GHSA-9pqp-7h25-4f32 ++--SKIPIF-- ++<?php ++if (!getenv('TEST_PHP_CGI_EXECUTABLE')) { ++ die("skip php-cgi not available"); ++} ++?> ++--FILE-- ++<?php ++ ++const FILLUNIT = 5 * 1024; ++ ++function test($boundaryLen) { ++ printf("Boundary len: %d\n", $boundaryLen); ++ ++ $cmd = [ ++ getenv('TEST_PHP_CGI_EXECUTABLE'), ++ '-C', ++ '-n', ++ __DIR__ . '/GHSA-9pqp-7h25-4f32.inc', ++ ]; ++ ++ $boundary = str_repeat('A', $boundaryLen); ++ $body = "" ++ . "--$boundary\r\n" ++ . "Content-Disposition: form-data; name=\"koko\"\r\n" ++ . "\r\n" ++ . "BBB\r\n--" . substr($boundary, 0, -1) . "CCC\r\n" ++ . "--$boundary--\r\n" ++ ; ++ ++ $env = array_merge($_ENV, [ ++ 'REDIRECT_STATUS' => '1', ++ 'CONTENT_TYPE' => "multipart/form-data; boundary=$boundary", ++ 'CONTENT_LENGTH' => strlen($body), ++ 'REQUEST_METHOD' => 'POST', ++ 'SCRIPT_FILENAME' => __DIR__ . '/GHSA-9pqp-7h25-4f32.inc', ++ ]); ++ ++ $spec = [ ++ 0 => ['pipe', 'r'], ++ 1 => STDOUT, ++ 2 => STDOUT, ++ ]; ++ ++ $pipes = []; ++ ++ print "Starting...\n"; ++ ++ $handle = proc_open($cmd, $spec, $pipes, getcwd(), $env); ++ ++ fwrite($pipes[0], $body); ++ ++ $status = proc_close($handle); ++ ++ print "\n"; ++} ++ ++for ($offset = -1; $offset <= 1; $offset++) { ++ test(FILLUNIT - strlen("\r\n--") + $offset); ++} ++ ++?> ++--EXPECTF-- ++Boundary len: 5115 ++Starting... ++X-Powered-By: %s ++Content-type: text/html; charset=UTF-8 ++ ++Hello world ++array(1) { ++ ["koko"]=> ++ string(5124) "BBB ++--AAA%sCCC" ++} ++ ++Boundary len: 5116 ++Starting... ++X-Powered-By: %s ++Content-type: text/html; charset=UTF-8 ++ ++Hello world ++array(1) { ++ ["koko"]=> ++ string(5125) "BBB ++--AAA%sCCC" ++} ++ ++Boundary len: 5117 ++Starting... ++X-Powered-By: %s ++Content-type: text/html; charset=UTF-8 ++ ++<br /> ++<b>Warning</b>: Boundary too large in multipart/form-data POST data in <b>Unknown</b> on line <b>0</b><br /> ++Hello world ++array(0) { ++} ++ +-- +2.46.1 + +From 0c9258e4914695ca21b3d0cd3b1746bfc926f02e Mon Sep 17 00:00:00 2001 +From: Jakub Zelenka <bukka@php.net> +Date: Mon, 23 Sep 2024 18:54:31 +0100 +Subject: [PATCH 6/8] Skip GHSA-9pqp-7h25-4f32 test on Windows + +(cherry picked from commit c70e25630832fa10d421328eed2b8e1a36af7a64) +(cherry picked from commit c75683864f6e4188439e8ca2adbb05824918be12) +(cherry picked from commit 2fd1b83817d20523e72bef3ad524cd5797f51acf) +(cherry picked from commit 79eace3a64544088738d2fd341407cc32fe3ecaf) +--- + tests/basic/GHSA-9pqp-7h25-4f32.phpt | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/tests/basic/GHSA-9pqp-7h25-4f32.phpt b/tests/basic/GHSA-9pqp-7h25-4f32.phpt +index af81916370..29bcb6557d 100644 +--- a/tests/basic/GHSA-9pqp-7h25-4f32.phpt ++++ b/tests/basic/GHSA-9pqp-7h25-4f32.phpt +@@ -5,6 +5,9 @@ GHSA-9pqp-7h25-4f32 + if (!getenv('TEST_PHP_CGI_EXECUTABLE')) { + die("skip php-cgi not available"); + } ++if (substr(PHP_OS, 0, 3) == 'WIN') { ++ die("skip not for Windows in CI - probably resource issue"); ++} + ?> + --FILE-- + <?php +-- +2.46.1 + +From d97de82afe8696b6d76cc11bc7b6d6c2652d06d9 Mon Sep 17 00:00:00 2001 +From: Remi Collet <remi@remirepo.net> +Date: Thu, 26 Sep 2024 15:49:03 +0200 +Subject: [PATCH 8/8] adapt GHSA-9pqp-7h25-4f32 test for 7.x + +(cherry picked from commit 29065f33f37f99ba33254cb23c941647bcd7372c) +(cherry picked from commit 87ed9429a17e38daec4dcfd7a3c3db194197ccb3) +--- + tests/basic/GHSA-9pqp-7h25-4f32.phpt | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/tests/basic/GHSA-9pqp-7h25-4f32.phpt b/tests/basic/GHSA-9pqp-7h25-4f32.phpt +index 29bcb6557d..b913edc1c4 100644 +--- a/tests/basic/GHSA-9pqp-7h25-4f32.phpt ++++ b/tests/basic/GHSA-9pqp-7h25-4f32.phpt +@@ -21,8 +21,10 @@ function test($boundaryLen) { + getenv('TEST_PHP_CGI_EXECUTABLE'), + '-C', + '-n', ++ '-dlog_errors=1', + __DIR__ . '/GHSA-9pqp-7h25-4f32.inc', + ]; ++ $cmd = implode(' ', $cmd); + + $boundary = str_repeat('A', $boundaryLen); + $body = "" +@@ -92,11 +94,10 @@ array(1) { + + Boundary len: 5117 + Starting... ++PHP Warning: Boundary too large in multipart/form-data POST data in Unknown on line 0 + X-Powered-By: %s + Content-type: text/html; charset=UTF-8 + +-<br /> +-<b>Warning</b>: Boundary too large in multipart/form-data POST data in <b>Unknown</b> on line <b>0</b><br /> + Hello world + array(0) { + } +-- +2.46.1 + diff --git a/php-cve-2024-8926.patch b/php-cve-2024-8926.patch new file mode 100644 index 0000000..8ef88ce --- /dev/null +++ b/php-cve-2024-8926.patch @@ -0,0 +1,204 @@ +From 669f8524ad99a6b9220ea2cee1a07a9de3964776 Mon Sep 17 00:00:00 2001 +From: Jan Ehrhardt <github@ehrhardt.nl> +Date: Wed, 5 Jun 2024 20:28:45 +0200 +Subject: [PATCH 1/8] Fix GHSA-3qgc-jrrr-25jv + +--- + sapi/cgi/cgi_main.c | 23 ++++++++++++++- + sapi/cgi/tests/ghsa-3qgc-jrrr-25jv.phpt | 38 +++++++++++++++++++++++++ + 2 files changed, 60 insertions(+), 1 deletion(-) + create mode 100644 sapi/cgi/tests/ghsa-3qgc-jrrr-25jv.phpt + +diff --git a/sapi/cgi/cgi_main.c b/sapi/cgi/cgi_main.c +index 16bb2126d2..970950a657 100644 +--- a/sapi/cgi/cgi_main.c ++++ b/sapi/cgi/cgi_main.c +@@ -1881,8 +1881,13 @@ int main(int argc, char *argv[]) + } + } + ++ /* Apache CGI will pass the query string to the command line if it doesn't contain a '='. ++ * This can create an issue where a malicious request can pass command line arguments to ++ * the executable. Ideally we skip argument parsing when we're in cgi or fastcgi mode, ++ * but that breaks PHP scripts on Linux with a hashbang: `#!/php-cgi -d option=value`. ++ * Therefore, this code only prevents passing arguments if the query string starts with a '-'. ++ * Similarly, scripts spawned in subprocesses on Windows may have the same issue. */ + if((query_string = getenv("QUERY_STRING")) != NULL && strchr(query_string, '=') == NULL) { +- /* we've got query string that has no = - apache CGI will pass it to command line */ + unsigned char *p; + decoded_query_string = strdup(query_string); + php_url_decode(decoded_query_string, strlen(decoded_query_string)); +@@ -1892,6 +1897,22 @@ int main(int argc, char *argv[]) + if(*p == '-') { + skip_getopt = 1; + } ++ ++ /* On Windows we have to take into account the "best fit" mapping behaviour. */ ++#ifdef PHP_WIN32 ++ if (*p >= 0x80) { ++ wchar_t wide_buf[1]; ++ wide_buf[0] = *p; ++ char char_buf[4]; ++ size_t wide_buf_len = sizeof(wide_buf) / sizeof(wide_buf[0]); ++ size_t char_buf_len = sizeof(char_buf) / sizeof(char_buf[0]); ++ if (WideCharToMultiByte(CP_ACP, 0, wide_buf, wide_buf_len, char_buf, char_buf_len, NULL, NULL) == 0 ++ || char_buf[0] == '-') { ++ skip_getopt = 1; ++ } ++ } ++#endif ++ + free(decoded_query_string); + } + +diff --git a/sapi/cgi/tests/ghsa-3qgc-jrrr-25jv.phpt b/sapi/cgi/tests/ghsa-3qgc-jrrr-25jv.phpt +new file mode 100644 +index 0000000000..fd2fcdfbf8 +--- /dev/null ++++ b/sapi/cgi/tests/ghsa-3qgc-jrrr-25jv.phpt +@@ -0,0 +1,38 @@ ++--TEST-- ++GHSA-3qgc-jrrr-25jv ++--SKIPIF-- ++<?php ++include 'skipif.inc'; ++if (PHP_OS_FAMILY !== "Windows") die("skip Only for Windows"); ++ ++$codepage = trim(shell_exec("powershell Get-ItemPropertyValue HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Nls\\CodePage ACP")); ++if ($codepage !== '932' && $codepage !== '936' && $codepage !== '950') die("skip Wrong codepage"); ++?> ++--FILE-- ++<?php ++include 'include.inc'; ++ ++$filename = __DIR__."/GHSA-3qgc-jrrr-25jv_tmp.php"; ++$script = '<?php echo "hello "; echo "world"; ?>'; ++file_put_contents($filename, $script); ++ ++$php = get_cgi_path(); ++reset_env_vars(); ++ ++putenv("SERVER_NAME=Test"); ++putenv("SCRIPT_FILENAME=$filename"); ++putenv("QUERY_STRING=%ads"); ++putenv("REDIRECT_STATUS=1"); ++ ++passthru("$php -s"); ++ ++?> ++--CLEAN-- ++<?php ++@unlink(__DIR__."/GHSA-3qgc-jrrr-25jv_tmp.php"); ++?> ++--EXPECTF-- ++X-Powered-By: PHP/%s ++Content-type: %s ++ ++hello world +-- +2.46.1 + +From cc70fdedb5b362b6d666bc6604658aac70c1aec0 Mon Sep 17 00:00:00 2001 +From: Jan Ehrhardt <github@ehrhardt.nl> +Date: Sun, 9 Jun 2024 20:12:52 +0200 +Subject: [PATCH 2/8] NEWS: Add backport from 8.1.29 + +--- + NEWS | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/NEWS b/NEWS +index 3bb175ea25..c52661abc3 100644 +--- a/NEWS ++++ b/NEWS +@@ -3,6 +3,10 @@ PHP NEWS + + Backported from 8.1.29 + ++- CGI: ++ . Fixed bug GHSA-3qgc-jrrr-25jv (Bypass of CVE-2012-1823, Argument Injection ++ in PHP-CGI). (CVE-2024-4577) (nielsdos) ++ + - Filter: + . Fixed bug GHSA-w8qr-v226-r27w (Filter bypass in filter_var FILTER_VALIDATE_URL). + (CVE-2024-5458) (nielsdos) +-- +2.46.1 + +From 53a0269aa1d952eec1c65e0e0d3e9800e0427ded Mon Sep 17 00:00:00 2001 +From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> +Date: Fri, 14 Jun 2024 19:49:22 +0200 +Subject: [PATCH 4/8] Fix GHSA-p99j-rfp4-xqvq + +It's no use trying to work around whatever the operating system and Apache +do because we'll be fighting that until eternity. +Change the skip_getopt condition such that when we're running in +CGI or FastCGI mode we always skip the argument parsing. +This is a BC break, but this seems to be the only way to get rid of this +class of issues. + +(cherry picked from commit abcfd980bfa03298792fd3aba051c78d52f10642) +(cherry picked from commit 2d2552e092b6ff32cd823692d512f126ee629842) +(cherry picked from commit 1158d06f0b20532ab7309cb20f0be843f9662e3c) +(cherry picked from commit 89c66773413267949de995671bfb4bd03c34fbf9) +--- + sapi/cgi/cgi_main.c | 26 ++++++++------------------ + 1 file changed, 8 insertions(+), 18 deletions(-) + +diff --git a/sapi/cgi/cgi_main.c b/sapi/cgi/cgi_main.c +index 970950a657..be273676ce 100644 +--- a/sapi/cgi/cgi_main.c ++++ b/sapi/cgi/cgi_main.c +@@ -1830,7 +1830,6 @@ int main(int argc, char *argv[]) + int status = 0; + #endif + char *query_string; +- char *decoded_query_string; + int skip_getopt = 0; + + #ifdef HAVE_SIGNAL_H +@@ -1886,10 +1885,15 @@ int main(int argc, char *argv[]) + * the executable. Ideally we skip argument parsing when we're in cgi or fastcgi mode, + * but that breaks PHP scripts on Linux with a hashbang: `#!/php-cgi -d option=value`. + * Therefore, this code only prevents passing arguments if the query string starts with a '-'. +- * Similarly, scripts spawned in subprocesses on Windows may have the same issue. */ ++ * Similarly, scripts spawned in subprocesses on Windows may have the same issue. ++ * However, Windows has lots of conversion rules and command line parsing rules that ++ * are too difficult and dangerous to reliably emulate. */ + if((query_string = getenv("QUERY_STRING")) != NULL && strchr(query_string, '=') == NULL) { ++#ifdef PHP_WIN32 ++ skip_getopt = cgi || fastcgi; ++#else + unsigned char *p; +- decoded_query_string = strdup(query_string); ++ char *decoded_query_string = strdup(query_string); + php_url_decode(decoded_query_string, strlen(decoded_query_string)); + for (p = (unsigned char *)decoded_query_string; *p && *p <= ' '; p++) { + /* skip all leading spaces */ +@@ -1898,22 +1902,8 @@ int main(int argc, char *argv[]) + skip_getopt = 1; + } + +- /* On Windows we have to take into account the "best fit" mapping behaviour. */ +-#ifdef PHP_WIN32 +- if (*p >= 0x80) { +- wchar_t wide_buf[1]; +- wide_buf[0] = *p; +- char char_buf[4]; +- size_t wide_buf_len = sizeof(wide_buf) / sizeof(wide_buf[0]); +- size_t char_buf_len = sizeof(char_buf) / sizeof(char_buf[0]); +- if (WideCharToMultiByte(CP_ACP, 0, wide_buf, wide_buf_len, char_buf, char_buf_len, NULL, NULL) == 0 +- || char_buf[0] == '-') { +- skip_getopt = 1; +- } +- } +-#endif +- + free(decoded_query_string); ++#endif + } + + while (!skip_getopt && (c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0, 2)) != -1) { +-- +2.46.1 + diff --git a/php-cve-2024-8927.patch b/php-cve-2024-8927.patch new file mode 100644 index 0000000..61470ea --- /dev/null +++ b/php-cve-2024-8927.patch @@ -0,0 +1,98 @@ +From 74f1553070cb6237e25945407be7f75a43736113 Mon Sep 17 00:00:00 2001 +From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> +Date: Tue, 18 Jun 2024 21:28:26 +0200 +Subject: [PATCH 5/8] Fix GHSA-94p6-54jq-9mwp + +Apache only generates REDIRECT_STATUS, so explicitly check for that +if the server name is Apache, don't allow other variable names. +Furthermore, redirect.so and Netscape no longer exist, so +remove those entries as we can't check their server name anymore. + +We now also check for the configuration override *first* such that it +always take precedence. This would allow for a mitigation path if +something like this happens in the future. + +(cherry picked from commit 48808d98f4fc2a05193cdcc1aedd6c66816450f1) +(cherry picked from commit 8aa748ee0657cdee8d883ba50d04b68bc450f686) +(cherry picked from commit c7308ba7cd0533501b40eba255602bb5e085550f) +(cherry picked from commit 21e2b0ab382a898f627c97d39f5e5afc2431afe7) +--- + sapi/cgi/cgi_main.c | 23 +++++++++++------------ + 1 file changed, 11 insertions(+), 12 deletions(-) + +diff --git a/sapi/cgi/cgi_main.c b/sapi/cgi/cgi_main.c +index be273676ce..205d559f6d 100644 +--- a/sapi/cgi/cgi_main.c ++++ b/sapi/cgi/cgi_main.c +@@ -1992,18 +1992,17 @@ int main(int argc, char *argv[]) + + /* check force_cgi after startup, so we have proper output */ + if (cgi && CGIG(force_redirect)) { +- /* Apache will generate REDIRECT_STATUS, +- * Netscape and redirect.so will generate HTTP_REDIRECT_STATUS. +- * redirect.so and installation instructions available from +- * http://www.koehntopp.de/php. +- * -- kk@netuse.de +- */ +- if (!getenv("REDIRECT_STATUS") && +- !getenv ("HTTP_REDIRECT_STATUS") && +- /* this is to allow a different env var to be configured +- * in case some server does something different than above */ +- (!CGIG(redirect_status_env) || !getenv(CGIG(redirect_status_env))) +- ) { ++ /* This is to allow a different environment variable to be configured ++ * in case the we cannot auto-detect which environment variable to use. ++ * Checking this first to allow user overrides in case the environment ++ * variable can be set by an untrusted party. */ ++ const char *redirect_status_env = CGIG(redirect_status_env); ++ if (!redirect_status_env) { ++ /* Apache will generate REDIRECT_STATUS. */ ++ redirect_status_env = "REDIRECT_STATUS"; ++ } ++ ++ if (!getenv(redirect_status_env)) { + zend_try { + SG(sapi_headers).http_response_code = 400; + PUTS("<b>Security Alert!</b> The PHP CGI cannot be accessed directly.\n\n\ +-- +2.46.1 + +From e80cb90b00aa403a5aa995f612ecb358323e9572 Mon Sep 17 00:00:00 2001 +From: Remi Collet <remi@remirepo.net> +Date: Thu, 26 Sep 2024 11:50:54 +0200 +Subject: [PATCH 7/8] NEWS for 8.1.30 backports + +(cherry picked from commit af3fb385e7b328ab89db26ec712d89c7096f0743) +(cherry picked from commit 1154fbd3ddfa418bf2492c5366adaefb47c47737) +(cherry picked from commit b4667e4ebe241d95775962b1e8b24788e7945de2) +--- + NEWS | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/NEWS b/NEWS +index c52661abc3..ced91f9577 100644 +--- a/NEWS ++++ b/NEWS +@@ -1,6 +1,19 @@ + PHP NEWS + ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| + ++Backported from 8.1.30 ++ ++- CGI: ++ . Fixed bug GHSA-p99j-rfp4-xqvq (Bypass of CVE-2024-4577, Parameter Injection ++ Vulnerability). (CVE-2024-8926) (nielsdos) ++ . Fixed bug GHSA-94p6-54jq-9mwp (cgi.force_redirect configuration is ++ bypassable due to the environment variable collision). (CVE-2024-8927) ++ (nielsdos) ++ ++- SAPI: ++ . Fixed bug GHSA-9pqp-7h25-4f32 (Erroneous parsing of multipart form data). ++ (CVE-2024-8925) (Arnaud) ++ + Backported from 8.1.29 + + - CGI: +-- +2.46.1 + diff --git a/php-cve-2024-8932.patch b/php-cve-2024-8932.patch new file mode 100644 index 0000000..2737c79 --- /dev/null +++ b/php-cve-2024-8932.patch @@ -0,0 +1,141 @@ +From f8756a7a1d185727a5bfd212b1442a6d153a9471 Mon Sep 17 00:00:00 2001 +From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> +Date: Thu, 26 Sep 2024 22:22:27 +0200 +Subject: [PATCH 5/9] Fix GHSA-g665-fm4p-vhff: OOB access in ldap_escape + +(cherry picked from commit f9ecf90070a11dad09ca7671a712f81cc2a7d52f) +(cherry picked from commit 9f367d847989b339c33369737daf573e30bab5f1) +(cherry picked from commit 50e9e72530a4805980384b8ea6672877af816145) +(cherry picked from commit 9822bfae85607dffc13848d40a2340daf090f39b) +--- + ext/ldap/ldap.c | 21 ++++++++++++++-- + ext/ldap/tests/GHSA-g665-fm4p-vhff-1.phpt | 28 ++++++++++++++++++++++ + ext/ldap/tests/GHSA-g665-fm4p-vhff-2.phpt | 29 +++++++++++++++++++++++ + 3 files changed, 76 insertions(+), 2 deletions(-) + create mode 100644 ext/ldap/tests/GHSA-g665-fm4p-vhff-1.phpt + create mode 100644 ext/ldap/tests/GHSA-g665-fm4p-vhff-2.phpt + +diff --git a/ext/ldap/ldap.c b/ext/ldap/ldap.c +index 3839f871a9..533c78138d 100644 +--- a/ext/ldap/ldap.c ++++ b/ext/ldap/ldap.c +@@ -54,6 +54,7 @@ + + #include "ext/standard/php_string.h" + #include "ext/standard/info.h" ++#include "Zend/zend_exceptions.h" + + #ifdef HAVE_LDAP_SASL_H + #include <sasl.h> +@@ -3005,13 +3006,23 @@ static zend_string* php_ldap_do_escape(const zend_bool *map, const char *value, + zend_string *ret; + + for (i = 0; i < valuelen; i++) { +- len += (map[(unsigned char) value[i]]) ? 3 : 1; ++ size_t addend = (map[(unsigned char) value[i]]) ? 3 : 1; ++ if (len > ZSTR_MAX_LEN - addend) { ++ return NULL; ++ } ++ len += addend; + } + /* Per RFC 4514, a leading and trailing space must be escaped */ + if ((flags & PHP_LDAP_ESCAPE_DN) && (value[0] == ' ')) { ++ if (len > ZSTR_MAX_LEN - 2) { ++ return NULL; ++ } + len += 2; + } + if ((flags & PHP_LDAP_ESCAPE_DN) && ((valuelen > 1) && (value[valuelen - 1] == ' '))) { ++ if (len > ZSTR_MAX_LEN - 2) { ++ return NULL; ++ } + len += 2; + } + +@@ -3078,7 +3089,13 @@ PHP_FUNCTION(ldap_escape) + php_ldap_escape_map_set_chars(map, ignores, ignoreslen, 0); + } + +- RETURN_NEW_STR(php_ldap_do_escape(map, value, valuelen, flags)); ++ zend_string *result = php_ldap_do_escape(map, value, valuelen, flags); ++ if (UNEXPECTED(!result)) { ++ zend_throw_exception(NULL, "Argument #1 ($value) is too long", 0); ++ return; ++ } ++ ++ RETURN_NEW_STR(result); + } + + #ifdef STR_TRANSLATION +diff --git a/ext/ldap/tests/GHSA-g665-fm4p-vhff-1.phpt b/ext/ldap/tests/GHSA-g665-fm4p-vhff-1.phpt +new file mode 100644 +index 0000000000..734bbe91d4 +--- /dev/null ++++ b/ext/ldap/tests/GHSA-g665-fm4p-vhff-1.phpt +@@ -0,0 +1,28 @@ ++--TEST-- ++GHSA-g665-fm4p-vhff (OOB access in ldap_escape) ++--EXTENSIONS-- ++ldap ++--INI-- ++memory_limit=-1 ++--SKIPIF-- ++<?php ++if (PHP_INT_SIZE !== 4) die("skip only for 32-bit"); ++if (getenv("SKIP_SLOW_TESTS")) die("skip slow test"); ++?> ++--FILE-- ++<?php ++try { ++ ldap_escape(' '.str_repeat("#", 1431655758), "", LDAP_ESCAPE_DN); ++} catch (Exception $e) { ++ echo $e->getMessage(), "\n"; ++} ++ ++try { ++ ldap_escape(str_repeat("#", 1431655758).' ', "", LDAP_ESCAPE_DN); ++} catch (Exception $e) { ++ echo $e->getMessage(), "\n"; ++} ++?> ++--EXPECT-- ++ldap_escape(): Argument #1 ($value) is too long ++ldap_escape(): Argument #1 ($value) is too long +diff --git a/ext/ldap/tests/GHSA-g665-fm4p-vhff-2.phpt b/ext/ldap/tests/GHSA-g665-fm4p-vhff-2.phpt +new file mode 100644 +index 0000000000..5c1b0fb661 +--- /dev/null ++++ b/ext/ldap/tests/GHSA-g665-fm4p-vhff-2.phpt +@@ -0,0 +1,29 @@ ++--TEST-- ++GHSA-g665-fm4p-vhff (OOB access in ldap_escape) ++--EXTENSIONS-- ++ldap ++--INI-- ++memory_limit=-1 ++--SKIPIF-- ++<?php ++if (PHP_INT_SIZE !== 4) die("skip only for 32-bit"); ++if (getenv("SKIP_SLOW_TESTS")) die("skip slow test"); ++?> ++--FILE-- ++<?php ++try { ++ ldap_escape(str_repeat("*", 1431655759), "", LDAP_ESCAPE_FILTER); ++} catch (Exception $e) { ++ echo $e->getMessage(), "\n"; ++} ++ ++// would allocate a string of length 2 ++try { ++ ldap_escape(str_repeat("*", 1431655766), "", LDAP_ESCAPE_FILTER); ++} catch (Exception $e) { ++ echo $e->getMessage(), "\n"; ++} ++?> ++--EXPECT-- ++ldap_escape(): Argument #1 ($value) is too long ++ldap_escape(): Argument #1 ($value) is too long +-- +2.47.0 + diff --git a/php-ghsa-4w77-75f9-2c8w.patch b/php-ghsa-4w77-75f9-2c8w.patch new file mode 100644 index 0000000..a93a3b3 --- /dev/null +++ b/php-ghsa-4w77-75f9-2c8w.patch @@ -0,0 +1,139 @@ +From b7c951d47acae54aab5ce896b8ec151d661c8fd0 Mon Sep 17 00:00:00 2001 +From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> +Date: Sat, 9 Nov 2024 15:29:52 +0100 +Subject: [PATCH 8/9] Fix GHSA-4w77-75f9-2c8w + +(cherry picked from commit 7dd336ae838bbf2c62dc47e3c900d657d3534c02) +(cherry picked from commit 462092a48aa0dbad24d9fa8a4a9d418faa14d309) +(cherry picked from commit 56488a8a4ec68e58eecc9e78dd75e41adf56984c) +(cherry picked from commit 6b8357c22f83a93104c2682d5cba9104c8de636d) +--- + sapi/cli/php_cli_server.c | 6 +--- + sapi/cli/tests/ghsa-4w77-75f9-2c8w.phpt | 41 +++++++++++++++++++++++++ + 2 files changed, 42 insertions(+), 5 deletions(-) + create mode 100644 sapi/cli/tests/ghsa-4w77-75f9-2c8w.phpt + +diff --git a/sapi/cli/php_cli_server.c b/sapi/cli/php_cli_server.c +index cdcd93ac72..5de98ad1c7 100644 +--- a/sapi/cli/php_cli_server.c ++++ b/sapi/cli/php_cli_server.c +@@ -1801,8 +1801,6 @@ static size_t php_cli_server_client_send_through(php_cli_server_client *client, + + static void php_cli_server_client_populate_request_info(const php_cli_server_client *client, sapi_request_info *request_info) /* {{{ */ + { +- char *val; +- + request_info->request_method = php_http_method_str(client->request.request_method); + request_info->proto_num = client->request.protocol_version; + request_info->request_uri = client->request.request_uri; +@@ -1810,9 +1808,7 @@ static void php_cli_server_client_populate_request_info(const php_cli_server_cli + request_info->query_string = client->request.query_string; + request_info->content_length = client->request.content_len; + request_info->auth_user = request_info->auth_password = request_info->auth_digest = NULL; +- if (NULL != (val = zend_hash_str_find_ptr(&client->request.headers, "content-type", sizeof("content-type")-1))) { +- request_info->content_type = val; +- } ++ request_info->content_type = zend_hash_str_find_ptr(&client->request.headers, "content-type", sizeof("content-type")-1); + } /* }}} */ + + static void destroy_request_info(sapi_request_info *request_info) /* {{{ */ +diff --git a/sapi/cli/tests/ghsa-4w77-75f9-2c8w.phpt b/sapi/cli/tests/ghsa-4w77-75f9-2c8w.phpt +new file mode 100644 +index 0000000000..44667e8389 +--- /dev/null ++++ b/sapi/cli/tests/ghsa-4w77-75f9-2c8w.phpt +@@ -0,0 +1,41 @@ ++--TEST-- ++GHSA-4w77-75f9-2c8w (Heap-Use-After-Free in sapi_read_post_data Processing in CLI SAPI Interface) ++--INI-- ++allow_url_fopen=1 ++--SKIPIF-- ++<?php ++include "skipif.inc"; ++?> ++--FILE-- ++<?php ++include "php_cli_server.inc"; ++ ++$serverCode = <<<'CODE' ++var_dump(file_get_contents('php://input')); ++CODE; ++ ++php_cli_server_start($serverCode, null); ++ ++$options = [ ++ "http" => [ ++ "method" => "POST", ++ "header" => "Content-Type: application/x-www-form-urlencoded", ++ "content" => "AAAAA", ++ ], ++]; ++$context = stream_context_create($options); ++ ++echo file_get_contents("http://" . PHP_CLI_SERVER_ADDRESS . "/", false, $context); ++ ++$options = [ ++ "http" => [ ++ "method" => "POST", ++ ], ++]; ++$context = stream_context_create($options); ++ ++echo file_get_contents("http://" . PHP_CLI_SERVER_ADDRESS . "/", false, $context); ++?> ++--EXPECT-- ++string(5) "AAAAA" ++string(0) "" +-- +2.47.0 + +From 46f3d442aae8d8caca33a4d4ff9c9470568aee80 Mon Sep 17 00:00:00 2001 +From: Remi Collet <remi@remirepo.net> +Date: Fri, 22 Nov 2024 08:58:10 +0100 +Subject: [PATCH 9/9] NEWS for 8.1.31 backports + +(cherry picked from commit 22bdb43da0ecd6e72d63b63aa6c1f3a25d1bca3a) +(cherry picked from commit d8d682d3d6a4d027771806c8fc77128cae078d29) +(cherry picked from commit b97a41a47f77df92771b3c01fbf7cf445c0e7a1b) +--- + NEWS | 24 ++++++++++++++++++++++++ + 1 file changed, 24 insertions(+) + +diff --git a/NEWS b/NEWS +index ced91f9577..cc2d877d94 100644 +--- a/NEWS ++++ b/NEWS +@@ -1,6 +1,30 @@ + PHP NEWS + ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| + ++Backported from 8.1.31 ++ ++- CLI: ++ . Fixed bug GHSA-4w77-75f9-2c8w (Heap-Use-After-Free in sapi_read_post_data ++ Processing in CLI SAPI Interface). (nielsdos) ++ ++- LDAP: ++ . Fixed bug GHSA-g665-fm4p-vhff (OOB access in ldap_escape). (CVE-2024-8932) ++ (nielsdos) ++ ++- PDO DBLIB: ++ . Fixed bug GHSA-5hqh-c84r-qjcv (Integer overflow in the dblib quoter causing ++ OOB writes). (CVE-2024-11236) (nielsdos) ++ ++- PDO Firebird: ++ . Fixed bug GHSA-5hqh-c84r-qjcv (Integer overflow in the firebird quoter ++ causing OOB writes). (CVE-2024-11236) (nielsdos) ++ ++- Streams: ++ . Fixed bug GHSA-c5f2-jwm7-mmq2 (Configuring a proxy in a stream context ++ might allow for CRLF injection in URIs). (CVE-2024-11234) (Jakub Zelenka) ++ . Fixed bug GHSA-r977-prxv-hc43 (Single byte overread with ++ convert.quoted-printable-decode filter). (CVE-2024-11233) (nielsdos) ++ + Backported from 8.1.30 + + - CGI: +-- +2.47.0 + @@ -55,8 +55,17 @@ %global mysql_sock %(mysql_config --socket 2>/dev/null || echo /var/lib/mysql/mysql.sock) -%global oraclever 21.7 -%global oraclelib 21.1 +%ifarch aarch64 +%global oraclever 19.24 +%global oraclemax 20 +%global oraclelib 19.1 +%global oracledir 19.24 +%else +%global oraclever 23.6 +%global oraclemax 24 +%global oraclelib 23.1 +%global oracledir 23 +%endif # Build for LiteSpeed Web Server (LSAPI) %global with_lsws 1 @@ -126,7 +135,7 @@ Summary: PHP scripting language for creating dynamic web sites Name: %{?scl_prefix}php Version: %{upver}%{?rcver:~%{rcver}} -Release: 12%{?dist} +Release: 25%{?dist} # All files licensed under PHP version 3.01, except # Zend is licensed under Zend # TSRM is licensed under BSD @@ -204,6 +213,25 @@ Patch208: php-bug81719.patch Patch209: php-bug81720.patch Patch210: php-bug81727.patch Patch211: php-bug81726.patch +Patch212: php-bug81738.patch +Patch213: php-bug81740.patch +Patch214: php-bug81744.patch +Patch215: php-bug81746.patch +Patch216: php-cve-2023-0662.patch +Patch217: php-cve-2023-3247.patch +Patch218: php-cve-2023-3823.patch +Patch219: php-cve-2023-3824.patch +Patch220: php-cve-2024-2756.patch +Patch221: php-cve-2024-3096.patch +Patch222: php-cve-2024-5458.patch +Patch223: php-cve-2024-8925.patch +Patch224: php-cve-2024-8926.patch +Patch225: php-cve-2024-8927.patch +Patch226: php-cve-2024-11236.patch +Patch227: php-cve-2024-11234.patch +Patch228: php-cve-2024-8932.patch +Patch229: php-cve-2024-11233.patch +Patch230: php-ghsa-4w77-75f9-2c8w.patch # Fixes for tests (300+) # Factory is droped from system tzdata @@ -629,15 +657,20 @@ Summary: A module for PHP applications that use OCI8 databases Group: Development/Languages # All files licensed under PHP version 3.01 License: PHP -BuildRequires: oracle-instantclient-devel >= %{oraclever} +%ifarch aarch64 +BuildRequires: oracle-instantclient%{oraclever}-devel +# Should requires libclntsh.so.19.1()(aarch-64), but it's not provided by Oracle RPM. +Requires: libclntsh.so.%{oraclelib} +AutoReq: 0 +%else +BuildRequires: (oracle-instantclient-devel >= %{oraclever} with oracle-instantclient-devel < %{oraclemax}) +%endif Requires: %{?scl_prefix}php-pdo%{?_isa} = %{version}-%{release} Provides: %{?scl_prefix}php_database Provides: %{?scl_prefix}php-pdo_oci, %{?scl_prefix}php-pdo_oci%{?_isa} Obsoletes: %{?scl_prefix}php-pecl-oci8 <= %{oci8ver} Conflicts: %{?scl_prefix}php-pecl-oci8 > %{oci8ver} Provides: %{?scl_prefix}php-pecl(oci8) = %{oci8ver}, %{?scl_prefix}php-pecl(oci8)%{?_isa} = %{oci8ver} -# Should requires libclntsh.so.18.3, but it's not provided by Oracle RPM. -AutoReq: 0 %description oci8 The %{?scl_prefix}php-oci8 packages provides the OCI8 extension version %{oci8ver} @@ -647,13 +680,9 @@ The extension is linked with Oracle client libraries %{oraclever} (Oracle Instant Client). For details, see Oracle's note "Oracle Client / Server Interoperability Support" (ID 207303.1). -You must install libclntsh.so.%{oraclelib} to use this package, provided -in the database installation, or in the free Oracle Instant Client -available from Oracle. - -Notice: -- %{?scl_prefix}php-oci8 provides oci8 and pdo_oci extensions from php sources. -- %{?scl_prefix}php-pecl-oci8 only provides oci8 extension. +You must install libclntsh.so.%{oraclelib} to use this package, +provided by Oracle Instant Client RPM available from Oracle on: +https://www.oracle.com/database/technologies/instant-client/downloads.html Documentation is at http://php.net/oci8 and http://php.net/pdo_oci %endif @@ -854,8 +883,12 @@ Group: System Environment/Libraries # All files licensed under PHP version 3.01 License: PHP Requires: %{?scl_prefix}php-common%{?_isa} = %{version}-%{release} +%if 0%{?rhel} # Upstream requires 4.0, we require 69.1 to ensure use of libicu69 BuildRequires: libicu-devel = 69.1 +%else +BuildRequires: libicu-devel +%endif %description intl The %{?scl_prefix}php-intl package contains a dynamic shared object that will add @@ -933,55 +966,74 @@ low-level PHP extension for the libsodium cryptographic library. %setup -q -n php-%{upver}%{?rcver} %endif -%patch1 -p1 -b .mpmcheck -%patch2 -p1 -b .true -%patch5 -p1 -b .includedir -%patch6 -p1 -b .embed -%patch7 -p1 -b .recode -%patch8 -p1 -b .libdb +%patch -P1 -p1 -b .mpmcheck +%patch -P2 -p1 -b .true +%patch -P5 -p1 -b .includedir +%patch -P6 -p1 -b .embed +%patch -P7 -p1 -b .recode +%patch -P8 -p1 -b .libdb %if 0%{?rhel} -%patch9 -p1 -b .curltls +%patch -P9 -p1 -b .curltls %endif -%patch10 -p1 -b .nodes +%patch -P10 -p1 -b .nodes -%patch40 -p1 -b .dlopen +%patch -P40 -p1 -b .dlopen %if 0%{?fedora} >= 28 || 0%{?rhel} >= 6 -%patch42 -p1 -b .systzdata +%patch -P42 -p1 -b .systzdata %endif -%patch43 -p1 -b .headers +%patch -P43 -p1 -b .headers sed -e 's/php-devel/%{?scl_prefix}php-devel/' -i scripts/phpize.in %if 0%{?fedora} >= 18 || 0%{?rhel} >= 7 -%patch45 -p1 -b .ldap_r +%patch -P45 -p1 -b .ldap_r %endif -%patch46 -p1 -b .fixheader -%patch47 -p1 -b .phpinfo -%patch48 -p1 -b .getallheaders -%patch49 -p1 -b .pdooci +%patch -P46 -p1 -b .fixheader +%patch -P47 -p1 -b .phpinfo +%patch -P48 -p1 -b .getallheaders +%patch -P49 -p1 -b .pdooci -%patch91 -p1 -b .remi-oci8 +%patch -P91 -p1 -b .remi-oci8 # upstream patches # security patches -%patch200 -p1 -b .bug77423 -%patch201 -p1 -b .bug80672 -%patch202 -p1 -b .bug80710 -%patch203 -p1 -b .bug81122 -%patch204 -p1 -b .bug76450 -%patch205 -p1 -b .bug81211 -%patch206 -p1 -b .bug81026 -%patch207 -p1 -b .bug79971 -%patch208 -p1 -b .bug81719 -%patch209 -p1 -b .bug81720 -%patch210 -p1 -b .bug81727 -%patch211 -p1 -b .bug81726 +%patch -P200 -p1 -b .bug77423 +%patch -P201 -p1 -b .bug80672 +%patch -P202 -p1 -b .bug80710 +%patch -P203 -p1 -b .bug81122 +%patch -P204 -p1 -b .bug76450 +%patch -P205 -p1 -b .bug81211 +%patch -P206 -p1 -b .bug81026 +%patch -P207 -p1 -b .bug79971 +%patch -P208 -p1 -b .bug81719 +%patch -P209 -p1 -b .bug81720 +%patch -P210 -p1 -b .bug81727 +%patch -P211 -p1 -b .bug81726 +%patch -P212 -p1 -b .bug81738 +%patch -P213 -p1 -b .bug81740 +%patch -P214 -p1 -b .bug81744 +%patch -P215 -p1 -b .bug81746 +%patch -P216 -p1 -b .cve0662 +%patch -P217 -p1 -b .cve3247 +%patch -P218 -p1 -b .cve3823 +%patch -P219 -p1 -b .cve3824 +%patch -P220 -p1 -b .cve2756 +%patch -P221 -p1 -b .cve3096 +%patch -P222 -p1 -b .cve5458 +%patch -P223 -p1 -b .cve8925 +%patch -P224 -p1 -b .cve8926 +%patch -P225 -p1 -b .cve8927 +%patch -P226 -p1 -b .cve11236 +%patch -P227 -p1 -b .cve11234 +%patch -P228 -p1 -b .cve8932 +%patch -P229 -p1 -b .cve11233 +%patch -P230 -p1 -b .ghsa4w77 # Fixes for tests -%patch300 -p1 -b .datetests +%patch -P300 -p1 -b .datetests %if %{with_libpcre} if ! pkg-config libpcre --atleast-version 8.34 ; then # Only apply when system libpcre < 8.34 -%patch301 -p1 -b .pcre834 +%patch -P301 -p1 -b .pcre834 fi %endif @@ -1274,8 +1326,8 @@ build --libdir=%{_libdir}/php \ --with-mysqli=shared,mysqlnd \ --with-mysql-sock=%{mysql_sock} \ %if %{with_oci8} - --with-oci8=shared,instantclient,%{_root_libdir}/oracle/%{oraclever}/client64/lib,%{oraclever} \ - --with-pdo-oci=shared,instantclient,%{_root_libdir}/oracle/%{oraclever}/client64/lib,%{oraclever} \ + --with-oci8=shared,instantclient,%{_root_prefix}/lib/oracle/%{oracledir}/client64/lib,%{oraclever} \ + --with-pdo-oci=shared,instantclient,%{_root_prefix}/lib/oracle/%{oracledir}/client64/lib,%{oraclever} \ %endif %if %{with_interbase} --with-interbase=shared \ @@ -1502,8 +1554,8 @@ mv $RPM_BUILD_ROOT%{_sysconfdir}/php-fpm.d/www.conf.default . %if %{with_systemd} install -Dm 644 %{SOURCE6} $RPM_BUILD_ROOT%{_unitdir}/%{?scl_prefix}php-fpm.service %if 0%{?fedora} >= 27 || 0%{?rhel} >= 8 -install -Dm 644 %{SOURCE12} $RPM_BUILD_ROOT%{_unitdir}/httpd.service.d/%{?scl_prefix}php-fpm.conf -install -Dm 644 %{SOURCE12} $RPM_BUILD_ROOT%{_unitdir}/nginx.service.d/%{?scl_prefix}php-fpm.conf +install -Dm 644 %{SOURCE12} $RPM_BUILD_ROOT%{_root_sysconfdir}/systemd/system/httpd.service.d/%{?scl_prefix}php-fpm.conf +install -Dm 644 %{SOURCE12} $RPM_BUILD_ROOT%{_root_sysconfdir}/systemd/system/nginx.service.d/%{?scl_prefix}php-fpm.conf %endif sed -e 's:/run:%{_localstatedir}/run:' \ -e 's:/etc/sysconfig:%{_sysconfdir}/sysconfig:' \ @@ -1763,7 +1815,7 @@ cat << EOF WARNING : PHP 7.2 have reached its "End of Life" in November 2020. Even, if this package includes some of - the important security fix, backported from 7.4, the + the important security fixes, backported from 8.1, the UPGRADE to a maintained version is very strongly RECOMMENDED. ===================================================================== @@ -1855,8 +1907,8 @@ EOF %{_unitdir}/%{?scl_prefix}php-fpm.service %dir %{_root_sysconfdir}/systemd/system/%{?scl_prefix}php-fpm.service.d %if 0%{?fedora} >= 27 || 0%{?rhel} >= 8 -%{_unitdir}/httpd.service.d/%{?scl_prefix}php-fpm.conf -%{_unitdir}/nginx.service.d/%{?scl_prefix}php-fpm.conf +%config(noreplace) %{_root_sysconfdir}/systemd/system/httpd.service.d/%{?scl_prefix}php-fpm.conf +%config(noreplace) %{_root_sysconfdir}/systemd/system/nginx.service.d/%{?scl_prefix}php-fpm.conf %endif %else %{_root_initddir}/%{?scl_prefix}php-fpm @@ -1945,7 +1997,81 @@ EOF %changelog -* Tue Sep 27 2022 Remi Collet <remi@remirepo.net> - 7.2.34-12 +* Tue Nov 26 2024 Remi Collet <remi@remirepo.net> - 7.2.34-25 +- Fix Heap-Use-After-Free in sapi_read_post_data Processing in CLI SAPI Interface + GHSA-4w77-75f9-2c8w +- Fix OOB access in ldap_escape + CVE-2024-8932 +- Fix Integer overflow in the dblib/firebird quoter causing OOB writes + CVE-2024-11236 +- Fix Configuring a proxy in a stream context might allow for CRLF injection in URIs + CVE-2024-11234 +- Fix Single byte overread with convert.quoted-printable-decode filter + CVE-2024-11233 + +* Thu Sep 26 2024 Remi Collet <remi@remirepo.net> - 7.2.34-24 +- Fix Bypass of CVE-2012-1823, Argument Injection in PHP-CGI + CVE-2024-4577 +- Fix Bypass of CVE-2024-4577, Parameter Injection Vulnerability + CVE-2024-8926 +- Fix cgi.force_redirect configuration is bypassable due to the environment variable collision + CVE-2024-8927 +- Fix Erroneous parsing of multipart form data + CVE-2024-8925 + +* Wed Jul 31 2024 Remi Collet <remi@remirepo.net> - 7.2.34-23 +- use oracle client library version 23.5 on x86_64 + +* Tue Jun 4 2024 Remi Collet <remi@remirepo.net> - 7.2.34-22 +- Fix filter bypass in filter_var FILTER_VALIDATE_URL + CVE-2024-5458 + +* Wed Apr 10 2024 Remi Collet <remi@remirepo.net> - 7.2.34-21 +- use oracle client library version 21.13 on x86_64, 19.19 on aarch64 +- Fix __Host-/__Secure- cookie bypass due to partial CVE-2022-31629 fix + CVE-2024-2756 +- Fix password_verify can erroneously return true opening ATO risk + CVE-2024-3096 + +* Thu Sep 21 2023 Remi Collet <remi@remirepo.net> - 7.2.34-20 +- use oracle client library version 21.11 on x86_64, 19.19 on aarch64 +- use official Oracle Instant Client RPM + +* Tue Aug 1 2023 Remi Collet <remi@remirepo.net> - 7.2.34-19 +- Fix Security issue with external entity loading in XML without enabling it + GHSA-3qrf-m4j2-pcrr CVE-2023-3823 +- Fix Buffer mismanagement in phar_dir_read() + GHSA-jqcx-ccgc-xwhv CVE-2023-3824 +- move httpd/nginx wants directive to config files in /etc + +* Tue Jun 20 2023 Remi Collet <remi@remirepo.net> - 7.2.34-18 +- fix possible buffer overflow in date +- define %%php72___phpize and %%php72___phpconfig + +* Wed Jun 7 2023 Remi Collet <remi@remirepo.net> - 7.2.34-17 +- Fix Missing error check and insufficient random bytes in HTTP Digest + authentication for SOAP + GHSA-76gg-c692-v2mw CVE-2023-3247 +- use oracle client library version 21.10 + +* Tue Feb 14 2023 Remi Collet <remi@remirepo.net> - 7.2.34-16 +- fix #81744: Password_verify() always return true with some hash + CVE-2023-0567 +- fix #81746: 1-byte array overrun in common path resolve code + CVE-2023-0568 +- fix DOS vulnerability when parsing multipart request body + CVE-2023-0662 + +* Mon Dec 19 2022 Remi Collet <remi@remirepo.net> - 7.2.34-15 +- pdo: fix #81740: PDO::quote() may return unquoted string + CVE-2022-31631 +- use oracle client library version 21.8 + +* Mon Oct 24 2022 Remi Collet <remi@remirepo.net> - 7.2.34-14 +- hash: fix #81738: buffer overflow in hash_update() on long parameter. + CVE-2022-37454 + +* Tue Sep 27 2022 Remi Collet <remi@remirepo.net> - 7.2.34-13 - phar: fix #81726 DOS when using quine gzip file. CVE-2022-31628 - core: fix #81727 Don't mangle HTTP variable names that clash with ones that have a specific semantic meaning. CVE-2022-31629 |