diff options
Diffstat (limited to 'debian-php-7.0.33.patch')
-rw-r--r-- | debian-php-7.0.33.patch | 4569 |
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хU9oљѕкнёљ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> |