summarylogtreecommitdiffstats
path: root/debian-php-7.0.33.patch
diff options
context:
space:
mode:
Diffstat (limited to 'debian-php-7.0.33.patch')
-rw-r--r--debian-php-7.0.33.patch4569
1 files changed, 4569 insertions, 0 deletions
diff --git a/debian-php-7.0.33.patch b/debian-php-7.0.33.patch
new file mode 100644
index 000000000000..d9b056ffc763
--- /dev/null
+++ b/debian-php-7.0.33.patch
@@ -0,0 +1,4569 @@
+
+diff --git a/ext/standard/proc_open.c b/ext/standard/proc_open.c
+index b274dc4..5df6647 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 7765cfe..bc53aed 100644
+--- a/php.ini-development
++++ b/php.ini-development
+@@ -291,6 +291,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 740cf14..1e8d51b 100644
+diff --git a/ext/dba/dba.c b/ext/dba/dba.c
+index 4335a86..a7b1bb5 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 c700dac..8932005 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 c165fb6..2e391eb 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 ff2fafd..a044916 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 1e8d51b..d2e6fd9 100644
+diff --git a/sapi/fpm/php-fpm.8.in b/sapi/fpm/php-fpm.8.in
+index cdee4c6..ed733c5 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 9643617..8133d7d 100644
+--- a/main/streams/plain_wrapper.c
++++ b/main/streams/plain_wrapper.c
+@@ -687,7 +687,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 a7b1bb5..fee8e98 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 90db5a0..ff80c75 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 344515d..34b7b68 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 6f2519d..900e763 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 5ebdfe8..cadf7a3 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 84deb0b..c1c9d56 100644
+--- a/ext/pcre/tests/match_flags3.phpt
++++ b/ext/pcre/tests/match_flags3.phpt
+@@ -42,5 +42,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/tidy/tidy.c b/ext/tidy/tidy.c
+index 4e307ee..8cecf17 100644
+--- a/ext/tidy/tidy.c
++++ b/ext/tidy/tidy.c
+@@ -31,7 +31,7 @@
+ #include "ext/standard/info.h"
+
+ #include "tidy.h"
+-#include "buffio.h"
++#include "tidybuffio.h"
+
+ /* compatibility with older versions of libtidy */
+ #ifndef TIDY_CALL
+diff --git a/ext/xmlrpc/libxmlrpc/xml_element.c b/ext/xmlrpc/libxmlrpc/xml_element.c
+index 6fc6bd3..a30b500 100644
+--- a/ext/xmlrpc/libxmlrpc/xml_element.c
++++ b/ext/xmlrpc/libxmlrpc/xml_element.c
+@@ -723,6 +723,9 @@
+ long byte_idx = XML_GetCurrentByteIndex(parser);
+ /* int byte_total = XML_GetCurrentByteCount(parser); */
+ const char * error_str = XML_ErrorString(err_code);
++ if(byte_idx > len) {
++ byte_idx = len;
++ }
+ if(byte_idx >= 0) {
+ snprintf(buf,
+ sizeof(buf),
+--- /dev/null
++++ b/ext/xmlrpc/tests/bug77242.phpt
+@@ -0,0 +1,10 @@
++--TEST--
++Bug #77242 (heap out of bounds read in xmlrpc_decode())
++--SKIPIF--
++<?php if (!extension_loaded("xmlrpc")) print "skip"; ?>
++--FILE--
++<?php
++var_dump(xmlrpc_decode(base64_decode("PD94bWwgdmVyc2lvbmVuY29kaW5nPSJJU084ODU5NyKkpKSkpKSkpKSkpKSkpKSkpKSkpKSk")));
++?>
++--EXPECT--
++NULL
+\ No newline at end of file
+diff --git a/ext/phar/phar.c b/ext/phar/phar.c
+index 308c1e9..1921fa1 100644
+--- a/ext/phar/phar.c
++++ b/ext/phar/phar.c
+@@ -2021,7 +2021,7 @@
+ }
+
+ while (pos != filename && (*(pos - 1) == '/' || *(pos - 1) == '\0')) {
+- pos = memchr(pos + 1, '.', filename_len - (pos - filename) + 1);
++ pos = memchr(pos + 1, '.', filename_len - (pos - filename) - 1);
+ if (!pos) {
+ return FAILURE;
+ }
+--- /dev/null
++++ b/ext/phar/tests/bug77247.phpt
+@@ -0,0 +1,14 @@
++--TEST--
++PHP bug #77247 (heap buffer overflow in phar_detect_phar_fname_ext)
++--SKIPIF--
++<?php if (!extension_loaded("phar")) die("skip"); ?>
++--FILE--
++<?php
++try {
++var_dump(new Phar('a/.b', 0,'test.phar'));
++} catch(UnexpectedValueException $e) {
++ echo "OK";
++}
++?>
++--EXPECT--
++OK
+\ No newline at end of file
+diff --git a/ext/standard/dns.c b/ext/standard/dns.c
+index d7513e0..84eddd2 100644
+--- a/ext/standard/dns.c
++++ b/ext/standard/dns.c
+@@ -549,7 +549,10 @@
+ CHECKCP(n);
+ add_assoc_stringl(subarray, "tag", (char*)cp, n);
+ cp += n;
+- add_assoc_string(subarray, "value", (char*)cp);
++ n = dlen - n - 2;
++ CHECKCP(n);
++ add_assoc_stringl(subarray, "value", (char*)cp, n);
++ cp += n;
+ break;
+ case DNS_T_TXT:
+ {
+diff --git a/ext/standard/tests/network/dns_get_record_caa.phpt b/ext/standard/tests/network/dns_get_record_caa.phpt
+index 121bb92..2128692 100644
+--- a/ext/standard/tests/network/dns_get_record_caa.phpt
++++ b/ext/standard/tests/network/dns_get_record_caa.phpt
+@@ -7,25 +7,32 @@
+ ?>
+ --FILE--
+ <?php
+-/* This must be a domain that publishes an RFC6844 CAA-type DNS record */
+-$domain = 'google.com';
+-$match = false;
+-$dns = dns_get_record($domain, DNS_CAA);
+-if (count($dns) > 0) {
+- if (array_key_exists('type', $dns[0])
+- and $dns[0]['type'] == 'CAA'
+- and array_key_exists('flags', $dns[0])
+- and array_key_exists('tag', $dns[0])
+- and array_key_exists('value', $dns[0])
+- ) {
+- $match = true;
++/* This must be domains which publish an RFC6844 CAA-type DNS record */
++$domains = ["big.basic.caatestsuite.com", "google.com"];
++foreach ($domains as $domain) {
++ $match = false;
++ $dns = dns_get_record($domain, DNS_CAA);
++ if (count($dns) > 0) {
++ if (array_key_exists("type", $dns[0])
++ and $dns[0]["type"] == "CAA"
++ and array_key_exists("flags", $dns[0])
++ and array_key_exists("tag", $dns[0])
++ and array_key_exists("value", $dns[0])
++ ) {
++ $chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-.";
++ if (strlen($dns[0]["value"]) == strspn($dns[0]["value"], $chars)) {
++ $match = true;
++ }
++ }
++ }
++ if ($match) {
++ echo "CAA record found\n";
++ } else {
++ echo "CAA lookup failed\n";
++ var_dump($dns);
+ }
+-}
+-if ($match) {
+- echo "CAA record found\n";
+-} else {
+- echo "CAA Lookup failed\n";
+ }
+ ?>
+ --EXPECT--
+ CAA record found
++CAA record found
+diff --git a/ext/mbstring/oniguruma/regparse.c b/ext/mbstring/oniguruma/regparse.c
+index d2925f1..252ca18 100644
+--- a/ext/mbstring/oniguruma/regparse.c
++++ b/ext/mbstring/oniguruma/regparse.c
+@@ -246,6 +246,12 @@
+ }
+ #endif
+
++#if (defined (__GNUC__) && __GNUC__ > 2 ) && !defined(DARWIN) && !defined(__hpux) && !defined(_AIX)
++# define UNEXPECTED(condition) __builtin_expect(condition, 0)
++#else
++# define UNEXPECTED(condition) (condition)
++#endif
++
+ /* scan pattern methods */
+ #define PEND_VALUE 0
+
+@@ -260,14 +266,17 @@
+ c = ONIGENC_MBC_TO_CODE(enc, p, end); \
+ pfetch_prev = p; \
+ p += ONIGENC_MBC_ENC_LEN(enc, p); \
++ if(UNEXPECTED(p > end)) p = end; \
+ } while (0)
+
+ #define PINC_S do { \
+ p += ONIGENC_MBC_ENC_LEN(enc, p); \
++ if(UNEXPECTED(p > end)) p = end; \
+ } while (0)
+ #define PFETCH_S(c) do { \
+ c = ONIGENC_MBC_TO_CODE(enc, p, end); \
+ p += ONIGENC_MBC_ENC_LEN(enc, p); \
++ if(UNEXPECTED(p > end)) p = end; \
+ } while (0)
+
+ #define PPEEK (p < end ? ONIGENC_MBC_TO_CODE(enc, p, end) : PEND_VALUE)
+--- /dev/null
++++ b/ext/mbstring/tests/bug77370.phpt
+@@ -0,0 +1,13 @@
++--TEST--
++Bug #77370 (Buffer overflow on mb regex functions - fetch_token)
++--SKIPIF--
++<?php extension_loaded('mbstring') or die('skip mbstring not available'); ?>
++--FILE--
++<?php
++var_dump(mb_split(" \xfd",""));
++?>
++--EXPECT--
++array(1) {
++ [0]=>
++ string(0) ""
++}
+diff --git a/ext/mbstring/oniguruma/regcomp.c b/ext/mbstring/oniguruma/regcomp.c
+index b93ca94..c72d65d 100644
+--- a/ext/mbstring/oniguruma/regcomp.c
++++ b/ext/mbstring/oniguruma/regcomp.c
+@@ -524,6 +524,7 @@
+
+ for (; p < end; ) {
+ len = enclen(enc, p);
++ if (p + len > end) len = end - p;
+ if (len == prev_len) {
+ slen++;
+ }
+--- /dev/null
++++ b/ext/mbstring/tests/bug77371.phpt
+@@ -0,0 +1,10 @@
++--TEST--
++Bug #77371 (heap buffer overflow in mb regex functions - compile_string_node)
++--SKIPIF--
++<?php extension_loaded('mbstring') or die('skip mbstring not available'); ?>
++--FILE--
++<?php
++var_dump(mb_ereg("()0\xfc00000\xfc00000\xfc00000\xfc",""))
++?>
++--EXPECT--
++bool(false)
+\ No newline at end of file
+diff --git a/ext/mbstring/oniguruma/enc/utf16_be.c b/ext/mbstring/oniguruma/enc/utf16_be.c
+index 1e909eb..9e2f73b 100644
+--- a/ext/mbstring/oniguruma/enc/utf16_be.c
++++ b/ext/mbstring/oniguruma/enc/utf16_be.c
+@@ -75,16 +75,18 @@
+ }
+
+ static OnigCodePoint
+-utf16be_mbc_to_code(const UChar* p, const UChar* end ARG_UNUSED)
++utf16be_mbc_to_code(const UChar* p, const UChar* end)
+ {
+ OnigCodePoint code;
+
+ if (UTF16_IS_SURROGATE_FIRST(*p)) {
++ if (end - p < 4) return 0;
+ code = ((((p[0] - 0xd8) << 2) + ((p[1] & 0xc0) >> 6) + 1) << 16)
+ + ((((p[1] & 0x3f) << 2) + (p[2] - 0xdc)) << 8)
+ + p[3];
+ }
+ else {
++ if (end - p < 2) return 0;
+ code = p[0] * 256 + p[1];
+ }
+ return code;
+diff --git a/ext/mbstring/oniguruma/enc/utf16_le.c b/ext/mbstring/oniguruma/enc/utf16_le.c
+index 5cc0759..580f8df 100644
+--- a/ext/mbstring/oniguruma/enc/utf16_le.c
++++ b/ext/mbstring/oniguruma/enc/utf16_le.c
+@@ -81,13 +81,14 @@
+ }
+
+ static OnigCodePoint
+-utf16le_mbc_to_code(const UChar* p, const UChar* end ARG_UNUSED)
++utf16le_mbc_to_code(const UChar* p, const UChar* end)
+ {
+ OnigCodePoint code;
+ UChar c0 = *p;
+ UChar c1 = *(p+1);
+
+ if (UTF16_IS_SURROGATE_FIRST(c1)) {
++ if (end - p < 4) return 0;
+ code = ((((c1 - 0xd8) << 2) + ((c0 & 0xc0) >> 6) + 1) << 16)
+ + ((((c0 & 0x3f) << 2) + (p[3] - 0xdc)) << 8)
+ + p[2];
+diff --git a/ext/mbstring/oniguruma/enc/utf32_be.c b/ext/mbstring/oniguruma/enc/utf32_be.c
+index b4f8226..5295f26 100644
+--- a/ext/mbstring/oniguruma/enc/utf32_be.c
++++ b/ext/mbstring/oniguruma/enc/utf32_be.c
+@@ -60,6 +60,7 @@
+ static OnigCodePoint
+ utf32be_mbc_to_code(const UChar* p, const UChar* end ARG_UNUSED)
+ {
++ if (end - p < 4) return 0;
+ return (OnigCodePoint )(((p[0] * 256 + p[1]) * 256 + p[2]) * 256 + p[3]);
+ }
+
+diff --git a/ext/mbstring/oniguruma/enc/utf32_le.c b/ext/mbstring/oniguruma/enc/utf32_le.c
+index 8f413bf..a78c4d0 100644
+--- a/ext/mbstring/oniguruma/enc/utf32_le.c
++++ b/ext/mbstring/oniguruma/enc/utf32_le.c
+@@ -60,6 +60,7 @@
+ static OnigCodePoint
+ utf32le_mbc_to_code(const UChar* p, const UChar* end ARG_UNUSED)
+ {
++ if (end - p < 4) return 0;
+ return (OnigCodePoint )(((p[3] * 256 + p[2]) * 256 + p[1]) * 256 + p[0]);
+ }
+
+--- /dev/null
++++ b/ext/mbstring/tests/bug77418.phpt
+@@ -0,0 +1,14 @@
++--TEST--
++Bug #77371 (Heap overflow in utf32be_mbc_to_code)
++--SKIPIF--
++<?php extension_loaded('mbstring') or die('skip mbstring not available'); ?>
++--FILE--
++<?php
++mb_regex_encoding("UTF-32");
++var_dump(mb_split("\x00\x00\x00\x5c\x00\x00\x00B","000000000000000000000000000000"));
++?>
++--EXPECT--
++array(1) {
++ [0]=>
++ string(30) "000000000000000000000000000000"
++}
+diff --git a/ext/xmlrpc/libxmlrpc/base64.c b/ext/xmlrpc/libxmlrpc/base64.c
+index 5ebdf31..a4fa193 100644
+--- a/ext/xmlrpc/libxmlrpc/base64.c
++++ b/ext/xmlrpc/libxmlrpc/base64.c
+@@ -77,7 +77,7 @@
+
+ while (!hiteof) {
+ unsigned char igroup[3], ogroup[4];
+- int c, n;
++ int c, n;
+
+ igroup[0] = igroup[1] = igroup[2] = 0;
+ for (n = 0; n < 3; n++) {
+@@ -169,7 +169,7 @@
+ return;
+ }
+
+- if (dtable[c] & 0x80) {
++ if (dtable[(unsigned char)c] & 0x80) {
+ /*
+ fprintf(stderr, "Offset %i length %i\n", offset, length);
+ fprintf(stderr, "character '%c:%x:%c' in input file.\n", c, c, dtable[c]);
+--- /dev/null
++++ b/ext/xmlrpc/tests/bug77380.phpt
+@@ -0,0 +1,17 @@
++--TEST--
++Bug #77380 (Global out of bounds read in xmlrpc base64 code)
++--SKIPIF--
++<?php
++if (!extension_loaded("xmlrpc")) print "skip";
++?>
++--FILE--
++<?php
++var_dump(xmlrpc_decode(base64_decode("PGJhc2U2ND7CkzwvYmFzZTY0Pgo=")));
++?>
++--EXPECT--
++object(stdClass)#1 (2) {
++ ["scalar"]=>
++ string(0) ""
++ ["xmlrpc_type"]=>
++ string(6) "base64"
++}
+diff --git a/ext/phar/phar.c b/ext/phar/phar.c
+index 1921fa1..583ed45 100644
+--- a/ext/phar/phar.c
++++ b/ext/phar/phar.c
+@@ -1390,6 +1390,9 @@
+ /* set up our manifest */
+ mydata = ecalloc(1, sizeof(phar_archive_data));
+ mydata->fname = expand_filepath(fname, NULL);
++ if (mydata->fname == NULL) {
++ return FAILURE;
++ }
+ fname_len = strlen(mydata->fname);
+ #ifdef PHP_WIN32
+ phar_unixify_path_separators(mydata->fname, fname_len);
+--- /dev/null
++++ b/ext/phar/tests/bug77396.phpt
+@@ -0,0 +1,15 @@
++--TEST--
++Bug #77396 Relative filename exceeding maximum path length causes null pointer dereference.
++--SKIPIF--
++<?php if (!extension_loaded("phar")) die("skip"); ?>
++--FILE--
++<?php
++$path = '../' . str_repeat("x", PHP_MAXPATHLEN) . '.tar';
++$phar = new PharData($path);
++?>
++--EXPECTF--
++Fatal error: Uncaught UnexpectedValueException: Phar creation or opening failed in %s/bug77396.php:%d
++Stack trace:
++#0 %s/bug77396.php(%d): PharData->__construct(%s)
++#1 {main}
++ thrown in %s/bug77396.php on line %d
+diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c
+index 41df661..300cf01 100644
+--- a/ext/spl/spl_directory.c
++++ b/ext/spl/spl_directory.c
+@@ -1109,7 +1109,7 @@
+ char *path;
+ size_t len;
+
+- if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "s", &path, &len) == FAILURE) {
++ if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "p", &path, &len) == FAILURE) {
+ return;
+ }
+
+--- /dev/null
++++ b/ext/spl/tests/bug77431.phpt
+@@ -0,0 +1,9 @@
++--TEST--
++Bug #77431 (SplFileInfo::__construct() accepts NUL bytes)
++--FILE--
++<?php
++new SplFileInfo("bad\0good");
++?>
++--EXPECTF--
++Fatal error: Uncaught TypeError: SplFileInfo::__construct() expects parameter 1 to be a valid path, string given in %s:%d
++Stack trace:%A
+\ No newline at end of file
+diff --git a/ext/exif/exif.c b/ext/exif/exif.c
+index 6fa60f7..e9aeaef 100644
+--- a/ext/exif/exif.c
++++ b/ext/exif/exif.c
+@@ -3566,10 +3566,10 @@
+ tag_table_type tag_table = exif_get_tag_table(section_index);
+
+ if (ImageInfo->ifd_nesting_level > MAX_IFD_NESTING_LEVEL) {
+- return FALSE;
+- }
++ return FALSE;
++ }
+
+- if (ImageInfo->FileSize >= dir_offset+2) {
++ if (ImageInfo->FileSize >= 2 && ImageInfo->FileSize - 2 >= dir_offset) {
+ sn = exif_file_sections_add(ImageInfo, M_PSEUDO, 2, NULL);
+ #ifdef EXIF_DEBUG
+ exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_NOTICE, "Read from TIFF: filesize(x%04X), IFD dir(x%04X + x%04X)", ImageInfo->FileSize, dir_offset, 2);
+@@ -3577,8 +3577,8 @@
+ php_stream_seek(ImageInfo->infile, dir_offset, SEEK_SET); /* we do not know the order of sections */
+ php_stream_read(ImageInfo->infile, (char*)ImageInfo->file.list[sn].data, 2);
+ num_entries = php_ifd_get16u(ImageInfo->file.list[sn].data, ImageInfo->motorola_intel);
+- dir_size = 2/*num dir entries*/ +12/*length of entry*/*num_entries +4/* offset to next ifd (points to thumbnail or NULL)*/;
+- if (ImageInfo->FileSize >= dir_offset+dir_size) {
++ dir_size = 2/*num dir entries*/ +12/*length of entry*/*(size_t)num_entries +4/* offset to next ifd (points to thumbnail or NULL)*/;
++ if (ImageInfo->FileSize >= dir_size && ImageInfo->FileSize - dir_size >= dir_offset) {
+ #ifdef EXIF_DEBUG
+ exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_NOTICE, "Read from TIFF: filesize(x%04X), IFD dir(x%04X + x%04X), IFD entries(%d)", ImageInfo->FileSize, dir_offset+2, dir_size-2, num_entries);
+ #endif
+@@ -3661,9 +3661,9 @@
+ }
+ }
+ }
+- if (ImageInfo->FileSize >= dir_offset + ImageInfo->file.list[sn].size) {
++ if (ImageInfo->FileSize >= ImageInfo->file.list[sn].size && ImageInfo->FileSize - ImageInfo->file.list[sn].size >= dir_offset) {
+ if (ifd_size > dir_size) {
+- if (dir_offset + ifd_size > ImageInfo->FileSize) {
++ if (ImageInfo->FileSize < ifd_size || dir_offset > ImageInfo->FileSize - ifd_size) {
+ exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_WARNING, "Error in TIFF: filesize(x%04X) less than size of IFD(x%04X + x%04X)", ImageInfo->FileSize, dir_offset, ifd_size);
+ return FALSE;
+ }
+diff --git a/ext/exif/exif.c b/ext/exif/exif.c
+index e9aeaef..b2de1a9 100644
+--- a/ext/exif/exif.c
++++ b/ext/exif/exif.c
+@@ -3508,7 +3508,7 @@
+ return FALSE;
+ marker = c;
+ length = php_jpg_get16(data+pos);
+- if (pos+length>=ImageInfo->Thumbnail.size) {
++ if (length > ImageInfo->Thumbnail.size || pos >= ImageInfo->Thumbnail.size - length) {
+ return FALSE;
+ }
+ #ifdef EXIF_DEBUG
+@@ -3529,6 +3529,10 @@
+ case M_SOF14:
+ case M_SOF15:
+ /* handle SOFn block */
++ if (length < 8 || ImageInfo->Thumbnail.size - 8 < pos) {
++ /* exif_process_SOFn needs 8 bytes */
++ return FALSE;
++ }
+ exif_process_SOFn(data+pos, marker, &sof_info);
+ ImageInfo->Thumbnail.height = sof_info.height;
+ ImageInfo->Thumbnail.width = sof_info.width;
+@@ -4176,7 +4180,9 @@
+ ZVAL_STRINGL(return_value, ImageInfo.Thumbnail.data, ImageInfo.Thumbnail.size);
+ if (arg_c >= 3) {
+ if (!ImageInfo.Thumbnail.width || !ImageInfo.Thumbnail.height) {
+- exif_scan_thumbnail(&ImageInfo);
++ if (!exif_scan_thumbnail(&ImageInfo)) {
++ ImageInfo.Thumbnail.width = ImageInfo.Thumbnail.height = 0;
++ }
+ }
+ zval_dtor(p_width);
+ zval_dtor(p_height);
+--- /dev/null
++++ b/ext/exif/tests/bug77540.jpg
+@@ -0,0 +1 @@
++џис
+\ No newline at end of file
+--- /dev/null
++++ b/ext/exif/tests/bug77540.phpt
+@@ -0,0 +1,16 @@
++--TEST--
++Bug 77540 (Invalid Read on exif_process_SOFn)
++--SKIPIF--
++<?php if (!extension_loaded('exif')) print 'skip exif extension not available';?>
++--FILE--
++<?php
++$width = $height = 42;
++$s = exif_thumbnail(__DIR__."/bug77540.jpg", $width, $height);
++echo "Width ".$width."\n";
++echo "Height ".$height."\n";
++?>
++DONE
++--EXPECTF--
++Width 0
++Height 0
++DONE
+\ No newline at end of file
+diff --git a/ext/exif/exif.c b/ext/exif/exif.c
+index b2de1a9..57567fb 100644
+--- a/ext/exif/exif.c
++++ b/ext/exif/exif.c
+@@ -2740,7 +2740,7 @@
+ break;
+ }
+
+- if (maker_note->offset >= value_len) {
++ if (value_len < 2 || maker_note->offset >= value_len - 1) {
+ /* Do not go past the value end */
+ exif_error_docref("exif_read_data#error_ifd" EXIFERR_CC, ImageInfo, E_WARNING, "IFD data too short: 0x%04X offset 0x%04X", value_len, maker_note->offset);
+ return FALSE;
+@@ -2793,6 +2793,7 @@
+ break;
+ default:
+ case MN_OFFSET_NORMAL:
++ data_len = value_len;
+ break;
+ }
+
+--- /dev/null
++++ b/ext/exif/tests/bug77563.jpg
+@@ -0,0 +1 @@
++џис
+\ No newline at end of file
+--- /dev/null
++++ b/ext/exif/tests/bug77563.phpt
+@@ -0,0 +1,16 @@
++--TEST--
++Bug 77563 (Uninitialized read in exif_process_IFD_in_MAKERNOTE)
++--SKIPIF--
++<?php if (!extension_loaded('exif')) print 'skip exif extension not available';?>
++--FILE--
++<?php
++$s = exif_thumbnail(__DIR__."/bug77563.jpg");
++?>
++DONE
++--EXPECTF--
++Warning: exif_thumbnail(bug77563.jpg): Illegal IFD offset in %s/bug77563.php on line %d
++
++Warning: exif_thumbnail(bug77563.jpg): File structure corrupted in %s/bug77563.php on line %d
++
++Warning: exif_thumbnail(bug77563.jpg): Invalid JPEG file in %s/bug77563.php on line %d
++DONE
+\ No newline at end of file
+diff --git a/ext/phar/tar.c b/ext/phar/tar.c
+index 37663ca..cacee8e 100644
+--- a/ext/phar/tar.c
++++ b/ext/phar/tar.c
+@@ -762,7 +762,12 @@
+ header.typeflag = entry->tar_type;
+
+ if (entry->link) {
+- strncpy(header.linkname, entry->link, strlen(entry->link));
++ if (strlcpy(header.linkname, entry->link, sizeof(header.linkname)) >= sizeof(header.linkname)) {
++ if (fp->error) {
++ spprintf(fp->error, 4096, "tar-based phar \"%s\" cannot be created, link \"%s\" is too long for format", entry->phar->fname, entry->link);
++ }
++ return ZEND_HASH_APPLY_STOP;
++ }
+ }
+
+ strncpy(header.magic, "ustar", sizeof("ustar")-1);
+diff --git a/ext/phar/tests/bug71488.phpt b/ext/phar/tests/bug71488.phpt
+index 22d2bf0..65bd7b2 100644
+--- a/ext/phar/tests/bug71488.phpt
++++ b/ext/phar/tests/bug71488.phpt
+@@ -13,5 +13,6 @@
+ <?php
+ @unlink(__DIR__."/bug71488.test");
+ ?>
+---EXPECT--
+-DONE
+\ No newline at end of file
++--EXPECTF--
++Fatal error: Uncaught BadMethodCallException: tar-based phar "%s/bug71488.test" cannot be created, link "%s" is too long for format in %sbug71488.php:%d
++Stack trace:%A
+--- /dev/null
++++ b/ext/phar/tests/bug77586.phpt
+@@ -0,0 +1,21 @@
++--TEST--
++Bug #77586 Symbolic link names in tar-formatted phar must be less than 100 bytes.
++--SKIPIF--
++<?php if (!extension_loaded("phar") || true /* blocked by bug 65332 */) die("skip"); ?>
++--FILE--
++<?php
++$dir = __DIR__."/bug77586";
++$phar = new PharData($dir . "/bug77586.tar");
++$phar->buildFromDirectory($dir . "/files");
++?>
++--CLEAN--
++<?php
++$dir = __DIR__."/bug77586";
++unlink($dir . "/bug77586.tar");
++?>
++--EXPECTF--
++Fatal error: Uncaught PharException: tar-based phar "%s/bug77586.tar" cannot be created, link "%s" is too long for format %s
++Stack trace:
++#0 %s/bug77586.php(%d): PharData->buildFromDirectory('%s')
++#1 {main}
++ thrown in %s/bug77586.php %s on line %d
+--- /dev/null
++++ b/ext/phar/tests/bug77586/files/link-nktarAMLdJBv7BGYnpzg-ZDycSpWN3Ne3kacltOSE-EqfhStJ1EoBpGuoua6VE-dne29hvpNWXiVbepwIf8-NRHWM9LITLo3nXZnKVNC
+@@ -0,0 +1 @@
++target
+\ No newline at end of file
+diff --git a/main/streams/plain_wrapper.c b/main/streams/plain_wrapper.c
+index 8133d7d..8c6c65b 100644
+--- a/main/streams/plain_wrapper.c
++++ b/main/streams/plain_wrapper.c
+@@ -1166,34 +1166,51 @@
+ # ifdef EXDEV
+ if (errno == EXDEV) {
+ zend_stat_t sb;
++# if !defined(ZTS) && !defined(TSRM_WIN32) && !defined(NETWARE)
++ /* not sure what to do in ZTS case, umask is not thread-safe */
++ int oldmask = umask(077);
++# endif
++ int success = 0;
+ if (php_copy_file(url_from, url_to) == SUCCESS) {
+ if (VCWD_STAT(url_from, &sb) == 0) {
++ success = 1;
+ # if !defined(TSRM_WIN32) && !defined(NETWARE)
+- if (VCWD_CHMOD(url_to, sb.st_mode)) {
+- if (errno == EPERM) {
+- php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", strerror(errno));
+- VCWD_UNLINK(url_from);
+- return 1;
+- }
++ /*
++ * Try to set user and permission info on the target.
++ * If we're not root, then some of these may fail.
++ * We try chown first, to set proper group info, relying
++ * on the system environment to have proper umask to not allow
++ * access to the file in the meantime.
++ */
++ if (VCWD_CHOWN(url_to, sb.st_uid, sb.st_gid)) {
+ php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", strerror(errno));
+- return 0;
++ if (errno != EPERM) {
++ success = 0;
++ }
+ }
+- if (VCWD_CHOWN(url_to, sb.st_uid, sb.st_gid)) {
+- if (errno == EPERM) {
++
++ if (success) {
++ if (VCWD_CHMOD(url_to, sb.st_mode)) {
+ php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", strerror(errno));
+- VCWD_UNLINK(url_from);
+- return 1;
++ if (errno != EPERM) {
++ success = 0;
++ }
+ }
+- php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", strerror(errno));
+- return 0;
+ }
+ # endif
+- VCWD_UNLINK(url_from);
+- return 1;
++ if (success) {
++ VCWD_UNLINK(url_from);
++ }
++ } else {
++ php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", strerror(errno));
+ }
++ } else {
++ php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", strerror(errno));
+ }
+- php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", strerror(errno));
+- return 0;
++# if !defined(ZTS) && !defined(TSRM_WIN32) && !defined(NETWARE)
++ umask(oldmask);
++# endif
++ return success;
+ }
+ # endif
+ #endif
+diff --git a/Zend/configure.in b/Zend/configure.in
+index 6d4d450..212a96b 100644
+--- a/Zend/configure.in
++++ b/Zend/configure.in
+@@ -70,7 +70,7 @@
+ #endif
+
+ #ifndef zend_isnan
+-#if HAVE_DECL_ISNAN
++#if HAVE_DECL_ISNAN && (!defined(__cplusplus) || __cplusplus < 201103L)
+ #define zend_isnan(a) isnan(a)
+ #elif defined(HAVE_FPCLASS)
+ #define zend_isnan(a) ((fpclass(a) == FP_SNAN) || (fpclass(a) == FP_QNAN))
+@@ -79,7 +79,7 @@
+ #endif
+ #endif
+
+-#if HAVE_DECL_ISINF
++#if HAVE_DECL_ISINF && (!defined(__cplusplus) || __cplusplus < 201103L)
+ #define zend_isinf(a) isinf(a)
+ #elif defined(INFINITY)
+ /* Might not work, but is required by ISO C99 */
+@@ -90,7 +90,7 @@
+ #define zend_isinf(a) 0
+ #endif
+
+-#if HAVE_DECL_ISFINITE
++#if HAVE_DECL_ISFINITE && (!defined(__cplusplus) || __cplusplus < 201103L)
+ #define zend_finite(a) isfinite(a)
+ #elif defined(HAVE_FINITE)
+ #define zend_finite(a) finite(a)
+diff --git a/configure.in b/configure.in
+index a45fe71..51bb70e 100644
+--- a/configure.in
++++ b/configure.in
+@@ -75,7 +75,7 @@
+ #endif
+
+ #ifndef zend_isnan
+-#if HAVE_DECL_ISNAN
++#if HAVE_DECL_ISNAN && (!defined(__cplusplus) || __cplusplus < 201103L)
+ #define zend_isnan(a) isnan(a)
+ #elif defined(HAVE_FPCLASS)
+ #define zend_isnan(a) ((fpclass(a) == FP_SNAN) || (fpclass(a) == FP_QNAN))
+@@ -84,7 +84,7 @@
+ #endif
+ #endif
+
+-#if HAVE_DECL_ISINF
++#if HAVE_DECL_ISINF && (!defined(__cplusplus) || __cplusplus < 201103L)
+ #define zend_isinf(a) isinf(a)
+ #elif defined(INFINITY)
+ /* Might not work, but is required by ISO C99 */
+@@ -95,7 +95,7 @@
+ #define zend_isinf(a) 0
+ #endif
+
+-#if HAVE_DECL_ISFINITE
++#if HAVE_DECL_ISFINITE && (!defined(__cplusplus) || __cplusplus < 201103L)
+ #define zend_finite(a) isfinite(a)
+ #elif defined(HAVE_FINITE)
+ #define zend_finite(a) finite(a)
+diff --git a/ext/readline/config.m4 b/ext/readline/config.m4
+index 0a00370..b0cefcc 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/exif/exif.c b/ext/exif/exif.c
+index 57567fb..cd6b824 100644
+--- a/ext/exif/exif.c
++++ b/ext/exif/exif.c
+@@ -2801,6 +2801,10 @@
+ exif_error_docref("exif_read_data#error_ifd" EXIFERR_CC, ImageInfo, E_WARNING, "Illegal IFD size: 2 + 0x%04X*12 = 0x%04X > 0x%04X", NumDirEntries, 2+NumDirEntries*12, value_len);
+ return FALSE;
+ }
++ if ((dir_start - value_ptr) > value_len - (2+NumDirEntries*12)) {
++ exif_error_docref("exif_read_data#error_ifd" EXIFERR_CC, ImageInfo, E_WARNING, "Illegal IFD size: 0x%04X > 0x%04X", (dir_start - value_ptr) + (2+NumDirEntries*12), value_len);
++ return FALSE;
++ }
+
+ for (de=0;de<NumDirEntries;de++) {
+ if (!exif_process_IFD_TAG(ImageInfo, dir_start + 2 + 12 * de,
+--- /dev/null
++++ b/ext/exif/tests/bug77753.phpt
+@@ -0,0 +1,16 @@
++--TEST--
++Bug #77753 (Heap-buffer-overflow in php_ifd_get32s)
++--SKIPIF--
++<?php if (!extension_loaded('exif')) print 'skip exif extension not available';?>
++--FILE--
++<?php
++var_dump(exif_read_data(__DIR__."/bug77753.tiff"));
++?>
++DONE
++--EXPECTF--
++%A
++Warning: exif_read_data(bug77753.tiff): Illegal IFD size: 0x006A > 0x0065 in %sbug77753.php on line %d
++
++Warning: exif_read_data(bug77753.tiff): Invalid TIFF file in %sbug77753.php on line %d
++bool(false)
++DONE
+\ No newline at end of file
+--- /dev/null
++++ b/ext/exif/tests/bug77753.tiff
+@@ -0,0 +1 @@
++II*
+\ No newline at end of file
+diff --git a/NEWS b/NEWS
+index 31c91ce..2ab2845 100644
+--- a/NEWS
++++ b/NEWS
+@@ -3,6 +3,10 @@
+
+ Backported from 7.1.28
+
++- EXIF:
++ . Fixed bug #77753 (Heap-buffer-overflow in php_ifd_get32s). (Stas)
++ . Fixed bug #77831 (Heap-buffer-overflow in exif_iif_add_value). (Stas)
++
+ - SQLite3:
+ . Added sqlite3.defensive INI directive. (BohwaZ)
+
+diff --git a/ext/exif/exif.c b/ext/exif/exif.c
+index cd6b824..a1c49e9 100644
+--- a/ext/exif/exif.c
++++ b/ext/exif/exif.c
+@@ -1654,10 +1654,10 @@
+ /* {{{ exif_iif_add_value
+ Add a value to image_info
+ */
+-static void exif_iif_add_value(image_info_type *image_info, int section_index, char *name, int tag, int format, int length, void* value, int motorola_intel)
++static void exif_iif_add_value(image_info_type *image_info, int section_index, char *name, int tag, int format, int length, void* value, size_t value_len, int motorola_intel)
+ {
+ size_t idex;
+- void *vptr;
++ void *vptr, *vptr_end;
+ image_info_value *info_value;
+ image_info_data *info_data;
+ image_info_data *list;
+@@ -1679,8 +1679,12 @@
+
+ switch (format) {
+ case TAG_FMT_STRING:
++ if (length > value_len) {
++ exif_error_docref("exif_iif_add_value" EXIFERR_CC, image_info, E_WARNING, "length > value_len: %d > %zu", length, value_len);
++ value = NULL;
++ }
+ if (value) {
+- length = php_strnlen(value, length);
++ length = (int)php_strnlen(value, length);
+ info_value->s = estrndup(value, length);
+ info_data->length = length;
+ } else {
+@@ -1702,6 +1706,10 @@
+ if (!length)
+ break;
+ case TAG_FMT_UNDEFINED:
++ if (length > value_len) {
++ exif_error_docref("exif_iif_add_value" EXIFERR_CC, image_info, E_WARNING, "length > value_len: %d > %zu", length, value_len);
++ value = NULL;
++ }
+ if (value) {
+ if (tag == TAG_MAKER_NOTE) {
+ length = (int) php_strnlen(value, length);
+@@ -1732,7 +1740,12 @@
+ } else {
+ info_value = &info_data->value;
+ }
++ vptr_end = value+value_len;
+ for (idex=0,vptr=value; idex<(size_t)length; idex++,vptr=(char *) vptr + php_tiff_bytes_per_format[format]) {
++ if (vptr_end - vptr < php_tiff_bytes_per_format[format]) {
++ exif_error_docref("exif_iif_add_value" EXIFERR_CC, image_info, E_WARNING, "Value too short");
++ break;
++ }
+ if (length>1) {
+ info_value = &info_data->value.list[idex];
+ }
+@@ -1768,7 +1781,7 @@
+ php_error_docref(NULL, E_WARNING, "Found value of type single");
+ #endif
+ info_value->f = *(float *)value;
+-
++ break;
+ case TAG_FMT_DOUBLE:
+ #ifdef EXIF_DEBUG
+ php_error_docref(NULL, E_WARNING, "Found value of type double");
+@@ -1786,9 +1799,9 @@
+ /* {{{ exif_iif_add_tag
+ Add a tag from IFD to image_info
+ */
+-static void exif_iif_add_tag(image_info_type *image_info, int section_index, char *name, int tag, int format, size_t length, void* value)
++static void exif_iif_add_tag(image_info_type *image_info, int section_index, char *name, int tag, int format, size_t length, void* value, size_t value_len)
+ {
+- exif_iif_add_value(image_info, section_index, name, tag, format, (int)length, value, image_info->motorola_intel);
++ exif_iif_add_value(image_info, section_index, name, tag, format, (int)length, value, value_len, image_info->motorola_intel);
+ }
+ /* }}} */
+
+@@ -2209,7 +2222,7 @@
+ */
+ static void exif_process_COM (image_info_type *image_info, char *value, size_t length)
+ {
+- exif_iif_add_tag(image_info, SECTION_COMMENT, "Comment", TAG_COMPUTED_VALUE, TAG_FMT_STRING, length-2, value+2);
++ exif_iif_add_tag(image_info, SECTION_COMMENT, "Comment", TAG_COMPUTED_VALUE, TAG_FMT_STRING, length-2, value+2, length-2);
+ }
+ /* }}} */
+
+@@ -2224,17 +2237,17 @@
+ if (length>3) {
+ switch(value[2]) {
+ case 0:
+- exif_iif_add_tag(image_info, SECTION_COMMENT, "Comment", TAG_COMPUTED_VALUE, TAG_FMT_UNDEFINED, length, value);
++ exif_iif_add_tag(image_info, SECTION_COMMENT, "Comment", TAG_COMPUTED_VALUE, TAG_FMT_UNDEFINED, length, value, length);
+ break;
+ case 1:
+- exif_iif_add_tag(image_info, SECTION_COMMENT, "Comment", TAG_COMPUTED_VALUE, TAG_FMT_STRING, length, value);
++ exif_iif_add_tag(image_info, SECTION_COMMENT, "Comment", TAG_COMPUTED_VALUE, TAG_FMT_STRING, length, value, length);
+ break;
+ default:
+ php_error_docref(NULL, E_NOTICE, "Undefined JPEG2000 comment encoding");
+ break;
+ }
+ } else {
+- exif_iif_add_tag(image_info, SECTION_COMMENT, "Comment", TAG_COMPUTED_VALUE, TAG_FMT_UNDEFINED, 0, NULL);
++ exif_iif_add_tag(image_info, SECTION_COMMENT, "Comment", TAG_COMPUTED_VALUE, TAG_FMT_UNDEFINED, 0, NULL, 0);
+ php_error_docref(NULL, E_NOTICE, "JPEG2000 comment section too small");
+ }
+ }
+@@ -2826,7 +2839,7 @@
+ static int exif_process_IFD_TAG(image_info_type *ImageInfo, char *dir_entry, char *offset_base, size_t IFDlength, size_t displacement, int section_index, int ReadNextIFD, tag_table_type tag_table)
+ {
+ size_t length;
+- int tag, format, components;
++ unsigned int tag, format, components;
+ char *value_ptr, tagname[64], cbuf[32], *outside=NULL;
+ size_t byte_count, offset_val, fpos, fgot;
+ int64_t byte_count_signed;
+@@ -3137,7 +3150,7 @@
+ }
+ }
+ }
+- exif_iif_add_tag(ImageInfo, section_index, exif_get_tagname(tag, tagname, sizeof(tagname), tag_table), tag, format, components, value_ptr);
++ exif_iif_add_tag(ImageInfo, section_index, exif_get_tagname(tag, tagname, sizeof(tagname), tag_table), tag, format, components, value_ptr, byte_count);
+ EFREE_IF(outside);
+ return TRUE;
+ }
+@@ -3295,10 +3308,10 @@
+ size_t l1, l2=0;
+
+ if ((l1 = php_strnlen(buffer+2, length-2)) > 0) {
+- exif_iif_add_tag(ImageInfo, SECTION_APP12, "Company", TAG_NONE, TAG_FMT_STRING, l1, buffer+2);
++ exif_iif_add_tag(ImageInfo, SECTION_APP12, "Company", TAG_NONE, TAG_FMT_STRING, l1, buffer+2, l1);
+ if (length > 2+l1+1) {
+ l2 = php_strnlen(buffer+2+l1+1, length-2-l1-1);
+- exif_iif_add_tag(ImageInfo, SECTION_APP12, "Info", TAG_NONE, TAG_FMT_STRING, l2, buffer+2+l1+1);
++ exif_iif_add_tag(ImageInfo, SECTION_APP12, "Info", TAG_NONE, TAG_FMT_STRING, l2, buffer+2+l1+1, l2);
+ }
+ }
+ #ifdef EXIF_DEBUG
+@@ -4099,7 +4112,7 @@
+ if (ImageInfo.Thumbnail.size) {
+ if (read_thumbnail) {
+ /* not exif_iif_add_str : this is a buffer */
+- exif_iif_add_tag(&ImageInfo, SECTION_THUMBNAIL, "THUMBNAIL", TAG_NONE, TAG_FMT_UNDEFINED, ImageInfo.Thumbnail.size, ImageInfo.Thumbnail.data);
++ exif_iif_add_tag(&ImageInfo, SECTION_THUMBNAIL, "THUMBNAIL", TAG_NONE, TAG_FMT_UNDEFINED, ImageInfo.Thumbnail.size, ImageInfo.Thumbnail.data, ImageInfo.Thumbnail.size);
+ }
+ if (!ImageInfo.Thumbnail.width || !ImageInfo.Thumbnail.height) {
+ /* try to evaluate if thumbnail data is present */
+--- /dev/null
++++ b/ext/exif/tests/bug77831.phpt
+@@ -0,0 +1,13 @@
++--TEST--
++Bug #77831 (Heap-buffer-overflow in exif_iif_add_value in EXIF)
++--SKIPIF--
++<?php if (!extension_loaded('exif')) print 'skip exif extension not available';?>
++--FILE--
++<?php
++var_dump(exif_read_data(__DIR__."/bug77831.tiff"));
++?>
++DONE
++--EXPECTF--
++%A
++bool(false)
++DONE
+\ No newline at end of file
+--- /dev/null
++++ b/ext/exif/tests/bug77831.tiff
+@@ -0,0 +1 @@
++џис
+\ No newline at end of file
+--- a/ext/exif/exif.c
++++ b/ext/exif/exif.c
+@@ -2890,7 +2890,7 @@
+ offset_base is ImageInfo->file.list[sn].data-dir_offset
+ dir_entry - offset_base is dir_offset+2+i*12
+ */
+- if (byte_count > IFDlength || offset_val > IFDlength-byte_count || value_ptr < dir_entry || offset_val < (size_t)(dir_entry-offset_base)) {
++ if (byte_count > IFDlength || offset_val > IFDlength-byte_count || value_ptr < dir_entry || offset_val < (size_t)(dir_entry-offset_base) || dir_entry <= offset_base) {
+ /* It is important to check for IMAGE_FILETYPE_TIFF
+ * JPEG does not use absolute pointers instead its pointers are
+ * relative to the start of the TIFF header in APP1 section. */
+diff --git a/ext/gd/libgd/xbm.c b/ext/gd/libgd/xbm.c
+index 044159d..16978a1 100644
+--- a/ext/gd/libgd/xbm.c
++++ b/ext/gd/libgd/xbm.c
+@@ -135,7 +135,11 @@
+ }
+ h[3] = ch;
+ }
+- sscanf(h, "%x", &b);
++ if (sscanf(h, "%x", &b) != 1) {
++ php_gd_error("invalid XBM");
++ gdImageDestroy(im);
++ return 0;
++ }
+ for (bit = 1; bit <= max_bit; bit = bit << 1) {
+ gdImageSetPixel(im, x++, y, (b & bit) ? 1 : 0);
+ if (x == im->sx) {
+--- /dev/null
++++ b/ext/gd/tests/bug77973.phpt
+@@ -0,0 +1,26 @@
++--TEST--
++Bug #77973 (Uninitialized read in gdImageCreateFromXbm)
++--SKIPIF--
++<?php
++if (!extension_loaded('gd')) die("skip gd extension not available");
++if (!function_exists('imagecreatefromxbm')) die("skip imagecreatefromxbm not available");
++?>
++--FILE--
++<?php
++$contents = hex2bin("23646566696e6520776964746820320a23646566696e652068656967687420320a737461746963206368617220626974735b5d203d7b0a7a7a787a7a");
++$filepath = __DIR__ . '/bug77973.xbm';
++file_put_contents($filepath, $contents);
++$im = imagecreatefromxbm($filepath);
++var_dump($im);
++?>
++===DONE===
++--EXPECTF--
++Warning: imagecreatefromxbm(): invalid XBM in %s on line %d
++
++Warning: imagecreatefromxbm(): '%s' is not a valid XBM file in %s on line %d
++bool(false)
++===DONE===
++--CLEAN--
++<?php
++unlink(__DIR__ . '/bug77973.xbm');
++?>
+diff --git a/ext/iconv/iconv.c b/ext/iconv/iconv.c
+index ea619aa..0614534 100644
+--- a/ext/iconv/iconv.c
++++ b/ext/iconv/iconv.c
+@@ -1645,7 +1645,9 @@
+ * we can do at this point. */
+ if (*(p1 + 1) == '=') {
+ ++p1;
+- --str_left;
++ if (str_left > 1) {
++ --str_left;
++ }
+ }
+
+ err = _php_iconv_appendl(pretval, encoded_word, (size_t)((p1 + 1) - encoded_word), cd_pl);
+--- /dev/null
++++ b/ext/iconv/tests/bug78069.data
+@@ -0,0 +1 @@
++SuLt; 0Jpaa
+\ No newline at end of file
+--- /dev/null
++++ b/ext/iconv/tests/bug78069.phpt
+@@ -0,0 +1,15 @@
++--TEST--
++Bug #78069 (Out-of-bounds read in iconv.c:_php_iconv_mime_decode() due to integer overflow)
++--SKIPIF--
++<?php
++if (!extension_loaded('iconv')) die('skip ext/iconv required');
++?>
++--FILE--
++<?php
++$hdr = iconv_mime_decode_headers(file_get_contents(__DIR__ . "/bug78069.data"),2);
++var_dump(count($hdr));
++?>
++DONE
++--EXPECT--
++int(1)
++DONE
+\ No newline at end of file
+--- a/ext/exif/exif.c
++++ b/ext/exif/exif.c
+@@ -3525,6 +3525,8 @@
+ if (c == 0xFF)
+ return FALSE;
+ marker = c;
++ if (pos>=ImageInfo->Thumbnail.size)
++ return FALSE;
+ length = php_jpg_get16(data+pos);
+ if (length > ImageInfo->Thumbnail.size || pos >= ImageInfo->Thumbnail.size - length) {
+ return FALSE;
+--- a/ext/sqlite3/sqlite3.c
++++ b/ext/sqlite3/sqlite3.c
+@@ -2054,6 +2054,15 @@
+ }
+ #endif
+
++ if (strncmp(arg3, "file:", 5) == 0) {
++ /* starts with "file:" */
++ if (!arg3[5]) {
++ return SQLITE_DENY;
++ }
++ if (php_check_open_basedir(arg3 + 5)) {
++ return SQLITE_DENY;
++ }
++ }
+ if (php_check_open_basedir(arg3)) {
+ return SQLITE_DENY;
+ }
+diff --git a/ext/curl/tests/check_win_config.phpt b/ext/curl/tests/check_win_config.phpt
+index 98f3e92..9e1ad98 100644
+--- a/ext/curl/tests/check_win_config.phpt
++++ b/ext/curl/tests/check_win_config.phpt
+@@ -45,7 +45,7 @@
+ KERBEROS5 => Yes
+ UNIX_SOCKETS => No
+ PSL => No
+-Protocols => dict, file, ftp, ftps, gopher, http, https, imap, imaps, ldap, pop3, pop3s, rtsp, scp, sftp, smtp, smtps, telnet, tftp
++Protocols => dict, file, ftp, ftps, gopher, http, https, imap, imaps, ldap, ldaps, pop3, pop3s, rtsp, scp, sftp, smb, smbs, smtp, smtps, telnet, tftp
+ Host => %s-pc-win32
+ SSL Version => OpenSSL/%s
+ ZLib Version => %s
+diff --git a/ext/curl/tests/curl_basic_009.phpt b/ext/curl/tests/curl_basic_009.phpt
+index 529e590..3b36a78 100644
+--- a/ext/curl/tests/curl_basic_009.phpt
++++ b/ext/curl/tests/curl_basic_009.phpt
+@@ -18,6 +18,6 @@
+
+
+ ?>
+---EXPECTF--
+-%unicode|string%(%d) "%Srotocol%s"
+-int(1)
++--EXPECTREGEX--
++string\(\d+\) "([^\r\n]*rotocol[^\r\n]+|Could not resolve host: .+)"
++int\(\d\)
+diff --git a/ext/pdo_mysql/tests/pdo_mysql_exec.phpt b/ext/pdo_mysql/tests/pdo_mysql_exec.phpt
+index acd9090..9830737 100644
+--- a/ext/pdo_mysql/tests/pdo_mysql_exec.phpt
++++ b/ext/pdo_mysql/tests/pdo_mysql_exec.phpt
+@@ -75,7 +75,7 @@
+ exec_and_count(19, $db, 'CREATE PROCEDURE p(OUT ver_param VARCHAR(255)) BEGIN SELECT VERSION() INTO ver_param; END;', 0);
+ // we got this far without problems. If there's an issue from now on, its a failure
+ $ignore_exception = false;
+- exec_and_count(20, $db, 'CALL p(@version)', 0);
++ exec_and_count(20, $db, 'CALL p(@version)', 1);
+ $stmt = $db->query('SELECT @version AS p_version');
+ $tmp = $stmt->fetchAll(PDO::FETCH_ASSOC);
+ if (count($tmp) > 1 || !isset($tmp[0]['p_version'])) {
+diff --git a/ext/pdo_mysql/tests/pdo_mysql_stmt_getcolumnmeta.phpt b/ext/pdo_mysql/tests/pdo_mysql_stmt_getcolumnmeta.phpt
+index 72b5315..82806ce 100644
+--- a/ext/pdo_mysql/tests/pdo_mysql_stmt_getcolumnmeta.phpt
++++ b/ext/pdo_mysql/tests/pdo_mysql_stmt_getcolumnmeta.phpt
+@@ -38,7 +38,7 @@
+ if (false !== ($tmp = @$stmt->getColumnMeta(-1)))
+ printf("[004] Expecting false got %s\n", var_export($tmp, true));
+
+- // Warning: PDOStatement::getColumnMeta() expects parameter 1 to be integer, array given in
++ // Warning: PDOStatement::getColumnMeta() expects parameter 1 to be int, array given in
+ if (false !== ($tmp = @$stmt->getColumnMeta(array())))
+ printf("[005] Expecting false got %s\n", var_export($tmp, true));
+
+@@ -162,37 +162,37 @@
+ test_meta($db, 100, 'INT', -2147483648, 'LONG', ($is_mysqlnd) ? PDO::PARAM_INT : PDO::PARAM_STR);
+ test_meta($db, 110, 'INT UNSIGNED', 4294967295, 'LONG', ($is_mysqlnd) ? PDO::PARAM_INT : PDO::PARAM_STR);
+
+- test_meta($db, 120, 'BIGINT', -9223372036854775808, 'LONGLONG', ($is_mysqlnd) ? ((PHP_INT_SIZE == 4) ? PDO::PARAM_STR : PDO::PARAM_INT) : PDO::PARAM_STR);
+- test_meta($db, 130, 'BIGINT UNSIGNED', 18446744073709551615, 'LONGLONG', ($is_mysqlnd) ? ((PHP_INT_SIZE == 4) ? PDO::PARAM_STR : PDO::PARAM_INT) : PDO::PARAM_STR);
++ test_meta($db, 120, 'BIGINT', '-9223372036854775808', 'LONGLONG', ($is_mysqlnd) ? ((PHP_INT_SIZE == 4) ? PDO::PARAM_STR : PDO::PARAM_INT) : PDO::PARAM_STR);
++ test_meta($db, 130, 'BIGINT UNSIGNED', '18446744073709551615', 'LONGLONG', ($is_mysqlnd) ? ((PHP_INT_SIZE == 4) ? PDO::PARAM_STR : PDO::PARAM_INT) : PDO::PARAM_STR);
+
+ test_meta($db, 130, 'REAL', -1.01, ($real_as_float) ? 'FLOAT' : 'DOUBLE', PDO::PARAM_STR);
+ test_meta($db, 140, 'REAL UNSIGNED', 1.01, ($real_as_float) ? 'FLOAT' : 'DOUBLE', PDO::PARAM_STR);
+- test_meta($db, 150, 'REAL ZEROFILL', -1.01, ($real_as_float) ? 'FLOAT' : 'DOUBLE', PDO::PARAM_STR);
++ test_meta($db, 150, 'REAL ZEROFILL', 1.01, ($real_as_float) ? 'FLOAT' : 'DOUBLE', PDO::PARAM_STR);
+ test_meta($db, 160, 'REAL UNSIGNED ZEROFILL', 1.01, ($real_as_float) ? 'FLOAT' : 'DOUBLE', PDO::PARAM_STR);
+
+ test_meta($db, 170, 'DOUBLE', -1.01, 'DOUBLE', PDO::PARAM_STR);
+ test_meta($db, 180, 'DOUBLE UNSIGNED', 1.01, 'DOUBLE', PDO::PARAM_STR);
+- test_meta($db, 190, 'DOUBLE ZEROFILL', -1.01, 'DOUBLE', PDO::PARAM_STR);
++ test_meta($db, 190, 'DOUBLE ZEROFILL', 1.01, 'DOUBLE', PDO::PARAM_STR);
+ test_meta($db, 200, 'DOUBLE UNSIGNED ZEROFILL', 1.01, 'DOUBLE', PDO::PARAM_STR);
+
+ test_meta($db, 210, 'FLOAT', -1.01, 'FLOAT', PDO::PARAM_STR);
+ test_meta($db, 220, 'FLOAT UNSIGNED', 1.01, 'FLOAT', PDO::PARAM_STR);
+- test_meta($db, 230, 'FLOAT ZEROFILL', -1.01, 'FLOAT', PDO::PARAM_STR);
++ test_meta($db, 230, 'FLOAT ZEROFILL', 1.01, 'FLOAT', PDO::PARAM_STR);
+ test_meta($db, 240, 'FLOAT UNSIGNED ZEROFILL', 1.01, 'FLOAT', PDO::PARAM_STR);
+
+ test_meta($db, 250, 'DECIMAL', -1.01, array('DECIMAL', 'NEWDECIMAL'), PDO::PARAM_STR);
+ test_meta($db, 260, 'DECIMAL UNSIGNED', 1.01, array('DECIMAL', 'NEWDECIMAL'), PDO::PARAM_STR);
+- test_meta($db, 270, 'DECIMAL ZEROFILL', -1.01, array('DECIMAL', 'NEWDECIMAL'), PDO::PARAM_STR);
++ test_meta($db, 270, 'DECIMAL ZEROFILL', 1.01, array('DECIMAL', 'NEWDECIMAL'), PDO::PARAM_STR);
+ test_meta($db, 280, 'DECIMAL UNSIGNED ZEROFILL', 1.01, array('DECIMAL', 'NEWDECIMAL'), PDO::PARAM_STR);
+
+ test_meta($db, 290, 'NUMERIC', -1.01, array('DECIMAL', 'NEWDECIMAL'), PDO::PARAM_STR);
+ test_meta($db, 300, 'NUMERIC UNSIGNED', 1.01, array('DECIMAL', 'NEWDECIMAL'), PDO::PARAM_STR);
+- test_meta($db, 310, 'NUMERIC ZEROFILL', -1.01, array('DECIMAL', 'NEWDECIMAL'), PDO::PARAM_STR);
++ test_meta($db, 310, 'NUMERIC ZEROFILL', 1.01, array('DECIMAL', 'NEWDECIMAL'), PDO::PARAM_STR);
+ test_meta($db, 320, 'NUMERIC UNSIGNED ZEROFILL', 1.01, array('DECIMAL', 'NEWDECIMAL'), PDO::PARAM_STR);
+
+ test_meta($db, 330, 'DATE', '2008-04-23', array('DATE', 'NEWDATE'), PDO::PARAM_STR);
+ test_meta($db, 340, 'TIME', '14:37:00', 'TIME', PDO::PARAM_STR);
+- test_meta($db, 350, 'TIMESTAMP', time(), 'TIMESTAMP', PDO::PARAM_STR);
++ test_meta($db, 350, 'TIMESTAMP', '2008-03-23 14:38:00', 'TIMESTAMP', PDO::PARAM_STR);
+ test_meta($db, 360, 'DATETIME', '2008-03-23 14:38:00', 'DATETIME', PDO::PARAM_STR);
+ test_meta($db, 370, 'YEAR', '2008', 'YEAR', ($is_mysqlnd) ? PDO::PARAM_INT : PDO::PARAM_STR);
+
+@@ -309,6 +309,6 @@
+ $db->exec('DROP TABLE IF EXISTS test');
+ print "done!";
+ ?>
+---EXPECTF--
++--EXPECT--
+ Testing native PS...
+ done!
+diff --git a/ext/standard/tests/streams/stream_socket_sendto.phpt b/ext/standard/tests/streams/stream_socket_sendto.phpt
+deleted file mode 100644
+index 62d9f6e..0000000
+--- a/ext/standard/tests/streams/stream_socket_sendto.phpt
++++ /dev/null
+@@ -1,58 +0,0 @@
+---TEST--
+-int stream_socket_sendto ( resource $socket , string $data [, int $flags = 0 [, string $address ]] );
+---CREDITS--
+-marcosptf - <marcosptf@yahoo.com.br> - @phpsp - sao paulo - br
+---SKIPIF--
+-<?php
+-if (getenv("SKIP_ONLINE_TESTS")) { die('skip: online test'); }
+-?>
+---FILE--
+-<?php
+-$serverUri = "tcp://127.0.0.1:31854";
+-$serverUrl = "http://php.net";
+-$stringSocket = "out of band data.";
+-$stringFWrite = "normal data to transmit";
+-$sock = stream_socket_server($serverUri, $errno, $errstr);
+-
+-if (is_resource($sock)) {
+- fwrite($sock, $stringFWrite);
+- var_dump(stream_socket_sendto());
+- var_dump(stream_socket_sendto($sock));
+- var_dump(stream_socket_sendto($sock, $stringSocket));
+- var_dump(stream_socket_sendto($sock, $stringSocket, STREAM_OOB));
+- var_dump(stream_socket_sendto($sock, $stringSocket, STREAM_OOB, $serverUri));
+- var_dump(stream_socket_sendto($sock, $stringSocket, STREAM_OOB, $serverUrl));
+-} else {
+- die("Test stream_socket_enable_crypto has failed; Unable to connect: {$errstr} ({$errno})");
+-}
+-?>
+---EXPECTF--
+-Notice: fwrite(): send of %i bytes failed with errno=%i Broken pipe in %s on line %i
+-
+-Warning: stream_socket_sendto() expects at least %i parameters, %i given in %s on line %i
+-bool(%s)
+-
+-Warning: stream_socket_sendto() expects at least %i parameters, %i given in %s on line %i
+-bool(%s)
+-
+-Warning: stream_socket_sendto(): Broken pipe
+- in %s on line %i
+-int(%i)
+-
+-Warning: stream_socket_sendto(): Broken pipe
+- in %s on line %i
+-int(%i)
+-
+-Warning: stream_socket_sendto(): php_network_getaddresses: getaddrinfo failed: Name or service not known in %s on line %i
+-
+-Warning: stream_socket_sendto(): Failed to resolve %s: php_network_getaddresses: getaddrinfo failed: Name or service not known in %s on line %i
+-
+-Warning: stream_socket_sendto(): Failed to parse %s into a valid network address in %s on line %i
+-bool(%s)
+-
+-Warning: stream_socket_sendto(): php_network_getaddresses: getaddrinfo failed: Name or service not known in %s on line %i
+-
+-Warning: stream_socket_sendto(): Failed to resolve %s: php_network_getaddresses: getaddrinfo failed: Name or service not known in %s on line %i
+-
+-Warning: stream_socket_sendto(): Failed to parse %s into a valid network address in %s on line %i
+-bool(%s)
+diff --git a/ext/standard/tests/strings/bug65769.phpt b/ext/standard/tests/strings/bug65769.phpt
+index 1a81d48..efe5788 100644
+--- a/ext/standard/tests/strings/bug65769.phpt
++++ b/ext/standard/tests/strings/bug65769.phpt
+@@ -26,6 +26,9 @@
+ $lconv['mon_decimal_point'],
+ $lconv['mon_thousands_sep']
+ );
++ if ($locale === 'Swedish_Sweden.1252') {
++ var_dump(in_array($lconv['mon_thousands_sep'], ['.', ' ']));
++ }
+ echo '++++++++++++++++++++++', "\n";
+ }
+
+@@ -38,7 +41,8 @@
+ string(3) "SEK"
+ string(2) "kr"
+ string(1) ","
+-string(1) "."
++string(1) "%c"
++bool(true)
+ ++++++++++++++++++++++
+ string(18) "French_France.1252"
+ string(1) ","
+@@ -64,7 +68,7 @@
+ string(1) ","
+ string(1) " "
+ ++++++++++++++++++++++
+-string(25) "Czech_Czech Republic.1250"
++string(%d) "Czech_Czech%s.1250"
+ string(1) ","
+ string(1) " "
+ string(3) "CZK"
+diff --git a/sapi/cli/tests/php_cli_server.inc b/sapi/cli/tests/php_cli_server.inc
+index 5ee3887..0ea90da 100644
+--- a/sapi/cli/tests/php_cli_server.inc
++++ b/sapi/cli/tests/php_cli_server.inc
+@@ -11,13 +11,14 @@
+ file_put_contents($doc_root . '/' . ($router ?: 'index.php'), '<?php ' . $code . ' ?>');
+ }
+
++ if (substr(PHP_OS, 0, 3) == 'WIN') {
+ $descriptorspec = array(
+ 0 => STDIN,
+ 1 => STDOUT,
+- 2 => STDERR,
++ 2 => array("pipe","w"),
+ );
+
+- if (substr(PHP_OS, 0, 3) == 'WIN') {
++
+ $cmd = "{$php_executable} -t {$doc_root} -n {$cmd_args} -S " . PHP_CLI_SERVER_ADDRESS;
+ if (!is_null($router)) {
+ $cmd .= " {$router}";
+@@ -25,6 +26,11 @@
+
+ $handle = proc_open(addslashes($cmd), $descriptorspec, $pipes, $doc_root, NULL, array("bypass_shell" => true, "suppress_errors" => true));
+ } else {
++ $descriptorspec = array(
++ 0 => STDIN,
++ 1 => STDOUT,
++ 2 => STDERR,
++ );
+ $cmd = "exec {$php_executable} -t {$doc_root} -n {$cmd_args} -S " . PHP_CLI_SERVER_ADDRESS;
+ if (!is_null($router)) {
+ $cmd .= " {$router}";
+diff --git a/ext/exif/exif.c b/ext/exif/exif.c
+index dd7d268..8b379bb 100644
+--- a/ext/exif/exif.c
++++ b/ext/exif/exif.c
+@@ -3497,7 +3497,7 @@
+ size_t length=2, pos=0;
+ jpeg_sof_info sof_info;
+
+- if (!data) {
++ if (!data || ImageInfo->Thumbnail.size < 4) {
+ return FALSE; /* nothing to do here */
+ }
+ if (memcmp(data, "\xFF\xD8\xFF", 3)) {
+--- /dev/null
++++ b/ext/exif/tests/bug78222.jpg
+@@ -0,0 +1 @@
++џис
+\ No newline at end of file
+--- /dev/null
++++ b/ext/exif/tests/bug78222.phpt
+@@ -0,0 +1,11 @@
++--TEST--
++Bug #78222 (heap-buffer-overflow on exif_scan_thumbnail)
++--SKIPIF--
++<?php if (!extension_loaded('exif')) print 'skip exif extension not available';?>
++--FILE--
++<?php
++exif_read_data(__DIR__."/bug78222.jpg", 'THUMBNAIL', FALSE, TRUE);
++?>
++DONE
++--EXPECTF--
++DONE
+\ No newline at end of file
+diff --git a/ext/exif/exif.c b/ext/exif/exif.c
+index 8b379bb..3f8dd90 100644
+--- a/ext/exif/exif.c
++++ b/ext/exif/exif.c
+@@ -2619,7 +2619,7 @@
+ {
+ int a;
+ char *decode;
+- size_t len;;
++ size_t len;
+
+ *pszEncoding = NULL;
+ /* Copy the comment */
+@@ -2632,11 +2632,11 @@
+ /* First try to detect BOM: ZERO WIDTH NOBREAK SPACE (FEFF 16)
+ * since we have no encoding support for the BOM yet we skip that.
+ */
+- if (!memcmp(szValuePtr, "\xFE\xFF", 2)) {
++ if (ByteCount >=2 && !memcmp(szValuePtr, "\xFE\xFF", 2)) {
+ decode = "UCS-2BE";
+ szValuePtr = szValuePtr+2;
+ ByteCount -= 2;
+- } else if (!memcmp(szValuePtr, "\xFF\xFE", 2)) {
++ } else if (ByteCount >=2 && !memcmp(szValuePtr, "\xFF\xFE", 2)) {
+ decode = "UCS-2LE";
+ szValuePtr = szValuePtr+2;
+ ByteCount -= 2;
+--- /dev/null
++++ b/ext/exif/tests/bug78256.jpg
+@@ -0,0 +1 @@
++џис
+\ No newline at end of file
+--- /dev/null
++++ b/ext/exif/tests/bug78256.phpt
+@@ -0,0 +1,11 @@
++--TEST--
++Bug #78256 (heap-buffer-overflow on exif_process_user_comment)
++--SKIPIF--
++<?php if (!extension_loaded('exif')) print 'skip exif extension not available';?>
++--FILE--
++<?php
++@exif_read_data(__DIR__."/bug78256.jpg", 'COMMENT', FALSE, TRUE);
++?>
++DONE
++--EXPECTF--
++DONE
+\ No newline at end of file
+diff --git a/ext/mbstring/oniguruma/regext.c b/ext/mbstring/oniguruma/regext.c
+index b1b957b..b108e63 100644
+--- a/ext/mbstring/oniguruma/regext.c
++++ b/ext/mbstring/oniguruma/regext.c
+@@ -29,6 +29,7 @@
+
+ #include "regint.h"
+
++#if 0
+ static void
+ conv_ext0be32(const UChar* s, const UChar* end, UChar* conv)
+ {
+@@ -158,6 +159,7 @@
+
+ return ONIGERR_NOT_SUPPORTED_ENCODING_COMBINATION;
+ }
++#endif
+
+ extern int
+ onig_new_deluxe(regex_t** reg, const UChar* pattern, const UChar* pattern_end,
+@@ -169,9 +171,7 @@
+ if (IS_NOT_NULL(einfo)) einfo->par = (UChar* )NULL;
+
+ if (ci->pattern_enc != ci->target_enc) {
+- r = conv_encoding(ci->pattern_enc, ci->target_enc, pattern, pattern_end,
+- &cpat, &cpat_end);
+- if (r) return r;
++ return ONIGERR_NOT_SUPPORTED_ENCODING_COMBINATION;
+ }
+ else {
+ cpat = (UChar* )pattern;
+diff --git a/ext/pcre/pcrelib/pcre_compile.c b/ext/pcre/pcrelib/pcre_compile.c
+index c782774..402c428 100644
+--- a/ext/pcre/pcrelib/pcre_compile.c
++++ b/ext/pcre/pcrelib/pcre_compile.c
+@@ -483,7 +483,7 @@
+ "lookbehind assertion is not fixed length\0"
+ "malformed number or name after (?(\0"
+ "conditional group contains more than two branches\0"
+- "assertion expected after (?(\0"
++ "assertion expected after (?( or (?(?C)\0"
+ "(?R or (?[+-]digits must be followed by )\0"
+ /* 30 */
+ "unknown POSIX class name\0"
+@@ -6732,6 +6732,15 @@
+ for (i = 3;; i++) if (!IS_DIGIT(ptr[i])) break;
+ if (ptr[i] == CHAR_RIGHT_PARENTHESIS)
+ tempptr += i + 1;
++
++ /* tempptr should now be pointing to the opening parenthesis of the
++ assertion condition. */
++
++ if (*tempptr != CHAR_LEFT_PARENTHESIS)
++ {
++ *errorcodeptr = ERR28;
++ goto FAILED;
++ }
+ }
+
+ /* For conditions that are assertions, check the syntax, and then exit
+--- /dev/null
++++ b/ext/pcre/tests/bug75457.phpt
+@@ -0,0 +1,10 @@
++--TEST--
++Bug #75457 (heap-use-after-free in php7.0.25)
++--FILE--
++<?php
++$pattern = "/(((?(?C)0?=))(?!()0|.(?0)0)())/";
++var_dump(preg_match($pattern, "hello"));
++?>
++--EXPECTF--
++Warning: preg_match(): Compilation failed: assertion expected after (?( or (?(?C) at offset 4 in %sbug75457.php on line %d
++bool(false)
+diff --git a/ext/opcache/tests/php_cli_server.inc b/ext/opcache/tests/php_cli_server.inc
+index 456ed66..ca781b7 100644
+--- a/ext/opcache/tests/php_cli_server.inc
++++ b/ext/opcache/tests/php_cli_server.inc
+@@ -7,16 +7,22 @@
+ $php_executable = getenv('TEST_PHP_EXECUTABLE');
+ $doc_root = __DIR__;
+
+- $descriptorspec = array(
+- 0 => STDIN,
+- 1 => STDOUT,
+- 2 => STDERR,
+- );
+-
+ if (substr(PHP_OS, 0, 3) == 'WIN') {
++ $descriptorspec = array(
++ 0 => STDIN,
++ 1 => STDOUT,
++ 2 => array("pipe", "w"),
++ );
++
+ $cmd = "{$php_executable} -t {$doc_root} $ini -S " . PHP_CLI_SERVER_ADDRESS;
+ $handle = proc_open(addslashes($cmd), $descriptorspec, $pipes, $doc_root, NULL, array("bypass_shell" => true, "suppress_errors" => true));
+ } else {
++ $descriptorspec = array(
++ 0 => STDIN,
++ 1 => STDOUT,
++ 2 => STDERR,
++ );
++
+ $cmd = "exec {$php_executable} -t {$doc_root} $ini -S " . PHP_CLI_SERVER_ADDRESS . " 2>/dev/null";
+ $handle = proc_open($cmd, $descriptorspec, $pipes, $doc_root);
+ }
+diff --git a/ext/opcache/tests/bug66461.phpt b/ext/opcache/tests/bug66461.phpt
+index 33132ab..2d09fef 100644
+--- a/ext/opcache/tests/bug66461.phpt
++++ b/ext/opcache/tests/bug66461.phpt
+@@ -4,6 +4,7 @@
+ opcache.enable=1
+ opcache.enable_cli=1
+ opcache.optimization_level=-1
++opcache.log_verbosity_level=1
+ opcache.file_update_protection=0
+ opcache.interned_strings_buffer=0
+ --SKIPIF--
+diff --git a/ext/opcache/tests/issue0115.phpt b/ext/opcache/tests/issue0115.phpt
+index 26d9908..8794a00 100644
+--- a/ext/opcache/tests/issue0115.phpt
++++ b/ext/opcache/tests/issue0115.phpt
+@@ -32,7 +32,7 @@
+ unset($p);
+
+ include "php_cli_server.inc";
+-php_cli_server_start('-d opcache.enable=1 -d opcache.enable_cli=1 -d extension=phar.'.PHP_SHLIB_SUFFIX);
++php_cli_server_start('-d opcache.enable=1 -d opcache.enable_cli=1 -d extension='.(substr(PHP_OS, 0, 3) == 'WIN' ? 'php_' : '').'phar.'.PHP_SHLIB_SUFFIX);
+ echo file_get_contents('http://' . PHP_CLI_SERVER_ADDRESS . '/issue0115_1.phar.php');
+ echo file_get_contents('http://' . PHP_CLI_SERVER_ADDRESS . '/issue0115_2.phar.php');
+ ?>
+diff --git a/ext/opcache/tests/issue0149.phpt b/ext/opcache/tests/issue0149.phpt
+index ba57623..f8ff972 100644
+--- a/ext/opcache/tests/issue0149.phpt
++++ b/ext/opcache/tests/issue0149.phpt
+@@ -20,7 +20,7 @@
+ unset($p);
+
+ include "php_cli_server.inc";
+-php_cli_server_start('-d opcache.enable=1 -d opcache.enable_cli=1 -d extension=phar.'.PHP_SHLIB_SUFFIX);
++php_cli_server_start('-d opcache.enable=1 -d opcache.enable_cli=1 -d extension='.(substr(PHP_OS, 0, 3) == 'WIN' ? 'php_' : '').'phar.'.PHP_SHLIB_SUFFIX);
+ echo file_get_contents('http://' . PHP_CLI_SERVER_ADDRESS . '/issue0149.phar.php');
+ echo file_get_contents('http://' . PHP_CLI_SERVER_ADDRESS . '/issue0149.phar.php');
+ echo file_get_contents('http://' . PHP_CLI_SERVER_ADDRESS . '/issue0149.phar.php');
+diff --git a/sapi/fpm/fpm/fpm_main.c b/sapi/fpm/fpm/fpm_main.c
+index 695839c..88c7c9f 100644
+--- a/sapi/fpm/fpm/fpm_main.c
++++ b/sapi/fpm/fpm/fpm_main.c
+@@ -1208,8 +1208,8 @@
+ path_info = script_path_translated + ptlen;
+ tflag = (slen != 0 && (!orig_path_info || strcmp(orig_path_info, path_info) != 0));
+ } else {
+- path_info = env_path_info ? env_path_info + pilen - slen : NULL;
+- tflag = (orig_path_info != path_info);
++ path_info = (env_path_info && pilen > slen) ? env_path_info + pilen - slen : NULL;
++ tflag = path_info && (orig_path_info != path_info);
+ }
+
+ if (tflag) {
+--- a/ext/bcmath/libbcmath/src/str2num.c
++++ b/ext/bcmath/libbcmath/src/str2num.c
+@@ -57,9 +57,9 @@
+ zero_int = FALSE;
+ if ( (*ptr == '+') || (*ptr == '-')) ptr++; /* Sign */
+ while (*ptr == '0') ptr++; /* Skip leading zeros. */
+- while (isdigit((int)*ptr)) ptr++, digits++; /* digits */
++ while (*ptr >= '0' && *ptr <= '9') ptr++, digits++; /* digits */
+ if (*ptr == '.') ptr++; /* decimal point */
+- while (isdigit((int)*ptr)) ptr++, strscale++; /* digits */
++ while (*ptr >= '0' && *ptr <= '9') ptr++, strscale++; /* digits */
+ if ((*ptr != '\0') || (digits+strscale == 0))
+ {
+ *num = bc_copy_num (BCG(_zero_));
+--- a/ext/spl/spl_directory.c
++++ b/ext/spl/spl_directory.c
+@@ -684,10 +684,10 @@
+
+ if (SPL_HAS_FLAG(ctor_flags, DIT_CTOR_FLAGS)) {
+ flags = SPL_FILE_DIR_KEY_AS_PATHNAME|SPL_FILE_DIR_CURRENT_AS_FILEINFO;
+- parsed = zend_parse_parameters(ZEND_NUM_ARGS(), "s|l", &path, &len, &flags);
++ parsed = zend_parse_parameters(ZEND_NUM_ARGS(), "p|l", &path, &len, &flags);
+ } else {
+ flags = SPL_FILE_DIR_KEY_AS_PATHNAME|SPL_FILE_DIR_CURRENT_AS_SELF;
+- parsed = zend_parse_parameters(ZEND_NUM_ARGS(), "s", &path, &len);
++ parsed = zend_parse_parameters(ZEND_NUM_ARGS(), "p", &path, &len);
+ }
+ if (SPL_HAS_FLAG(ctor_flags, SPL_FILE_DIR_SKIPDOTS)) {
+ flags |= SPL_FILE_DIR_SKIPDOTS;
+diff --git a/ext/exif/exif.c b/ext/exif/exif.c
+index 3f8dd90..a7da928 100644
+--- a/ext/exif/exif.c
++++ b/ext/exif/exif.c
+@@ -2820,8 +2820,9 @@
+ }
+
+ for (de=0;de<NumDirEntries;de++) {
+- if (!exif_process_IFD_TAG(ImageInfo, dir_start + 2 + 12 * de,
+- offset_base, data_len, displacement, section_index, 0, maker_note->tag_table)) {
++ size_t offset = 2 + 12 * de;
++ if (!exif_process_IFD_TAG(ImageInfo, dir_start + offset,
++ offset_base, data_len - offset, displacement, section_index, 0, maker_note->tag_table)) {
+ return FALSE;
+ }
+ }
+--- a/ext/exif/exif.c
++++ b/ext/exif/exif.c
+@@ -2748,7 +2748,8 @@
+ continue;
+ if (maker_note->model && (!ImageInfo->model || strcmp(maker_note->model, ImageInfo->model)))
+ continue;
+- if (maker_note->id_string && strncmp(maker_note->id_string, value_ptr, maker_note->id_string_len))
++ if (maker_note->id_string && value_len >= maker_note->id_string_len
++ && strncmp(maker_note->id_string, value_ptr, maker_note->id_string_len))
+ continue;
+ break;
+ }
+diff --git a/ext/standard/string.c b/ext/standard/string.c
+index a8b39ee..c4b5e03 100644
+--- a/ext/standard/string.c
++++ b/ext/standard/string.c
+@@ -4757,7 +4757,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 != '\\') {
+@@ -4784,7 +4784,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 {
+@@ -4811,7 +4811,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 122ff4c..657eb98 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 c4b5e03..7c044af 100644
+--- a/ext/standard/string.c
++++ b/ext/standard/string.c
+@@ -4707,7 +4707,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;
+@@ -4728,7 +4728,7 @@
+ break;
+
+ case 2: /* PHP */
+- if (!br && lc != '\"' && *(p-1) == '?') {
++ if (!br && lc != '\"' && p >= buf + 1 && *(p-1) == '?') {
+ in_q = state = 0;
+ tp = tbuf;
+ }
+--- a/ext/dom/document.c
++++ b/ext/dom/document.c
+@@ -341,7 +341,7 @@
+
+ str = zval_get_string(newval);
+
+- handler = xmlFindCharEncodingHandler(Z_STRVAL_P(newval));
++ handler = xmlFindCharEncodingHandler(ZSTR_VAL(str));
+
+ if (handler != NULL) {
+ xmlCharEncCloseFunc(handler);
+--- /dev/null
++++ b/ext/dom/tests/bug77569.phpt
+@@ -0,0 +1,14 @@
++--TEST--
++Bug #77569 (Write Acess Violation in DomImplementation)
++--SKIPIF--
++<?php
++if (!extension_loaded('dom')) die('skip dom extension not available');
++?>
++--FILE--
++<?php
++$imp = new DOMImplementation;
++$dom = $imp->createDocument("", "");
++$dom->encoding = null;
++?>
++--EXPECTF--
++Warning: main(): Invalid Document Encoding in %s on line %d
+diff --git a/ext/session/session.c b/ext/session/session.c
+index bd557b0..48a15b6 100644
+--- a/ext/session/session.c
++++ b/ext/session/session.c
+@@ -3108,9 +3108,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 d4ad4e0..8a0d369 100644
+--- a/ext/phar/phar_object.c
++++ b/ext/phar/phar_object.c
+@@ -1451,6 +1451,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);
+
+@@ -1745,6 +1746,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/openssl/tests/bug54992-ca.pem b/ext/openssl/tests/bug54992-ca.pem
+index ac13917..266f08c 100644
+--- a/ext/openssl/tests/bug54992-ca.pem
++++ b/ext/openssl/tests/bug54992-ca.pem
+@@ -1,35 +1,35 @@
+ -----BEGIN CERTIFICATE-----
+-MIIGAzCCA+ugAwIBAgIUVL06vQzqQ1uRdJ7NAAZyylsKOpYwDQYJKoZIhvcNAQEL
++MIIGAzCCA+ugAwIBAgIUZOucIjT7OfT7rQQu4W5rghLGMYEwDQYJKoZIhvcNAQEL
+ BQAwgZAxCzAJBgNVBAYTAlBUMQ8wDQYDVQQIDAZMaXNib2ExDzANBgNVBAcMBkxp
+ c2JvYTEXMBUGA1UECgwOUEhQIEZvdW5kYXRpb24xHjAcBgNVBAMMFVJvb3QgQ0Eg
+ Zm9yIFBIUCBUZXN0czEmMCQGCSqGSIb3DQEJARYXaW50ZXJuYWxzQGxpc3RzLnBo
+-cC5uZXQwHhcNMTgxMjAxMjEzNTUwWhcNMTgxMjMxMjEzNTUwWjCBkDELMAkGA1UE
++cC5uZXQwHhcNMjAwMjE4MDg1MDM0WhcNMjEwMzI0MDg1MDM0WjCBkDELMAkGA1UE
+ BhMCUFQxDzANBgNVBAgMBkxpc2JvYTEPMA0GA1UEBwwGTGlzYm9hMRcwFQYDVQQK
+ DA5QSFAgRm91bmRhdGlvbjEeMBwGA1UEAwwVUm9vdCBDQSBmb3IgUEhQIFRlc3Rz
+ MSYwJAYJKoZIhvcNAQkBFhdpbnRlcm5hbHNAbGlzdHMucGhwLm5ldDCCAiIwDQYJ
+-KoZIhvcNAQEBBQADggIPADCCAgoCggIBANVgTLlHH3bNkxx+XA1xhr842rf+lP5A
+-XDhM5N9vRCXs/6FAB6iFAfnR+YVgcHD/ppgrrOlAIf6QF2J9EOA4h9oOtCrbhC9y
+-3uKT/dnPWpa39NAdHDJMl2GndulhfyNzXoPmHR+UmVl8RIwJa2yzq8kfI28VZOdG
+-4oW+L8hybO1r+7kewnI/3TQme+yxRMtI/RDAneBPUu4yx+VTy6gP1R7PMwEnMgLC
+-msdBEJh2FR2rjboejZiBAHRG5cWbmRlYV0ApDZAgaKbKGCgken7FF9mImduv7c9H
+-pHkSKAFdt5hYaeJJy48lh5wC7gMjBo62WKUnBqnV1gBBniWSfsgfNJKPV5a3EO32
+-7KinHzzCH4V1C8tCU26om0CoRI+Bm/dpnwuDZWELzMnnyAeCmGWnPi2s/+QaWwKC
+-sMXn0+3CFYtlZ+zEZm0KB10RMypRLhn9md9/TfxJNNjDIHCMCLJkxyxFnYOWqtCd
+-zAA09r117AgM3tbRYY9NYvNzLw5hnPs2W3gB4vrUzqBcgdfIdVaE1QUyy8rWjMNI
+-fIVJVFeyN2mcg3JQw2WmKINDQJWZxXFJR9BPgISpR93BF5zIfGZSSRPuBXaXQ6j/
+-9aw+fnA8asietOL2wGa60zqX1WKopNYvRlt6CCIYkFcfRRkoEjcMRpyVsSn2U9Dd
+-pFlDHq9iE6SLAgMBAAGjUzBRMB0GA1UdDgQWBBQKZYIWtrUo8Iv5zBWfBn40D7p9
+-1DAfBgNVHSMEGDAWgBQKZYIWtrUo8Iv5zBWfBn40D7p91DAPBgNVHRMBAf8EBTAD
+-AQH/MA0GCSqGSIb3DQEBCwUAA4ICAQAEJhZ6mMgRUJGF4dM5r+SfrwCTbNGDJkFz
+-DSbeb6WMTtvzL1g2P5zHQ0OvlX+mvmqCRXM40sUFMHDLCQzIgKLpgd44yZM6k4wL
+-hReX2okQ8tEwB73ahy/H3TaRr3B2l6s16kx4obDpyTsbrBZgiks515ru5EM2pv7x
+-31Ya2sUlXBWt+Kc+Z/6UI2Eot7G4M11oeRGpWnFBqPFAIByEbnCR4NCPbAKl2t2q
+-vhsQh0zAo9qB4uUyc/XblKKRtdupDnRceSCLg18ZwnBxrVZBuSK5oUCAwAFtE4BZ
+-G793gbwIUeR0pFgNMKkfPnXy3Ii8OmPDc9CsxO0Qg4Xh2VXWpVI+N5xL5L/M3O1i
+-UDDO2PeoaEVfz3htOCYo1U6BSQqMzg5JD2JifzKEscy3rFkpH21EHLg07Fv4ZSFo
+-HG22zt00dJpNatyAzzaYHlMel4K1fwNrGrUH5M2OeRtvkUMlDKwp8qrKIDpTi6vT
+-GW0woBoRlR1+qGGG9RHBqm937uhHJsLw8lFJmvO0ObqbdpdfW4nWugL8x1LZC9oz
+-uaH7hwj5i0SKK/StuLxAPP6cl4RqQhXO5rxEz2iFjl4nwwtRH3KPEDEAvQcnNXpi
+-2YV5z8C78j1amzbSJBlGpu3aoJNn+WPgjePmeBe7oE9t1/5kvIVIAj8kg6CaKfHz
+-6hiK1Erl8g==
++KoZIhvcNAQEBBQADggIPADCCAgoCggIBANDtiwpbgpWNthaPNRpgjvNagqaq1EjS
++19CNFq1+w5jRI8K130RvAWkDwnDcr70RSuNKhbJ2dEool3sUi8puNdvWLa8p95k9
++wg1HtCICixxIdLoYAzprkBJw7QUu/XH9SJeJRkYL7EUFoSDnQF9kbW1qMxZBRlFI
++JEacK1crUBGekudu1DjHCM6dumyObrH4FYZtDdKHLu3PVTO299J7ILsHlAJ31qOG
++zK96yBkjRomru/+Yr9ZjT915slvg19+PGLRSRLMXoolw+WEk5gc00/AsGqXQpavN
++njDu9uw+33Eimrj8KnVsCh9cBQFmrCdqOdJmv8VwD63lcYLruAXkfHIUgdyeVMVT
++Q8O+bgGQWaUrxRED4pJ932TicC23BhiZ/78/nyLwry473mHSIw4Y3M6kGSmEOs+3
++fDcsF8waqOeGXbgdOUjBTu92io+lGsCnUZBRe7sOus6aKHYDE1aBDeGtO4oALS+V
++kNrbCh/VpRIwO9Ah4PvxweqW0ZdloW3TRIXRgRxmGJ9NFe1Rkvv7FB7i2l8IeAKS
++ckuew31vxP6LgGUe5j/qt6xv6GOysefOCAAoHHeNEH+ZSlD1tiglvMVhsUmY9Rit
++XEnB+X8FtOAM3SFiX5tsgB6n4hRKue5WkZywnbkPx7sDu4LQCA00i55dzjP/39M0
++yPnsQrJfOnj5AgMBAAGjUzBRMB0GA1UdDgQWBBSHvApjxItCycV/u9J4Z3b6UAP7
++jzAfBgNVHSMEGDAWgBSHvApjxItCycV/u9J4Z3b6UAP7jzAPBgNVHRMBAf8EBTAD
++AQH/MA0GCSqGSIb3DQEBCwUAA4ICAQB6ffwQmqI9Rq3qiPspJiFLsAT9Um8A/kd0
++unYdMyBRl9T0llGXBeN3YYrJLVAd01UAOSSDV3Cf8L2J2zvKRT8YbC3/LxB/RLIM
++/eHVMGSxpy0S5U8HVChbYGEx/zC9p71HwL31Xj+NfOW1nFbEEPqSbGRmou+X2twZ
++Omwz4Vm4MEpIQLRdgV5bLMN1SETH3TGwdMmTE2S8iKrqeDGB8NEl2LcDvbHAvPNw
++KjitZRiicU99KzSSiGh7dsG/d9JsZqtCSmD+a2PesoUPSPsCaInLQG3aGkApt8Gl
++TtFTxJo9QW7YWxFr9Efb2eU6UIilPSsVj8tvIfS1PRTTJrOlBpJDI6TL5YYtFuw3
++Ij27ILbXSwqUM5MIDYoRDxschNiMRhkRjmnebir2KQdvbt43rW8czwooOzTkd1Bi
++RCAbUCAh1TqVu4vLGcoA8/Rf/1n4M8Zdgq19yfInmU4xs7kaiVvnnAxLSF1TmJl6
++8FCN7ONvHNNXciRkzIxw5Yn6GODa/e8Fzvaza/vkSvW4ry4Hu7T6ze10SuHagN3R
++wwBGBlEI5FEyEKFsTZeHdDMoYzv7Ls4OXZzAo7B/Lwa4OTql7ApVw7MwHEplN3SS
++1Qn4YhhmwJqiGvTGQZSA1gv6Ua/HPHjs1y1fSz+uRukUqlBemDhllmVjWHKJetOv
+++FMLf6DmBw==
+ -----END CERTIFICATE-----
+diff --git a/ext/openssl/tests/bug54992.pem b/ext/openssl/tests/bug54992.pem
+index 1a64a4e..a04c68c 100644
+--- a/ext/openssl/tests/bug54992.pem
++++ b/ext/openssl/tests/bug54992.pem
+@@ -1,26 +1,26 @@
+ -----BEGIN CERTIFICATE-----
+-MIID7jCCAdYCFBDKe4ra5M5zJIb81D7zwFRmyHQGMA0GCSqGSIb3DQEBCwUAMIGQ
++MIID7jCCAdYCFF2eDgBNSufPjQA1YmkSEu4tWGvTMA0GCSqGSIb3DQEBCwUAMIGQ
+ MQswCQYDVQQGEwJQVDEPMA0GA1UECAwGTGlzYm9hMQ8wDQYDVQQHDAZMaXNib2Ex
+ FzAVBgNVBAoMDlBIUCBGb3VuZGF0aW9uMR4wHAYDVQQDDBVSb290IENBIGZvciBQ
+ SFAgVGVzdHMxJjAkBgkqhkiG9w0BCQEWF2ludGVybmFsc0BsaXN0cy5waHAubmV0
+-MB4XDTE4MTIwMTIxNDU0MloXDTE4MTIzMTIxNDU0MlowWjEXMBUGA1UEAxMOYnVn
++MB4XDTIwMDIxODA4NTA0N1oXDTIxMDMyNDA4NTA0N1owWjEXMBUGA1UEAxMOYnVn
+ NTQ5OTIubG9jYWwxCzAJBgNVBAYTAlBUMQ8wDQYDVQQHEwZMaXNib2ExDzANBgNV
+ BAgTBkxpc2JvYTEQMA4GA1UEChMHcGhwLm5ldDCBnzANBgkqhkiG9w0BAQEFAAOB
+ jQAwgYkCgYEAtUAVQKTgpUPgtFOJ3w3kDJETS45tWeT96kUg1NeYLKW+jNbFhxPo
+ PJv7XhfemCaqh2tbq1cdYW906Wp1L+eNQvdTYA2IQG4EQBUlmfyIakOIMsN/RizV
+ kF09vlNQwTpaMpqTv7wB8vvwbxb9jbC2ZhQUBEg6PIn18dSstbM9FZ0CAwEAATAN
+-BgkqhkiG9w0BAQsFAAOCAgEAid90+ulRK+4ifB2tKnt2MyuqXZexv2yQ4u15EYmE
+-NLOpP5ZWN8vSvRI3IGruNA00dX/F2EOT+u82ApOxzYyxceAx29Ytpt7PSd2nUqkN
+-TbDAsDTUZdoDLUa6dGPe5Faaai00nfNJ3lqmC9xPbBPKyJ3hjz0Uj6gi51Lfi410
+-4GZa4oIL3NEIKVtaK942EAYCjeWx1VT8AnsvK4Nqufo97sbZNHJhgY+ApM168kox
+-kFA/RNYp/pNS0FCc8b9DwMnu38n2n33iDl3P54chpAcyuWJE5wL/kN2gnS6iMsLP
+-14NtBg2mm++4XqBpt9glmWr56HZtvyFW0IhpDwQgRe4GSIwPES2g1s7iUs3T4VdJ
+-aHkF4v8Bdl6DWXSVdbqIq8CpVZLhf7vt6pV/22YpVCjQFmiLtc8a4gWaYvpn6j+L
+-nAajb9JpdkNeqNiBxmtfQwL7xtY+1goLd9OKtIO1b2517ZRgU9NkUfLKCTl2W2L8
+-sMY7FPVs6Z1jfaXw+vIWKCJKe0thf0HMV4q11ptsqpzyIzAAjAfma1b/MM5ATHsa
+-6h7Poh0yg+WMSdXurjhDWogOWrzPXSe0izUYpREkTVl1oLhzorxlEDh7vBLB2TS3
+-TPAEdNxEbsIutMjoz5ql5dYxgZQGW7HARXrXhMbk6cBU8khNcGGqz1uzX1x7Vb2d
+-hKs=
++BgkqhkiG9w0BAQsFAAOCAgEAEhDpl41vWZF9lGSlxz5uwIGguibrbeBYn/1PYpw4
++jF0i/DxNWYmAh/9vM/ClXhL9rVtHev88eO6goIDjiU2W59ksffxxw0Xno6XOgElb
++8sdWBF4wLKiCuZrAYJ+N+CWKWkWFgsdBEHGktBk/UIh7Aw2LjVneMMj8lIgpDw9l
++PfMZ1SAajBEh5D4TrM6TR3ImT2x0t4Rb1LOrfdn34eHHp/K1wpsZfDwzQKXF1RNb
++XqQwzsB5kEMdOBC1ykOXcLqiUPxMakiVAfnt8w1UCdCB3TH63HkxATqoqZLXFYRX
++JZRLkAUvoqdDNVP2gOYRewInWJL+EaRNt3P5DR8tEgCOUyw0UYgpI7KDHV5cL3MB
++JKeLXmQu0o9ZviPk3saEdmhnSaPCGcVoF5E1vnSudcla7wz65U0w+bEX94DxGad/
++CrsGVS0VbdTV6lPQgcbP/IP4sxBUqZvpDlr20XzgsgdwCBgGwcJ47Y1zDQh17sAe
++rZxhtxHG6PJbCwdj7z9FNgsMPmfFXoqcLFyN+N3vbGMpOaO6KCoylmFvNSQCwFrm
++y/V+z5fQFe42trqLr04DEVw7rzGN6I8vyGPu7267FNDO5bdwuJ0FVjB88IW2mcRw
++S52CzP5H7wavwVsKQ9iZTsBWYwxiU2YCwjhx0v5WWZAnQfjjzA5vvFokWhrWDvca
++auw=
+ -----END CERTIFICATE-----
+ -----BEGIN RSA PRIVATE KEY-----
+ MIICXgIBAAKBgQC1QBVApOClQ+C0U4nfDeQMkRNLjm1Z5P3qRSDU15gspb6M1sWH
+diff --git a/ext/openssl/tests/bug65538.phar b/ext/openssl/tests/bug65538.phar
+index 3e10d5e..5eb1bd4 100644
+--- a/ext/openssl/tests/bug65538.phar
++++ b/ext/openssl/tests/bug65538.phar
+@@ -289,64 +289,64 @@
+ }
+
+ Extract_Phar::go();
+-__HALT_COMPILER(); ?>e
+-MIIGAzCCA+ugAwIBAgIUVL06vQzqQ1uRdJ7NAAZyylsKOpYwDQYJKoZIhvcNAQEL
++__HALT_COMPILER(); ?>e
++MIIGAzCCA+ugAwIBAgIUZOucIjT7OfT7rQQu4W5rghLGMYEwDQYJKoZIhvcNAQEL
+ BQAwgZAxCzAJBgNVBAYTAlBUMQ8wDQYDVQQIDAZMaXNib2ExDzANBgNVBAcMBkxp
+ c2JvYTEXMBUGA1UECgwOUEhQIEZvdW5kYXRpb24xHjAcBgNVBAMMFVJvb3QgQ0Eg
+ Zm9yIFBIUCBUZXN0czEmMCQGCSqGSIb3DQEJARYXaW50ZXJuYWxzQGxpc3RzLnBo
+-cC5uZXQwHhcNMTgxMjAxMjEzNTUwWhcNMTgxMjMxMjEzNTUwWjCBkDELMAkGA1UE
++cC5uZXQwHhcNMjAwMjE4MDg1MDM0WhcNMjEwMzI0MDg1MDM0WjCBkDELMAkGA1UE
+ BhMCUFQxDzANBgNVBAgMBkxpc2JvYTEPMA0GA1UEBwwGTGlzYm9hMRcwFQYDVQQK
+ DA5QSFAgRm91bmRhdGlvbjEeMBwGA1UEAwwVUm9vdCBDQSBmb3IgUEhQIFRlc3Rz
+ MSYwJAYJKoZIhvcNAQkBFhdpbnRlcm5hbHNAbGlzdHMucGhwLm5ldDCCAiIwDQYJ
+-KoZIhvcNAQEBBQADggIPADCCAgoCggIBANVgTLlHH3bNkxx+XA1xhr842rf+lP5A
+-XDhM5N9vRCXs/6FAB6iFAfnR+YVgcHD/ppgrrOlAIf6QF2J9EOA4h9oOtCrbhC9y
+-3uKT/dnPWpa39NAdHDJMl2GndulhfyNzXoPmHR+UmVl8RIwJa2yzq8kfI28VZOdG
+-4oW+L8hybO1r+7kewnI/3TQme+yxRMtI/RDAneBPUu4yx+VTy6gP1R7PMwEnMgLC
+-msdBEJh2FR2rjboejZiBAHRG5cWbmRlYV0ApDZAgaKbKGCgken7FF9mImduv7c9H
+-pHkSKAFdt5hYaeJJy48lh5wC7gMjBo62WKUnBqnV1gBBniWSfsgfNJKPV5a3EO32
+-7KinHzzCH4V1C8tCU26om0CoRI+Bm/dpnwuDZWELzMnnyAeCmGWnPi2s/+QaWwKC
+-sMXn0+3CFYtlZ+zEZm0KB10RMypRLhn9md9/TfxJNNjDIHCMCLJkxyxFnYOWqtCd
+-zAA09r117AgM3tbRYY9NYvNzLw5hnPs2W3gB4vrUzqBcgdfIdVaE1QUyy8rWjMNI
+-fIVJVFeyN2mcg3JQw2WmKINDQJWZxXFJR9BPgISpR93BF5zIfGZSSRPuBXaXQ6j/
+-9aw+fnA8asietOL2wGa60zqX1WKopNYvRlt6CCIYkFcfRRkoEjcMRpyVsSn2U9Dd
+-pFlDHq9iE6SLAgMBAAGjUzBRMB0GA1UdDgQWBBQKZYIWtrUo8Iv5zBWfBn40D7p9
+-1DAfBgNVHSMEGDAWgBQKZYIWtrUo8Iv5zBWfBn40D7p91DAPBgNVHRMBAf8EBTAD
+-AQH/MA0GCSqGSIb3DQEBCwUAA4ICAQAEJhZ6mMgRUJGF4dM5r+SfrwCTbNGDJkFz
+-DSbeb6WMTtvzL1g2P5zHQ0OvlX+mvmqCRXM40sUFMHDLCQzIgKLpgd44yZM6k4wL
+-hReX2okQ8tEwB73ahy/H3TaRr3B2l6s16kx4obDpyTsbrBZgiks515ru5EM2pv7x
+-31Ya2sUlXBWt+Kc+Z/6UI2Eot7G4M11oeRGpWnFBqPFAIByEbnCR4NCPbAKl2t2q
+-vhsQh0zAo9qB4uUyc/XblKKRtdupDnRceSCLg18ZwnBxrVZBuSK5oUCAwAFtE4BZ
+-G793gbwIUeR0pFgNMKkfPnXy3Ii8OmPDc9CsxO0Qg4Xh2VXWpVI+N5xL5L/M3O1i
+-UDDO2PeoaEVfz3htOCYo1U6BSQqMzg5JD2JifzKEscy3rFkpH21EHLg07Fv4ZSFo
+-HG22zt00dJpNatyAzzaYHlMel4K1fwNrGrUH5M2OeRtvkUMlDKwp8qrKIDpTi6vT
+-GW0woBoRlR1+qGGG9RHBqm937uhHJsLw8lFJmvO0ObqbdpdfW4nWugL8x1LZC9oz
+-uaH7hwj5i0SKK/StuLxAPP6cl4RqQhXO5rxEz2iFjl4nwwtRH3KPEDEAvQcnNXpi
+-2YV5z8C78j1amzbSJBlGpu3aoJNn+WPgjePmeBe7oE9t1/5kvIVIAj8kg6CaKfHz
+-6hiK1Erl8g==
++KoZIhvcNAQEBBQADggIPADCCAgoCggIBANDtiwpbgpWNthaPNRpgjvNagqaq1EjS
++19CNFq1+w5jRI8K130RvAWkDwnDcr70RSuNKhbJ2dEool3sUi8puNdvWLa8p95k9
++wg1HtCICixxIdLoYAzprkBJw7QUu/XH9SJeJRkYL7EUFoSDnQF9kbW1qMxZBRlFI
++JEacK1crUBGekudu1DjHCM6dumyObrH4FYZtDdKHLu3PVTO299J7ILsHlAJ31qOG
++zK96yBkjRomru/+Yr9ZjT915slvg19+PGLRSRLMXoolw+WEk5gc00/AsGqXQpavN
++njDu9uw+33Eimrj8KnVsCh9cBQFmrCdqOdJmv8VwD63lcYLruAXkfHIUgdyeVMVT
++Q8O+bgGQWaUrxRED4pJ932TicC23BhiZ/78/nyLwry473mHSIw4Y3M6kGSmEOs+3
++fDcsF8waqOeGXbgdOUjBTu92io+lGsCnUZBRe7sOus6aKHYDE1aBDeGtO4oALS+V
++kNrbCh/VpRIwO9Ah4PvxweqW0ZdloW3TRIXRgRxmGJ9NFe1Rkvv7FB7i2l8IeAKS
++ckuew31vxP6LgGUe5j/qt6xv6GOysefOCAAoHHeNEH+ZSlD1tiglvMVhsUmY9Rit
++XEnB+X8FtOAM3SFiX5tsgB6n4hRKue5WkZywnbkPx7sDu4LQCA00i55dzjP/39M0
++yPnsQrJfOnj5AgMBAAGjUzBRMB0GA1UdDgQWBBSHvApjxItCycV/u9J4Z3b6UAP7
++jzAfBgNVHSMEGDAWgBSHvApjxItCycV/u9J4Z3b6UAP7jzAPBgNVHRMBAf8EBTAD
++AQH/MA0GCSqGSIb3DQEBCwUAA4ICAQB6ffwQmqI9Rq3qiPspJiFLsAT9Um8A/kd0
++unYdMyBRl9T0llGXBeN3YYrJLVAd01UAOSSDV3Cf8L2J2zvKRT8YbC3/LxB/RLIM
++/eHVMGSxpy0S5U8HVChbYGEx/zC9p71HwL31Xj+NfOW1nFbEEPqSbGRmou+X2twZ
++Omwz4Vm4MEpIQLRdgV5bLMN1SETH3TGwdMmTE2S8iKrqeDGB8NEl2LcDvbHAvPNw
++KjitZRiicU99KzSSiGh7dsG/d9JsZqtCSmD+a2PesoUPSPsCaInLQG3aGkApt8Gl
++TtFTxJo9QW7YWxFr9Efb2eU6UIilPSsVj8tvIfS1PRTTJrOlBpJDI6TL5YYtFuw3
++Ij27ILbXSwqUM5MIDYoRDxschNiMRhkRjmnebir2KQdvbt43rW8czwooOzTkd1Bi
++RCAbUCAh1TqVu4vLGcoA8/Rf/1n4M8Zdgq19yfInmU4xs7kaiVvnnAxLSF1TmJl6
++8FCN7ONvHNNXciRkzIxw5Yn6GODa/e8Fzvaza/vkSvW4ry4Hu7T6ze10SuHagN3R
++wwBGBlEI5FEyEKFsTZeHdDMoYzv7Ls4OXZzAo7B/Lwa4OTql7ApVw7MwHEplN3SS
++1Qn4YhhmwJqiGvTGQZSA1gv6Ua/HPHjs1y1fSz+uRukUqlBemDhllmVjWHKJetOv
+++FMLf6DmBw==
+ -----END CERTIFICATE-----
+ -----BEGIN CERTIFICATE-----
+-MIID7jCCAdYCFBDKe4ra5M5zJIb81D7zwFRmyHQGMA0GCSqGSIb3DQEBCwUAMIGQ
++MIID7jCCAdYCFF2eDgBNSufPjQA1YmkSEu4tWGvTMA0GCSqGSIb3DQEBCwUAMIGQ
+ MQswCQYDVQQGEwJQVDEPMA0GA1UECAwGTGlzYm9hMQ8wDQYDVQQHDAZMaXNib2Ex
+ FzAVBgNVBAoMDlBIUCBGb3VuZGF0aW9uMR4wHAYDVQQDDBVSb290IENBIGZvciBQ
+ SFAgVGVzdHMxJjAkBgkqhkiG9w0BCQEWF2ludGVybmFsc0BsaXN0cy5waHAubmV0
+-MB4XDTE4MTIwMTIxNDU0MloXDTE4MTIzMTIxNDU0MlowWjEXMBUGA1UEAxMOYnVn
++MB4XDTIwMDIxODA4NTA0N1oXDTIxMDMyNDA4NTA0N1owWjEXMBUGA1UEAxMOYnVn
+ NTQ5OTIubG9jYWwxCzAJBgNVBAYTAlBUMQ8wDQYDVQQHEwZMaXNib2ExDzANBgNV
+ BAgTBkxpc2JvYTEQMA4GA1UEChMHcGhwLm5ldDCBnzANBgkqhkiG9w0BAQEFAAOB
+ jQAwgYkCgYEAtUAVQKTgpUPgtFOJ3w3kDJETS45tWeT96kUg1NeYLKW+jNbFhxPo
+ PJv7XhfemCaqh2tbq1cdYW906Wp1L+eNQvdTYA2IQG4EQBUlmfyIakOIMsN/RizV
+ kF09vlNQwTpaMpqTv7wB8vvwbxb9jbC2ZhQUBEg6PIn18dSstbM9FZ0CAwEAATAN
+-BgkqhkiG9w0BAQsFAAOCAgEAid90+ulRK+4ifB2tKnt2MyuqXZexv2yQ4u15EYmE
+-NLOpP5ZWN8vSvRI3IGruNA00dX/F2EOT+u82ApOxzYyxceAx29Ytpt7PSd2nUqkN
+-TbDAsDTUZdoDLUa6dGPe5Faaai00nfNJ3lqmC9xPbBPKyJ3hjz0Uj6gi51Lfi410
+-4GZa4oIL3NEIKVtaK942EAYCjeWx1VT8AnsvK4Nqufo97sbZNHJhgY+ApM168kox
+-kFA/RNYp/pNS0FCc8b9DwMnu38n2n33iDl3P54chpAcyuWJE5wL/kN2gnS6iMsLP
+-14NtBg2mm++4XqBpt9glmWr56HZtvyFW0IhpDwQgRe4GSIwPES2g1s7iUs3T4VdJ
+-aHkF4v8Bdl6DWXSVdbqIq8CpVZLhf7vt6pV/22YpVCjQFmiLtc8a4gWaYvpn6j+L
+-nAajb9JpdkNeqNiBxmtfQwL7xtY+1goLd9OKtIO1b2517ZRgU9NkUfLKCTl2W2L8
+-sMY7FPVs6Z1jfaXw+vIWKCJKe0thf0HMV4q11ptsqpzyIzAAjAfma1b/MM5ATHsa
+-6h7Poh0yg+WMSdXurjhDWogOWrzPXSe0izUYpREkTVl1oLhzorxlEDh7vBLB2TS3
+-TPAEdNxEbsIutMjoz5ql5dYxgZQGW7HARXrXhMbk6cBU8khNcGGqz1uzX1x7Vb2d
+-hKs=
++BgkqhkiG9w0BAQsFAAOCAgEAEhDpl41vWZF9lGSlxz5uwIGguibrbeBYn/1PYpw4
++jF0i/DxNWYmAh/9vM/ClXhL9rVtHev88eO6goIDjiU2W59ksffxxw0Xno6XOgElb
++8sdWBF4wLKiCuZrAYJ+N+CWKWkWFgsdBEHGktBk/UIh7Aw2LjVneMMj8lIgpDw9l
++PfMZ1SAajBEh5D4TrM6TR3ImT2x0t4Rb1LOrfdn34eHHp/K1wpsZfDwzQKXF1RNb
++XqQwzsB5kEMdOBC1ykOXcLqiUPxMakiVAfnt8w1UCdCB3TH63HkxATqoqZLXFYRX
++JZRLkAUvoqdDNVP2gOYRewInWJL+EaRNt3P5DR8tEgCOUyw0UYgpI7KDHV5cL3MB
++JKeLXmQu0o9ZviPk3saEdmhnSaPCGcVoF5E1vnSudcla7wz65U0w+bEX94DxGad/
++CrsGVS0VbdTV6lPQgcbP/IP4sxBUqZvpDlr20XzgsgdwCBgGwcJ47Y1zDQh17sAe
++rZxhtxHG6PJbCwdj7z9FNgsMPmfFXoqcLFyN+N3vbGMpOaO6KCoylmFvNSQCwFrm
++y/V+z5fQFe42trqLr04DEVw7rzGN6I8vyGPu7267FNDO5bdwuJ0FVjB88IW2mcRw
++S52CzP5H7wavwVsKQ9iZTsBWYwxiU2YCwjhx0v5WWZAnQfjjzA5vvFokWhrWDvca
++auw=
+ -----END CERTIFICATE-----
+ -----BEGIN RSA PRIVATE KEY-----
+ MIICXgIBAAKBgQC1QBVApOClQ+C0U4nfDeQMkRNLjm1Z5P3qRSDU15gspb6M1sWH
+@@ -363,4 +363,4 @@
+ FqU0zPvrnBZ6Zwlgm2cSVQJAPLYA51Z9piajbTuggpioQ5qbUEDkJjmYHbm8eJnK
+ h5NW/EtCk4SBxAc+8ElPrvJjtZyOPWfm4vZF5sDKtC3Fkg==
+ -----END RSA PRIVATE KEY-----
+-.c{˜еTхU‘9oљѕкнё—љS
+\ No newline at end of file
++ЁЇЌ–? =Ц)9ж r…ШЫuТ
+\ No newline at end of file
+diff --git a/ext/openssl/tests/openssl_peer_fingerprint_basic.phpt b/ext/openssl/tests/openssl_peer_fingerprint_basic.phpt
+index 39d62b2..49ecaac 100644
+--- a/ext/openssl/tests/openssl_peer_fingerprint_basic.phpt
++++ b/ext/openssl/tests/openssl_peer_fingerprint_basic.phpt
+@@ -32,12 +32,17 @@
+
+ phpt_wait();
+
+- // should be: 3610606deda596b3ae3859d33c4ce1d9
+- stream_context_set_option($clientCtx, 'ssl', 'peer_fingerprint', '3610606deda596b3ae3859d33c4ce1da');
++ // Run the following to get actual md5 (from sources root):
++ // openssl x509 -noout -fingerprint -md5 -inform pem -in ext/openssl/tests/bug54992.pem | cut -d '=' -f 2 | tr -d ':' | tr 'A-F' 'a-f'
++ // Currently it's 4edbbaf40a6a4b6af22b6d6d9818378f
++ // One below is intentionally broken (compare the last character):
++ stream_context_set_option($clientCtx, 'ssl', 'peer_fingerprint', '9aa2c02d62358f2fa0db575806e37799');
+ var_dump(stream_socket_client($serverUri, $errno, $errstr, 2, $clientFlags, $clientCtx));
+
++ // Run the following to get actual sha256 (from sources root):
++ // openssl x509 -noout -fingerprint -sha256 -inform pem -in ext/openssl/tests/bug54992.pem | cut -d '=' -f 2 | tr -d ':' | tr 'A-F' 'a-f'
+ stream_context_set_option($clientCtx, 'ssl', 'peer_fingerprint', [
+- 'sha256' => 'dffa72247ab7e44d94b2858528e3f67015925782148d2cf0b15cd82d1c931215',
++ 'sha256' => '62e70554daabf366ba9ada30d3af794ec421368e79b68f64dc9ed546d834ae7d',
+ ]);
+ var_dump(stream_socket_client($serverUri, $errno, $errstr, 2, $clientFlags, $clientCtx));
+ CODE;
+diff --git a/ext/exif/exif.c b/ext/exif/exif.c
+index 9e42a62..4c38f17 100644
+--- a/ext/exif/exif.c
++++ b/ext/exif/exif.c
+@@ -3242,6 +3242,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;
+@@ -3394,7 +3399,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/url.c b/ext/standard/url.c
+index 9c42afb..2990bd9 100644
+--- a/ext/standard/url.c
++++ b/ext/standard/url.c
+@@ -659,7 +659,7 @@
+ HashTable *hashT;
+ zend_long format = 0;
+
+- if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|l", &url, &url_len, &format) == FAILURE) {
++ if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|l", &url, &url_len, &format) == FAILURE) {
+ return;
+ }
+ context = FG(default_context) ? FG(default_context) : (FG(default_context) = php_stream_context_alloc());
+diff --git a/ext/standard/exec.c b/ext/standard/exec.c
+index d6f0cbf..e486f52 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 2990bd9..a9cc06b 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/Zend/zend_signal.c b/Zend/zend_signal.c
+index b12f30d..7fa3a7f 100644
+--- a/Zend/zend_signal.c
++++ b/Zend/zend_signal.c
+@@ -304,34 +304,45 @@
+
+ SIGG(active) = 1;
+ SIGG(depth) = 0;
++ SIGG(check) = ZEND_DEBUG;
+ } /* }}} */
+
+ /* {{{ zend_signal_deactivate
+ * */
+ void zend_signal_deactivate(void)
+ {
+-
+ if (SIGG(check)) {
+ int x;
+ struct sigaction sa = {{0}};
+ if (SIGG(depth) != 0) {
+ zend_error(E_CORE_WARNING, "zend_signal: shutdown with non-zero blocking depth (%d)", SIGG(depth));
+ }
++
+ /* did anyone steal our installed handler */
+ for (x = 0; x < sizeof(zend_sigs) / sizeof(*zend_sigs); x++) {
+ sigaction(zend_sigs[x], NULL, &sa);
+- if (sa.sa_sigaction != zend_signal_handler_defer) {
++ if (sa.sa_sigaction != zend_signal_handler_defer &&
++ sa.sa_sigaction != (void *) SIG_IGN) {
+ zend_error(E_CORE_WARNING, "zend_signal: handler was replaced for signal (%d) after startup", zend_sigs[x]);
+ }
+ }
+ }
+
+- SIGNAL_BEGIN_CRITICAL();
+- SIGG(active) = 0;
++ /* After active=0 is set, signal handlers will be called directly and other
++ * state that is reset below will not be accessed. */
++ *((volatile int *) &SIGG(active)) = 0;
++
+ SIGG(running) = 0;
+ SIGG(blocked) = 0;
+ SIGG(depth) = 0;
+- SIGNAL_END_CRITICAL();
++
++ /* If there are any queued signals because of a missed unblock, drop them. */
++ if (SIGG(phead) && SIGG(ptail)) {
++ SIGG(ptail)->next = SIGG(pavail);
++ SIGG(pavail) = SIGG(phead);
++ SIGG(phead) = NULL;
++ SIGG(ptail) = NULL;
++ }
+ }
+ /* }}} */
+
+diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c
+index 5227601..2116726 100644
+--- a/ext/opcache/ZendAccelerator.c
++++ b/ext/opcache/ZendAccelerator.c
+@@ -1478,7 +1478,9 @@
+
+ /* check blacklist right after ensuring that file was opened */
+ if (file_handle->opened_path && zend_accel_blacklist_is_blacklisted(&accel_blacklist, ZSTR_VAL(file_handle->opened_path))) {
++ SHM_UNPROTECT();
+ ZCSG(blacklist_misses)++;
++ SHM_PROTECT();
+ *op_array_p = accelerator_orig_compile_file(file_handle, type);
+ return NULL;
+ }
+@@ -1509,7 +1511,9 @@
+ }
+
+ if (ZCG(accel_directives).max_file_size > 0 && size > (size_t)ZCG(accel_directives).max_file_size) {
++ SHM_UNPROTECT();
+ ZCSG(blacklist_misses)++;
++ SHM_PROTECT();
+ *op_array_p = accelerator_orig_compile_file(file_handle, type);
+ return NULL;
+ }
+@@ -1860,11 +1864,16 @@
+ return accelerator_orig_compile_file(file_handle, type);
+ }
+
++ SHM_PROTECT();
++ HANDLE_UNBLOCK_INTERRUPTIONS();
++ persistent_script = opcache_compile_file(file_handle, type, key, key ? key_length : 0, &op_array);
++ HANDLE_BLOCK_INTERRUPTIONS();
++ SHM_UNPROTECT();
++
+ /* Try and cache the script and assume that it is returned from_shared_memory.
+ * If it isn't compile_and_cache_file() changes the flag to 0
+ */
+ from_shared_memory = 0;
+- persistent_script = opcache_compile_file(file_handle, type, key, key ? key_length : 0, &op_array);
+ if (persistent_script) {
+ persistent_script = cache_script_in_shared_memory(persistent_script, key, key ? key_length : 0, &from_shared_memory);
+ }
+@@ -1983,7 +1992,7 @@
+ zend_string *resolved_path;
+ int key_length;
+ char *key = NULL;
+-
++
+ if (!ZCG(accel_directives).revalidate_path) {
+ /* lookup by "not-real" path */
+ key = accel_make_persistent_key(filename, filename_len, &key_length);
+diff --git a/main/main.c b/main/main.c
+index 93ac6ca..91f9ead 100644
+--- a/main/main.c
++++ b/main/main.c
+@@ -1882,6 +1882,11 @@
+ zend_unset_timeout();
+ } zend_end_try();
+
++ /* 17. Deactivate Zend signals */
++#ifdef ZEND_SIGNALS
++ zend_signal_deactivate();
++#endif
++
+ #ifdef PHP_WIN32
+ if (PG(com_initialized)) {
+ CoUninitialize();
+diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c
+index aee355b..8815e8a 100644
+--- a/ext/zip/php_zip.c
++++ b/ext/zip/php_zip.c
+@@ -1451,6 +1451,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 5949802..ee07ea5 100644
+--- a/main/rfc1867.c
++++ b/main/rfc1867.c
+@@ -690,7 +690,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;
+@@ -1124,7 +1125,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 ee07ea5..6159284 100644
+--- a/main/rfc1867.c
++++ b/main/rfc1867.c
+@@ -614,7 +614,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;
+@@ -653,7 +653,7 @@
+ self->buf_begin += len;
+ }
+
+- return (int)len;
++ return len;
+ }
+
+ /*
+@@ -663,7 +663,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);
+--- a/ext/phar/zip.c
++++ b/ext/phar/zip.c
+@@ -704,7 +704,7 @@
+ efree(actual_alias);
+ }
+
+- zend_hash_str_add_ptr(&(PHAR_G(phar_alias_map)), actual_alias, mydata->alias_len, mydata);
++ zend_hash_str_add_ptr(&(PHAR_G(phar_alias_map)), mydata->alias, mydata->alias_len, mydata);
+ } else {
+ phar_archive_data *fd_ptr;
+
+diff --git a/NEWS b/NEWS
+index be7af22..bfde893 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 2074d28..c2f4092 100644
+--- a/ext/standard/image.c
++++ b/ext/standard/image.c
+@@ -1403,6 +1403,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 d3cfb7f..50ecc66 100644
+--- a/main/php_variables.c
++++ b/main/php_variables.c
+@@ -464,7 +464,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)) {
+@@ -475,7 +477,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 e172061..80e164a 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 e468066..c9e9d32 100644
+--- a/ext/standard/tests/url/parse_url_basic_001.phpt
++++ b/ext/standard/tests/url/parse_url_basic_001.phpt
+@@ -507,15 +507,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 70dc4bb..431de27 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 b2ca06f..b2c1a1d 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 a9cc06b..3bb62c7 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,
+--- a/ext/soap/php_sdl.c
++++ b/ext/soap/php_sdl.c
+@@ -314,6 +314,8 @@
+ ctx->context = NULL;
+ }
+
++#define SAFE_STR(a) ((a)?a:"")
++
+ static void load_wsdl_ex(zval *this_ptr, char *struri, sdlCtx *ctx, int include)
+ {
+ sdlPtr tmpsdl = ctx->sdl;
+@@ -375,7 +377,7 @@
+ if (node_is_equal_ex(trav2, "schema", XSD_NAMESPACE)) {
+ load_schema(ctx, trav2);
+ } else if (is_wsdl_element(trav2) && !node_is_equal(trav2,"documentation")) {
+- soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", trav2->name);
++ soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", SAFE_STR(trav2->name));
+ }
+ trav2 = trav2->next;
+ }
+@@ -436,7 +438,7 @@
+ soap_error0(E_ERROR, "Parsing WSDL: <service> has no name attribute");
+ }
+ } else if (!node_is_equal(trav,"documentation")) {
+- soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", trav->name);
++ soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", SAFE_STR(trav->name));
+ }
+ trav = trav->next;
+ }
+@@ -546,7 +548,7 @@
+ }
+ smart_str_free(&key);
+ } else if (is_wsdl_element(trav) && !node_is_equal(trav,"documentation")) {
+- soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", trav->name);
++ soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", SAFE_STR(trav->name));
+ }
+ trav = trav->next;
+ }
+@@ -648,7 +650,7 @@
+ }
+ smart_str_free(&key);
+ } else if (is_wsdl_element(trav) && !node_is_equal(trav,"documentation")) {
+- soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", trav->name);
++ soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", SAFE_STR(trav->name));
+ }
+ trav = trav->next;
+ }
+@@ -680,14 +682,14 @@
+ sdlParamPtr param;
+
+ if (trav->ns != NULL && strcmp((char*)trav->ns->href, WSDL_NAMESPACE) != 0) {
+- soap_error1(E_ERROR, "Parsing WSDL: Unexpected extensibility element <%s>", trav->name);
++ soap_error1(E_ERROR, "Parsing WSDL: Unexpected extensibility element <%s>", SAFE_STR(trav->name));
+ }
+ if (node_is_equal(trav,"documentation")) {
+ trav = trav->next;
+ continue;
+ }
+ if (!node_is_equal(trav,"part")) {
+- soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", trav->name);
++ soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", SAFE_STR(trav->name));
+ }
+ part = trav;
+ param = emalloc(sizeof(sdlParam));
+@@ -696,7 +698,7 @@
+
+ name = get_attribute(part->properties, "name");
+ if (name == NULL) {
+- soap_error1(E_ERROR, "Parsing WSDL: No name associated with <part> '%s'", message->name);
++ soap_error1(E_ERROR, "Parsing WSDL: No name associated with <part> '%s'", SAFE_STR(message->name));
+ }
+
+ param->paramName = estrdup((char*)name->children->content);
+@@ -765,7 +767,7 @@
+ continue;
+ }
+ if (!node_is_equal(trav,"port")) {
+- soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", trav->name);
++ soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", SAFE_STR(trav->name));
+ }
+
+ port = trav;
+@@ -804,7 +806,7 @@
+ }
+ }
+ if (trav2 != address && is_wsdl_element(trav2) && !node_is_equal(trav2,"documentation")) {
+- soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", trav2->name);
++ soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", SAFE_STR(trav2->name));
+ }
+ trav2 = trav2->next;
+ }
+@@ -906,7 +908,7 @@
+ continue;
+ }
+ if (!node_is_equal(trav2,"operation")) {
+- soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", trav2->name);
++ soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", SAFE_STR(trav2->name));
+ }
+
+ operation = trav2;
+@@ -925,7 +927,7 @@
+ !node_is_equal(trav3,"output") &&
+ !node_is_equal(trav3,"fault") &&
+ !node_is_equal(trav3,"documentation")) {
+- soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", trav3->name);
++ soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", SAFE_STR(trav3->name));
+ }
+ trav3 = trav3->next;
+ }
+@@ -1103,7 +1105,7 @@
+ }
+ }
+ } else if (is_wsdl_element(trav) && !node_is_equal(trav,"documentation")) {
+- soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", trav->name);
++ soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", SAFE_STR(trav->name));
+ }
+ trav = trav->next;
+ }
+diff --git a/ext/soap/php_xml.c b/ext/soap/php_xml.c
+index fb00c42..a9c6a56 100644
+--- a/ext/soap/php_xml.c
++++ b/ext/soap/php_xml.c
+@@ -204,7 +204,7 @@
+
+ int attr_is_equal_ex(xmlAttrPtr node, char *name, char *ns)
+ {
+- if (name == NULL || strcmp((char*)node->name, name) == 0) {
++ if (name == NULL || ((node->name) && strcmp((char*)node->name, name) == 0)) {
+ if (ns) {
+ xmlNsPtr nsPtr = attr_find_ns(node);
+ if (nsPtr) {
+@@ -220,7 +220,7 @@
+
+ int node_is_equal_ex(xmlNodePtr node, char *name, char *ns)
+ {
+- if (name == NULL || strcmp((char*)node->name, name) == 0) {
++ if (name == NULL || ((node->name) && strcmp((char*)node->name, name) == 0)) {
+ if (ns) {
+ xmlNsPtr nsPtr = node_find_ns(node);
+ if (nsPtr) {
+--- /dev/null
++++ b/ext/soap/tests/bug80672.phpt
+@@ -0,0 +1,15 @@
++--TEST--
++Bug #80672 Null Dereference in SoapClient
++--SKIPIF--
++<?php require_once('skipif.inc'); ?>
++--FILE--
++<?php
++try {
++ $client = new SoapClient(__DIR__ . "/bug80672.xml");
++ $query = $soap->query(array('sXML' => 'something'));
++} catch(SoapFault $e) {
++ print $e->getMessage();
++}
++?>
++--EXPECTF--
++SOAP-ERROR: Parsing WSDL: Unexpected WSDL element <>
+\ No newline at end of file
+--- /dev/null
++++ b/ext/soap/tests/bug80672.xml
+@@ -0,0 +1,6 @@
++<?xml version="1.0" encoding="ISO-8859-1"?>
++<soap:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
++ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
++ xmlns:soap="http://schemas.xmlsoap.org/wsdl/">
++<![CDATA[test]]>
++</soap:definitions>
+diff --git a/ext/imap/php_imap.c b/ext/imap/php_imap.c
+index 011cbc0..5f8c0da 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/interbase/config.m4 b/ext/interbase/config.m4
+index ace3047..5b4cde5 100644
+--- a/ext/interbase/config.m4
++++ b/ext/interbase/config.m4
+@@ -3,39 +3,54 @@
+ install directory [/opt/firebird]])
+
+ if test "$PHP_INTERBASE" != "no"; then
+- if test "$PHP_INTERBASE" = "yes"; then
+- IBASE_INCDIR=/opt/firebird/include
+- IBASE_LIBDIR=/opt/firebird/lib
++
++ AC_PATH_PROG(FB_CONFIG, fb_config, no)
++
++ if test -x "$FB_CONFIG" && test "$PHP_INTERBASE" = "yes"; then
++ AC_MSG_CHECKING(for libfbconfig)
++ FB_CFLAGS=`$FB_CONFIG --cflags`
++ FB_LIBDIR=`$FB_CONFIG --libs`
++ FB_VERSION=`$FB_CONFIG --version`
++ AC_MSG_RESULT(version $FB_VERSION)
++ PHP_EVAL_LIBLINE($FB_LIBDIR, INTERBASE_SHARED_LIBADD)
++ PHP_EVAL_INCLINE($FB_CFLAGS)
++
+ else
+- IBASE_INCDIR=$PHP_INTERBASE/include
+- IBASE_LIBDIR=$PHP_INTERBASE/$PHP_LIBDIR
+- fi
++ if test "$PHP_INTERBASE" = "yes"; then
++ IBASE_INCDIR=/opt/firebird/include
++ IBASE_LIBDIR=/opt/firebird/lib
++ else
++ IBASE_INCDIR=$PHP_INTERBASE/include
++ IBASE_LIBDIR=$PHP_INTERBASE/$PHP_LIBDIR
++ fi
+
+- PHP_CHECK_LIBRARY(fbclient, isc_detach_database,
+- [
+- IBASE_LIBNAME=fbclient
+- ], [
+- PHP_CHECK_LIBRARY(gds, isc_detach_database,
++ PHP_CHECK_LIBRARY(fbclient, isc_detach_database,
+ [
+- IBASE_LIBNAME=gds
++ IBASE_LIBNAME=fbclient
+ ], [
+- PHP_CHECK_LIBRARY(ib_util, isc_detach_database,
++ PHP_CHECK_LIBRARY(gds, isc_detach_database,
+ [
+- IBASE_LIBNAME=ib_util
++ IBASE_LIBNAME=gds
+ ], [
+- AC_MSG_ERROR([libfbclient, libgds or libib_util not found! Check config.log for more information.])
++ PHP_CHECK_LIBRARY(ib_util, isc_detach_database,
++ [
++ IBASE_LIBNAME=ib_util
++ ], [
++ AC_MSG_ERROR([libfbclient, libgds or libib_util not found! Check config.log for more information.])
++ ], [
++ -L$IBASE_LIBDIR
++ ])
+ ], [
+ -L$IBASE_LIBDIR
+ ])
+ ], [
+ -L$IBASE_LIBDIR
+ ])
+- ], [
+- -L$IBASE_LIBDIR
+- ])
+
+- PHP_ADD_LIBRARY_WITH_PATH($IBASE_LIBNAME, $IBASE_LIBDIR, INTERBASE_SHARED_LIBADD)
+- PHP_ADD_INCLUDE($IBASE_INCDIR)
++ PHP_ADD_LIBRARY_WITH_PATH($IBASE_LIBNAME, $IBASE_LIBDIR, INTERBASE_SHARED_LIBADD)
++ PHP_ADD_INCLUDE($IBASE_INCDIR)
++ fi
++
+ AC_DEFINE(HAVE_IBASE,1,[ ])
+ PHP_NEW_EXTENSION(interbase, interbase.c ibase_query.c ibase_service.c ibase_events.c ibase_blobs.c, $ext_shared,, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1)
+ PHP_SUBST(INTERBASE_SHARED_LIBADD)
+diff --git a/ext/pdo_firebird/config.m4 b/ext/pdo_firebird/config.m4
+index f9188a0..e6362cd 100644
+--- a/ext/pdo_firebird/config.m4
++++ b/ext/pdo_firebird/config.m4
+@@ -8,43 +8,56 @@
+ AC_MSG_ERROR([PDO is not enabled! Add --enable-pdo to your configure line.])
+ fi
+
+- if test "$PHP_PDO_FIREBIRD" = "yes"; then
+- FIREBIRD_INCDIR=
+- FIREBIRD_LIBDIR=
+- FIREBIRD_LIBDIR_FLAG=
++ AC_PATH_PROG(FB_CONFIG, fb_config, no)
++
++ if test -x "$FB_CONFIG" && test "$PHP_PDO_FIREBIRD" = "yes"; then
++ AC_MSG_CHECKING(for libfbconfig)
++ FB_CFLAGS=`$FB_CONFIG --cflags`
++ FB_LIBDIR=`$FB_CONFIG --libs`
++ FB_VERSION=`$FB_CONFIG --version`
++ AC_MSG_RESULT(version $FB_VERSION)
++ PHP_EVAL_LIBLINE($FB_LIBDIR, PDO_FIREBIRD_SHARED_LIBADD)
++ PHP_EVAL_INCLINE($FB_CFLAGS)
++
+ else
+- FIREBIRD_INCDIR=$PHP_PDO_FIREBIRD/include
+- FIREBIRD_LIBDIR=$PHP_PDO_FIREBIRD/$PHP_LIBDIR
+- FIREBIRD_LIBDIR_FLAG=-L$FIREBIRD_LIBDIR
+- fi
++ if test "$PHP_PDO_FIREBIRD" = "yes"; then
++ FIREBIRD_INCDIR=
++ FIREBIRD_LIBDIR=
++ FIREBIRD_LIBDIR_FLAG=
++ else
++ FIREBIRD_INCDIR=$PHP_PDO_FIREBIRD/include
++ FIREBIRD_LIBDIR=$PHP_PDO_FIREBIRD/$PHP_LIBDIR
++ FIREBIRD_LIBDIR_FLAG=-L$FIREBIRD_LIBDIR
++ fi
+
+- PHP_CHECK_LIBRARY(fbclient, isc_detach_database,
+- [
+- FIREBIRD_LIBNAME=fbclient
+- ], [
+- PHP_CHECK_LIBRARY(gds, isc_detach_database,
++ PHP_CHECK_LIBRARY(fbclient, isc_detach_database,
+ [
+- FIREBIRD_LIBNAME=gds
++ FIREBIRD_LIBNAME=fbclient
+ ], [
+- PHP_CHECK_LIBRARY(ib_util, isc_detach_database,
++ PHP_CHECK_LIBRARY(gds, isc_detach_database,
+ [
+- FIREBIRD_LIBNAME=ib_util
++ FIREBIRD_LIBNAME=gds
+ ], [
+- AC_MSG_ERROR([libfbclient, libgds or libib_util not found! Check config.log for more information.])
++ PHP_CHECK_LIBRARY(ib_util, isc_detach_database,
++ [
++ FIREBIRD_LIBNAME=ib_util
++ ], [
++ AC_MSG_ERROR([libfbclient, libgds or libib_util not found! Check config.log for more information.])
++ ], [
++ $FIREBIRD_LIBDIR_FLAG
++ ])
+ ], [
+ $FIREBIRD_LIBDIR_FLAG
+ ])
+ ], [
+ $FIREBIRD_LIBDIR_FLAG
+ ])
+- ], [
+- $FIREBIRD_LIBDIR_FLAG
+- ])
++ PHP_ADD_LIBRARY_WITH_PATH($FIREBIRD_LIBNAME, $FIREBIRD_LIBDIR, PDO_FIREBIRD_SHARED_LIBADD)
++ PHP_ADD_INCLUDE($FIREBIRD_INCDIR)
++ fi
+
+ PHP_CHECK_PDO_INCLUDES
+
+- PHP_ADD_LIBRARY_WITH_PATH($FIREBIRD_LIBNAME, $FIREBIRD_LIBDIR, PDO_FIREBIRD_SHARED_LIBADD)
+- PHP_ADD_INCLUDE($FIREBIRD_INCDIR)
+ AC_DEFINE(HAVE_PDO_FIREBIRD,1,[ ])
+ PHP_NEW_EXTENSION(pdo_firebird, pdo_firebird.c firebird_driver.c firebird_statement.c, $ext_shared,,-I$pdo_cv_inc_path)
+ PHP_SUBST(PDO_FIREBIRD_SHARED_LIBADD)
+diff --git a/ext/pdo_firebird/firebird_statement.c b/ext/pdo_firebird/firebird_statement.c
+index 3feeedf..88be6da 100644
+--- a/ext/pdo_firebird/firebird_statement.c
++++ b/ext/pdo_firebird/firebird_statement.c
+@@ -294,7 +294,7 @@
+ unsigned short seg_len;
+ ISC_STATUS stat;
+
+- *ptr = S->fetch_buf[colno] = erealloc(*ptr, *len+1);
++ *ptr = S->fetch_buf[colno] = erealloc(S->fetch_buf[colno], *len+1);
+
+ for (cur_len = stat = 0; (!stat || stat == isc_segment) && cur_len < *len; cur_len += seg_len) {
+
+--- /dev/null
++++ b/ext/pdo_firebird/tests/bug_76488.phpt
+@@ -0,0 +1,32 @@
++--TEST--
++PDO_Firebird: Bug #76488 Memory leak when fetching a BLOB field
++--SKIPIF--
++<?php if (!extension_loaded('interbase') || !extension_loaded('pdo_firebird')) die('skip'); ?>
++--FILE--
++<?php
++require 'testdb.inc';
++$dbh = new PDO('firebird:dbname='.$test_base, $user, $password) or die;
++
++$sql = '
++with recursive r(n) as (
++ select 1 from rdb$database
++ union all
++ select n+1 from r where n < 1000
++)
++select n,
++ cast(lpad(\'A\', 8000, \'A\') as BLOB sub_type TEXT) as SRC
++from r
++';
++
++ for ($i = 0; $i < 10; $i++) {
++ $sth = $dbh->prepare($sql);
++ $sth->execute();
++ $rows = $sth->fetchAll();
++ unset($rows);
++ unset($sth);
++ }
++ unset($dbh);
++ echo "OK";
++?>
++--EXPECT--
++OK
+\ No newline at end of file
+diff --git a/ext/pdo_firebird/firebird_statement.c b/ext/pdo_firebird/firebird_statement.c
+index fde8971..537f6f4 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 2420489..8481d03 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 8481d03..cfcae47 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/sapi/fpm/fpm/fpm_children.c b/sapi/fpm/fpm/fpm_children.c
+index b48fa54..c7f97fd 100644
+--- a/sapi/fpm/fpm/fpm_children.c
++++ b/sapi/fpm/fpm/fpm_children.c
+@@ -239,7 +239,7 @@
+
+ fpm_child_unlink(child);
+
+- fpm_scoreboard_proc_free(wp->scoreboard, child->scoreboard_i);
++ fpm_scoreboard_proc_free(child);
+
+ fpm_clock_get(&tv1);
+
+@@ -249,9 +249,9 @@
+ if (!fpm_pctl_can_spawn_children()) {
+ severity = ZLOG_DEBUG;
+ }
+- zlog(severity, "[pool %s] child %d exited %s after %ld.%06d seconds from start", child->wp->config->name, (int) pid, buf, tv2.tv_sec, (int) tv2.tv_usec);
++ zlog(severity, "[pool %s] child %d exited %s after %ld.%06d seconds from start", wp->config->name, (int) pid, buf, tv2.tv_sec, (int) tv2.tv_usec);
+ } else {
+- zlog(ZLOG_DEBUG, "[pool %s] child %d has been killed by the process management after %ld.%06d seconds from start", child->wp->config->name, (int) pid, tv2.tv_sec, (int) tv2.tv_usec);
++ zlog(ZLOG_DEBUG, "[pool %s] child %d has been killed by the process management after %ld.%06d seconds from start", wp->config->name, (int) pid, tv2.tv_sec, (int) tv2.tv_usec);
+ }
+
+ fpm_child_close(child, 1 /* in event_loop */);
+@@ -317,7 +317,7 @@
+ return 0;
+ }
+
+- if (0 > fpm_scoreboard_proc_alloc(wp->scoreboard, &c->scoreboard_i)) {
++ if (0 > fpm_scoreboard_proc_alloc(c)) {
+ fpm_stdio_discard_pipes(c);
+ fpm_child_free(c);
+ return 0;
+@@ -329,7 +329,7 @@
+
+ static void fpm_resources_discard(struct fpm_child_s *child) /* {{{ */
+ {
+- fpm_scoreboard_proc_free(child->wp->scoreboard, child->scoreboard_i);
++ fpm_scoreboard_proc_free(child);
+ fpm_stdio_discard_pipes(child);
+ fpm_child_free(child);
+ }
+@@ -342,10 +342,10 @@
+ if (wp == child->wp) {
+ continue;
+ }
+- fpm_scoreboard_free(wp->scoreboard);
++ fpm_scoreboard_free(wp);
+ }
+
+- fpm_scoreboard_child_use(child->wp->scoreboard, child->scoreboard_i, getpid());
++ fpm_scoreboard_child_use(child, getpid());
+ fpm_stdio_child_use_pipes(child);
+ fpm_child_free(child);
+ }
+diff --git a/sapi/fpm/fpm/fpm_request.c b/sapi/fpm/fpm/fpm_request.c
+index 3f82a7d..a707fd2 100644
+--- a/sapi/fpm/fpm/fpm_request.c
++++ b/sapi/fpm/fpm/fpm_request.c
+@@ -287,7 +287,7 @@
+ struct fpm_scoreboard_proc_s *proc;
+
+ /* no need in atomicity here */
+- proc = fpm_scoreboard_proc_get(child->wp->scoreboard, child->scoreboard_i);
++ proc = fpm_scoreboard_proc_get_from_child(child);
+ if (!proc) {
+ return 0;
+ }
+@@ -302,7 +302,7 @@
+
+ if (!tv) return -1;
+
+- proc = fpm_scoreboard_proc_get(child->wp->scoreboard, child->scoreboard_i);
++ proc = fpm_scoreboard_proc_get_from_child(child);
+ if (!proc) {
+ return -1;
+ }
+diff --git a/sapi/fpm/fpm/fpm_scoreboard.c b/sapi/fpm/fpm/fpm_scoreboard.c
+index 5693ce4..45d44f4 100644
+--- a/sapi/fpm/fpm/fpm_scoreboard.c
++++ b/sapi/fpm/fpm/fpm_scoreboard.c
+@@ -8,6 +8,7 @@
+ #include <time.h>
+
+ #include "fpm_config.h"
++#include "fpm_children.h"
+ #include "fpm_scoreboard.h"
+ #include "fpm_shm.h"
+ #include "fpm_sockets.h"
+@@ -25,7 +26,6 @@
+ int fpm_scoreboard_init_main() /* {{{ */
+ {
+ struct fpm_worker_pool_s *wp;
+- unsigned int i;
+
+ #ifdef HAVE_TIMES
+ #if (defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK))
+@@ -42,7 +42,7 @@
+
+
+ for (wp = fpm_worker_all_pools; wp; wp = wp->next) {
+- size_t scoreboard_size, scoreboard_nprocs_size;
++ size_t scoreboard_procs_size;
+ void *shm_mem;
+
+ if (wp->config->pm_max_children < 1) {
+@@ -55,22 +55,15 @@
+ return -1;
+ }
+
+- scoreboard_size = sizeof(struct fpm_scoreboard_s) + (wp->config->pm_max_children) * sizeof(struct fpm_scoreboard_proc_s *);
+- scoreboard_nprocs_size = sizeof(struct fpm_scoreboard_proc_s) * wp->config->pm_max_children;
+- shm_mem = fpm_shm_alloc(scoreboard_size + scoreboard_nprocs_size);
++ scoreboard_procs_size = sizeof(struct fpm_scoreboard_proc_s) * wp->config->pm_max_children;
++ shm_mem = fpm_shm_alloc(sizeof(struct fpm_scoreboard_s) + scoreboard_procs_size);
+
+ if (!shm_mem) {
+ return -1;
+ }
+- wp->scoreboard = shm_mem;
++ wp->scoreboard = shm_mem;
++ wp->scoreboard->pm = wp->config->pm;
+ wp->scoreboard->nprocs = wp->config->pm_max_children;
+- shm_mem += scoreboard_size;
+-
+- for (i = 0; i < wp->scoreboard->nprocs; i++, shm_mem += sizeof(struct fpm_scoreboard_proc_s)) {
+- wp->scoreboard->procs[i] = shm_mem;
+- }
+-
+- wp->scoreboard->pm = wp->config->pm;
+ wp->scoreboard->start_epoch = time(NULL);
+ strlcpy(wp->scoreboard->pool, wp->config->name, sizeof(wp->scoreboard->pool));
+ }
+@@ -164,28 +157,47 @@
+ }
+ /* }}} */
+
+-struct fpm_scoreboard_proc_s *fpm_scoreboard_proc_get(struct fpm_scoreboard_s *scoreboard, int child_index) /* {{{*/
++static inline struct fpm_scoreboard_proc_s *fpm_scoreboard_proc_get_ex(
++ struct fpm_scoreboard_s *scoreboard, int child_index, unsigned int nprocs) /* {{{*/
+ {
+ if (!scoreboard) {
+- scoreboard = fpm_scoreboard;
++ return NULL;
+ }
+
+- if (!scoreboard) {
++ if (child_index < 0 || (unsigned int)child_index >= nprocs) {
+ return NULL;
+ }
+
++ return &scoreboard->procs[child_index];
++}
++/* }}} */
++
++struct fpm_scoreboard_proc_s *fpm_scoreboard_proc_get(
++ struct fpm_scoreboard_s *scoreboard, int child_index) /* {{{*/
++{
++ if (!scoreboard) {
++ scoreboard = fpm_scoreboard;
++ }
++
+ if (child_index < 0) {
+ child_index = fpm_scoreboard_i;
+ }
+
+- if (child_index < 0 || child_index >= scoreboard->nprocs) {
+- return NULL;
+- }
++ return fpm_scoreboard_proc_get_ex(scoreboard, child_index, scoreboard->nprocs);
++}
++
++struct fpm_scoreboard_proc_s *fpm_scoreboard_proc_get_from_child(struct fpm_child_s *child) /* {{{*/
++{
++ struct fpm_worker_pool_s *wp = child->wp;
++ unsigned int nprocs = wp->config->pm_max_children;
++ struct fpm_scoreboard_s *scoreboard = wp->scoreboard;
++ int child_index = child->scoreboard_i;
+
+- return scoreboard->procs[child_index];
++ return fpm_scoreboard_proc_get_ex(scoreboard, child_index, nprocs);
+ }
+ /* }}} */
+
++
+ struct fpm_scoreboard_s *fpm_scoreboard_acquire(struct fpm_scoreboard_s *scoreboard, int nohang) /* {{{ */
+ {
+ struct fpm_scoreboard_s *s;
+@@ -236,28 +248,28 @@
+ proc->lock = 0;
+ }
+
+-void fpm_scoreboard_free(struct fpm_scoreboard_s *scoreboard) /* {{{ */
++void fpm_scoreboard_free(struct fpm_worker_pool_s *wp) /* {{{ */
+ {
+- size_t scoreboard_size, scoreboard_nprocs_size;
++ size_t scoreboard_procs_size;
++ struct fpm_scoreboard_s *scoreboard = wp->scoreboard;
+
+ if (!scoreboard) {
+ zlog(ZLOG_ERROR, "**scoreboard is NULL");
+ return;
+ }
+
+- scoreboard_size = sizeof(struct fpm_scoreboard_s) + (scoreboard->nprocs) * sizeof(struct fpm_scoreboard_proc_s *);
+- scoreboard_nprocs_size = sizeof(struct fpm_scoreboard_proc_s) * scoreboard->nprocs;
+-
+- fpm_shm_free(scoreboard, scoreboard_size + scoreboard_nprocs_size);
++ scoreboard_procs_size = sizeof(struct fpm_scoreboard_proc_s) * wp->config->pm_max_children;
++
++ fpm_shm_free(scoreboard, sizeof(struct fpm_scoreboard_s) + scoreboard_procs_size);
+ }
+ /* }}} */
+
+-void fpm_scoreboard_child_use(struct fpm_scoreboard_s *scoreboard, int child_index, pid_t pid) /* {{{ */
++void fpm_scoreboard_child_use(struct fpm_child_s *child, pid_t pid) /* {{{ */
+ {
+ struct fpm_scoreboard_proc_s *proc;
+- fpm_scoreboard = scoreboard;
+- fpm_scoreboard_i = child_index;
+- proc = fpm_scoreboard_proc_get(scoreboard, child_index);
++ fpm_scoreboard = child->wp->scoreboard;
++ fpm_scoreboard_i = child->scoreboard_i;
++ proc = fpm_scoreboard_proc_get_from_child(child);
+ if (!proc) {
+ return;
+ }
+@@ -266,18 +278,22 @@
+ }
+ /* }}} */
+
+-void fpm_scoreboard_proc_free(struct fpm_scoreboard_s *scoreboard, int child_index) /* {{{ */
++void fpm_scoreboard_proc_free(struct fpm_child_s *child) /* {{{ */
+ {
++ struct fpm_worker_pool_s *wp = child->wp;
++ struct fpm_scoreboard_s *scoreboard = wp->scoreboard;
++ int child_index = child->scoreboard_i;
++
+ if (!scoreboard) {
+ return;
+ }
+
+- if (child_index < 0 || child_index >= scoreboard->nprocs) {
++ if (child_index < 0 || child_index >= wp->config->pm_max_children) {
+ return;
+ }
+
+- if (scoreboard->procs[child_index] && scoreboard->procs[child_index]->used > 0) {
+- memset(scoreboard->procs[child_index], 0, sizeof(struct fpm_scoreboard_proc_s));
++ if (scoreboard->procs[child_index].used > 0) {
++ memset(&scoreboard->procs[child_index], 0, sizeof(struct fpm_scoreboard_proc_s));
+ }
+
+ /* set this slot as free to avoid search on next alloc */
+@@ -285,41 +301,44 @@
+ }
+ /* }}} */
+
+-int fpm_scoreboard_proc_alloc(struct fpm_scoreboard_s *scoreboard, int *child_index) /* {{{ */
++int fpm_scoreboard_proc_alloc(struct fpm_child_s *child) /* {{{ */
+ {
+ int i = -1;
++ struct fpm_worker_pool_s *wp = child->wp;
++ struct fpm_scoreboard_s *scoreboard = wp->scoreboard;
++ int nprocs = wp->config->pm_max_children;
+
+- if (!scoreboard || !child_index) {
++ if (!scoreboard) {
+ return -1;
+ }
+
+ /* first try the slot which is supposed to be free */
+- if (scoreboard->free_proc >= 0 && scoreboard->free_proc < scoreboard->nprocs) {
+- if (scoreboard->procs[scoreboard->free_proc] && !scoreboard->procs[scoreboard->free_proc]->used) {
++ if (scoreboard->free_proc >= 0 && scoreboard->free_proc < nprocs) {
++ if (!scoreboard->procs[scoreboard->free_proc].used) {
+ i = scoreboard->free_proc;
+ }
+ }
+
+ if (i < 0) { /* the supposed free slot is not, let's search for a free slot */
+ zlog(ZLOG_DEBUG, "[pool %s] the proc->free_slot was not free. Let's search", scoreboard->pool);
+- for (i = 0; i < scoreboard->nprocs; i++) {
+- if (scoreboard->procs[i] && !scoreboard->procs[i]->used) { /* found */
++ for (i = 0; i < nprocs; i++) {
++ if (!scoreboard->procs[i].used) { /* found */
+ break;
+ }
+ }
+ }
+
+ /* no free slot */
+- if (i < 0 || i >= scoreboard->nprocs) {
++ if (i < 0 || i >= nprocs) {
+ zlog(ZLOG_ERROR, "[pool %s] no free scoreboard slot", scoreboard->pool);
+ return -1;
+ }
+
+- scoreboard->procs[i]->used = 1;
+- *child_index = i;
++ scoreboard->procs[i].used = 1;
++ child->scoreboard_i = i;
+
+ /* supposed next slot is free */
+- if (i + 1 >= scoreboard->nprocs) {
++ if (i + 1 >= nprocs) {
+ scoreboard->free_proc = 0;
+ } else {
+ scoreboard->free_proc = i + 1;
+diff --git a/sapi/fpm/fpm/fpm_scoreboard.h b/sapi/fpm/fpm/fpm_scoreboard.h
+index f58a287..a0cc093 100644
+--- a/sapi/fpm/fpm/fpm_scoreboard.h
++++ b/sapi/fpm/fpm/fpm_scoreboard.h
+@@ -65,7 +65,7 @@
+ unsigned int nprocs;
+ int free_proc;
+ unsigned long int slow_rq;
+- struct fpm_scoreboard_proc_s *procs[];
++ struct fpm_scoreboard_proc_s procs[];
+ };
+
+ int fpm_scoreboard_init_main();
+@@ -74,18 +74,19 @@
+ void fpm_scoreboard_update(int idle, int active, int lq, int lq_len, int requests, int max_children_reached, int slow_rq, int action, struct fpm_scoreboard_s *scoreboard);
+ struct fpm_scoreboard_s *fpm_scoreboard_get();
+ struct fpm_scoreboard_proc_s *fpm_scoreboard_proc_get(struct fpm_scoreboard_s *scoreboard, int child_index);
++struct fpm_scoreboard_proc_s *fpm_scoreboard_proc_get_from_child(struct fpm_child_s *child);
+
+ struct fpm_scoreboard_s *fpm_scoreboard_acquire(struct fpm_scoreboard_s *scoreboard, int nohang);
+ void fpm_scoreboard_release(struct fpm_scoreboard_s *scoreboard);
+ struct fpm_scoreboard_proc_s *fpm_scoreboard_proc_acquire(struct fpm_scoreboard_s *scoreboard, int child_index, int nohang);
+ void fpm_scoreboard_proc_release(struct fpm_scoreboard_proc_s *proc);
+
+-void fpm_scoreboard_free(struct fpm_scoreboard_s *scoreboard);
++void fpm_scoreboard_free(struct fpm_worker_pool_s *wp);
+
+-void fpm_scoreboard_child_use(struct fpm_scoreboard_s *scoreboard, int child_index, pid_t pid);
++void fpm_scoreboard_child_use(struct fpm_child_s *child, pid_t pid);
+
+-void fpm_scoreboard_proc_free(struct fpm_scoreboard_s *scoreboard, int child_index);
+-int fpm_scoreboard_proc_alloc(struct fpm_scoreboard_s *scoreboard, int *child_index);
++void fpm_scoreboard_proc_free(struct fpm_child_s *child);
++int fpm_scoreboard_proc_alloc(struct fpm_child_s *child);
+
+ #ifdef HAVE_TIMES
+ float fpm_scoreboard_get_tick();
+diff --git a/sapi/fpm/fpm/fpm_status.c b/sapi/fpm/fpm/fpm_status.c
+index 3e82fac..666a1d9 100644
+--- a/sapi/fpm/fpm/fpm_status.c
++++ b/sapi/fpm/fpm/fpm_status.c
+@@ -402,10 +402,10 @@
+
+ first = 1;
+ for (i=0; i<scoreboard_p->nprocs; i++) {
+- if (!scoreboard_p->procs[i] || !scoreboard_p->procs[i]->used) {
++ if (!scoreboard_p->procs[i].used) {
+ continue;
+ }
+- proc = *scoreboard_p->procs[i];
++ proc = scoreboard_p->procs[i];
+
+ if (first) {
+ first = 0;
+diff --git a/sapi/fpm/fpm/fpm_worker_pool.c b/sapi/fpm/fpm/fpm_worker_pool.c
+index a002291..c778b33 100644
+--- a/sapi/fpm/fpm/fpm_worker_pool.c
++++ b/sapi/fpm/fpm/fpm_worker_pool.c
+@@ -44,7 +44,7 @@
+ fpm_worker_pool_config_free(wp->config);
+ fpm_children_free(wp->children);
+ if ((which & FPM_CLEANUP_CHILD) == 0 && fpm_globals.parent_pid == getpid()) {
+- fpm_scoreboard_free(wp->scoreboard);
++ fpm_scoreboard_free(wp);
+ }
+ fpm_worker_pool_free(wp);
+ }
+diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c
+index 8815e8a..88de8e1 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 ee050e2..486a49d 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 da30004..f481353 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>