diff options
Diffstat (limited to 'debian-php-5.3.29.patch')
-rw-r--r-- | debian-php-5.3.29.patch | 2703 |
1 files changed, 2703 insertions, 0 deletions
diff --git a/debian-php-5.3.29.patch b/debian-php-5.3.29.patch new file mode 100644 index 000000000000..1c1820958909 --- /dev/null +++ b/debian-php-5.3.29.patch @@ -0,0 +1,2703 @@ + +diff --git a/ext/standard/proc_open.c b/ext/standard/proc_open.c +index ac4f5b7..1e99293 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 c8399c4..d7103b2 100644 +--- a/php.ini-development ++++ b/php.ini-development +@@ -295,6 +295,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/mysql/config.m4 b/ext/mysql/config.m4 +index fd7f52e..999c47b 100644 +--- a/ext/mysql/config.m4 ++++ b/ext/mysql/config.m4 +@@ -77,7 +77,7 @@ + Note that the MySQL client library is not bundled anymore!]) + fi + +- if test "$enable_maintainer_zts" = "yes"; then ++ if true || test "$enable_maintainer_zts" = "yes"; then + MYSQL_LIBNAME=mysqlclient_r + else + MYSQL_LIBNAME=mysqlclient +diff --git a/ext/mysqli/config.m4 b/ext/mysqli/config.m4 +index f6c86e7..9192600 100644 +--- a/ext/mysqli/config.m4 ++++ b/ext/mysqli/config.m4 +@@ -26,7 +26,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 f237f41..3483cca 100755 +--- a/ext/pdo_mysql/config.m4 ++++ b/ext/pdo_mysql/config.m4 +@@ -55,7 +55,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 3eb2616..98e55ea 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 cb1224e..794f508 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 f472bad..9805bfc 100644 +--- a/main/streams/plain_wrapper.c ++++ b/main/streams/plain_wrapper.c +@@ -656,7 +656,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: + do_fstat(data, 1); +diff --git a/ext/dba/dba.c b/ext/dba/dba.c +index cf9674a..7554203 100644 +--- a/ext/dba/dba.c ++++ b/ext/dba/dba.c +@@ -930,7 +930,7 @@ + } + } + +- if (error || hptr->open(info, &error TSRMLS_CC) != SUCCESS) { ++ if (error || (hptr->open)(info, &error TSRMLS_CC) != SUCCESS) { + dba_close(info TSRMLS_CC); + php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(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 2d0ad86..ddb2440 100644 +--- a/ext/dba/dba_db3.c ++++ b/ext/dba/dba_db3.c +@@ -91,7 +91,7 @@ + + if ((err=db_create(&dbp, NULL, 0)) == 0) { + dbp->set_errcall(dbp, php_dba_db3_errcall_fcn); +- if ((err=dbp->open(dbp, info->path, NULL, type, gmode, filemode)) == 0) { ++ if ((err=(dbp->open)(dbp, info->path, NULL, type, gmode, filemode)) == 0) { + dba_db3_data *data; + + data = pemalloc(sizeof(*data), info->flags&DBA_PERSISTENT); +diff --git a/ext/dba/dba_db4.c b/ext/dba/dba_db4.c +index 2dfb33a..1aac4cc 100644 +--- a/ext/dba/dba_db4.c ++++ b/ext/dba/dba_db4.c +@@ -126,9 +126,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/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/Zend/zend_strtod.c b/Zend/zend_strtod.c +index e74cf0e..7ec0366 100644 +--- a/Zend/zend_strtod.c ++++ b/Zend/zend_strtod.c +@@ -152,14 +152,25 @@ + #define IEEE_LITTLE_ENDIAN + #endif + +-#if defined(__arm__) && !defined(__VFP_FP__) +-/* +- * * Although the CPU is little endian the FP has different +- * * byte and word endianness. The byte order is still little endian +- * * but the word order is big endian. +- * */ +-#define IEEE_BIG_ENDIAN ++#if defined(__arm__) || defined(__thumb__) ++/* ARM traditionally used big-endian words; and within those words the ++ byte ordering was big or little endian depending upon the target. ++ Modern floating-point formats are naturally ordered; in this case ++ __VFP_FP__ will be defined, even if soft-float. */ + #undef IEEE_LITTLE_ENDIAN ++#undef IEEE_BIG_ENDIAN ++#if defined(__VFP_FP__) || defined(__MAVERICK__) ++# ifdef __ARMEL__ ++# define IEEE_LITTLE_ENDIAN ++# else ++# define IEEE_BIG_ENDIAN ++# endif ++#else ++# define IEEE_BIG_ENDIAN ++# ifdef __ARMEL__ ++# define IEEE_BYTES_LITTLE_ENDIAN ++# endif ++#endif + #endif + + #ifdef __vax__ +@@ -287,7 +298,7 @@ + * An alternative that might be better on some machines is + * #define Storeinc(a,b,c) (*a++ = b << 16 | c & 0xffff) + */ +-#if defined(IEEE_LITTLE_ENDIAN) + defined(VAX) + defined(__arm__) ++#if defined(IEEE_LITTLE_ENDIAN) + defined(VAX) + defined(IEEE_BYTES_LITTLE_ENDIAN) + #define Storeinc(a,b,c) (((unsigned short *)a)[1] = (unsigned short)b, \ + ((unsigned short *)a)[0] = (unsigned short)c, a++) + #else +diff --git a/ext/mssql/php_mssql.c b/ext/mssql/php_mssql.c +index 66497f1..6196690 100644 +--- a/ext/mssql/php_mssql.c ++++ b/ext/mssql/php_mssql.c +@@ -178,6 +178,38 @@ + PHP_FE(mssql_execute, arginfo_mssql_execute) + PHP_FE(mssql_free_statement, arginfo_mssql_free_statement) + PHP_FE(mssql_guid_string, arginfo_mssql_guid_string) ++#if !defined(PHP_WIN32) && !defined(HAVE_SYBASE_CT) ++ PHP_FALIAS(sybase_connect, mssql_connect, arginfo_mssql_connect) ++ PHP_FALIAS(sybase_pconnect, mssql_pconnect, arginfo_mssql_connect) ++ PHP_FALIAS(sybase_close, mssql_close, arginfo_mssql_close) ++ PHP_FALIAS(sybase_select_db, mssql_select_db, arginfo_mssql_select_db) ++ PHP_FALIAS(sybase_query, mssql_query, arginfo_mssql_query) ++ PHP_FALIAS(sybase_fetch_batch, mssql_fetch_batch, arginfo_mssql_fetch_batch) ++ PHP_FALIAS(sybase_affected_rows, mssql_rows_affected, arginfo_mssql_rows_affected) ++ PHP_FALIAS(sybase_free_result, mssql_free_result, arginfo_mssql_fetch_batch) ++ PHP_FALIAS(sybase_get_last_message, mssql_get_last_message, arginfo_mssql_get_last_message) ++ PHP_FALIAS(sybase_num_rows, mssql_num_rows, arginfo_mssql_fetch_batch) ++ PHP_FALIAS(sybase_num_fields, mssql_num_fields, arginfo_mssql_fetch_batch) ++ PHP_FALIAS(sybase_fetch_field, mssql_fetch_field, arginfo_mssql_fetch_field) ++ PHP_FALIAS(sybase_fetch_row, mssql_fetch_row, arginfo_mssql_fetch_batch) ++ PHP_FALIAS(sybase_fetch_array, mssql_fetch_array, arginfo_mssql_fetch_array) ++ PHP_FALIAS(sybase_fetch_assoc, mssql_fetch_assoc, arginfo_mssql_fetch_assoc) ++ PHP_FALIAS(sybase_fetch_object, mssql_fetch_object, arginfo_mssql_fetch_batch) ++ PHP_FALIAS(sybase_field_length, mssql_field_length, arginfo_mssql_field_length) ++ PHP_FALIAS(sybase_field_name, mssql_field_name, arginfo_mssql_field_length) ++ PHP_FALIAS(sybase_field_type, mssql_field_type, arginfo_mssql_field_length) ++ PHP_FALIAS(sybase_data_seek, mssql_data_seek, arginfo_mssql_data_seek) ++ PHP_FALIAS(sybase_field_seek, mssql_field_seek, arginfo_mssql_fetch_field) ++ PHP_FALIAS(sybase_result, mssql_result, arginfo_mssql_result) ++ PHP_FALIAS(sybase_next_result, mssql_next_result, arginfo_mssql_fetch_assoc) ++ PHP_FALIAS(sybase_min_error_severity, mssql_min_error_severity, arginfo_mssql_min_error_severity) ++ PHP_FALIAS(sybase_min_message_severity, mssql_min_message_severity, arginfo_mssql_min_error_severity) ++ PHP_FALIAS(sybase_init, mssql_init, arginfo_mssql_init) ++ PHP_FALIAS(sybase_bind, mssql_bind, arginfo_mssql_bind) ++ PHP_FALIAS(sybase_execute, mssql_execute, arginfo_mssql_execute) ++ PHP_FALIAS(sybase_free_statement, mssql_free_statement, arginfo_mssql_free_statement) ++ PHP_FALIAS(sybase_guid_string, mssql_guid_string, arginfo_mssql_guid_string) ++#endif + PHP_FE_END + }; + /* }}} */ +diff --git a/Zend/zend.h b/Zend/zend.h +index 35fa013..3d93018 100644 +--- a/Zend/zend.h ++++ b/Zend/zend.h +@@ -90,11 +90,11 @@ + # endif + + # if defined(RTLD_GROUP) && defined(RTLD_WORLD) && defined(RTLD_PARENT) +-# define DL_LOAD(libname) dlopen(libname, RTLD_LAZY | RTLD_GLOBAL | RTLD_GROUP | RTLD_WORLD | RTLD_PARENT) ++# define DL_LOAD(libname) dlopen(libname, RTLD_NOW | RTLD_GLOBAL | RTLD_GROUP | RTLD_WORLD | RTLD_PARENT) + # elif defined(RTLD_DEEPBIND) +-# define DL_LOAD(libname) dlopen(libname, RTLD_LAZY | RTLD_GLOBAL | RTLD_DEEPBIND) ++# define DL_LOAD(libname) dlopen(libname, RTLD_NOW | RTLD_GLOBAL | RTLD_DEEPBIND) + # else +-# define DL_LOAD(libname) dlopen(libname, RTLD_LAZY | RTLD_GLOBAL) ++# define DL_LOAD(libname) dlopen(libname, RTLD_NOW | RTLD_GLOBAL) + # endif + # define DL_UNLOAD dlclose + # if defined(DLSYM_NEEDS_UNDERSCORE) +diff --git a/sapi/apache2handler/config.m4 b/sapi/apache2handler/config.m4 +index f170ea9..3b280dd 100644 +--- a/sapi/apache2handler/config.m4 ++++ b/sapi/apache2handler/config.m4 +@@ -69,7 +69,7 @@ + \$(mkinstalldirs) '$APXS_SYSCONFDIR' && \ + $APXS -S LIBEXECDIR='$APXS_LIBEXECDIR' \ + -S SYSCONFDIR='$APXS_SYSCONFDIR' \ +- -i -a -n php5" ++ -i -n php5" + fi + + case $host_alias in +diff --git a/ext/mysql/php_mysql.c b/ext/mysql/php_mysql.c +index 2d3ba60..679d417 100644 +--- a/ext/mysql/php_mysql.c ++++ b/ext/mysql/php_mysql.c +@@ -735,13 +735,13 @@ + E_DEPRECATED, + "The mysql extension is deprecated and will be removed in the future: use mysqli or PDO instead"); + +-#if !defined(MYSQL_USE_MYSQLND) +- if ((MYSQL_VERSION_ID / 100) != (mysql_get_client_version() / 100)) { +- php_error_docref(NULL TSRMLS_CC, E_WARNING, +- "Headers and client library minor version mismatch. Headers:%d Library:%ld", +- MYSQL_VERSION_ID, mysql_get_client_version()); +- } +-#endif ++/* #if !defined(MYSQL_USE_MYSQLND) */ ++/* if ((MYSQL_VERSION_ID / 100) != (mysql_get_client_version() / 100)) { */ ++/* php_error_docref(NULL TSRMLS_CC, E_WARNING, */ ++/* "Headers and client library minor version mismatch. Headers:%d Library:%ld", */ ++/* MYSQL_VERSION_ID, mysql_get_client_version()); */ ++/* } */ ++/* #endif */ + + connect_timeout = MySG(connect_timeout); + +diff --git a/ext/mysqli/mysqli_nonapi.c b/ext/mysqli/mysqli_nonapi.c +index f1e805c..9ebdca1 100644 +--- a/ext/mysqli/mysqli_nonapi.c ++++ b/ext/mysqli/mysqli_nonapi.c +@@ -74,13 +74,13 @@ + zend_bool self_alloced = 0; + + +-#if !defined(MYSQL_USE_MYSQLND) +- if ((MYSQL_VERSION_ID / 100) != (mysql_get_client_version() / 100)) { +- php_error_docref(NULL TSRMLS_CC, E_WARNING, +- "Headers and client library minor version mismatch. Headers:%d Library:%ld", +- MYSQL_VERSION_ID, mysql_get_client_version()); +- } +-#endif ++/* #if !defined(MYSQL_USE_MYSQLND) */ ++/* if ((MYSQL_VERSION_ID / 100) != (mysql_get_client_version() / 100)) { */ ++/* php_error_docref(NULL TSRMLS_CC, E_WARNING, */ ++/* "Headers and client library minor version mismatch. Headers:%d Library:%ld", */ ++/* MYSQL_VERSION_ID, mysql_get_client_version()); */ ++/* } */ ++/* #endif */ + + if (getThis() && !ZEND_NUM_ARGS() && in_ctor) { + php_mysqli_init(INTERNAL_FUNCTION_PARAM_PASSTHRU); +diff --git a/ext/tidy/tidy.c b/ext/tidy/tidy.c +index 57f050b..4af30f2 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/Zend/zend_gc.c b/Zend/zend_gc.c +index e72655c..e7c5098 100644 +--- a/Zend/zend_gc.c ++++ b/Zend/zend_gc.c +@@ -310,16 +310,25 @@ + } + } + while (p != NULL) { +- pz = *(zval**)p->pData; +- if (Z_TYPE_P(pz) != IS_ARRAY || Z_ARRVAL_P(pz) != &EG(symbol_table)) { +- pz->refcount__gc++; +- } +- if (GC_ZVAL_GET_COLOR(pz) != GC_BLACK) { +- if (p->pListNext == NULL) { +- goto tail_call; ++ if (p->pData != NULL) { ++ pz = *(zval**)p->pData; ++ if (pz != NULL) { ++ if (Z_TYPE_P(pz) != IS_ARRAY || Z_ARRVAL_P(pz) != &EG(symbol_table)) { ++ pz->refcount__gc++; ++ } ++ if (GC_ZVAL_GET_COLOR(pz) != GC_BLACK) { ++ if (p->pListNext == NULL) { ++ goto tail_call; ++ } else { ++ zval_scan_black(pz TSRMLS_CC); ++ } ++ } + } else { +- zval_scan_black(pz TSRMLS_CC); ++ /* Now this is really odd ... we've got a p->pData which references a NULL pointer */ + } ++ } else { ++ /* shall we log something when encountering a p->pData == NULL */ ++ + } + p = p->pListNext; + } +@@ -353,12 +362,20 @@ + } + p = props->pListHead; + while (p != NULL) { +- pz = *(zval**)p->pData; +- if (Z_TYPE_P(pz) != IS_ARRAY || Z_ARRVAL_P(pz) != &EG(symbol_table)) { +- pz->refcount__gc++; +- } +- if (GC_ZVAL_GET_COLOR(pz) != GC_BLACK) { +- zval_scan_black(pz TSRMLS_CC); ++ if (p->pData != NULL) { ++ pz = *(zval**)p->pData; ++ if (pz != NULL) { ++ if (Z_TYPE_P(pz) != IS_ARRAY || Z_ARRVAL_P(pz) != &EG(symbol_table)) { ++ pz->refcount__gc++; ++ } ++ if (GC_ZVAL_GET_COLOR(pz) != GC_BLACK) { ++ zval_scan_black(pz TSRMLS_CC); ++ } ++ } else { ++ /* pz is NULL - maybe there should be some logging? */ ++ } ++ } else { ++ /* p->pData is NULL - maybe there should be some logging? */ + } + p = p->pListNext; + } +@@ -417,14 +434,23 @@ + } + } + while (p != NULL) { +- pz = *(zval**)p->pData; +- if (Z_TYPE_P(pz) != IS_ARRAY || Z_ARRVAL_P(pz) != &EG(symbol_table)) { +- pz->refcount__gc--; +- } +- if (p->pListNext == NULL) { +- goto tail_call; ++ if (p->pData != NULL) { ++ pz = *(zval**)p->pData; ++ if (pz != NULL) { ++ if (Z_TYPE_P(pz) != IS_ARRAY || Z_ARRVAL_P(pz) != &EG(symbol_table)) { ++ pz->refcount__gc--; ++ } ++ if (p->pListNext == NULL) { ++ goto tail_call; ++ } else { ++ zval_mark_grey(pz TSRMLS_CC); ++ } ++ } else { ++ /* Now this is odd - we have a valid pz and a pData which is NULL */ ++ ++ } + } else { +- zval_mark_grey(pz TSRMLS_CC); ++ /* Some logging maybe? p->pData is NULL */ + } + p = p->pListNext; + } +@@ -459,11 +485,19 @@ + } + p = props->pListHead; + while (p != NULL) { +- pz = *(zval**)p->pData; +- if (Z_TYPE_P(pz) != IS_ARRAY || Z_ARRVAL_P(pz) != &EG(symbol_table)) { +- pz->refcount__gc--; ++ if (p->pData != NULL) { ++ pz = *(zval**)p->pData; ++ if (pz != NULL) { ++ if (Z_TYPE_P(pz) != IS_ARRAY || Z_ARRVAL_P(pz) != &EG(symbol_table)) { ++ pz->refcount__gc--; ++ } ++ zval_mark_grey(pz TSRMLS_CC); ++ } else { ++ /* TODO: Some logging maybe? */ ++ } ++ } else { ++ /* TODO: Some logging maybe? */ + } +- zval_mark_grey(pz TSRMLS_CC); + p = p->pListNext; + } + } +diff --git a/ext/phar/phar.c b/ext/phar/phar.c +index 6e5cec2..850a6e6 100644 +--- a/ext/phar/phar.c ++++ b/ext/phar/phar.c +@@ -1385,6 +1385,9 @@ + /* set up our manifest */ + mydata = ecalloc(1, sizeof(phar_archive_data)); + mydata->fname = expand_filepath(fname, NULL TSRMLS_CC); ++ 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/exif/exif.c b/ext/exif/exif.c +index cad29b7..47055a1 100644 +--- a/ext/exif/exif.c ++++ b/ext/exif/exif.c +@@ -3577,10 +3577,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); +@@ -3588,8 +3588,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 +@@ -3672,9 +3672,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 47055a1..5497068 100644 +--- a/ext/exif/exif.c ++++ b/ext/exif/exif.c +@@ -3519,7 +3519,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 +@@ -3540,6 +3540,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; +@@ -4183,7 +4187,9 @@ + ZVAL_STRINGL(return_value, ImageInfo.Thumbnail.data, ImageInfo.Thumbnail.size, 1); + if (arg_c >= 3) { + if (!ImageInfo.Thumbnail.width || !ImageInfo.Thumbnail.height) { +- exif_scan_thumbnail(&ImageInfo TSRMLS_CC); ++ if (!exif_scan_thumbnail(&ImageInfo TSRMLS_CC)) { ++ 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/phar/tar.c b/ext/phar/tar.c +index 898ff85..7ad95eb 100644 +--- a/ext/phar/tar.c ++++ b/ext/phar/tar.c +@@ -765,7 +765,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/main/streams/plain_wrapper.c b/main/streams/plain_wrapper.c +index 9805bfc..a5a09e2 100644 +--- a/main/streams/plain_wrapper.c ++++ b/main/streams/plain_wrapper.c +@@ -1132,34 +1132,50 @@ + # ifdef EXDEV + if (errno == EXDEV) { + struct stat 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 TSRMLS_CC) == SUCCESS) { + if (VCWD_STAT(url_from, &sb) == 0) { ++ success = 1; + # if !defined(TSRM_WIN32) && !defined(NETWARE) +- if (VCWD_CHMOD(url_to, sb.st_mode)) { ++ /* ++ * 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 TSRMLS_CC, url_from, url_to, E_WARNING, "%s", strerror(errno)); + if (errno == EPERM) { +- php_error_docref2(NULL TSRMLS_CC, url_from, url_to, E_WARNING, "%s", strerror(errno)); +- VCWD_UNLINK(url_from); +- return 1; ++ success = 0; + } +- php_error_docref2(NULL TSRMLS_CC, url_from, url_to, E_WARNING, "%s", strerror(errno)); +- return 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 TSRMLS_CC, url_from, url_to, E_WARNING, "%s", strerror(errno)); +- VCWD_UNLINK(url_from); +- return 1; ++ if (errno == EPERM) { ++ success = 0; ++ } + } +- php_error_docref2(NULL TSRMLS_CC, 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 TSRMLS_CC, url_from, url_to, E_WARNING, "%s", strerror(errno)); + } ++ } else { ++ php_error_docref2(NULL TSRMLS_CC, url_from, url_to, E_WARNING, "%s", strerror(errno)); + } +- php_error_docref2(NULL TSRMLS_CC, 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/ext/exif/exif.c b/ext/exif/exif.c +index ce8db17..4350124 100644 +--- a/ext/exif/exif.c ++++ b/ext/exif/exif.c +@@ -2812,6 +2812,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/ext/pdo_pgsql/tests/bug48764.phpt b/ext/pdo_pgsql/tests/bug48764.phpt +index 83fa565..14c1f68 100644 +--- a/ext/pdo_pgsql/tests/bug48764.phpt ++++ b/ext/pdo_pgsql/tests/bug48764.phpt +@@ -12,7 +12,7 @@ + $client_version = $db->getAttribute(PDO::ATTR_CLIENT_VERSION); + $server_version = $db->getAttribute(PDO::ATTR_SERVER_VERSION); + +-if (version_compare($server_version, '7.4', '<') || version_compare($client_version, '7.4', '<')) { ++if (version_compare($server_version, '7.4', '<') || version_compare($client_version, '7.4', '<') || version_compare($server_version, '10', '>=')) { + die('skip'); + } + +--- a/ext/exif/exif.c ++++ b/ext/exif/exif.c +@@ -2901,7 +2901,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 503ac82..99931a5 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 335dbd1..bbc4b0f 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 +diff --git a/ext/exif/exif.c b/ext/exif/exif.c +index 15e091b..b6c3177 100644 +--- a/ext/exif/exif.c ++++ b/ext/exif/exif.c +@@ -3536,6 +3536,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; +--- /dev/null ++++ b/ext/exif/tests/bug77988.jpg +@@ -0,0 +1 @@ ++ÿØ0 +\ No newline at end of file +--- /dev/null ++++ b/ext/exif/tests/bug77988.phpt +@@ -0,0 +1,11 @@ ++--TEST-- ++Bug #77988 (heap-buffer-overflow on php_jpg_get16) ++--SKIPIF-- ++<?php if (!extension_loaded('exif')) print 'skip exif extension not available';?> ++--FILE-- ++<?php ++exif_read_data(__DIR__."/bug77988.jpg", 'COMMENT', FALSE, TRUE); ++?> ++DONE ++--EXPECTF-- ++DONE +\ No newline at end of file +diff --git a/ext/sqlite3/sqlite3.c b/ext/sqlite3/sqlite3.c +index 761b777..7bf873f 100644 +--- a/ext/sqlite3/sqlite3.c ++++ b/ext/sqlite3/sqlite3.c +@@ -2062,6 +2062,15 @@ + } + #endif + ++ if (strncmp(arg3, "file:", 5) == 0) { ++ /* starts with "file:" */ ++ if (!arg3[5]) { ++ return SQLITE_DENY; ++ } ++ if (php_check_open_basedir(arg3 + 5 TSRMLS_CC)) { ++ return SQLITE_DENY; ++ } ++ } + if (php_check_open_basedir(arg3 TSRMLS_CC)) { + return SQLITE_DENY; + } +diff --git a/run-tests.php b/run-tests.php +index 0949d50..7dab5ab 100755 +--- a/run-tests.php ++++ b/run-tests.php +@@ -1553,6 +1553,11 @@ + $info = " (warn: $m[1])"; + } + } ++ ++ if (!strncasecmp('xfail', ltrim($output), 5)) { ++ // Pretend we have an XFAIL section ++ $section_text['XFAIL'] = trim(substr(ltrim($output), 5)); ++ } + } + } + +diff --git a/ext/phar/tests/phar_bz2.phpt b/ext/phar/tests/phar_bz2.phpt +index 0e6e3ec..106fa89 100644 +--- a/ext/phar/tests/phar_bz2.phpt ++++ b/ext/phar/tests/phar_bz2.phpt +@@ -5,6 +5,7 @@ + if (!extension_loaded("phar")) die("skip"); + if (!extension_loaded("spl")) die("skip SPL not available"); + if (!extension_loaded("bz2")) die("skip bz2 not available"); ++if (phpversion() < "7.0.0" && extension_loaded('Zend OPcache') && ini_get('opcache.enable_cli')==1) die("xfail for PHP version lower than 7 when OPcache enabled"); + ?> + --INI-- + phar.readonly=0 +diff --git a/ext/phar/tests/phar_gzip.phpt b/ext/phar/tests/phar_gzip.phpt +index c722834..19d5606 100644 +--- a/ext/phar/tests/phar_gzip.phpt ++++ b/ext/phar/tests/phar_gzip.phpt +@@ -7,6 +7,7 @@ + if (!extension_loaded("spl")) die("skip SPL not available"); + if (!extension_loaded("zlib")) die("skip zlib not available"); + if (version_compare(phpversion(), '5.2.6', '<')) die("skip zlib is buggy in PHP < 5.2.6"); ++if (phpversion() < "7.0.0" && extension_loaded('Zend OPcache') && ini_get('opcache.enable_cli')==1) die("xfail for PHP version lower than 7 when OPcache enabled"); + ?> + --INI-- + phar.readonly=0 +diff --git a/ext/phar/tests/tar/rename.phpt b/ext/phar/tests/tar/rename.phpt +index 96588a6..9b2b4f4 100644 +--- a/ext/phar/tests/tar/rename.phpt ++++ b/ext/phar/tests/tar/rename.phpt +@@ -1,7 +1,10 @@ + --TEST-- + Phar: rename test tar-based + --SKIPIF-- +-<?php if (!extension_loaded("phar")) die("skip"); ?> ++<?php ++if (!extension_loaded("phar")) die("skip"); ++if (phpversion() < "7.0.0" && extension_loaded('Zend OPcache') && ini_get('opcache.enable_cli')==1) die("xfail for PHP version lower than 7 when OPcache enabled"); ++?> + --INI-- + phar.readonly=0 + phar.require_hash=0 +diff --git a/ext/phar/tests/tar/rename_dir.phpt b/ext/phar/tests/tar/rename_dir.phpt +index 0b95789..4ca8ceb 100644 +--- a/ext/phar/tests/tar/rename_dir.phpt ++++ b/ext/phar/tests/tar/rename_dir.phpt +@@ -1,7 +1,10 @@ + --TEST-- + Phar: rename_dir test tar-based + --SKIPIF-- +-<?php if (!extension_loaded("phar")) die("skip"); ?> ++<?php ++if (!extension_loaded("phar")) die("skip"); ++if (phpversion() < "7.0.0" && extension_loaded('Zend OPcache') && ini_get('opcache.enable_cli')==1) die("xfail for PHP version lower than 7 when OPcache enabled"); ++?> + --INI-- + phar.readonly=0 + phar.require_hash=0 +diff --git a/ext/phar/tests/tar/rmdir.phpt b/ext/phar/tests/tar/rmdir.phpt +index be03782..6cb5eab 100644 +--- a/ext/phar/tests/tar/rmdir.phpt ++++ b/ext/phar/tests/tar/rmdir.phpt +@@ -1,7 +1,10 @@ + --TEST-- + Phar: rmdir test tar-based + --SKIPIF-- +-<?php if (!extension_loaded("phar")) die("skip"); ?> ++<?php ++if (!extension_loaded("phar")) die("skip"); ++if (phpversion() < "7.0.0" && extension_loaded('Zend OPcache') && ini_get('opcache.enable_cli')==1) die("xfail for PHP version lower than 7 when OPcache enabled"); ++?> + --INI-- + phar.readonly=0 + phar.require_hash=0 +diff --git a/ext/phar/tests/tar/tar_gzip.phpt b/ext/phar/tests/tar/tar_gzip.phpt +index d44e1b1..a13a80a 100644 +--- a/ext/phar/tests/tar/tar_gzip.phpt ++++ b/ext/phar/tests/tar/tar_gzip.phpt +@@ -7,6 +7,7 @@ + if (!extension_loaded("spl")) die("skip SPL not available"); + if (!extension_loaded("zlib")) die("skip zlib not available"); + if (version_compare(phpversion(), '5.2.6', '<')) die("skip zlib is buggy in PHP < 5.2.6"); ++if (phpversion() < "7.0.0" && extension_loaded('Zend OPcache') && ini_get('opcache.enable_cli')==1) die("xfail for PHP version lower than 7 when OPcache enabled"); + ?> + --INI-- + phar.readonly=0 +diff --git a/ext/phar/tests/zip/rename.phpt b/ext/phar/tests/zip/rename.phpt +index 9b1f5c9..776bcae 100644 +--- a/ext/phar/tests/zip/rename.phpt ++++ b/ext/phar/tests/zip/rename.phpt +@@ -1,7 +1,10 @@ + --TEST-- + Phar: rename test zip-based + --SKIPIF-- +-<?php if (!extension_loaded("phar")) die("skip"); ?> ++<?php ++if (!extension_loaded("phar")) die("skip"); ++if (phpversion() < "7.0.0" && extension_loaded('Zend OPcache') && ini_get('opcache.enable_cli')==1) die("xfail for PHP version lower than 7 when OPcache enabled"); ++?> + --INI-- + phar.readonly=0 + phar.require_hash=0 +diff --git a/ext/phar/tests/zip/rename_dir.phpt b/ext/phar/tests/zip/rename_dir.phpt +index bb03c7f..3452f8f 100644 +--- a/ext/phar/tests/zip/rename_dir.phpt ++++ b/ext/phar/tests/zip/rename_dir.phpt +@@ -1,7 +1,10 @@ + --TEST-- + Phar: rename_dir test zip-based + --SKIPIF-- +-<?php if (!extension_loaded("phar")) die("skip"); ?> ++<?php ++if (!extension_loaded("phar")) die("skip"); ++if (phpversion() < "7.0.0" && extension_loaded('Zend OPcache') && ini_get('opcache.enable_cli')==1) die("xfail for PHP version lower than 7 when OPcache enabled"); ++?> + --INI-- + phar.readonly=0 + phar.require_hash=0 +diff --git a/ext/phar/tests/zip/rmdir.phpt b/ext/phar/tests/zip/rmdir.phpt +index c7ef9da..7d062d5 100644 +--- a/ext/phar/tests/zip/rmdir.phpt ++++ b/ext/phar/tests/zip/rmdir.phpt +@@ -1,7 +1,10 @@ + --TEST-- + Phar: rmdir test zip-based + --SKIPIF-- +-<?php if (!extension_loaded("phar")) die("skip"); ?> ++<?php ++if (!extension_loaded("phar")) die("skip"); ++if (phpversion() < "7.0.0" && extension_loaded('Zend OPcache') && ini_get('opcache.enable_cli')==1) die("xfail for PHP version lower than 7 when OPcache enabled"); ++?> + --INI-- + phar.readonly=0 + phar.require_hash=0 +diff --git a/ext/exif/exif.c b/ext/exif/exif.c +index b6c3177..a5fa0b8 100644 +--- a/ext/exif/exif.c ++++ b/ext/exif/exif.c +@@ -3508,7 +3508,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/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/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 d2097f1..a217127 100644 +--- a/ext/pdo_mysql/tests/pdo_mysql_stmt_getcolumnmeta.phpt ++++ b/ext/pdo_mysql/tests/pdo_mysql_stmt_getcolumnmeta.phpt +@@ -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); + +diff --git a/sapi/fpm/fpm/fpm_main.c b/sapi/fpm/fpm/fpm_main.c +index 0848fd8..c4bb370 100644 +--- a/sapi/fpm/fpm/fpm_main.c ++++ b/sapi/fpm/fpm/fpm_main.c +@@ -1245,8 +1245,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) { +diff --git a/ext/bcmath/libbcmath/src/str2num.c b/ext/bcmath/libbcmath/src/str2num.c +index c484c15..a5e7850 100644 +--- 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_)); +--- /dev/null ++++ b/ext/bcmath/tests/bug78878.phpt +@@ -0,0 +1,13 @@ ++--TEST-- ++Bug #78878 (Buffer underflow in bc_shift_addsub) ++--SKIPIF-- ++<?php ++if (!extension_loaded('bcmath')) die('skip bcmath extension not available'); ++?> ++--FILE-- ++<?php ++print @bcmul("\xB26483605105519922841849335928742092", bcpowmod(2, 65535, -4e-4)); ++?> ++--EXPECT-- ++bc math warning: non-zero scale in modulus ++0 +diff --git a/ext/standard/link_win32.c b/ext/standard/link_win32.c +index 059201c..4c537db 100644 +--- a/ext/standard/link_win32.c ++++ b/ext/standard/link_win32.c +@@ -208,7 +208,7 @@ + + /*First argument to link function is the target and hence should go to frompath + Second argument to link function is the link itself and hence should go to topath */ +- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &frompath, &frompath_len, &topath, &topath_len) == FAILURE) { ++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "pp", &frompath, &frompath_len, &topath, &topath_len) == FAILURE) { + return; + } + +--- /dev/null ++++ b/ext/standard/tests/file/windows_links/bug78862.phpt +@@ -0,0 +1,17 @@ ++--TEST-- ++Bug #78862 (link() silently truncates after a null byte on Windows) ++--FILE-- ++<?php ++file_put_contents(__DIR__ . '/bug78862.target', 'foo'); ++var_dump(link(__DIR__ . "/bug78862.target\0more", __DIR__ . "/bug78862.link\0more")); ++var_dump(file_exists(__DIR__ . '/bug78862.link')); ++?> ++--EXPECTF-- ++Warning: link() expects parameter 1 to be a valid path, string given in %s on line %d ++NULL ++bool(false) ++--CLEAN-- ++<?php ++unlink(__DIR__ . '/bug78862.target'); ++unlink(__DIR__ . '/bug78862.link'); ++?> +diff --git a/ext/exif/exif.c b/ext/exif/exif.c +index 6a3bb91..f64a14e 100644 +--- a/ext/exif/exif.c ++++ b/ext/exif/exif.c +@@ -2759,7 +2759,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; + } +--- /dev/null ++++ b/ext/exif/tests/bug78910.phpt +@@ -0,0 +1,17 @@ ++--TEST-- ++Bug #78910: Heap-buffer-overflow READ in exif (OSS-Fuzz #19044) ++--FILE-- ++<?php ++ ++var_dump(exif_read_data('data:image/jpg;base64,TU0AKgAAAAwgICAgAAIBDwAEAAAAAgAAACKSfCAgAAAAAEZVSklGSUxN')); ++ ++?> ++--EXPECTF-- ++Notice: exif_read_data(): Read from TIFF: tag(0x927C, MakerNote ): Illegal format code 0x2020, switching to BYTE in %s on line %d ++ ++Warning: exif_read_data(): Process tag(x927C=MakerNote ): Illegal format code 0x2020, suppose BYTE in %s on line %d ++ ++Warning: exif_read_data(): IFD data too short: 0x0000 offset 0x000C in %s on line %d ++ ++Warning: exif_read_data(): Invalid TIFF file in %s on line %d ++bool(false) +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/phar/tests/tar/phar_commitwrite.phpt b/ext/phar/tests/tar/phar_commitwrite.phpt +index 262ea1d..bfbac61 100644 +--- a/ext/phar/tests/tar/phar_commitwrite.phpt ++++ b/ext/phar/tests/tar/phar_commitwrite.phpt +@@ -5,9 +5,6 @@ + --INI-- + phar.require_hash=0 + phar.readonly=0 +---ENV-- +-TEMP=. +-TMP=. + --FILE-- + <?php + $p = new Phar(dirname(__FILE__) . '/brandnewphar.phar.tar', 0, 'brandnewphar.phar'); +diff --git a/ext/phar/tests/tar/phar_setsignaturealgo2.phpt b/ext/phar/tests/tar/phar_setsignaturealgo2.phpt +index b68bbf6..c16e752 100644 +--- a/ext/phar/tests/tar/phar_setsignaturealgo2.phpt ++++ b/ext/phar/tests/tar/phar_setsignaturealgo2.phpt +@@ -9,9 +9,6 @@ + --INI-- + phar.require_hash=0 + phar.readonly=0 +---ENV-- +-TEMP=. +-TMP=. + --FILE-- + <?php + $fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.tar'; +diff --git a/ext/phar/tests/zip/phar_commitwrite.phpt b/ext/phar/tests/zip/phar_commitwrite.phpt +index 4e18a6b..eb3aeae 100644 +--- a/ext/phar/tests/zip/phar_commitwrite.phpt ++++ b/ext/phar/tests/zip/phar_commitwrite.phpt +@@ -5,9 +5,6 @@ + --INI-- + phar.require_hash=0 + phar.readonly=0 +---ENV-- +-TEMP=. +-TMP=. + --FILE-- + <?php + $p = new Phar(dirname(__FILE__) . '/brandnewphar.phar.zip', 0, 'brandnewphar.phar'); +diff --git a/ext/exif/exif.c b/ext/exif/exif.c +index f64a14e..bf2fd61 100644 +--- a/ext/exif/exif.c ++++ b/ext/exif/exif.c +@@ -3253,6 +3253,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; +@@ -3405,7 +3410,7 @@ + return FALSE; + } + +- sn = exif_file_sections_add(ImageInfo, marker, itemlen+1, NULL); ++ sn = exif_file_sections_add(ImageInfo, marker, itemlen, NULL); + Data = ImageInfo->file.list[sn].data; + + /* Store first two pre-read bytes. */ +--- /dev/null ++++ b/ext/exif/tests/bug79282.phpt +@@ -0,0 +1,15 @@ ++--TEST-- ++Bug #79282: Use-of-uninitialized-value in exif ++--FILE-- ++<?php ++ ++var_dump(exif_read_data('data://image/jpeg;base64,/9jhAAlFeGlmAAAg')); ++ ++?> ++--EXPECTF-- ++Warning: exif_read_data(): Invalid TIFF alignment marker in %s on line %d ++ ++Warning: exif_read_data(): File structure corrupted in %s on line %d ++ ++Warning: exif_read_data(): Invalid JPEG file in %s on line %d ++bool(false) +diff --git a/ext/standard/exec.c b/ext/standard/exec.c +index 88a6b4a..a586b78 100644 +--- a/ext/standard/exec.c ++++ b/ext/standard/exec.c +@@ -537,6 +537,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 d6e71fa..0278bd4 100644 +--- a/ext/standard/url.c ++++ b/ext/standard/url.c +@@ -545,7 +545,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; +@@ -647,7 +647,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; +--- /dev/null ++++ b/ext/openssl/tests/bug72333.phpt +@@ -0,0 +1,54 @@ ++--TEST-- ++Bug #72333: fwrite() on non-blocking SSL sockets doesn't work ++--SKIPIF-- ++<?php ++if (!extension_loaded("openssl")) die("skip openssl not loaded"); ++if (!function_exists("proc_open")) die("skip no proc_open"); ++?> ++--FILE-- ++<?php ++$serverCode = <<<'CODE' ++ $context = stream_context_create(['ssl' => ['local_cert' => __DIR__ . '/bug54992.pem']]); ++ ++ $flags = STREAM_SERVER_BIND|STREAM_SERVER_LISTEN; ++ $fp = stream_socket_server("ssl://127.0.0.1:10011", $errornum, $errorstr, $flags, $context); ++ phpt_notify(); ++ $conn = stream_socket_accept($fp); ++ ++ for ($i = 0; $i < 5; $i++) { ++ fread($conn, 100000); ++ usleep(200000); ++ } ++CODE; ++ ++$clientCode = <<<'CODE' ++ $context = stream_context_create(['ssl' => ['verify_peer' => false, 'peer_name' => 'bug54992.local']]); ++ ++ phpt_wait(); ++ $fp = stream_socket_client("ssl://127.0.0.1:10011", $errornum, $errorstr, 3000, STREAM_CLIENT_CONNECT, $context); ++ stream_set_blocking($fp, 0); ++ ++ function blocking_fwrite($fp, $buf) { ++ $write = [$fp]; ++ $total = 0; ++ while (stream_select($read, $write, $except, 180)) { ++ $result = fwrite($fp, $buf); ++ $total += $result; ++ if ($total >= strlen($buf)) { ++ return $total; ++ } ++ $buf = substr($buf, $total); ++ } ++ } ++ ++ $str1 = str_repeat("a", 5000000); ++ blocking_fwrite($fp, $str1); ++ echo "done"; ++CODE; ++ ++include 'ServerClientTestCase.inc'; ++ServerClientTestCase::getInstance()->run($clientCode, $serverCode); ++?> ++--EXPECT-- ++done ++ +diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c +index c2d477c..6a7dcd7 100644 +--- a/ext/openssl/xp_ssl.c ++++ b/ext/openssl/xp_ssl.c +@@ -1714,6 +1714,14 @@ + + if (SUCCESS == php_set_sock_blocking(sslsock->s.socket, 0 TSRMLS_CC)) { + sslsock->s.is_blocked = 0; ++ SSL_set_mode( ++ sslsock->ssl_handle, ++ ( ++ SSL_get_mode(sslsock->ssl_handle) | ++ SSL_MODE_ENABLE_PARTIAL_WRITE | ++ SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER ++ ) ++ ); + } + + timeout = sslsock->is_client ? &sslsock->connect_timeout : &sslsock->s.timeout; +diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c +index 52f058c..8fa14f3 100644 +--- a/ext/zip/php_zip.c ++++ b/ext/zip/php_zip.c +@@ -1572,6 +1572,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) { ++ struct stat 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/php_variables.c b/main/php_variables.c +index 6da79bd..084b10f 100644 +--- a/main/php_variables.c ++++ b/main/php_variables.c +@@ -472,7 +472,9 @@ + unsigned int 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 TSRMLS_CC)) { +@@ -483,7 +485,9 @@ + int val_len; + unsigned int 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 TSRMLS_CC)) { +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" ++} +--- a/ext/soap/php_sdl.c ++++ b/ext/soap/php_sdl.c +@@ -318,6 +318,8 @@ + ctx->context = NULL; + } + ++#define SAFE_STR(a) ((a)?a:"") ++ + static void load_wsdl_ex(zval *this_ptr, char *struri, sdlCtx *ctx, int include TSRMLS_DC) + { + sdlPtr tmpsdl = ctx->sdl; +@@ -379,7 +381,7 @@ + if (node_is_equal_ex(trav2, "schema", XSD_NAMESPACE)) { + load_schema(ctx, trav2 TSRMLS_CC); + } 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; + } +@@ -440,7 +442,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; + } +@@ -550,7 +552,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; + } +@@ -655,7 +657,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; + } +@@ -687,14 +689,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)); +@@ -703,7 +705,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); +@@ -773,7 +775,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; +@@ -812,7 +814,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; + } +@@ -914,7 +916,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; +@@ -933,7 +935,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; + } +@@ -1111,7 +1113,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 f3b49df..4694b4e 100644 +--- a/ext/soap/php_xml.c ++++ b/ext/soap/php_xml.c +@@ -205,7 +205,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) { +@@ -221,7 +221,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 b30440f..5dfe122 100644 +--- a/ext/imap/php_imap.c ++++ b/ext/imap/php_imap.c +@@ -3491,6 +3491,21 @@ + } + /* }}} */ + ++static zend_bool header_injection(char *p, zend_bool adrlist) ++{ ++ 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) +@@ -3511,6 +3526,13 @@ + return; + } + ++#define CHECK_HEADER_INJECTION(zstr, adrlist, header) \ ++ if (header_injection(zstr, adrlist)) { \ ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "header injection attempt in " header); \ ++ RETVAL_FALSE; \ ++ goto done; \ ++ } ++ + #define PHP_RFC822_PARSE_ADRLIST(target, value) \ + str_copy = estrndup(Z_STRVAL_PP(value), Z_STRLEN_PP(value)); \ + rfc822_parse_adrlist(target, str_copy, "NO HOST"); \ +@@ -3519,46 +3541,57 @@ + env = mail_newenvelope(); + if (zend_hash_find(Z_ARRVAL_P(envelope), "remail", sizeof("remail"), (void **) &pvalue)== SUCCESS) { + convert_to_string_ex(pvalue); ++ CHECK_HEADER_INJECTION(Z_STRVAL_PP(pvalue), 0, "remail"); + env->remail = cpystr(Z_STRVAL_PP(pvalue)); + } + if (zend_hash_find(Z_ARRVAL_P(envelope), "return_path", sizeof("return_path"), (void **) &pvalue)== SUCCESS) { + convert_to_string_ex(pvalue); ++ CHECK_HEADER_INJECTION(Z_STRVAL_PP(pvalue), 1, "return_path"); + PHP_RFC822_PARSE_ADRLIST(&env->return_path, pvalue); + } + if (zend_hash_find(Z_ARRVAL_P(envelope), "date", sizeof("date"), (void **) &pvalue)== SUCCESS) { + convert_to_string_ex(pvalue); ++ CHECK_HEADER_INJECTION(Z_STRVAL_PP(pvalue), 0, "date"); + env->date = cpystr(Z_STRVAL_PP(pvalue)); + } + if (zend_hash_find(Z_ARRVAL_P(envelope), "from", sizeof("from"), (void **) &pvalue)== SUCCESS) { + convert_to_string_ex(pvalue); ++ CHECK_HEADER_INJECTION(Z_STRVAL_PP(pvalue), 1, "from"); + PHP_RFC822_PARSE_ADRLIST(&env->from, pvalue); + } + if (zend_hash_find(Z_ARRVAL_P(envelope), "reply_to", sizeof("reply_to"), (void **) &pvalue)== SUCCESS) { + convert_to_string_ex(pvalue); ++ CHECK_HEADER_INJECTION(Z_STRVAL_PP(pvalue), 1, "reply_to"); + PHP_RFC822_PARSE_ADRLIST(&env->reply_to, pvalue); + } + if (zend_hash_find(Z_ARRVAL_P(envelope), "in_reply_to", sizeof("in_reply_to"), (void **) &pvalue)== SUCCESS) { + convert_to_string_ex(pvalue); ++ CHECK_HEADER_INJECTION(Z_STRVAL_PP(pvalue), 0, "in_reply_to"); + env->in_reply_to = cpystr(Z_STRVAL_PP(pvalue)); + } + if (zend_hash_find(Z_ARRVAL_P(envelope), "subject", sizeof("subject"), (void **) &pvalue)== SUCCESS) { + convert_to_string_ex(pvalue); ++ CHECK_HEADER_INJECTION(Z_STRVAL_PP(pvalue), 0, "subject"); + env->subject = cpystr(Z_STRVAL_PP(pvalue)); + } + if (zend_hash_find(Z_ARRVAL_P(envelope), "to", sizeof("to"), (void **) &pvalue)== SUCCESS) { + convert_to_string_ex(pvalue); ++ CHECK_HEADER_INJECTION(Z_STRVAL_PP(pvalue), 1, "to"); + PHP_RFC822_PARSE_ADRLIST(&env->to, pvalue); + } + if (zend_hash_find(Z_ARRVAL_P(envelope), "cc", sizeof("cc"), (void **) &pvalue)== SUCCESS) { + convert_to_string_ex(pvalue); ++ CHECK_HEADER_INJECTION(Z_STRVAL_PP(pvalue), 1, "cc"); + PHP_RFC822_PARSE_ADRLIST(&env->cc, pvalue); + } + if (zend_hash_find(Z_ARRVAL_P(envelope), "bcc", sizeof("bcc"), (void **) &pvalue)== SUCCESS) { + convert_to_string_ex(pvalue); ++ CHECK_HEADER_INJECTION(Z_STRVAL_PP(pvalue), 1, "bcc"); + PHP_RFC822_PARSE_ADRLIST(&env->bcc, pvalue); + } + if (zend_hash_find(Z_ARRVAL_P(envelope), "message_id", sizeof("message_id"), (void **) &pvalue)== SUCCESS) { + convert_to_string_ex(pvalue); ++ CHECK_HEADER_INJECTION(Z_STRVAL_PP(pvalue), 0, "message_id"); + env->message_id=cpystr(Z_STRVAL_PP(pvalue)); + } + +@@ -3568,6 +3601,7 @@ + while (zend_hash_get_current_data(Z_ARRVAL_PP(pvalue), (void **) &env_data) == SUCCESS) { + custom_headers_param = mail_newbody_parameter(); + convert_to_string_ex(env_data); ++ CHECK_HEADER_INJECTION(Z_STRVAL_PP(env_data), 0, "custom_headers"); + custom_headers_param->value = (char *) fs_get(Z_STRLEN_PP(env_data) + 1); + custom_headers_param->attribute = NULL; + memcpy(custom_headers_param->value, Z_STRVAL_PP(env_data), Z_STRLEN_PP(env_data) + 1); +@@ -3598,6 +3632,7 @@ + } + if (zend_hash_find(Z_ARRVAL_PP(data), "charset", sizeof("charset"), (void **) &pvalue)== SUCCESS) { + convert_to_string_ex(pvalue); ++ CHECK_HEADER_INJECTION(Z_STRVAL_PP(pvalue), 0, "body charset"); + tmp_param = mail_newbody_parameter(); + tmp_param->value = cpystr(Z_STRVAL_PP(pvalue)); + tmp_param->attribute = cpystr("CHARSET"); +@@ -3608,10 +3643,12 @@ + if(Z_TYPE_PP(pvalue) == IS_ARRAY) { + disp_param = tmp_param = NULL; + while (zend_hash_get_current_data(Z_ARRVAL_PP(pvalue), (void **) &disp_data) == SUCCESS) { ++ CHECK_HEADER_INJECTION(key, 0, "body disposition key"); + disp_param = mail_newbody_parameter(); + zend_hash_get_current_key(Z_ARRVAL_PP(pvalue), &key, &ind, 0); + disp_param->attribute = cpystr(key); + convert_to_string_ex(disp_data); ++ CHECK_HEADER_INJECTION(Z_STRVAL_PP(disp_data), 0, "body disposition value"); + disp_param->value = (char *) fs_get(Z_STRLEN_PP(disp_data) + 1); + memcpy(disp_param->value, Z_STRVAL_PP(disp_data), Z_STRLEN_PP(disp_data) + 1); + zend_hash_move_forward(Z_ARRVAL_PP(pvalue)); +@@ -3623,18 +3660,22 @@ + } + if (zend_hash_find(Z_ARRVAL_PP(data), "subtype", sizeof("subtype"), (void **) &pvalue)== SUCCESS) { + convert_to_string_ex(pvalue); ++ CHECK_HEADER_INJECTION(Z_STRVAL_PP(pvalue), 0, "body subtype"); + bod->subtype = cpystr(Z_STRVAL_PP(pvalue)); + } + if (zend_hash_find(Z_ARRVAL_PP(data), "id", sizeof("id"), (void **) &pvalue)== SUCCESS) { + convert_to_string_ex(pvalue); ++ CHECK_HEADER_INJECTION(Z_STRVAL_PP(pvalue), 0, "body id"); + bod->id = cpystr(Z_STRVAL_PP(pvalue)); + } + if (zend_hash_find(Z_ARRVAL_PP(data), "description", sizeof("description"), (void **) &pvalue)== SUCCESS) { + convert_to_string_ex(pvalue); ++ CHECK_HEADER_INJECTION(Z_STRVAL_PP(pvalue), 0, "body description"); + bod->description = cpystr(Z_STRVAL_PP(pvalue)); + } + if (zend_hash_find(Z_ARRVAL_PP(data), "disposition.type", sizeof("disposition.type"), (void **) &pvalue)== SUCCESS) { + convert_to_string_ex(pvalue); ++ CHECK_HEADER_INJECTION(Z_STRVAL_PP(pvalue), 0, "body disposition.type"); + bod->disposition.type = (char *) fs_get(Z_STRLEN_PP(pvalue) + 1); + memcpy(bod->disposition.type, Z_STRVAL_PP(pvalue), Z_STRLEN_PP(pvalue)+1); + } +@@ -3642,10 +3683,12 @@ + if (Z_TYPE_PP(pvalue) == IS_ARRAY) { + disp_param = tmp_param = NULL; + while (zend_hash_get_current_data(Z_ARRVAL_PP(pvalue), (void **) &disp_data) == SUCCESS) { ++ CHECK_HEADER_INJECTION(key, 0, "body type.parameters key"); + disp_param = mail_newbody_parameter(); + zend_hash_get_current_key(Z_ARRVAL_PP(pvalue), &key, &ind, 0); + disp_param->attribute = cpystr(key); + convert_to_string_ex(disp_data); ++ CHECK_HEADER_INJECTION(Z_STRVAL_PP(disp_data), 0, "body type.parameters value"); + disp_param->value = (char *) fs_get(Z_STRLEN_PP(disp_data) + 1); + memcpy(disp_param->value, Z_STRVAL_PP(disp_data), Z_STRLEN_PP(disp_data) + 1); + zend_hash_move_forward(Z_ARRVAL_PP(pvalue)); +@@ -3675,6 +3718,7 @@ + } + if (zend_hash_find(Z_ARRVAL_PP(data), "md5", sizeof("md5"), (void **) &pvalue)== SUCCESS) { + convert_to_string_ex(pvalue); ++ CHECK_HEADER_INJECTION(Z_STRVAL_PP(pvalue), 0, "body md5"); + bod->md5 = cpystr(Z_STRVAL_PP(pvalue)); + } + } +@@ -3710,6 +3754,7 @@ + } + if (zend_hash_find(Z_ARRVAL_PP(data), "charset", sizeof("charset"), (void **) &pvalue)== SUCCESS) { + convert_to_string_ex(pvalue); ++ CHECK_HEADER_INJECTION(Z_STRVAL_PP(pvalue), 0, "body charset"); + tmp_param = mail_newbody_parameter(); + tmp_param->value = (char *) fs_get(Z_STRLEN_PP(pvalue) + 1); + memcpy(tmp_param->value, Z_STRVAL_PP(pvalue), Z_STRLEN_PP(pvalue) + 1); +@@ -3723,8 +3768,10 @@ + while (zend_hash_get_current_data(Z_ARRVAL_PP(pvalue), (void **) &disp_data) == SUCCESS) { + disp_param = mail_newbody_parameter(); + zend_hash_get_current_key(Z_ARRVAL_PP(pvalue), &key, &ind, 0); ++ CHECK_HEADER_INJECTION(key, 0, "body type.parameters key"); + disp_param->attribute = cpystr(key); + convert_to_string_ex(disp_data); ++ CHECK_HEADER_INJECTION(Z_STRVAL_PP(disp_data), 0, "body type.parameters value"); + disp_param->value = (char *) fs_get(Z_STRLEN_PP(disp_data) + 1); + memcpy(disp_param->value, Z_STRVAL_PP(disp_data), Z_STRLEN_PP(disp_data) + 1); + zend_hash_move_forward(Z_ARRVAL_PP(pvalue)); +@@ -3736,18 +3783,22 @@ + } + if (zend_hash_find(Z_ARRVAL_PP(data), "subtype", sizeof("subtype"), (void **) &pvalue)== SUCCESS) { + convert_to_string_ex(pvalue); ++ CHECK_HEADER_INJECTION(Z_STRVAL_PP(pvalue), 0, "body subtype"); + bod->subtype = cpystr(Z_STRVAL_PP(pvalue)); + } + if (zend_hash_find(Z_ARRVAL_PP(data), "id", sizeof("id"), (void **) &pvalue)== SUCCESS) { + convert_to_string_ex(pvalue); ++ CHECK_HEADER_INJECTION(Z_STRVAL_PP(pvalue), 0, "body id"); + bod->id = cpystr(Z_STRVAL_PP(pvalue)); + } + if (zend_hash_find(Z_ARRVAL_PP(data), "description", sizeof("description"), (void **) &pvalue)== SUCCESS) { + convert_to_string_ex(pvalue); ++ CHECK_HEADER_INJECTION(Z_STRVAL_PP(pvalue), 0, "body description"); + bod->description = cpystr(Z_STRVAL_PP(pvalue)); + } + if (zend_hash_find(Z_ARRVAL_PP(data), "disposition.type", sizeof("disposition.type"), (void **) &pvalue)== SUCCESS) { + convert_to_string_ex(pvalue); ++ CHECK_HEADER_INJECTION(Z_STRVAL_PP(pvalue), 0, "body disposition.type"); + bod->disposition.type = (char *) fs_get(Z_STRLEN_PP(pvalue) + 1); + memcpy(bod->disposition.type, Z_STRVAL_PP(pvalue), Z_STRLEN_PP(pvalue)+1); + } +@@ -3757,8 +3808,10 @@ + while (zend_hash_get_current_data(Z_ARRVAL_PP(pvalue), (void **) &disp_data) == SUCCESS) { + disp_param = mail_newbody_parameter(); + zend_hash_get_current_key(Z_ARRVAL_PP(pvalue), &key, &ind, 0); ++ CHECK_HEADER_INJECTION(key, 0, "body disposition key"); + disp_param->attribute = cpystr(key); + convert_to_string_ex(disp_data); ++ CHECK_HEADER_INJECTION(Z_STRVAL_PP(disp_data), 0, "body disposition value"); + disp_param->value = (char *) fs_get(Z_STRLEN_PP(disp_data) + 1); + memcpy(disp_param->value, Z_STRVAL_PP(disp_data), Z_STRLEN_PP(disp_data) + 1); + zend_hash_move_forward(Z_ARRVAL_PP(pvalue)); +@@ -3788,6 +3841,7 @@ + } + if (zend_hash_find(Z_ARRVAL_PP(data), "md5", sizeof("md5"), (void **) &pvalue)== SUCCESS) { + convert_to_string_ex(pvalue); ++ CHECK_HEADER_INJECTION(Z_STRVAL_PP(pvalue), 0, "body md5"); + bod->md5 = cpystr(Z_STRVAL_PP(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 6aa1b36..8bb4c2e 100644 +--- a/ext/interbase/config.m4 ++++ b/ext/interbase/config.m4 +@@ -3,39 +3,54 @@ + install directory [/usr/interbase]]) + + if test "$PHP_INTERBASE" != "no"; then +- if test "$PHP_INTERBASE" = "yes"; then +- IBASE_INCDIR=/usr/interbase/include +- IBASE_LIBDIR=/usr/interbase/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=/usr/interbase/include ++ IBASE_LIBDIR=/usr/interbase/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([libgds, libib_util or libfbclient not found! Check config.log for more information.]) ++ PHP_CHECK_LIBRARY(ib_util, isc_detach_database, ++ [ ++ IBASE_LIBNAME=ib_util ++ ], [ ++ AC_MSG_ERROR([libgds, libib_util or libfbclient 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) + 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 d1f1012..8b8f822 100644 +--- a/ext/pdo_firebird/firebird_statement.c ++++ b/ext/pdo_firebird/firebird_statement.c +@@ -267,8 +267,8 @@ + 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) { + + unsigned short chunk_size = (*len-cur_len) > USHRT_MAX ? USHRT_MAX +--- /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 cb7e4bd..a87bcc1 100644 +--- a/ext/pdo_firebird/firebird_statement.c ++++ b/ext/pdo_firebird/firebird_statement.c +@@ -120,8 +120,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); + } +@@ -145,7 +151,8 @@ + return 1; + } while (0); + +- RECORD_ERROR(stmt); ++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 2e71d9d..baa1b96 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 baa1b96..23bf8d8 100644 +--- a/ext/pdo_firebird/firebird_driver.c ++++ b/ext/pdo_firebird/firebird_driver.c +@@ -539,14 +539,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); + } + } + /* }}} */ +@@ -557,8 +559,8 @@ + 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); + return 1; +--- /dev/null ++++ b/ext/pdo_firebird/tests/bug_76448.data +@@ -0,0 +1 @@ ++ +\ No newline at end of file +--- /dev/null ++++ b/ext/pdo_firebird/tests/bug_76448.phpt +@@ -0,0 +1,23 @@ ++--TEST-- ++Bug #76448 (Stack buffer overflow in firebird_info_cb) ++--SKIPIF-- ++<?php ++if (!extension_loaded('pdo_firebird')) die("skip podo_firebird extension not available"); ++if (!extension_loaded('sockets')) die("skip sockets extension not available"); ++?> ++--FILE-- ++<?php ++require_once "payload_server.inc"; ++ ++$address = run_server(__DIR__ . "/bug_76448.data"); ++ ++// no need to change the credentials; we're running against a falke server ++$dsn = "firebird:dbname=inet://$address/test"; ++$username = 'SYSDBA'; ++$password = 'masterkey'; ++ ++$dbh = new PDO($dsn, $username, $password, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]); ++var_dump($dbh->getAttribute(PDO::ATTR_SERVER_INFO)); ++?> ++--EXPECT-- ++bool(false) +diff --git a/ext/pdo_firebird/firebird_driver.c b/ext/pdo_firebird/firebird_driver.c +index 23bf8d8..f8a44e7 100644 +--- a/ext/pdo_firebird/firebird_driver.c ++++ b/ext/pdo_firebird/firebird_driver.c +@@ -239,14 +239,16 @@ + /* execute the statement */ + if (isc_dsql_execute2(H->isc_status, &H->tr, &stmt, PDO_FB_SQLDA_VERSION, &in_sqlda, &out_sqlda)) { + RECORD_ERROR(dbh); +- return -1; ++ ret = -1; ++ goto free_statement; + } + + /* find out how many rows were affected */ + if (isc_dsql_sql_info(H->isc_status, &stmt, sizeof(info_count), const_cast(info_count), + sizeof(result), result)) { + RECORD_ERROR(dbh); +- return -1; ++ ret = -1; ++ goto free_statement; + } + + if (result[0] == isc_info_sql_records) { +@@ -275,6 +277,12 @@ + RECORD_ERROR(dbh); + } + ++free_statement: ++ ++ if (isc_dsql_free_statement(H->isc_status, &stmt, DSQL_drop)) { ++ RECORD_ERROR(dbh); ++ } ++ + return ret; + } + /* }}} */ +diff --git a/ext/pdo_firebird/firebird_driver.c b/ext/pdo_firebird/firebird_driver.c +index f8a44e7..c53fd31 100644 +--- a/ext/pdo_firebird/firebird_driver.c ++++ b/ext/pdo_firebird/firebird_driver.c +@@ -139,7 +139,7 @@ + HashTable *np; + + do { +- isc_stmt_handle s = NULL; ++ isc_stmt_handle s = PDO_FIREBIRD_HANDLE_INITIALIZER; + XSQLDA num_sqlda; + static char const info[] = { isc_info_sql_stmt_type }; + char result[8]; +@@ -220,7 +220,7 @@ + static long firebird_handle_doer(pdo_dbh_t *dbh, const char *sql, long sql_len TSRMLS_DC) /* {{{ */ + { + pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data; +- isc_stmt_handle stmt = NULL; ++ isc_stmt_handle stmt = PDO_FIREBIRD_HANDLE_INITIALIZER; + static char const info_count[] = { isc_info_sql_records }; + char result[64]; + int ret = 0; +diff --git a/ext/pdo_firebird/firebird_statement.c b/ext/pdo_firebird/firebird_statement.c +index a87bcc1..dc64c19 100644 +--- a/ext/pdo_firebird/firebird_statement.c ++++ b/ext/pdo_firebird/firebird_statement.c +@@ -230,7 +230,7 @@ + { + pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data; + pdo_firebird_db_handle *H = S->H; +- isc_blob_handle blobh = NULL; ++ isc_blob_handle blobh = PDO_FIREBIRD_HANDLE_INITIALIZER; + char const bl_item = isc_info_blob_total_length; + char bl_info[20]; + unsigned short i; +@@ -424,7 +424,7 @@ + { + pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data; + pdo_firebird_db_handle *H = S->H; +- isc_blob_handle h = NULL; ++ isc_blob_handle h = PDO_FIREBIRD_HANDLE_INITIALIZER; + unsigned long put_cnt = 0, rem_cnt; + unsigned short chunk_size; + int result = 1; +diff --git a/ext/pdo_firebird/php_pdo_firebird_int.h b/ext/pdo_firebird/php_pdo_firebird_int.h +index 796f383..09cd485 100644 +--- a/ext/pdo_firebird/php_pdo_firebird_int.h ++++ b/ext/pdo_firebird/php_pdo_firebird_int.h +@@ -61,6 +61,12 @@ + #define min(a,b) ((a)<(b)?(a):(b)) + #endif + ++#if defined(_LP64) || defined(__LP64__) || defined(__arch64__) || defined(_WIN64) ++# define PDO_FIREBIRD_HANDLE_INITIALIZER 0U ++#else ++# define PDO_FIREBIRD_HANDLE_INITIALIZER NULL ++#endif ++ + typedef struct { + + /* the result of the last API call */ +diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c +index 8fa14f3..0768c48 100644 +--- a/ext/zip/php_zip.c ++++ b/ext/zip/php_zip.c +@@ -122,8 +122,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; +diff --git a/ext/libxml/libxml.c b/ext/libxml/libxml.c +index d4a47ff..02453ff 100644 +--- a/ext/libxml/libxml.c ++++ b/ext/libxml/libxml.c +@@ -433,6 +433,8 @@ + void *context = NULL; + char *unescaped = NULL; + ++ TSRMLS_FETCH(); ++ + if (URI == NULL) + return(NULL); + |