summarylogtreecommitdiffstats
path: root/debian-php-7.1.33.patch
diff options
context:
space:
mode:
authorEugene Lamskoy2022-02-03 20:42:36 +0200
committerEugene Lamskoy2022-02-03 20:42:36 +0200
commit022812fa41ddc6e6a2c665f7961eade3c4ffe846 (patch)
tree59120ae4cfd6726ad5a461347728101f0b540f58 /debian-php-7.1.33.patch
parentcdeefa925911841f044d9f551f03694877f25b9a (diff)
downloadaur-022812fa41ddc6e6a2c665f7961eade3c4ffe846.tar.gz
new version
Diffstat (limited to 'debian-php-7.1.33.patch')
-rw-r--r--debian-php-7.1.33.patch1890
1 files changed, 1890 insertions, 0 deletions
diff --git a/debian-php-7.1.33.patch b/debian-php-7.1.33.patch
new file mode 100644
index 000000000000..06129eafbb06
--- /dev/null
+++ b/debian-php-7.1.33.patch
@@ -0,0 +1,1890 @@
+
+diff --git a/ext/standard/proc_open.c b/ext/standard/proc_open.c
+index 17dcdb1..5c1d514 100644
+--- a/ext/standard/proc_open.c
++++ b/ext/standard/proc_open.c
+@@ -62,7 +62,7 @@
+ * */
+ #ifdef PHP_CAN_SUPPORT_PROC_OPEN
+
+-#if 0 && HAVE_PTSNAME && HAVE_GRANTPT && HAVE_UNLOCKPT && HAVE_SYS_IOCTL_H && HAVE_TERMIOS_H
++#if HAVE_PTSNAME && HAVE_GRANTPT && HAVE_UNLOCKPT && HAVE_SYS_IOCTL_H && HAVE_TERMIOS_H
+ # include <sys/ioctl.h>
+ # include <termios.h>
+ # define PHP_CAN_DO_PTS 1
+diff --git a/php.ini-development b/php.ini-development
+index 654968b..d78d2f4 100644
+--- a/php.ini-development
++++ b/php.ini-development
+@@ -306,6 +306,12 @@
+ ; and below. This directive makes most sense if used in a per-directory
+ ; or per-virtualhost web server configuration file.
+ ; http://php.net/open-basedir
++
++; NOTE: this is considered a "broken" security measure.
++; Applications relying on this feature will not receive full
++; support by the security team. For more information please
++; see /usr/share/doc/php-common/README.Debian.security
++;
+ ;open_basedir =
+
+ ; This directive allows you to disable certain functions for security reasons.
+diff --git a/ext/dba/config.m4 b/ext/dba/config.m4
+index ced02de..64e1661 100644
+--- a/ext/dba/config.m4
++++ b/ext/dba/config.m4
+@@ -312,61 +312,13 @@
+ dbdp4="/usr/local/BerkeleyDB.4."
+ dbdp5="/usr/local/BerkeleyDB.5."
+ for i in $PHP_DB4 ${dbdp5}1 ${dbdp5}0 ${dbdp4}8 ${dbdp4}7 ${dbdp4}6 ${dbdp4}5 ${dbdp4}4 ${dbdp4}3 ${dbdp4}2 ${dbdp4}1 ${dbdp}0 /usr/local /usr; do
+- if test -f "$i/db5/db.h"; then
+- THIS_PREFIX=$i
+- THIS_INCLUDE=$i/db5/db.h
+- break
+- elif test -f "$i/db4/db.h"; then
+- THIS_PREFIX=$i
+- THIS_INCLUDE=$i/db4/db.h
+- break
+- elif test -f "$i/include/db5.3/db.h"; then
+- THIS_PREFIX=$i
+- THIS_INCLUDE=$i/include/db5.3/db.h
+- break
+- elif test -f "$i/include/db5.1/db.h"; then
+- THIS_PREFIX=$i
+- THIS_INCLUDE=$i/include/db5.1/db.h
+- break
+- elif test -f "$i/include/db5.0/db.h"; then
+- THIS_PREFIX=$i
+- THIS_INCLUDE=$i/include/db5.0/db.h
+- break
+- elif test -f "$i/include/db4.8/db.h"; then
+- THIS_PREFIX=$i
+- THIS_INCLUDE=$i/include/db4.8/db.h
+- break
+- elif test -f "$i/include/db4.7/db.h"; then
+- THIS_PREFIX=$i
+- THIS_INCLUDE=$i/include/db4.7/db.h
+- break
+- elif test -f "$i/include/db4.6/db.h"; then
+- THIS_PREFIX=$i
+- THIS_INCLUDE=$i/include/db4.6/db.h
+- break
+- elif test -f "$i/include/db4.5/db.h"; then
+- THIS_PREFIX=$i
+- THIS_INCLUDE=$i/include/db4.5/db.h
+- break
+- elif test -f "$i/include/db4/db.h"; then
+- THIS_PREFIX=$i
+- THIS_INCLUDE=$i/include/db4/db.h
+- break
+- elif test -f "$i/include/db/db4.h"; then
+- THIS_PREFIX=$i
+- THIS_INCLUDE=$i/include/db/db4.h
+- break
+- elif test -f "$i/include/db4.h"; then
+- THIS_PREFIX=$i
+- THIS_INCLUDE=$i/include/db4.h
+- break
+- elif test -f "$i/include/db.h"; then
++ if test -f "$i/include/db.h"; then
+ THIS_PREFIX=$i
+ THIS_INCLUDE=$i/include/db.h
+ break
+ fi
+ done
+- PHP_DBA_DB_CHECK(4, db-5.3 db-5.1 db-5.0 db-4.8 db-4.7 db-4.6 db-4.5 db-4.4 db-4.3 db-4.2 db-4.1 db-4.0 db-4 db4 db, [(void)db_create((DB**)0, (DB_ENV*)0, 0)])
++ PHP_DBA_DB_CHECK(4, db, [(void)db_create((DB**)0, (DB_ENV*)0, 0)])
+ fi
+ PHP_DBA_STD_RESULT(db4,Berkeley DB4)
+
+diff --git a/ext/dba/dba.c b/ext/dba/dba.c
+index a36c679..b2de3b2 100644
+--- a/ext/dba/dba.c
++++ b/ext/dba/dba.c
+@@ -52,6 +52,10 @@
+ #include "php_qdbm.h"
+ #include "php_tcadb.h"
+
++#ifdef DB4_INCLUDE_FILE
++#include DB4_INCLUDE_FILE
++#endif
++
+ /* {{{ arginfo */
+ ZEND_BEGIN_ARG_INFO_EX(arginfo_dba_popen, 0, 0, 2)
+ ZEND_ARG_INFO(0, path)
+@@ -552,6 +556,10 @@
+
+ php_info_print_table_start();
+ php_info_print_table_row(2, "DBA support", "enabled");
++#ifdef DB_VERSION_STRING
++ php_info_print_table_row(2, "libdb header version", DB_VERSION_STRING);
++ php_info_print_table_row(2, "libdb library version", db_version(NULL, NULL, NULL));
++#endif
+ if (handlers.s) {
+ smart_str_0(&handlers);
+ php_info_print_table_row(2, "Supported handlers", ZSTR_VAL(handlers.s));
+diff --git a/ext/mysqli/config.m4 b/ext/mysqli/config.m4
+index c5dfe5d..87dd43e 100644
+--- a/ext/mysqli/config.m4
++++ b/ext/mysqli/config.m4
+@@ -59,7 +59,7 @@
+ MYSQL_LIB_CFG='--libmysqld-libs'
+ dnl mysqlnd doesn't support embedded, so we have to add some extra stuff
+ mysqli_extra_sources="mysqli_embedded.c"
+- elif test "$enable_maintainer_zts" = "yes"; then
++ elif true || test "$enable_maintainer_zts" = "yes"; then
+ MYSQL_LIB_CFG='--libs_r'
+ MYSQL_LIB_NAME='mysqlclient_r'
+ else
+diff --git a/ext/pdo_mysql/config.m4 b/ext/pdo_mysql/config.m4
+index 96f0441..6828e1d 100755
+--- a/ext/pdo_mysql/config.m4
++++ b/ext/pdo_mysql/config.m4
+@@ -67,7 +67,7 @@
+ if test "x$SED" = "x"; then
+ AC_PATH_PROG(SED, sed)
+ fi
+- if test "$enable_maintainer_zts" = "yes"; then
++ if true || test "$enable_maintainer_zts" = "yes"; then
+ PDO_MYSQL_LIBNAME=mysqlclient_r
+ PDO_MYSQL_LIBS=`$PDO_MYSQL_CONFIG --libs_r | $SED -e "s/'//g"`
+ else
+--- /dev/null
++++ b/tests/func/null-new_val.phpt
+@@ -0,0 +1,10 @@
++--TEST--
++ini_restore strcmp NULL new_val
++--FILE--
++<?php
++
++ini_set('error_log','ini_set_works');
++ini_restore('error_log');
++
++?>
++--EXPECT--
+diff --git a/build/build.mk b/build/build.mk
+index 1ce958f..b8c7492 100644
+--- a/build/build.mk
++++ b/build/build.mk
+@@ -63,6 +63,5 @@
+ @if (test ! -f '.git/info/exclude' || grep -s "git-ls-files" .git/info/exclude); then \
+ (echo "Rebuild .git/info/exclude" && echo '*.o' > .git/info/exclude && git svn propget svn:ignore | grep -v config.nice >> .git/info/exclude); \
+ fi; \
+- git clean -X -f -d;
+
+ .PHONY: $(ALWAYS) snapshot
+diff --git a/ext/dba/config.m4 b/ext/dba/config.m4
+index 64e1661..edc7d11 100644
+--- a/ext/dba/config.m4
++++ b/ext/dba/config.m4
+@@ -113,6 +113,10 @@
+ THIS_PREFIX=$i
+ THIS_INCLUDE=$i/include/depot.h
+ break
++ elif test -f "$i/include/qdbm/depot.h"; then
++ THIS_PREFIX=$i
++ THIS_INCLUDE=$i/include/qdbm/depot.h
++ break
+ fi
+ done
+
+diff --git a/sapi/fpm/php-fpm.8.in b/sapi/fpm/php-fpm.8.in
+index 86edaa8..19e66a0 100644
+--- a/sapi/fpm/php-fpm.8.in
++++ b/sapi/fpm/php-fpm.8.in
+@@ -139,22 +139,8 @@
+ .TP
+ .B php.ini
+ The standard php configuration file.
+-.SH EXAMPLES
+-For any unix systems which use init.d for their main process manager, you should use the init script provided to start and stop the php-fpm daemon.
+-.P
+-.PD 1
+-.RS
+-sudo /etc/init.d/php-fpm start
+-.RE
+-.TP
+-For any unix systems which use systemd for their main process manager, you should use the unit file provided to start and stop the php-fpm daemon.
+-.P
+-.PD 1
+-.RS
+-sudo systemctl start php-fpm.service
+-.RE
+-.TP
+-If your installation has no appropriate init script, launch php-fpm with no arguments. It will launch as a daemon (background process) by default. The file @php_fpm_localstatedir@/run/php-fpm.pid determines whether php-fpm is already up and running. Once started, php-fpm then responds to several POSIX signals:
++.SH SIGNAL
++Once started, php-fpm then responds to several POSIX signals:
+ .P
+ .PD 0
+ .RS
+@@ -168,10 +154,6 @@
+ .RE
+ .PD 1
+ .P
+-.SH TIPS
+-The PHP-FPM CGI daemon will work well with most popular webservers, including Apache2, lighttpd and nginx.
+-.PD 1
+-.P
+ .SH SEE ALSO
+ The PHP-FPM website:
+ .PD 0
+diff --git a/main/streams/plain_wrapper.c b/main/streams/plain_wrapper.c
+index 7fdf906..76dd0dd 100644
+--- a/main/streams/plain_wrapper.c
++++ b/main/streams/plain_wrapper.c
+@@ -693,7 +693,13 @@
+
+ switch (value) {
+ case PHP_STREAM_MMAP_SUPPORTED:
+- return fd == -1 ? PHP_STREAM_OPTION_RETURN_ERR : PHP_STREAM_OPTION_RETURN_OK;
++ if (fd == -1)
++ return PHP_STREAM_OPTION_RETURN_ERR;
++ /* Don't mmap large files */
++ do_fstat(data, 1);
++ if (data->sb.st_size > 4 * 1024 * 1024)
++ return PHP_STREAM_OPTION_RETURN_ERR;
++ return PHP_STREAM_OPTION_RETURN_OK;
+
+ case PHP_STREAM_MMAP_MAP_RANGE:
+ if(do_fstat(data, 1) != 0) {
+diff --git a/ext/dba/dba.c b/ext/dba/dba.c
+index b2de3b2..51c5ccf 100644
+--- a/ext/dba/dba.c
++++ b/ext/dba/dba.c
+@@ -940,7 +940,7 @@
+ }
+ }
+
+- if (error || hptr->open(info, &error) != SUCCESS) {
++ if (error || (hptr->open)(info, &error) != SUCCESS) {
+ dba_close(info);
+ php_error_docref2(NULL, Z_STRVAL(args[0]), Z_STRVAL(args[1]), E_WARNING, "Driver initialization failed for handler: %s%s%s", hptr->name, error?": ":"", error?error:"");
+ FREENOW;
+diff --git a/ext/dba/dba_db3.c b/ext/dba/dba_db3.c
+index dd1bcb8..aca3c93 100644
+--- a/ext/dba/dba_db3.c
++++ b/ext/dba/dba_db3.c
+@@ -96,9 +96,9 @@
+ dbp->set_errcall(dbp, php_dba_db3_errcall_fcn);
+ if(
+ #if (DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1))
+- (err=dbp->open(dbp, 0, info->path, NULL, type, gmode, filemode)) == 0) {
++ (err=(dbp->open)(dbp, 0, info->path, NULL, type, gmode, filemode)) == 0) {
+ #else
+- (err=dbp->open(dbp, info->path, NULL, type, gmode, filemode)) == 0) {
++ (err=(dbp->open)(dbp, info->path, NULL, type, gmode, filemode)) == 0) {
+ #endif
+ dba_db3_data *data;
+
+diff --git a/ext/dba/dba_db4.c b/ext/dba/dba_db4.c
+index 63a69bd..a77cc22 100644
+--- a/ext/dba/dba_db4.c
++++ b/ext/dba/dba_db4.c
+@@ -125,9 +125,9 @@
+ dbp->set_errcall(dbp, php_dba_db4_errcall_fcn);
+ if (
+ #if (DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1))
+- (err=dbp->open(dbp, 0, info->path, NULL, type, gmode, filemode)) == 0) {
++ (err=(dbp->open)(dbp, 0, info->path, NULL, type, gmode, filemode)) == 0) {
+ #else
+- (err=dbp->open(dbp, info->path, NULL, type, gmode, filemode)) == 0) {
++ (err=(dbp->open)(dbp, info->path, NULL, type, gmode, filemode)) == 0) {
+ #endif
+ dba_db4_data *data;
+
+diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c
+index ad825ce..50d8f34 100644
+--- a/ext/zlib/zlib.c
++++ b/ext/zlib/zlib.c
+@@ -49,6 +49,18 @@
+ int le_deflate;
+ int le_inflate;
+
++/*
++ * zlib include files can define the following preprocessor defines which rename
++ * the corresponding PHP functions to gzopen64, gzseek64 and gztell64 and thereby
++ * breaking some software, most notably PEAR's Archive_Tar, which halts execution
++ * without error message on gzip compressed archivesa.
++ *
++ * This only seems to happen on 32bit systems with large file support.
++ */
++#undef gzopen
++#undef gzseek
++#undef gztell
++
+ ZEND_DECLARE_MODULE_GLOBALS(zlib);
+
+ /* {{{ Memory management wrappers */
+diff --git a/ext/standard/tests/strings/setlocale_variation2.phpt b/ext/standard/tests/strings/setlocale_variation2.phpt
+index fad3298..346c987 100644
+--- a/ext/standard/tests/strings/setlocale_variation2.phpt
++++ b/ext/standard/tests/strings/setlocale_variation2.phpt
+@@ -55,6 +55,7 @@
+ //try different locale names
+ $failure_locale = array();
+ $success_count = 0;
++$expected = 0;
+
+ echo "-- Test setlocale() with all available locale in the system --\n";
+ // gather all locales installed in the system(stored $all_system_locales),
+@@ -64,6 +65,10 @@
+ if(setlocale(LC_ALL,$value )){
+ $success_count++;
+ }
++ else if ($value == 'no_NO.ISO-8859-1') {
++ // ignore this one, see rhbz #971416
++ $expected++;
++ }
+ else{
+ //failure values are put in to an array $failure_locale
+ $failure_locale[] = $value;
+@@ -72,11 +77,11 @@
+
+ echo "No of locales found on the machine = ".count($all_system_locales)."\n";
+ echo "No of setlocale() success = ".$success_count."\n";
+-echo "Expected no of failures = 0\n";
++echo "Expected no of failures = $expected\n";
+ echo "Test ";
+ // check if there were any failure of setlocale() function earlier, if any
+ // failure then dump the list of failing locales
+-if($success_count != count($all_system_locales)){
++if($success_count + $expected != count($all_system_locales)){
+ echo "FAILED\n";
+ echo "Names of locale() for which setlocale() failed ...\n";
+ var_dump($failure_locale);
+@@ -92,6 +97,6 @@
+ -- Test setlocale() with all available locale in the system --
+ No of locales found on the machine = %d
+ No of setlocale() success = %d
+-Expected no of failures = 0
++Expected no of failures = %d
+ Test PASSED
+ Done
+diff --git a/ext/pcre/tests/bug37911.phpt b/ext/pcre/tests/bug37911.phpt
+index 2b7481a..0d2859d 100644
+--- a/ext/pcre/tests/bug37911.phpt
++++ b/ext/pcre/tests/bug37911.phpt
+@@ -37,5 +37,5 @@
+ string(4) "blub"
+ }
+
+-Warning: preg_replace_callback(): Compilation failed: group name must start with a non-digit at offset %d in %sbug37911.php on line %d
++Warning: preg_replace_callback(): Numeric named subpatterns are not allowed in %sbug37911.php on line %d
+ NULL
+diff --git a/ext/pcre/tests/grep2.phpt b/ext/pcre/tests/grep2.phpt
+index 1a8476c..0cf8d4a 100644
+--- a/ext/pcre/tests/grep2.phpt
++++ b/ext/pcre/tests/grep2.phpt
+@@ -40,12 +40,6 @@
+ string(1) "1"
+ }
+ bool(true)
+-array(3) {
+- [5]=>
+- string(1) "a"
+- ["xyz"]=>
+- string(2) "q6"
+- [6]=>
+- string(3) "h20"
++array(0) {
+ }
+-bool(false)
++bool(true)
+diff --git a/ext/pcre/tests/match_flags3.phpt b/ext/pcre/tests/match_flags3.phpt
+index 695f0c1..05c62a0 100644
+--- a/ext/pcre/tests/match_flags3.phpt
++++ b/ext/pcre/tests/match_flags3.phpt
+@@ -41,5 +41,5 @@
+ }
+ }
+
+-Warning: preg_match(): Compilation failed: group name must start with a non-digit at offset %d in %smatch_flags3.php on line %d
++Warning: preg_match(): Numeric named subpatterns are not allowed in %smatch_flags3.php on line %d
+ bool(false)
+diff --git a/ext/curl/config.m4 b/ext/curl/config.m4
+index 1ad688f..59fb585 100644
+--- a/ext/curl/config.m4
++++ b/ext/curl/config.m4
+@@ -6,12 +6,12 @@
+ [ --with-curl[=DIR] Include cURL support])
+
+ if test "$PHP_CURL" != "no"; then
+- if test -r $PHP_CURL/include/curl/easy.h; then
++ if test -r $PHP_CURL/include/$DEB_HOST_MULTIARCH/curl/easy.h || test -r $PHP_CURL/include/curl/easy.h; then
+ CURL_DIR=$PHP_CURL
+ else
+ AC_MSG_CHECKING(for cURL in default path)
+ for i in /usr/local /usr; do
+- if test -r $i/include/curl/easy.h; then
++ if test -r $i/include/$DEB_HOST_MULTIARCH/curl/easy.h || test -r $i/include/curl/easy.h; then
+ CURL_DIR=$i
+ AC_MSG_RESULT(found in $i)
+ break
+diff --git a/ext/readline/config.m4 b/ext/readline/config.m4
+index d63df8b..62e873b 100644
+--- a/ext/readline/config.m4
++++ b/ext/readline/config.m4
+@@ -67,6 +67,13 @@
+ -L$READLINE_DIR/$PHP_LIBDIR $PHP_READLINE_LIBS
+ ])
+
++ PHP_CHECK_LIBRARY(readline, rl_completion_matches,
++ [
++ AC_DEFINE(HAVE_RL_COMPLETION_MATCHES, 1, [ ])
++ ],[],[
++ -L$READLINE_DIR/$PHP_LIBDIR $PHP_READLINE_LIBS
++ ])
++
+ AC_DEFINE(HAVE_LIBREADLINE, 1, [ ])
+
+ elif test "$PHP_LIBEDIT" != "no"; then
+@@ -114,11 +121,17 @@
+ -L$READLINE_DIR/$PHP_LIBDIR
+ ])
+
++ PHP_CHECK_LIBRARY(edit, rl_completion_matches,
++ [
++ AC_DEFINE(HAVE_RL_COMPLETION_MATCHES, 1, [ ])
++ ],[],[
++ -L$READLINE_DIR/$PHP_LIBDIR $PHP_READLINE_LIBS
++ ])
++
+ AC_DEFINE(HAVE_LIBEDIT, 1, [ ])
+ fi
+
+ if test "$PHP_READLINE" != "no" || test "$PHP_LIBEDIT" != "no"; then
+- AC_CHECK_FUNCS([rl_completion_matches])
+ PHP_NEW_EXTENSION(readline, readline.c readline_cli.c, $ext_shared, cli)
+ PHP_SUBST(READLINE_SHARED_LIBADD)
+ fi
+diff --git a/ext/fileinfo/libmagic/cdf.c b/ext/fileinfo/libmagic/cdf.c
+index 28084fb..01af1e4 100644
+--- a/ext/fileinfo/libmagic/cdf.c
++++ b/ext/fileinfo/libmagic/cdf.c
+@@ -872,8 +872,9 @@
+ i, inp[i].pi_id, inp[i].pi_type, q - p, offs));
+ if (inp[i].pi_type & CDF_VECTOR) {
+ nelements = CDF_GETUINT32(q, 1);
+- if (nelements == 0) {
+- DPRINTF(("CDF_VECTOR with nelements == 0\n"));
++ if (nelements > CDF_ELEMENT_LIMIT || nelements == 0) {
++ DPRINTF(("CDF_VECTOR with nelements == %"
++ SIZE_T_FORMAT "u\n", nelements));
+ goto out;
+ }
+ o = 2;
+@@ -948,8 +949,6 @@
+ *info = inp;
+ inp = *info + nelem;
+ }
+- DPRINTF(("nelements = %" SIZE_T_FORMAT "u\n",
+- nelements));
+ for (j = 0; j < nelements && i < sh.sh_properties;
+ j++, i++)
+ {
+diff --git a/ext/fileinfo/libmagic/cdf.h b/ext/fileinfo/libmagic/cdf.h
+index 9006a68..6ad5bce 100644
+--- a/ext/fileinfo/libmagic/cdf.h
++++ b/ext/fileinfo/libmagic/cdf.h
+@@ -50,6 +50,7 @@
+ typedef int32_t cdf_secid_t;
+
+ #define CDF_LOOP_LIMIT 10000
++#define CDF_ELEMENT_LIMIT 100000
+
+ #define CDF_SECID_NULL 0
+ #define CDF_SECID_FREE -1
+diff --git a/ext/standard/string.c b/ext/standard/string.c
+index 922d4fc..c88135d 100644
+--- a/ext/standard/string.c
++++ b/ext/standard/string.c
+@@ -4781,7 +4781,7 @@
+ if (state == 4) {
+ /* Inside <!-- comment --> */
+ break;
+- } else if (state == 2 && *(p-1) != '\\') {
++ } else if (state == 2 && p >= buf + 1 && *(p-1) != '\\') {
+ if (lc == c) {
+ lc = '\0';
+ } else if (lc != '\\') {
+@@ -4808,7 +4808,7 @@
+
+ case '!':
+ /* JavaScript & Other HTML scripting languages */
+- if (state == 1 && *(p-1) == '<') {
++ if (state == 1 && p >= buf + 1 && *(p-1) == '<') {
+ state = 3;
+ lc = c;
+ } else {
+@@ -4835,7 +4835,7 @@
+
+ case '?':
+
+- if (state == 1 && *(p-1) == '<') {
++ if (state == 1 && p >= buf + 1 && *(p-1) == '<') {
+ br=0;
+ state=2;
+ break;
+--- /dev/null
++++ b/ext/standard/tests/file/bug79099.phpt
+@@ -0,0 +1,32 @@
++--TEST--
++Bug #79099 (OOB read in php_strip_tags_ex)
++--FILE--
++<?php
++$stream = fopen('php://memory', 'w+');
++fputs($stream, "<?\n\"\n");
++rewind($stream);
++var_dump(fgetss($stream));
++var_dump(fgetss($stream));
++fclose($stream);
++
++$stream = fopen('php://memory', 'w+');
++fputs($stream, "<\0\n!\n");
++rewind($stream);
++var_dump(fgetss($stream));
++var_dump(fgetss($stream));
++fclose($stream);
++
++$stream = fopen('php://memory', 'w+');
++fputs($stream, "<\0\n?\n");
++rewind($stream);
++var_dump(fgetss($stream));
++var_dump(fgetss($stream));
++fclose($stream);
++?>
++--EXPECT--
++string(0) ""
++string(0) ""
++string(0) ""
++string(0) ""
++string(0) ""
++string(0) ""
+diff --git a/ext/mbstring/libmbfl/filters/mbfilter_big5.c b/ext/mbstring/libmbfl/filters/mbfilter_big5.c
+index f5ab880..5e1ca81 100644
+--- a/ext/mbstring/libmbfl/filters/mbfilter_big5.c
++++ b/ext/mbstring/libmbfl/filters/mbfilter_big5.c
+@@ -138,6 +138,17 @@
+ {0xf70f,0xf848,0xc740,0xc8fe},
+ };
+
++static inline int is_in_cp950_pua(int c1, int c) {
++ if ((c1 >= 0xfa && c1 <= 0xfe) || (c1 >= 0x8e && c1 <= 0xa0) ||
++ (c1 >= 0x81 && c1 <= 0x8d) || (c1 >= 0xc7 && c1 <= 0xc8)) {
++ return (c >=0x40 && c <= 0x7e) || (c >= 0xa1 && c <= 0xfe);
++ }
++ if (c1 == 0xc6) {
++ return c >= 0xa1 && c <= 0xfe;
++ }
++ return 0;
++}
++
+ /*
+ * Big5 => wchar
+ */
+@@ -186,11 +197,7 @@
+
+ if (filter->from->no_encoding == mbfl_no_encoding_cp950) {
+ /* PUA for CP950 */
+- if (w <= 0 &&
+- (((c1 >= 0xfa && c1 <= 0xfe) || (c1 >= 0x8e && c1 <= 0xa0) ||
+- (c1 >= 0x81 && c1 <= 0x8d) ||(c1 >= 0xc7 && c1 <= 0xc8))
+- && ((c > 0x39 && c < 0x7f) || (c > 0xa0 && c < 0xff))) ||
+- ((c1 == 0xc6) && (c > 0xa0 && c < 0xff))) {
++ if (w <= 0 && is_in_cp950_pua(c1, c)) {
+ c2 = c1 << 8 | c;
+ for (k = 0; k < sizeof(cp950_pua_tbl)/(sizeof(unsigned short)*4); k++) {
+ if (c2 >= cp950_pua_tbl[k][2] && c2 <= cp950_pua_tbl[k][3]) {
+--- /dev/null
++++ b/ext/mbstring/tests/bug79037.phpt
+@@ -0,0 +1,10 @@
++--TEST--
++Bug #79037: global buffer-overflow in `mbfl_filt_conv_big5_wchar`
++--FILE--
++<?php
++
++var_dump(mb_convert_encoding("\x81\x3a", "UTF-8", "CP950"));
++
++?>
++--EXPECT--
++string(1) "?"
+diff --git a/ext/standard/string.c b/ext/standard/string.c
+index c88135d..018e919 100644
+--- a/ext/standard/string.c
++++ b/ext/standard/string.c
+@@ -4731,7 +4731,7 @@
+ switch (state) {
+ case 1: /* HTML/XML */
+ lc = '>';
+- if (is_xml && *(p -1) == '-') {
++ if (is_xml && p >= buf + 1 && *(p-1) == '-') {
+ break;
+ }
+ in_q = state = is_xml = 0;
+@@ -4752,7 +4752,7 @@
+ break;
+
+ case 2: /* PHP */
+- if (!br && lc != '\"' && *(p-1) == '?') {
++ if (!br && lc != '\"' && p >= buf + 1 && *(p-1) == '?') {
+ in_q = state = 0;
+ tp = tbuf;
+ }
+diff --git a/ext/session/session.c b/ext/session/session.c
+index bf8797a..d3226ee 100644
+--- a/ext/session/session.c
++++ b/ext/session/session.c
+@@ -2999,9 +2999,11 @@
+ if (PS(rfc1867_cleanup)) {
+ php_session_rfc1867_cleanup(progress);
+ } else {
+- add_assoc_bool_ex(&progress->data, "done", sizeof("done") - 1, 1);
+- Z_LVAL_P(progress->post_bytes_processed) = data->post_bytes_processed;
+- php_session_rfc1867_update(progress, 1);
++ if (!Z_ISUNDEF(progress->data)) {
++ add_assoc_bool_ex(&progress->data, "done", sizeof("done") - 1, 1);
++ Z_LVAL_P(progress->post_bytes_processed) = data->post_bytes_processed;
++ php_session_rfc1867_update(progress, 1);
++ }
+ }
+ php_rshutdown_session_globals();
+ }
+--- /dev/null
++++ b/ext/session/tests/bug79221.phpt
+@@ -0,0 +1,45 @@
++--TEST--
++Null Pointer Dereference in PHP Session Upload Progress
++--INI--
++error_reporting=0
++file_uploads=1
++upload_max_filesize=1024
++session.save_path=
++session.name=PHPSESSID
++session.serialize_handler=php
++session.use_strict_mode=0
++session.use_cookies=1
++session.use_only_cookies=0
++session.upload_progress.enabled=1
++session.upload_progress.cleanup=0
++session.upload_progress.prefix=upload_progress_
++session.upload_progress.name=PHP_SESSION_UPLOAD_PROGRESS
++session.upload_progress.freq=1%
++session.upload_progress.min_freq=0.000000001
++--COOKIE--
++PHPSESSID=session-upload
++--POST_RAW--
++Content-Type: multipart/form-data; boundary=---------------------------20896060251896012921717172737
++-----------------------------20896060251896012921717172737
++Content-Disposition: form-data; name="PHPSESSID"
++
++session-upload
++-----------------------------20896060251896012921717172737
++Content-Disposition: form-data; name="PHP_SESSION_UPLOAD_PROGRESS"
++
++ryat
++-----------------------------20896060251896012921717172737
++Content-Disposition: form-data; file="file"; ryat="filename"
++
++1
++-----------------------------20896060251896012921717172737--
++--FILE--
++<?php
++
++session_start();
++var_dump($_SESSION);
++session_destroy();
++
++--EXPECTF--
++array(0) {
++}
+diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c
+index c1ba97a..b22a6ac 100644
+--- a/ext/phar/phar_object.c
++++ b/ext/phar/phar_object.c
+@@ -1439,6 +1439,7 @@
+ char *str_key;
+ zend_class_entry *ce = p_obj->c;
+ phar_archive_object *phar_obj = p_obj->p;
++ php_stream_statbuf ssb;
+
+ value = iter->funcs->get_current_data(iter);
+
+@@ -1718,6 +1719,16 @@
+ php_stream_copy_to_stream_ex(fp, p_obj->fp, PHP_STREAM_COPY_ALL, &contents_len);
+ data->internal_file->uncompressed_filesize = data->internal_file->compressed_filesize =
+ php_stream_tell(p_obj->fp) - data->internal_file->offset;
++ if (php_stream_stat(fp, &ssb) != -1) {
++ data->internal_file->flags = ssb.sb.st_mode & PHAR_ENT_PERM_MASK ;
++ } else {
++#ifndef _WIN32
++ mode_t mask;
++ mask = umask(0);
++ umask(mask);
++ data->internal_file->flags &= ~mask;
++#endif
++ }
+ }
+
+ if (close_fp) {
+--- /dev/null
++++ b/ext/phar/tests/bug79082.phpt
+@@ -0,0 +1,52 @@
++--TEST--
++Phar: Bug #79082: Files added to tar with Phar::buildFromIterator have all-access permissions
++--SKIPIF--
++<?php
++if (!extension_loaded("phar")) die("skip");
++if (defined("PHP_WINDOWS_VERSION_MAJOR")) die("skip not for Windows")
++?>
++--FILE--
++<?php
++umask(022);
++var_dump(decoct(umask()));
++chmod(__DIR__ . '/test79082/test79082-testfile', 0644);
++chmod(__DIR__ . '/test79082/test79082-testfile2', 0400);
++
++foreach([Phar::TAR => 'tar', Phar::ZIP => 'zip'] as $mode => $ext) {
++ clearstatcache();
++ $phar = new PharData(__DIR__ . '/test79082.' . $ext, null, null, $mode);
++ $phar->buildFromIterator(new \RecursiveDirectoryIterator(__DIR__ . '/test79082', \FilesystemIterator::SKIP_DOTS), __DIR__ . '/test79082');
++ $phar->extractTo(__DIR__);
++ var_dump(decoct(stat(__DIR__ . '/test79082-testfile')['mode']));
++ var_dump(decoct(stat(__DIR__ . '/test79082-testfile2')['mode']));
++ unlink(__DIR__ . '/test79082-testfile');
++ unlink(__DIR__ . '/test79082-testfile2');
++}
++foreach([Phar::TAR => 'tar', Phar::ZIP => 'zip'] as $mode => $ext) {
++ clearstatcache();
++ $phar = new PharData(__DIR__ . '/test79082-d.' . $ext, null, null, $mode);
++ $phar->buildFromDirectory(__DIR__ . '/test79082');
++ $phar->extractTo(__DIR__);
++ var_dump(decoct(stat(__DIR__ . '/test79082-testfile')['mode']));
++ var_dump(decoct(stat(__DIR__ . '/test79082-testfile2')['mode']));
++ unlink(__DIR__ . '/test79082-testfile');
++ unlink(__DIR__ . '/test79082-testfile2');
++}
++?>
++--CLEAN--
++<?
++unlink(__DIR__ . '/test79082.tar');
++unlink(__DIR__ . '/test79082.zip');
++unlink(__DIR__ . '/test79082-d.tar');
++unlink(__DIR__ . '/test79082-d.zip');
++?>
++--EXPECT--
++string(2) "22"
++string(6) "100644"
++string(6) "100400"
++string(6) "100644"
++string(6) "100400"
++string(6) "100644"
++string(6) "100400"
++string(6) "100644"
++string(6) "100400"
+--- /dev/null
++++ b/ext/phar/tests/test79082/test79082-testfile
+@@ -0,0 +1 @@
++test
+--- /dev/null
++++ b/ext/phar/tests/test79082/test79082-testfile2
+@@ -0,0 +1 @@
++test
+diff --git a/ext/exif/exif.c b/ext/exif/exif.c
+index 406fee4..9130cea 100644
+--- a/ext/exif/exif.c
++++ b/ext/exif/exif.c
+@@ -3243,6 +3243,11 @@
+ {
+ unsigned exif_value_2a, offset_of_ifd;
+
++ if (length < 2) {
++ exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_WARNING, "Missing TIFF alignment marker");
++ return;
++ }
++
+ /* set the thumbnail stuff to nothing so we can test to see if they get set up */
+ if (memcmp(CharBuf, "II", 2) == 0) {
+ ImageInfo->motorola_intel = 0;
+@@ -3395,7 +3400,7 @@
+ return FALSE;
+ }
+
+- sn = exif_file_sections_add(ImageInfo, marker, itemlen+1, NULL);
++ sn = exif_file_sections_add(ImageInfo, marker, itemlen, NULL);
+ Data = ImageInfo->file.list[sn].data;
+
+ /* Store first two pre-read bytes. */
+--- /dev/null
++++ b/ext/exif/tests/bug79282.phpt
+@@ -0,0 +1,15 @@
++--TEST--
++Bug #79282: Use-of-uninitialized-value in exif
++--FILE--
++<?php
++
++var_dump(exif_read_data('data://image/jpeg;base64,/9jhAAlFeGlmAAAg'));
++
++?>
++--EXPECTF--
++Warning: exif_read_data(): Invalid TIFF alignment marker in %s on line %d
++
++Warning: exif_read_data(): File structure corrupted in %s on line %d
++
++Warning: exif_read_data(): Invalid JPEG file in %s on line %d
++bool(false)
+diff --git a/ext/standard/exec.c b/ext/standard/exec.c
+index 8af1180..02d9539 100644
+--- a/ext/standard/exec.c
++++ b/ext/standard/exec.c
+@@ -524,6 +524,15 @@
+ return;
+ }
+
++ if (!command_len) {
++ php_error_docref(NULL, E_WARNING, "Cannot execute a blank command");
++ RETURN_FALSE;
++ }
++ if (strlen(command) != command_len) {
++ php_error_docref(NULL, E_WARNING, "NULL byte detected. Possible attack");
++ RETURN_FALSE;
++ }
++
+ #ifdef PHP_WIN32
+ if ((in=VCWD_POPEN(command, "rt"))==NULL) {
+ #else
+diff --git a/ext/standard/url.c b/ext/standard/url.c
+index 39e5b1b..4cc1f77 100644
+--- a/ext/standard/url.c
++++ b/ext/standard/url.c
+@@ -540,7 +540,7 @@
+ #ifndef CHARSET_EBCDIC
+ *dest = (char) php_htoi(data + 1);
+ #else
+- *dest = os_toebcdic[(char) php_htoi(data + 1)];
++ *dest = os_toebcdic[(unsigned char) php_htoi(data + 1)];
+ #endif
+ data += 2;
+ len -= 2;
+@@ -632,7 +632,7 @@
+ #ifndef CHARSET_EBCDIC
+ *dest = (char) php_htoi(data + 1);
+ #else
+- *dest = os_toebcdic[(char) php_htoi(data + 1)];
++ *dest = os_toebcdic[(unsigned char) php_htoi(data + 1)];
+ #endif
+ data += 2;
+ len -= 2;
+diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c
+index cdf77f2..8f0c5db 100644
+--- a/ext/zip/php_zip.c
++++ b/ext/zip/php_zip.c
+@@ -1454,6 +1454,21 @@
+ ze_obj->filename = NULL;
+ }
+
++#if LIBZIP_VERSION_MAJOR > 1 || LIBZIP_VERSION_MAJOR == 1 && LIBZIP_VERSION_MINOR >= 6
++ /* reduce BC break introduce in libzip 1.6.0
++ "Do not accept empty files as valid zip archives any longer" */
++
++ /* open for write without option to empty the archive */
++ if ((flags & (ZIP_TRUNCATE | ZIP_RDONLY)) == 0) {
++ zend_stat_t st;
++
++ /* exists and is empty */
++ if (VCWD_STAT(resolved_path, &st) == 0 && st.st_size == 0) {
++ flags |= ZIP_TRUNCATE;
++ }
++ }
++#endif
++
+ intern = zip_open(resolved_path, flags, &err);
+ if (!intern || err) {
+ efree(resolved_path);
+diff --git a/main/rfc1867.c b/main/rfc1867.c
+index b930e07..14ffbea 100644
+--- a/main/rfc1867.c
++++ b/main/rfc1867.c
+@@ -692,7 +692,8 @@
+ char *boundary, *s = NULL, *boundary_end = NULL, *start_arr = NULL, *array_index = NULL;
+ char *lbuf = NULL, *abuf = NULL;
+ zend_string *temp_filename = NULL;
+- int boundary_len = 0, cancel_upload = 0, is_arr_upload = 0, array_len = 0;
++ int boundary_len = 0, cancel_upload = 0, is_arr_upload = 0;
++ size_t array_len = 0;
+ int64_t total_bytes = 0, max_file_size = 0;
+ int skip_upload = 0, anonindex = 0, is_anonymous;
+ HashTable *uploaded_files = NULL;
+@@ -1126,7 +1127,7 @@
+ is_arr_upload = (start_arr = strchr(param,'[')) && (param[strlen(param)-1] == ']');
+
+ if (is_arr_upload) {
+- array_len = (int)strlen(start_arr);
++ array_len = strlen(start_arr);
+ if (array_index) {
+ efree(array_index);
+ }
+diff --git a/main/rfc1867.c b/main/rfc1867.c
+index 14ffbea..1742b9c 100644
+--- a/main/rfc1867.c
++++ b/main/rfc1867.c
+@@ -616,7 +616,7 @@
+ }
+
+ /* read until a boundary condition */
+-static int multipart_buffer_read(multipart_buffer *self, char *buf, size_t bytes, int *end)
++static size_t multipart_buffer_read(multipart_buffer *self, char *buf, size_t bytes, int *end)
+ {
+ size_t len, max;
+ char *bound;
+@@ -655,7 +655,7 @@
+ self->buf_begin += len;
+ }
+
+- return (int)len;
++ return len;
+ }
+
+ /*
+@@ -665,7 +665,7 @@
+ static char *multipart_buffer_read_body(multipart_buffer *self, size_t *len)
+ {
+ char buf[FILLUNIT], *out=NULL;
+- int total_bytes=0, read_bytes=0;
++ size_t total_bytes=0, read_bytes=0;
+
+ while((read_bytes = multipart_buffer_read(self, buf, sizeof(buf), NULL))) {
+ out = erealloc(out, total_bytes + read_bytes + 1);
+diff --git a/NEWS b/NEWS
+index 15bf59b..74fbea5 100644
+--- a/NEWS
++++ b/NEWS
+@@ -3,6 +3,10 @@
+
+ Backported from 7.2.33
+
++- Core:
++ . Fixed bug #79877 (getimagesize function silently truncates after a null
++ byte) (cmb)
++
+ - Phar:
+ . Fixed bug #79797 (Use of freed hash key in the phar_parse_zipfile
+ function). (CVE-2020-7068) (cmb)
+diff --git a/ext/standard/image.c b/ext/standard/image.c
+index 1d999ca..a5a86c2 100644
+--- a/ext/standard/image.c
++++ b/ext/standard/image.c
+@@ -1474,6 +1474,11 @@
+ return;
+ }
+
++ if (mode == FROM_PATH && CHECK_NULL_PATH(input, input_len)) {
++ php_error_docref(NULL, E_WARNING, "Invalid path");
++ return;
++ }
++
+ if (argc == 2) {
+ zval_dtor(info);
+ array_init(info);
+--- /dev/null
++++ b/ext/standard/tests/image/bug79877.phpt
+@@ -0,0 +1,9 @@
++--TEST--
++Bug #79877 (getimagesize function silently truncates after a null byte)
++--FILE--
++<?php
++var_dump(getimagesize("/tmp/a.png\0xx"));
++?>
++--EXPECTF--
++Warning: getimagesize(): Invalid path in %s on line %d
++NULL
+diff --git a/main/php_variables.c b/main/php_variables.c
+index c56d230..d0223df 100644
+--- a/main/php_variables.c
++++ b/main/php_variables.c
+@@ -484,7 +484,9 @@
+ size_t new_val_len;
+
+ *val++ = '\0';
+- php_url_decode(var, strlen(var));
++ if (arg != PARSE_COOKIE) {
++ php_url_decode(var, strlen(var));
++ }
+ val_len = php_url_decode(val, strlen(val));
+ val = estrndup(val, val_len);
+ if (sapi_module.input_filter(arg, var, &val, val_len, &new_val_len)) {
+@@ -495,7 +497,9 @@
+ size_t val_len;
+ size_t new_val_len;
+
+- php_url_decode(var, strlen(var));
++ if (arg != PARSE_COOKIE) {
++ php_url_decode(var, strlen(var));
++ }
+ val_len = 0;
+ val = estrndup("", val_len);
+ if (sapi_module.input_filter(arg, var, &val, val_len, &new_val_len)) {
+diff --git a/tests/basic/022.phpt b/tests/basic/022.phpt
+index 0ab70d4..bd1db13 100644
+--- a/tests/basic/022.phpt
++++ b/tests/basic/022.phpt
+@@ -10,7 +10,7 @@
+ var_dump($_COOKIE);
+ ?>
+ --EXPECT--
+-array(10) {
++array(12) {
+ ["cookie1"]=>
+ string(6) "val1 "
+ ["cookie2"]=>
+@@ -19,11 +19,15 @@
+ string(6) "val 3."
+ ["cookie_4"]=>
+ string(10) " value 4 ;"
++ ["%20cookie1"]=>
++ string(6) "ignore"
++ ["+cookie1"]=>
++ string(6) "ignore"
+ ["cookie__5"]=>
+ string(7) " value"
+- ["cookie_6"]=>
++ ["cookie%206"]=>
+ string(3) "þæö"
+- ["cookie_7"]=>
++ ["cookie+7"]=>
+ string(0) ""
+ ["$cookie_8"]=>
+ string(0) ""
+diff --git a/tests/basic/023.phpt b/tests/basic/023.phpt
+index ca5f1dc..0e2e0ac 100644
+--- a/tests/basic/023.phpt
++++ b/tests/basic/023.phpt
+@@ -10,9 +10,11 @@
+ var_dump($_COOKIE);
+ ?>
+ --EXPECT--
+-array(3) {
++array(4) {
+ ["c_o_o_k_i_e"]=>
+ string(5) "value"
++ ["c%20o+o_k+i%20e"]=>
++ string(1) "v"
+ ["name"]=>
+ string(24) ""value","value",UEhQIQ=="
+ ["UEhQIQ"]=>
+--- /dev/null
++++ b/tests/basic/bug79699.phpt
+@@ -0,0 +1,22 @@
++--TEST--
++Cookies Security Bug
++--INI--
++max_input_vars=1000
++filter.default=unsafe_raw
++--COOKIE--
++__%48ost-evil=evil; __Host-evil=good; %66oo=baz;foo=bar
++--FILE--
++<?php
++var_dump($_COOKIE);
++?>
++--EXPECT--
++array(4) {
++ ["__%48ost-evil"]=>
++ string(4) "evil"
++ ["__Host-evil"]=>
++ string(4) "good"
++ ["%66oo"]=>
++ string(3) "baz"
++ ["foo"]=>
++ string(3) "bar"
++}
+diff --git a/ext/standard/tests/strings/url_t.phpt b/ext/standard/tests/strings/url_t.phpt
+index 79ff3bc..f564f59 100644
+--- a/ext/standard/tests/strings/url_t.phpt
++++ b/ext/standard/tests/strings/url_t.phpt
+@@ -575,15 +575,13 @@
+ string(16) "some_page_ref123"
+ }
+
+---> http://secret@hideout@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123: array(7) {
++--> http://secret@hideout@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123: array(6) {
+ ["scheme"]=>
+ string(4) "http"
+ ["host"]=>
+- string(11) "www.php.net"
++ string(26) "secret@hideout@www.php.net"
+ ["port"]=>
+ int(80)
+- ["user"]=>
+- string(14) "secret@hideout"
+ ["path"]=>
+ string(10) "/index.php"
+ ["query"]=>
+--- /dev/null
++++ b/ext/standard/tests/url/bug77423.phpt
+@@ -0,0 +1,30 @@
++--TEST--
++Bug #77423 (parse_url() will deliver a wrong host to user)
++--FILE--
++<?php
++$urls = array(
++ "http://php.net\@aliyun.com/aaa.do",
++ "https://example.com\uFF03@bing.com",
++);
++foreach ($urls as $url) {
++ var_dump(filter_var($url, FILTER_VALIDATE_URL));
++ var_dump(parse_url($url));
++}
++?>
++--EXPECT--
++bool(false)
++array(3) {
++ ["scheme"]=>
++ string(4) "http"
++ ["host"]=>
++ string(19) "php.net\@aliyun.com"
++ ["path"]=>
++ string(7) "/aaa.do"
++}
++bool(false)
++array(2) {
++ ["scheme"]=>
++ string(5) "https"
++ ["host"]=>
++ string(26) "example.com\uFF03@bing.com"
++}
+diff --git a/ext/standard/tests/url/parse_url_basic_001.phpt b/ext/standard/tests/url/parse_url_basic_001.phpt
+index 4606849..5101099 100644
+--- a/ext/standard/tests/url/parse_url_basic_001.phpt
++++ b/ext/standard/tests/url/parse_url_basic_001.phpt
+@@ -506,15 +506,13 @@
+ string(16) "some_page_ref123"
+ }
+
+---> http://secret@hideout@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123: array(7) {
++--> http://secret@hideout@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123: array(6) {
+ ["scheme"]=>
+ string(4) "http"
+ ["host"]=>
+- string(11) "www.php.net"
++ string(26) "secret@hideout@www.php.net"
+ ["port"]=>
+ int(80)
+- ["user"]=>
+- string(14) "secret@hideout"
+ ["path"]=>
+ string(10) "/index.php"
+ ["query"]=>
+diff --git a/ext/standard/tests/url/parse_url_basic_003.phpt b/ext/standard/tests/url/parse_url_basic_003.phpt
+index 3d5a4a3..7968fd3 100644
+--- a/ext/standard/tests/url/parse_url_basic_003.phpt
++++ b/ext/standard/tests/url/parse_url_basic_003.phpt
+@@ -68,7 +68,7 @@
+ --> http://secret:@www.php.net/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123 : string(11) "www.php.net"
+ --> http://:hideout@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123 : string(11) "www.php.net"
+ --> http://secret:hideout@www.php.net/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123 : string(11) "www.php.net"
+---> http://secret@hideout@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123 : string(11) "www.php.net"
++--> http://secret@hideout@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123 : string(26) "secret@hideout@www.php.net"
+ --> http://secret:hid:out@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123 : string(11) "www.php.net"
+ --> nntp://news.php.net : string(12) "news.php.net"
+ --> ftp://ftp.gnu.org/gnu/glic/glibc.tar.gz : string(11) "ftp.gnu.org"
+diff --git a/ext/standard/tests/url/parse_url_basic_005.phpt b/ext/standard/tests/url/parse_url_basic_005.phpt
+index aefb339..ba778bf 100644
+--- a/ext/standard/tests/url/parse_url_basic_005.phpt
++++ b/ext/standard/tests/url/parse_url_basic_005.phpt
+@@ -68,7 +68,7 @@
+ --> http://secret:@www.php.net/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123 : string(6) "secret"
+ --> http://:hideout@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123 : string(0) ""
+ --> http://secret:hideout@www.php.net/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123 : string(6) "secret"
+---> http://secret@hideout@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123 : string(14) "secret@hideout"
++--> http://secret@hideout@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123 : NULL
+ --> http://secret:hid:out@www.php.net:80/index.php?test=1&test2=char&test3=mixesCI#some_page_ref123 : string(6) "secret"
+ --> nntp://news.php.net : NULL
+ --> ftp://ftp.gnu.org/gnu/glic/glibc.tar.gz : NULL
+diff --git a/ext/standard/url.c b/ext/standard/url.c
+index 4cc1f77..d56dc24 100644
+--- a/ext/standard/url.c
++++ b/ext/standard/url.c
+@@ -92,6 +92,22 @@
+ return php_url_parse_ex(str, strlen(str));
+ }
+
++static int is_userinfo_valid(const char *str, size_t len)
++{
++ char *valid = "-._~!$&'()*+,;=:";
++ char *p = str;
++ while (p - str < len) {
++ if (isalpha(*p) || isdigit(*p) || strchr(valid, *p)) {
++ p++;
++ } else if (*p == '%' && p - str <= len - 3 && isdigit(*(p+1)) && isxdigit(*(p+2))) {
++ p += 3;
++ } else {
++ return 0;
++ }
++ }
++ return 1;
++}
++
+ /* {{{ php_url_parse
+ */
+ PHPAPI php_url *php_url_parse_ex(char const *str, size_t length)
+@@ -235,13 +251,18 @@
+ ret->pass = estrndup(pp, (p-pp));
+ php_replace_controlchars_ex(ret->pass, (p-pp));
+ } else {
++ if (!is_userinfo_valid(s, p-s)) {
++ goto check_port;
++ }
+ ret->user = estrndup(s, (p-s));
+ php_replace_controlchars_ex(ret->user, (p-s));
++
+ }
+
+ s = p + 1;
+ }
+
++check_port:
+ /* check for port */
+ if (s < ue && *s == '[' && *(e-1) == ']') {
+ /* Short circuit portscan,
+diff --git a/ext/imap/php_imap.c b/ext/imap/php_imap.c
+index 6ce4b78..7de074a 100644
+--- a/ext/imap/php_imap.c
++++ b/ext/imap/php_imap.c
+@@ -3531,6 +3531,23 @@
+ }
+ /* }}} */
+
++static zend_bool header_injection(zend_string *str, zend_bool adrlist)
++{
++ char *p = ZSTR_VAL(str);
++
++ while ((p = strpbrk(p, "\r\n")) != NULL) {
++ if (!(p[0] == '\r' && p[1] == '\n')
++ /* adrlists do not support folding, but swallow trailing line breaks */
++ && !((adrlist && p[1] == '\0')
++ /* other headers support folding */
++ || !adrlist && (p[1] == ' ' || p[1] == '\t'))) {
++ return 1;
++ }
++ p++;
++ }
++ return 0;
++}
++
+ /* {{{ proto string imap_mail_compose(array envelope, array body)
+ Create a MIME message based on given envelope and body sections */
+ PHP_FUNCTION(imap_mail_compose)
+@@ -3551,6 +3568,13 @@
+ return;
+ }
+
++#define CHECK_HEADER_INJECTION(zstr, adrlist, header) \
++ if (header_injection(zstr, adrlist)) { \
++ php_error_docref(NULL, E_WARNING, "header injection attempt in " header); \
++ RETVAL_FALSE; \
++ goto done; \
++ }
++
+ #define PHP_RFC822_PARSE_ADRLIST(target, value) \
+ str_copy = estrndup(Z_STRVAL_P(value), Z_STRLEN_P(value)); \
+ rfc822_parse_adrlist(target, str_copy, "NO HOST"); \
+@@ -3559,46 +3583,57 @@
+ env = mail_newenvelope();
+ if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(envelope), "remail", sizeof("remail") - 1)) != NULL) {
+ convert_to_string_ex(pvalue);
++ CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "remail");
+ env->remail = cpystr(Z_STRVAL_P(pvalue));
+ }
+ if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(envelope), "return_path", sizeof("return_path") - 1)) != NULL) {
+ convert_to_string_ex(pvalue);
++ CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 1, "return_path");
+ PHP_RFC822_PARSE_ADRLIST(&env->return_path, pvalue);
+ }
+ if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(envelope), "date", sizeof("date") - 1)) != NULL) {
+ convert_to_string_ex(pvalue);
++ CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "date");
+ env->date = (unsigned char*)cpystr(Z_STRVAL_P(pvalue));
+ }
+ if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(envelope), "from", sizeof("from") - 1)) != NULL) {
+ convert_to_string_ex(pvalue);
++ CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 1, "from");
+ PHP_RFC822_PARSE_ADRLIST(&env->from, pvalue);
+ }
+ if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(envelope), "reply_to", sizeof("reply_to") - 1)) != NULL) {
+ convert_to_string_ex(pvalue);
++ CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 1, "reply_to");
+ PHP_RFC822_PARSE_ADRLIST(&env->reply_to, pvalue);
+ }
+ if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(envelope), "in_reply_to", sizeof("in_reply_to") - 1)) != NULL) {
+ convert_to_string_ex(pvalue);
++ CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "in_reply_to");
+ env->in_reply_to = cpystr(Z_STRVAL_P(pvalue));
+ }
+ if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(envelope), "subject", sizeof("subject") - 1)) != NULL) {
+ convert_to_string_ex(pvalue);
++ CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "subject");
+ env->subject = cpystr(Z_STRVAL_P(pvalue));
+ }
+ if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(envelope), "to", sizeof("to") - 1)) != NULL) {
+ convert_to_string_ex(pvalue);
++ CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 1, "to");
+ PHP_RFC822_PARSE_ADRLIST(&env->to, pvalue);
+ }
+ if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(envelope), "cc", sizeof("cc") - 1)) != NULL) {
+ convert_to_string_ex(pvalue);
++ CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 1, "cc");
+ PHP_RFC822_PARSE_ADRLIST(&env->cc, pvalue);
+ }
+ if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(envelope), "bcc", sizeof("bcc") - 1)) != NULL) {
+ convert_to_string_ex(pvalue);
++ CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 1, "bcc");
+ PHP_RFC822_PARSE_ADRLIST(&env->bcc, pvalue);
+ }
+ if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(envelope), "message_id", sizeof("message_id") - 1)) != NULL) {
+ convert_to_string_ex(pvalue);
++ CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "message_id");
+ env->message_id=cpystr(Z_STRVAL_P(pvalue));
+ }
+
+@@ -3608,6 +3643,7 @@
+ ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(pvalue), env_data) {
+ custom_headers_param = mail_newbody_parameter();
+ convert_to_string_ex(env_data);
++ CHECK_HEADER_INJECTION(Z_STR_P(env_data), 0, "custom_headers");
+ custom_headers_param->value = (char *) fs_get(Z_STRLEN_P(env_data) + 1);
+ custom_headers_param->attribute = NULL;
+ memcpy(custom_headers_param->value, Z_STRVAL_P(env_data), Z_STRLEN_P(env_data) + 1);
+@@ -3640,6 +3676,7 @@
+ }
+ if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "charset", sizeof("charset") - 1)) != NULL) {
+ convert_to_string_ex(pvalue);
++ CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body charset");
+ tmp_param = mail_newbody_parameter();
+ tmp_param->value = cpystr(Z_STRVAL_P(pvalue));
+ tmp_param->attribute = cpystr("CHARSET");
+@@ -3650,9 +3687,11 @@
+ if(Z_TYPE_P(pvalue) == IS_ARRAY) {
+ disp_param = tmp_param = NULL;
+ ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(pvalue), key, disp_data) {
++ CHECK_HEADER_INJECTION(key, 0, "body disposition key");
+ disp_param = mail_newbody_parameter();
+ disp_param->attribute = cpystr(ZSTR_VAL(key));
+ convert_to_string_ex(disp_data);
++ CHECK_HEADER_INJECTION(Z_STR_P(disp_data), 0, "body disposition value");
+ disp_param->value = (char *) fs_get(Z_STRLEN_P(disp_data) + 1);
+ memcpy(disp_param->value, Z_STRVAL_P(disp_data), Z_STRLEN_P(disp_data) + 1);
+ disp_param->next = tmp_param;
+@@ -3663,18 +3702,22 @@
+ }
+ if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "subtype", sizeof("subtype") - 1)) != NULL) {
+ convert_to_string_ex(pvalue);
++ CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body subtype");
+ bod->subtype = cpystr(Z_STRVAL_P(pvalue));
+ }
+ if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "id", sizeof("id") - 1)) != NULL) {
+ convert_to_string_ex(pvalue);
++ CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body id");
+ bod->id = cpystr(Z_STRVAL_P(pvalue));
+ }
+ if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "description", sizeof("description") - 1)) != NULL) {
+ convert_to_string_ex(pvalue);
++ CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body description");
+ bod->description = cpystr(Z_STRVAL_P(pvalue));
+ }
+ if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "disposition.type", sizeof("disposition.type") - 1)) != NULL) {
+ convert_to_string_ex(pvalue);
++ CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body disposition.type");
+ bod->disposition.type = (char *) fs_get(Z_STRLEN_P(pvalue) + 1);
+ memcpy(bod->disposition.type, Z_STRVAL_P(pvalue), Z_STRLEN_P(pvalue)+1);
+ }
+@@ -3682,9 +3725,11 @@
+ if (Z_TYPE_P(pvalue) == IS_ARRAY) {
+ disp_param = tmp_param = NULL;
+ ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(pvalue), key, disp_data) {
++ CHECK_HEADER_INJECTION(key, 0, "body type.parameters key");
+ disp_param = mail_newbody_parameter();
+ disp_param->attribute = cpystr(ZSTR_VAL(key));
+ convert_to_string_ex(disp_data);
++ CHECK_HEADER_INJECTION(Z_STR_P(disp_data), 0, "body type.parameters value");
+ disp_param->value = (char *) fs_get(Z_STRLEN_P(disp_data) + 1);
+ memcpy(disp_param->value, Z_STRVAL_P(disp_data), Z_STRLEN_P(disp_data) + 1);
+ disp_param->next = tmp_param;
+@@ -3713,6 +3758,7 @@
+ }
+ if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "md5", sizeof("md5") - 1)) != NULL) {
+ convert_to_string_ex(pvalue);
++ CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body md5");
+ bod->md5 = cpystr(Z_STRVAL_P(pvalue));
+ }
+ } else if (Z_TYPE_P(data) == IS_ARRAY) {
+@@ -3743,6 +3789,7 @@
+ }
+ if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "charset", sizeof("charset") - 1)) != NULL) {
+ convert_to_string_ex(pvalue);
++ CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body charset");
+ tmp_param = mail_newbody_parameter();
+ tmp_param->value = (char *) fs_get(Z_STRLEN_P(pvalue) + 1);
+ memcpy(tmp_param->value, Z_STRVAL_P(pvalue), Z_STRLEN_P(pvalue) + 1);
+@@ -3754,9 +3801,11 @@
+ if (Z_TYPE_P(pvalue) == IS_ARRAY) {
+ disp_param = tmp_param = NULL;
+ ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(pvalue), key, disp_data) {
++ CHECK_HEADER_INJECTION(key, 0, "body type.parameters key");
+ disp_param = mail_newbody_parameter();
+ disp_param->attribute = cpystr(ZSTR_VAL(key));
+ convert_to_string_ex(disp_data);
++ CHECK_HEADER_INJECTION(Z_STR_P(disp_data), 0, "body type.parameters value");
+ disp_param->value = (char *)fs_get(Z_STRLEN_P(disp_data) + 1);
+ memcpy(disp_param->value, Z_STRVAL_P(disp_data), Z_STRLEN_P(disp_data) + 1);
+ disp_param->next = tmp_param;
+@@ -3767,18 +3816,22 @@
+ }
+ if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "subtype", sizeof("subtype") - 1)) != NULL) {
+ convert_to_string_ex(pvalue);
++ CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body subtype");
+ bod->subtype = cpystr(Z_STRVAL_P(pvalue));
+ }
+ if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "id", sizeof("id") - 1)) != NULL) {
+ convert_to_string_ex(pvalue);
++ CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body id");
+ bod->id = cpystr(Z_STRVAL_P(pvalue));
+ }
+ if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "description", sizeof("description") - 1)) != NULL) {
+ convert_to_string_ex(pvalue);
++ CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body description");
+ bod->description = cpystr(Z_STRVAL_P(pvalue));
+ }
+ if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "disposition.type", sizeof("disposition.type") - 1)) != NULL) {
+ convert_to_string_ex(pvalue);
++ CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body disposition.type");
+ bod->disposition.type = (char *) fs_get(Z_STRLEN_P(pvalue) + 1);
+ memcpy(bod->disposition.type, Z_STRVAL_P(pvalue), Z_STRLEN_P(pvalue)+1);
+ }
+@@ -3786,9 +3839,11 @@
+ if (Z_TYPE_P(pvalue) == IS_ARRAY) {
+ disp_param = tmp_param = NULL;
+ ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(pvalue), key, disp_data) {
++ CHECK_HEADER_INJECTION(key, 0, "body disposition key");
+ disp_param = mail_newbody_parameter();
+ disp_param->attribute = cpystr(ZSTR_VAL(key));
+ convert_to_string_ex(disp_data);
++ CHECK_HEADER_INJECTION(Z_STR_P(disp_data), 0, "body disposition value");
+ disp_param->value = (char *) fs_get(Z_STRLEN_P(disp_data) + 1);
+ memcpy(disp_param->value, Z_STRVAL_P(disp_data), Z_STRLEN_P(disp_data) + 1);
+ disp_param->next = tmp_param;
+@@ -3817,6 +3872,7 @@
+ }
+ if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "md5", sizeof("md5") - 1)) != NULL) {
+ convert_to_string_ex(pvalue);
++ CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body md5");
+ bod->md5 = cpystr(Z_STRVAL_P(pvalue));
+ }
+ }
+--- /dev/null
++++ b/ext/imap/tests/bug80710_1.phpt
+@@ -0,0 +1,37 @@
++--TEST--
++Bug #80710 (imap_mail_compose() header injection) - MIME Splitting Attack
++--SKIPIF--
++<?php
++if (!extension_loaded("imap")) die("skip imap extension not available");
++?>
++--FILE--
++<?php
++$envelope["from"]= "joe@example.com\n From : X-INJECTED";
++$envelope["to"] = "foo@example.com\nFrom: X-INJECTED";
++$envelope["cc"] = "bar@example.com\nFrom: X-INJECTED";
++$envelope["subject"] = "bar@example.com\n\n From : X-INJECTED";
++$envelope["x-remail"] = "bar@example.com\nFrom: X-INJECTED";
++$envelope["something"] = "bar@example.com\nFrom: X-INJECTED";
++
++$part1["type"] = TYPEMULTIPART;
++$part1["subtype"] = "mixed";
++
++$part2["type"] = TYPEAPPLICATION;
++$part2["encoding"] = ENCBINARY;
++$part2["subtype"] = "octet-stream\nContent-Type: X-INJECTED";
++$part2["description"] = "some file\nContent-Type: X-INJECTED";
++$part2["contents.data"] = "ABC\nContent-Type: X-INJECTED";
++
++$part3["type"] = TYPETEXT;
++$part3["subtype"] = "plain";
++$part3["description"] = "description3";
++$part3["contents.data"] = "contents.data3\n\n\n\t";
++
++$body[1] = $part1;
++$body[2] = $part2;
++$body[3] = $part3;
++
++echo imap_mail_compose($envelope, $body);
++?>
++--EXPECTF--
++Warning: imap_mail_compose(): header injection attempt in from in %s on line %d
+--- /dev/null
++++ b/ext/imap/tests/bug80710_2.phpt
+@@ -0,0 +1,37 @@
++--TEST--
++Bug #80710 (imap_mail_compose() header injection) - Remail
++--SKIPIF--
++<?php
++if (!extension_loaded("imap")) die("skip imap extension not available");
++?>
++--FILE--
++<?php
++$envelope["from"]= "joe@example.com\n From : X-INJECTED";
++$envelope["to"] = "foo@example.com\nFrom: X-INJECTED";
++$envelope["cc"] = "bar@example.com\nFrom: X-INJECTED";
++$envelope["subject"] = "bar@example.com\n\n From : X-INJECTED";
++$envelope["remail"] = "X-INJECTED-REMAIL: X-INJECTED\nFrom: X-INJECTED-REMAIL-FROM"; //<--- Injected as first hdr
++$envelope["something"] = "bar@example.com\nFrom: X-INJECTED";
++
++$part1["type"] = TYPEMULTIPART;
++$part1["subtype"] = "mixed";
++
++$part2["type"] = TYPEAPPLICATION;
++$part2["encoding"] = ENCBINARY;
++$part2["subtype"] = "octet-stream\nContent-Type: X-INJECTED";
++$part2["description"] = "some file\nContent-Type: X-INJECTED";
++$part2["contents.data"] = "ABC\nContent-Type: X-INJECTED";
++
++$part3["type"] = TYPETEXT;
++$part3["subtype"] = "plain";
++$part3["description"] = "description3";
++$part3["contents.data"] = "contents.data3\n\n\n\t";
++
++$body[1] = $part1;
++$body[2] = $part2;
++$body[3] = $part3;
++
++echo imap_mail_compose($envelope, $body);
++?>
++--EXPECTF--
++Warning: imap_mail_compose(): header injection attempt in remail in %s on line %d
+diff --git a/ext/pdo_firebird/firebird_statement.c b/ext/pdo_firebird/firebird_statement.c
+index c5e6b68..bdde6c7 100644
+--- a/ext/pdo_firebird/firebird_statement.c
++++ b/ext/pdo_firebird/firebird_statement.c
+@@ -133,8 +133,14 @@
+ }
+ if (result[0] == isc_info_sql_records) {
+ unsigned i = 3, result_size = isc_vax_integer(&result[1], 2);
++ if (result_size > sizeof(result)) {
++ goto error;
++ }
+ while (result[i] != isc_info_end && i < result_size) {
+ short len = (short) isc_vax_integer(&result[i + 1], 2);
++ if (len != 1 && len != 2 && len != 4) {
++ goto error;
++ }
+ if (result[i] != isc_info_req_select_count) {
+ affected_rows += isc_vax_integer(&result[i + 3], len);
+ }
+@@ -158,6 +164,7 @@
+ return 1;
+ } while (0);
+
++error:
+ RECORD_ERROR(stmt);
+
+ return 0;
+--- /dev/null
++++ b/ext/pdo_firebird/tests/bug_76450.data
+@@ -0,0 +1 @@
++
+\ No newline at end of file
+--- /dev/null
++++ b/ext/pdo_firebird/tests/bug_76450.phpt
+@@ -0,0 +1,29 @@
++--TEST--
++Bug #76450 (SIGSEGV in firebird_stmt_execute)
++--SKIPIF--
++<?php
++if (!extension_loaded('pdo_firebird')) die("skip pdo_firebird extension not available");
++if (!extension_loaded('sockets')) die("skip sockets extension not available");
++?>
++--FILE--
++<?php
++require_once "payload_server.inc";
++
++$address = run_server(__DIR__ . "/bug_76450.data");
++
++// no need to change the credentials; we're running against a fake server
++$dsn = "firebird:dbname=inet://$address/test";
++$username = 'SYSDBA';
++$password = 'masterkey';
++
++$dbh = new PDO($dsn, $username, $password, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
++$sql = "EXECUTE PROCEDURE test_proc 123";
++$query = $dbh->prepare($sql);
++try {
++ $query->execute();
++} catch (Exception $ex) {
++ echo "{$ex->getMessage()}\n";
++}
++?>
++--EXPECT--
++SQLSTATE[HY000]: General error
+diff --git a/ext/pdo_firebird/firebird_driver.c b/ext/pdo_firebird/firebird_driver.c
+index 446f52d..0fc1c95 100644
+--- a/ext/pdo_firebird/firebird_driver.c
++++ b/ext/pdo_firebird/firebird_driver.c
+@@ -252,8 +252,17 @@
+ if (result[0] == isc_info_sql_records) {
+ unsigned i = 3, result_size = isc_vax_integer(&result[1],2);
+
++ if (result_size > sizeof(result)) {
++ ret = -1;
++ goto free_statement;
++ }
+ while (result[i] != isc_info_end && i < result_size) {
+ short len = (short)isc_vax_integer(&result[i+1],2);
++ /* bail out on bad len */
++ if (len != 1 && len != 2 && len != 4) {
++ ret = -1;
++ goto free_statement;
++ }
+ if (result[i] != isc_info_req_select_count) {
+ ret += isc_vax_integer(&result[i+3],len);
+ }
+--- /dev/null
++++ b/ext/pdo_firebird/tests/bug_76449.data
+@@ -0,0 +1 @@
++
+\ No newline at end of file
+--- /dev/null
++++ b/ext/pdo_firebird/tests/bug_76449.phpt
+@@ -0,0 +1,23 @@
++--TEST--
++Bug #76449 (SIGSEGV in firebird_handle_doer)
++--SKIPIF--
++<?php
++if (!extension_loaded('pdo_firebird')) die("skip pdo_firebird extension not available");
++if (!extension_loaded('sockets')) die("skip sockets extension not available");
++?>
++--FILE--
++<?php
++require_once "payload_server.inc";
++
++$address = run_server(__DIR__ . "/bug_76449.data");
++
++// no need to change the credentials; we're running against a fake server
++$dsn = "firebird:dbname=inet://$address/test";
++$username = 'SYSDBA';
++$password = 'masterkey';
++
++$dbh = new PDO($dsn, $username, $password, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
++var_dump($dbh->exec("INSERT INTO test VALUES ('hihi2', 'xxxxx')"));
++?>
++--EXPECT--
++bool(false)
+diff --git a/ext/pdo_firebird/firebird_driver.c b/ext/pdo_firebird/firebird_driver.c
+index 0fc1c95..f555511 100644
+--- a/ext/pdo_firebird/firebird_driver.c
++++ b/ext/pdo_firebird/firebird_driver.c
+@@ -555,14 +555,16 @@
+ }
+ /* }}} */
+
++#define INFO_BUF_LEN 512
++
+ /* callback to used to report database server info */
+ static void firebird_info_cb(void *arg, char const *s) /* {{{ */
+ {
+ if (arg) {
+ if (*(char*)arg) { /* second call */
+- strcat(arg, " ");
++ strlcat(arg, " ", INFO_BUF_LEN);
+ }
+- strcat(arg, s);
++ strlcat(arg, s, INFO_BUF_LEN);
+ }
+ }
+ /* }}} */
+@@ -573,7 +575,7 @@
+ pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data;
+
+ switch (attr) {
+- char tmp[512];
++ char tmp[INFO_BUF_LEN];
+
+ case PDO_ATTR_AUTOCOMMIT:
+ ZVAL_LONG(val,dbh->auto_commit);
+--- /dev/null
++++ b/ext/pdo_firebird/tests/bug_76448.data
+@@ -0,0 +1 @@
++
+\ No newline at end of file
+--- /dev/null
++++ b/ext/pdo_firebird/tests/bug_76448.phpt
+@@ -0,0 +1,23 @@
++--TEST--
++Bug #76448 (Stack buffer overflow in firebird_info_cb)
++--SKIPIF--
++<?php
++if (!extension_loaded('pdo_firebird')) die("skip podo_firebird extension not available");
++if (!extension_loaded('sockets')) die("skip sockets extension not available");
++?>
++--FILE--
++<?php
++require_once "payload_server.inc";
++
++$address = run_server(__DIR__ . "/bug_76448.data");
++
++// no need to change the credentials; we're running against a falke server
++$dsn = "firebird:dbname=inet://$address/test";
++$username = 'SYSDBA';
++$password = 'masterkey';
++
++$dbh = new PDO($dsn, $username, $password, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
++var_dump($dbh->getAttribute(PDO::ATTR_SERVER_INFO));
++?>
++--EXPECT--
++bool(false)
+diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c
+index 8f0c5db..72827ac 100644
+--- a/ext/zip/php_zip.c
++++ b/ext/zip/php_zip.c
+@@ -101,8 +101,8 @@
+ return NULL;
+ }
+
+- if (IS_SLASH(path[0])) {
+- return path + 1;
++ if (IS_ABSOLUTE_PATH(path, path_len)) {
++ return path + COPY_WHEN_ABSOLUTE(path) + 1;
+ }
+
+ i = path_len;
+--- /dev/null
++++ b/ext/zip/tests/bug81420.phpt
+@@ -0,0 +1,24 @@
++--TEST--
++Bug #81420 (ZipArchive::extractTo extracts outside of destination)
++--SKIPIF--
++<?php
++if (!extension_loaded("zip")) die("skip zip extension not available");
++?>
++--FILE--
++<?php
++$zip = new ZipArchive();
++$zip->open(__DIR__ . "/bug81420.zip");
++$destination = __DIR__ . "/bug81420";
++mkdir($destination);
++$zip->extractTo($destination);
++var_dump(file_exists("$destination/nt1/zzr_noharm.php"));
++?>
++--CLEAN--
++<?php
++$destination = __DIR__ . "/bug81420";
++@unlink("$destination/nt1/zzr_noharm.php");
++@rmdir("$destination/nt1");
++@rmdir($destination);
++?>
++--EXPECT--
++bool(true)
+--- /dev/null
++++ b/ext/zip/tests/bug81420.zip
+@@ -0,0 +1,2 @@
++PK
++
+\ No newline at end of file
+diff --git a/ext/dom/domimplementation.c b/ext/dom/domimplementation.c
+index 28e35eb..f4d1358 100644
+--- a/ext/dom/domimplementation.c
++++ b/ext/dom/domimplementation.c
+@@ -114,6 +114,11 @@
+ pch2 = (xmlChar *) systemid;
+ }
+
++ if (strstr(name, "%00")) {
++ php_error_docref(NULL, E_WARNING, "URI must not contain percent-encoded NUL bytes");
++ RETURN_FALSE;
++ }
++
+ uri = xmlParseURI(name);
+ if (uri != NULL && uri->opaque != NULL) {
+ localname = xmlStrdup((xmlChar *) uri->opaque);
+--- /dev/null
++++ b/ext/dom/tests/bug79971_2.phpt
+@@ -0,0 +1,20 @@
++--TEST--
++Bug #79971 (special character is breaking the path in xml function)
++--SKIPIF--
++<?php
++if (!extension_loaded('dom')) die('skip dom extension not available');
++?>
++--FILE--
++<?php
++$imp = new DOMImplementation;
++if (PHP_OS_FAMILY === 'Windows') {
++ $path = '/' . str_replace('\\', '/', __DIR__);
++} else {
++ $path = __DIR__;
++}
++$uri = "file://$path/bug79971_2.xml";
++var_dump($imp->createDocumentType("$uri%00foo"));
++?>
++--EXPECTF--
++Warning: DOMImplementation::createDocumentType(): URI must not contain percent-encoded NUL bytes in %s on line %d
++bool(false)
+diff --git a/ext/libxml/libxml.c b/ext/libxml/libxml.c
+index 85f239d..98344d1 100644
+--- a/ext/libxml/libxml.c
++++ b/ext/libxml/libxml.c
+@@ -308,6 +308,10 @@
+ int isescaped=0;
+ xmlURI *uri;
+
++ if (strstr(filename, "%00")) {
++ php_error_docref(NULL, E_WARNING, "URI must not contain percent-encoded NUL bytes");
++ return NULL;
++ }
+
+ uri = xmlParseURI(filename);
+ if (uri && (uri->scheme == NULL ||
+@@ -438,6 +442,11 @@
+ if (URI == NULL)
+ return(NULL);
+
++ if (strstr(URI, "%00")) {
++ php_error_docref(NULL, E_WARNING, "URI must not contain percent-encoded NUL bytes");
++ return NULL;
++ }
++
+ puri = xmlParseURI(URI);
+ if (puri != NULL) {
+ if (puri->scheme != NULL)
+--- /dev/null
++++ b/ext/simplexml/tests/bug79971_1.phpt
+@@ -0,0 +1,27 @@
++--TEST--
++Bug #79971 (special character is breaking the path in xml function)
++--SKIPIF--
++<?php
++if (!extension_loaded('simplexml')) die('skip simplexml extension not available');
++?>
++--FILE--
++<?php
++if (PHP_OS_FAMILY === 'Windows') {
++ $path = '/' . str_replace('\\', '/', __DIR__);
++} else {
++ $path = __DIR__;
++}
++$uri = "file://$path/bug79971_1.xml";
++var_dump(simplexml_load_file("$uri%00foo"));
++
++$sxe = simplexml_load_file($uri);
++var_dump($sxe->asXML("$uri.out%00foo"));
++?>
++--EXPECTF--
++Warning: simplexml_load_file(): URI must not contain percent-encoded NUL bytes in %s on line %d
++
++Warning: simplexml_load_file(): I/O warning : failed to load external entity "%s/bug79971_1.xml%00foo" in %s on line %d
++bool(false)
++
++Warning: SimpleXMLElement::asXML(): URI must not contain percent-encoded NUL bytes in %s on line %d
++bool(false)
+--- /dev/null
++++ b/ext/simplexml/tests/bug79971_1.xml
+@@ -0,0 +1,2 @@
++<?xml version="1.0"?>
++<root></root>