From 239a26fa909f76d281a8375246fe1d48e05da93c Mon Sep 17 00:00:00 2001 From: Sergey Panteleev Date: Tue, 7 Nov 2023 17:12:19 +0300 Subject: [PATCH 01/92] PHP-8.2 is now for PHP 8.2.14-dev --- NEWS | 5 ++++- Zend/zend.h | 2 +- configure.ac | 2 +- main/php_version.h | 6 +++--- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/NEWS b/NEWS index aec27dd8614fe..bdab6dfa211a2 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? ????, PHP 8.2.13 +?? ??? ????, PHP 8.2.14 + + +23 Nov 2023, PHP 8.2.13 - Core: . Fixed double-free of non-interned enum case name. (ilutov) diff --git a/Zend/zend.h b/Zend/zend.h index 4ae4b2d8f0670..7dd0ed1071feb 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -20,7 +20,7 @@ #ifndef ZEND_H #define ZEND_H -#define ZEND_VERSION "4.2.13-dev" +#define ZEND_VERSION "4.2.14-dev" #define ZEND_ENGINE_3 diff --git a/configure.ac b/configure.ac index c8521f8f04133..76f3368274fdf 100644 --- a/configure.ac +++ b/configure.ac @@ -17,7 +17,7 @@ dnl Basic autoconf initialization, generation of config.nice. dnl ---------------------------------------------------------------------------- AC_PREREQ([2.68]) -AC_INIT([PHP],[8.2.13-dev],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) +AC_INIT([PHP],[8.2.14-dev],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) AC_CONFIG_SRCDIR([main/php_version.h]) AC_CONFIG_AUX_DIR([build]) AC_PRESERVE_HELP_ORDER diff --git a/main/php_version.h b/main/php_version.h index 41359e73d4d12..87eb6ba3b3ac7 100644 --- a/main/php_version.h +++ b/main/php_version.h @@ -2,7 +2,7 @@ /* edit configure.ac to change version number */ #define PHP_MAJOR_VERSION 8 #define PHP_MINOR_VERSION 2 -#define PHP_RELEASE_VERSION 13 +#define PHP_RELEASE_VERSION 14 #define PHP_EXTRA_VERSION "-dev" -#define PHP_VERSION "8.2.13-dev" -#define PHP_VERSION_ID 80213 +#define PHP_VERSION "8.2.14-dev" +#define PHP_VERSION_ID 80214 From 55dfc29539731a8eeae095fb8237a52e474e4323 Mon Sep 17 00:00:00 2001 From: Ben Ramsey Date: Tue, 7 Nov 2023 14:28:31 -0600 Subject: [PATCH 02/92] PHP-8.1 is now for PHP 8.1.27-dev --- NEWS | 6 +++++- Zend/zend.h | 2 +- configure.ac | 2 +- main/php_version.h | 6 +++--- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/NEWS b/NEWS index ba16baf5930f0..b3e754ab4ee4c 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,10 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? ????, PHP 8.1.26 +?? ??? ????, PHP 8.1.27 + + + +23 Nov 2023, PHP 8.1.26 - Core: . Fixed bug GH-12468 (Double-free of doc_comment when overriding static diff --git a/Zend/zend.h b/Zend/zend.h index 0df86327eb517..3c320ddc88cac 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -20,7 +20,7 @@ #ifndef ZEND_H #define ZEND_H -#define ZEND_VERSION "4.1.26-dev" +#define ZEND_VERSION "4.1.27-dev" #define ZEND_ENGINE_3 diff --git a/configure.ac b/configure.ac index 464ee54c9cfcf..0c5304b9e4822 100644 --- a/configure.ac +++ b/configure.ac @@ -17,7 +17,7 @@ dnl Basic autoconf initialization, generation of config.nice. dnl ---------------------------------------------------------------------------- AC_PREREQ([2.68]) -AC_INIT([PHP],[8.1.26-dev],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) +AC_INIT([PHP],[8.1.27-dev],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) AC_CONFIG_SRCDIR([main/php_version.h]) AC_CONFIG_AUX_DIR([build]) AC_PRESERVE_HELP_ORDER diff --git a/main/php_version.h b/main/php_version.h index 4d3b2f5e1ace5..64e387dec6834 100644 --- a/main/php_version.h +++ b/main/php_version.h @@ -2,7 +2,7 @@ /* edit configure.ac to change version number */ #define PHP_MAJOR_VERSION 8 #define PHP_MINOR_VERSION 1 -#define PHP_RELEASE_VERSION 26 +#define PHP_RELEASE_VERSION 27 #define PHP_EXTRA_VERSION "-dev" -#define PHP_VERSION "8.1.26-dev" -#define PHP_VERSION_ID 80126 +#define PHP_VERSION "8.1.27-dev" +#define PHP_VERSION_ID 80127 From 5a77870492e8e293a3d12b0e94d91b890ed78197 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 8 Nov 2023 22:03:42 +0300 Subject: [PATCH 03/92] Fixed empty array inference --- Zend/Optimizer/zend_inference.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Zend/Optimizer/zend_inference.c b/Zend/Optimizer/zend_inference.c index 794f630ac920c..ae04094f12f09 100644 --- a/Zend/Optimizer/zend_inference.c +++ b/Zend/Optimizer/zend_inference.c @@ -2674,6 +2674,9 @@ static zend_always_inline zend_result _zend_update_type_info( } } if (opline->extended_value == IS_ARRAY) { + if (t1 & (MAY_BE_UNDEF|MAY_BE_NULL)) { + tmp |= MAY_BE_ARRAY_EMPTY; + } if (t1 & MAY_BE_ARRAY) { tmp |= t1 & (MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF); } @@ -3387,6 +3390,9 @@ static zend_always_inline zend_result _zend_update_type_info( arr_type = RES_USE_INFO(); } tmp = MAY_BE_RC1|MAY_BE_ARRAY|arr_type; + if (opline->opcode == ZEND_INIT_ARRAY && opline->op1_type == IS_UNUSED) { + tmp |= MAY_BE_ARRAY_EMPTY; + } if (opline->op1_type != IS_UNUSED && (opline->op2_type == IS_UNUSED || (t2 & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE|MAY_BE_RESOURCE|MAY_BE_STRING)))) { From 10b2b4a52c38ed83d4e988d0185bacf05668d02f Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Mon, 23 Oct 2023 21:36:01 +0200 Subject: [PATCH 04/92] Fix memory leak in standard syslog device handling The BG(syslog_device) is leaked in RINIT. Closes GH-12501 --- NEWS | 3 ++- ext/standard/basic_functions.c | 10 +--------- ext/standard/php_ext_syslog.h | 4 ---- ext/standard/syslog.c | 16 +--------------- 4 files changed, 4 insertions(+), 29 deletions(-) diff --git a/NEWS b/NEWS index b3e754ab4ee4c..13adf6f0b1736 100644 --- a/NEWS +++ b/NEWS @@ -2,7 +2,8 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.1.27 - +- Standard: + . Fix memory leak in syslog device handling. (danog) 23 Nov 2023, PHP 8.1.26 diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index 1e50a37f2c687..cdffeebed66a2 100755 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -427,9 +427,6 @@ PHP_MINIT_FUNCTION(basic) /* {{{ */ PHP_MSHUTDOWN_FUNCTION(basic) /* {{{ */ { -#ifdef HAVE_SYSLOG_H - PHP_MSHUTDOWN(syslog)(SHUTDOWN_FUNC_ARGS_PASSTHRU); -#endif #ifdef ZTS ts_free_id(basic_globals_id); #ifdef PHP_WIN32 @@ -487,9 +484,6 @@ PHP_RINIT_FUNCTION(basic) /* {{{ */ BG(user_shutdown_function_names) = NULL; PHP_RINIT(filestat)(INIT_FUNC_ARGS_PASSTHRU); -#ifdef HAVE_SYSLOG_H - BASIC_RINIT_SUBMODULE(syslog) -#endif BASIC_RINIT_SUBMODULE(dir) BASIC_RINIT_SUBMODULE(url_scanner_ex) @@ -541,9 +535,7 @@ PHP_RSHUTDOWN_FUNCTION(basic) /* {{{ */ PHP_RSHUTDOWN(filestat)(SHUTDOWN_FUNC_ARGS_PASSTHRU); #ifdef HAVE_SYSLOG_H -#ifdef PHP_WIN32 - BASIC_RSHUTDOWN_SUBMODULE(syslog)(SHUTDOWN_FUNC_ARGS_PASSTHRU); -#endif + BASIC_RSHUTDOWN_SUBMODULE(syslog); #endif BASIC_RSHUTDOWN_SUBMODULE(assert) BASIC_RSHUTDOWN_SUBMODULE(url_scanner_ex) diff --git a/ext/standard/php_ext_syslog.h b/ext/standard/php_ext_syslog.h index 5e091fb5280df..fd7958fad2929 100644 --- a/ext/standard/php_ext_syslog.h +++ b/ext/standard/php_ext_syslog.h @@ -22,11 +22,7 @@ #include "php_syslog.h" PHP_MINIT_FUNCTION(syslog); -PHP_RINIT_FUNCTION(syslog); -#ifdef PHP_WIN32 PHP_RSHUTDOWN_FUNCTION(syslog); -#endif -PHP_MSHUTDOWN_FUNCTION(syslog); #endif diff --git a/ext/standard/syslog.c b/ext/standard/syslog.c index 70fa8e241abdd..6ea10cef24711 100644 --- a/ext/standard/syslog.c +++ b/ext/standard/syslog.c @@ -96,23 +96,9 @@ PHP_MINIT_FUNCTION(syslog) } /* }}} */ -PHP_RINIT_FUNCTION(syslog) -{ - BG(syslog_device) = NULL; - return SUCCESS; -} - - -#ifdef PHP_WIN32 PHP_RSHUTDOWN_FUNCTION(syslog) { - closelog(); - return SUCCESS; -} -#endif - -PHP_MSHUTDOWN_FUNCTION(syslog) -{ + php_closelog(); if (BG(syslog_device)) { free(BG(syslog_device)); BG(syslog_device) = NULL; From 78fba9cb80c5ec2f9e375ef7ad09c6396c123ef2 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Wed, 8 Nov 2023 08:39:05 +0100 Subject: [PATCH 05/92] Fix GH-12628: The gh11374 test fails on Alpinelinux Closes GH-12636. --- NEWS | 3 +++ ext/pcre/tests/gh11374.phpt | 6 ++++++ ext/zend_test/test.c | 10 ++++++++++ ext/zend_test/test.stub.php | 2 ++ ext/zend_test/test_arginfo.h | 10 +++++++--- 5 files changed, 28 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index 13adf6f0b1736..5395077bbd973 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.1.27 +- PCRE: + . Fixed bug GH-12628 (The gh11374 test fails on Alpinelinux). (nielsdos) + - Standard: . Fix memory leak in syslog device handling. (danog) diff --git a/ext/pcre/tests/gh11374.phpt b/ext/pcre/tests/gh11374.phpt index 07f8f4bccfd0a..29f6485cc0440 100644 --- a/ext/pcre/tests/gh11374.phpt +++ b/ext/pcre/tests/gh11374.phpt @@ -1,5 +1,11 @@ --TEST-- GH-11374 (PCRE regular expression without JIT enabled gives different result) +--EXTENSIONS-- +zend_test +--SKIPIF-- + --FILE-- Date: Thu, 9 Nov 2023 10:04:10 +0900 Subject: [PATCH 06/92] Fix GH-12633: sqlite3_defensive.phpt fails with sqlite 3.44.0 Removes 'PRAGMA writable_schema;'. From sqlite changelog https://www.sqlite.org/releaselog/3_44_0.html: > The SQLITE_DBCONFIG_DEFENSIVE setting now prevents PRAGMA writable_schema > from being turned on. > Previously writable_schema could be turned on, but would not actually allow > the schema to be writable. Now it simply cannot be turned on. Closes GH-12636. --- NEWS | 4 ++++ ext/sqlite3/tests/sqlite3_defensive.phpt | 4 +--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index 5395077bbd973..a69f1cefb2809 100644 --- a/NEWS +++ b/NEWS @@ -8,6 +8,10 @@ PHP NEWS - Standard: . Fix memory leak in syslog device handling. (danog) +- SQLite3: + . Fixed bug GH-12633 (sqlite3_defensive.phpt fails with sqlite 3.44.0). + (SakiTakamachi) + 23 Nov 2023, PHP 8.1.26 - Core: diff --git a/ext/sqlite3/tests/sqlite3_defensive.phpt b/ext/sqlite3/tests/sqlite3_defensive.phpt index 033e661d8a393..056f716170c4c 100644 --- a/ext/sqlite3/tests/sqlite3_defensive.phpt +++ b/ext/sqlite3/tests/sqlite3_defensive.phpt @@ -20,7 +20,6 @@ var_dump($db->exec('CREATE TABLE test (a, b);')); // This does not generate an error! var_dump($db->exec('PRAGMA writable_schema = ON;')); -var_dump($db->querySingle('PRAGMA writable_schema;')); // Should be 1 var_dump($db->querySingle('SELECT COUNT(*) FROM sqlite_master;')); @@ -35,8 +34,7 @@ var_dump($db->querySingle('SELECT COUNT(*) FROM sqlite_master;')); bool(true) bool(true) int(1) -int(1) Warning: SQLite3::querySingle(): Unable to prepare statement: 1, table sqlite_master may not be modified in %s on line %d bool(false) -int(1) \ No newline at end of file +int(1) From 6a43135c1d3a5a6b5b9be76d9bc5b0281b81e4d8 Mon Sep 17 00:00:00 2001 From: SakiTakamachi Date: Thu, 9 Nov 2023 09:54:10 +0900 Subject: [PATCH 07/92] Fix timezone dependent test Closes GH-12637 --- ext/intl/tests/dateformat_format_relative.phpt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ext/intl/tests/dateformat_format_relative.phpt b/ext/intl/tests/dateformat_format_relative.phpt index b06dbca830fe2..c93c1fd4a332b 100644 --- a/ext/intl/tests/dateformat_format_relative.phpt +++ b/ext/intl/tests/dateformat_format_relative.phpt @@ -5,6 +5,8 @@ intl --FILE-- From 333cf3c11135c00f30b478a41387b3a994695e0e Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 11 Nov 2023 14:15:23 +0100 Subject: [PATCH 08/92] Fix GH-12635: Test bug69398.phpt fails with ICU 74.1 ICU 74.1 contains new locale data that breaks the test. Split the test based on the version number to resolve the issue. Closes GH-12653. --- NEWS | 3 +++ ext/intl/tests/bug69398-icu74.1.phpt | 19 +++++++++++++++++++ ext/intl/tests/bug69398.phpt | 5 ++++- 3 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 ext/intl/tests/bug69398-icu74.1.phpt diff --git a/NEWS b/NEWS index 4c22f21bcbbcb..a1a33700ed0de 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.2.14 +- Intl: + . Fixed bug GH-12635 (Test bug69398.phpt fails with ICU 74.1). (nielsdos) + - PCRE: . Fixed bug GH-12628 (The gh11374 test fails on Alpinelinux). (nielsdos) diff --git a/ext/intl/tests/bug69398-icu74.1.phpt b/ext/intl/tests/bug69398-icu74.1.phpt new file mode 100644 index 0000000000000..cf8ce39d1e270 --- /dev/null +++ b/ext/intl/tests/bug69398-icu74.1.phpt @@ -0,0 +1,19 @@ +--TEST-- +IntlDateFormatter::formatObject(): returns wrong value when time style is NONE. +--EXTENSIONS-- +intl +--SKIPIF-- + +--FILE-- +setTime($millitimestamp); +echo IntlDateFormatter::formatObject($date, array(IntlDateFormatter::SHORT, IntlDateFormatter::NONE), 'vi_VN'), "\n"; +echo IntlDateFormatter::formatObject ($date, array(IntlDateFormatter::SHORT, IntlDateFormatter::NONE), 'ko_KR'), "\n"; +?> +--EXPECT-- +4/4/15 +15. 4. 4. diff --git a/ext/intl/tests/bug69398.phpt b/ext/intl/tests/bug69398.phpt index 02c4b7daeff9f..075dd5f4bd0c8 100644 --- a/ext/intl/tests/bug69398.phpt +++ b/ext/intl/tests/bug69398.phpt @@ -3,7 +3,10 @@ IntlDateFormatter::formatObject(): returns wrong value when time style is NONE. --EXTENSIONS-- intl --SKIPIF-- -= 51.1.2'); ?> += 0) die('skip for ICU >= 74.1'); +?> --FILE-- Date: Wed, 8 Nov 2023 20:06:18 +0100 Subject: [PATCH 09/92] Fix GH-12621: browscap segmentation fault when configured in the vhost The temporary HashTable has a destructor that releases the string held by the entry's value. However, browscap_intern_str(_ci) only incremented the refcount for the reference created by the return value. As the HashTable is only used during parsing, we don't need to manage the reference count of the value anyway, so get rid of the destructor. This is triggerable in two cases: - When using php_admin_value to set the ini at the activation stage - When running out of space for the opcache-interned strings Closes GH-12634. --- NEWS | 2 ++ ext/standard/browscap.c | 10 ++++---- sapi/fpm/tests/gh12621.phpt | 46 +++++++++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 6 deletions(-) create mode 100644 sapi/fpm/tests/gh12621.phpt diff --git a/NEWS b/NEWS index a1a33700ed0de..22d900c51eb81 100644 --- a/NEWS +++ b/NEWS @@ -10,6 +10,8 @@ PHP NEWS - Standard: . Fix memory leak in syslog device handling. (danog) + . Fixed bug GH-12621 (browscap segmentation fault when configured in the + vhost). (nielsdos) - SQLite3: . Fixed bug GH-12633 (sqlite3_defensive.phpt fails with sqlite 3.44.0). diff --git a/ext/standard/browscap.c b/ext/standard/browscap.c index 4fa766e3df802..d7b53e659939d 100644 --- a/ext/standard/browscap.c +++ b/ext/standard/browscap.c @@ -228,7 +228,7 @@ static zend_string *browscap_intern_str( } else { interned = zend_string_copy(str); if (persistent) { - interned = zend_new_interned_string(str); + interned = zend_new_interned_string(interned); } zend_hash_add_new_ptr(&ctx->str_interned, interned, interned); } @@ -397,10 +397,6 @@ static void php_browscap_parser_cb(zval *arg1, zval *arg2, zval *arg3, int callb } /* }}} */ -static void str_interned_dtor(zval *zv) { - zend_string_release(Z_STR_P(zv)); -} - static int browscap_read_file(char *filename, browser_data *browdata, int persistent) /* {{{ */ { zend_file_handle fh; @@ -430,7 +426,9 @@ static int browscap_read_file(char *filename, browser_data *browdata, int persis ctx.bdata = browdata; ctx.current_entry = NULL; ctx.current_section_name = NULL; - zend_hash_init(&ctx.str_interned, 8, NULL, str_interned_dtor, persistent); + /* No dtor because we don't inc the refcount for the reference stored within the hash table's entry value + * as the hash table is only temporary anyway. */ + zend_hash_init(&ctx.str_interned, 8, NULL, NULL, persistent); zend_parse_ini_file(&fh, persistent, ZEND_INI_SCANNER_RAW, (zend_ini_parser_cb_t) php_browscap_parser_cb, &ctx); diff --git a/sapi/fpm/tests/gh12621.phpt b/sapi/fpm/tests/gh12621.phpt new file mode 100644 index 0000000000000..0ee64fbe415bd --- /dev/null +++ b/sapi/fpm/tests/gh12621.phpt @@ -0,0 +1,46 @@ +--TEST-- +GH-12621 (browscap segmentation fault when configured with php_admin_value) +--SKIPIF-- + +--FILE-- +browser_name_pattern; +var_dump(\$cv); +EOT; + +$tester = new FPM\Tester($cfg, $code); +$tester->start(); +$tester->expectLogStartNotices(); +echo $tester + ->request() + ->getBody(); +$tester->terminate(); +$tester->close(); + +?> +--EXPECT-- +string(14) "*Konqueror/2.*" +--CLEAN-- + From 7440a1bd1f9bdbcf1fb07b7e29be93cbdce3c0f1 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Fri, 10 Nov 2023 12:42:17 +0100 Subject: [PATCH 10/92] Fix undeclared variable in stat tests Closes GH-12645 --- ext/standard/tests/file/file.inc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/standard/tests/file/file.inc b/ext/standard/tests/file/file.inc index d4ad02a363bd5..0901069717a16 100644 --- a/ext/standard/tests/file/file.inc +++ b/ext/standard/tests/file/file.inc @@ -590,9 +590,9 @@ $all_stat_keys = array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, "rdev", "size", "atime", "mtime", "ctime", "blksize", "blocks"); -$stat_time_diff_keys = array(8, 'atime'); - function compare_stats($stat1, $stat2, $fields, $op = "==", $flag = false ) { + $stat_time_diff_keys = array(8, 'atime'); + // dump the stat if requested if ( $flag == true ) { var_dump($stat1); From ca22505c8ca02950385f523e6056a9e129cf2289 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 9 Nov 2023 20:44:30 +0100 Subject: [PATCH 11/92] Disable -fsanitize=function on Clang 17 Closes GH-12642 --- configure.ac | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/configure.ac b/configure.ac index 76f3368274fdf..dd3464216108f 100644 --- a/configure.ac +++ b/configure.ac @@ -1581,6 +1581,23 @@ if test "$PHP_UNDEFINED_SANITIZER" = "yes"; then CFLAGS="$CFLAGS -fno-sanitize=object-size" CXXFLAGS="$CFLAGS -fno-sanitize=object-size" ]) + + dnl Clang 17 adds stricter function pointer compatibility checks where pointer args cannot be + dnl cast to void*. In that case, set -fno-sanitize=function. + OLD_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -fno-sanitize-recover=undefined" + AC_RUN_IFELSE([AC_LANG_SOURCE([[ +void foo(char *string) {} +int main(void) { + void (*f)(void *) = (void (*)(void *))foo; + f("foo"); +} + ]])],,[ubsan_needs_no_function=yes],) + CFLAGS="$OLD_CFLAGS" + if test "$ubsan_needs_no_function" = yes; then + CFLAGS="$CFLAGS -fno-sanitize=function" + CXXFLAGS="$CFLAGS -fno-sanitize=function" + fi ], [AC_MSG_ERROR([UndefinedBehaviorSanitizer is not available])]) fi From d224faa10f978fdae0b289718b9014540df7ffc5 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Sun, 12 Nov 2023 14:06:02 +0100 Subject: [PATCH 12/92] Fix astat imperciseness excemption in test --- ext/standard/tests/file/file.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/standard/tests/file/file.inc b/ext/standard/tests/file/file.inc index 0901069717a16..c53c217e970ac 100644 --- a/ext/standard/tests/file/file.inc +++ b/ext/standard/tests/file/file.inc @@ -608,7 +608,7 @@ function compare_stats($stat1, $stat2, $fields, $op = "==", $flag = false ) { { case "==": if ( $stat1[ $fields[$index] ] != $stat2[ $fields[$index] ] ) { - if ( ! in_array( $index, $stat_time_diff_keys ) ) { + if ( ! in_array( $fields[$index], $stat_time_diff_keys ) ) { $result = false; echo "Error: stat1 do not match with stat2 at key value: $fields[$index]\n"; } elseif (abs($stat1[ $fields[$index] ] - $stat2[ $fields[$index] ]) > 1) { From c60c2a0d679b7d567b3de02fb9adac5a9dd25afb Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 13 Nov 2023 13:26:17 +0300 Subject: [PATCH 13/92] Backport fix for GH-12512: JIT Assertion `info & (1 << type)' failed (#12660) --- ext/opcache/jit/zend_jit_trace.c | 72 ++++++++++++++++++++++++++-- ext/opcache/tests/jit/gh12512.phpt | 41 ++++++++++++++++ ext/opcache/tests/jit/gh12512_2.phpt | 44 +++++++++++++++++ 3 files changed, 154 insertions(+), 3 deletions(-) create mode 100644 ext/opcache/tests/jit/gh12512.phpt create mode 100644 ext/opcache/tests/jit/gh12512_2.phpt diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c index 4a57986130666..86cd2aae06094 100644 --- a/ext/opcache/jit/zend_jit_trace.c +++ b/ext/opcache/jit/zend_jit_trace.c @@ -5022,6 +5022,21 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par zend_may_throw_ex(opline, ssa_op, op_array, ssa, op1_info, op2_info))) { goto jit_failure; } + if (ssa_op->op2_def > 0 + && Z_MODE(op2_addr) == IS_REG + && ssa->vars[ssa_op->op2_def].no_val) { + uint8_t type = (op2_info & MAY_BE_LONG) ? IS_LONG : IS_DOUBLE; + uint32_t var_num = EX_VAR_TO_NUM(opline->op2.var); + + if (STACK_MEM_TYPE(stack, var_num) != type + && ssa->vars[ssa_op->op2_def].use_chain < 0 + && !ssa->vars[ssa_op->op2_def].phi_use_chain) { + if (!zend_jit_store_var_type(&dasm_state, var_num, type)) { + return 0; + } + SET_STACK_TYPE(stack, var_num, type, 1); + } + } if (opline->op2_type == IS_CV && ssa_op->op2_def >= 0 && ssa->vars[ssa_op->op2_def].alias == NO_ALIAS) { @@ -5058,6 +5073,21 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par res_use_info, res_info, res_addr)) { goto jit_failure; } + if (ssa_op->op1_def > 0 + && Z_MODE(op1_addr) == IS_REG + && ssa->vars[ssa_op->op1_def].no_val) { + uint8_t type = (op1_info & MAY_BE_LONG) ? IS_LONG : IS_DOUBLE; + uint32_t var_num = EX_VAR_TO_NUM(opline->op1.var); + + if (STACK_MEM_TYPE(stack, var_num) != type + && ssa->vars[ssa_op->op1_def].use_chain < 0 + && !ssa->vars[ssa_op->op1_def].phi_use_chain) { + if (!zend_jit_store_var_type(&dasm_state, var_num, type)) { + return 0; + } + SET_STACK_TYPE(stack, var_num, type, 1); + } + } if (opline->op1_type == IS_CV && ssa_op->op1_def >= 0 && ssa->vars[ssa_op->op1_def].alias == NO_ALIAS) { @@ -5140,6 +5170,21 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par op1_info, op1_addr, op1_def_addr)) { goto jit_failure; } + if (ssa_op->op1_def > 0 + && Z_MODE(op1_addr) == IS_REG + && ssa->vars[ssa_op->op1_def].no_val) { + uint8_t type = (op1_info & MAY_BE_LONG) ? IS_LONG : IS_DOUBLE; + uint32_t var_num = EX_VAR_TO_NUM(opline->op1.var); + + if (STACK_MEM_TYPE(stack, var_num) != type + && ssa->vars[ssa_op->op1_def].use_chain < 0 + && !ssa->vars[ssa_op->op1_def].phi_use_chain) { + if (!zend_jit_store_var_type(&dasm_state, var_num, type)) { + return 0; + } + SET_STACK_TYPE(stack, var_num, type, 1); + } + } if (opline->op1_type == IS_CV && ssa_op->op1_def >= 0 && ssa->vars[ssa_op->op1_def].alias == NO_ALIAS) { @@ -6872,9 +6917,30 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par } } else if (p->stop == ZEND_JIT_TRACE_STOP_LINK || p->stop == ZEND_JIT_TRACE_STOP_INTERPRETER) { - if (!zend_jit_trace_deoptimization(&dasm_state, 0, NULL, - stack, op_array->last_var + op_array->T, NULL, NULL, NULL, 0)) { - goto jit_failure; + if (ra + && (p-1)->op != ZEND_JIT_TRACE_ENTER + && (p-1)->op != ZEND_JIT_TRACE_BACK + && opline->opcode != ZEND_DO_UCALL + && opline->opcode != ZEND_DO_FCALL + && opline->opcode != ZEND_DO_FCALL_BY_NAME + && opline->opcode != ZEND_INCLUDE_OR_EVAL) { + if (!zend_jit_trace_deoptimization(&dasm_state, 0, NULL, + stack, op_array->last_var + op_array->T, NULL, NULL, NULL, 0)) { + goto jit_failure; + } + for (i = 0; i < op_array->last_var; i++) { + int8_t reg = STACK_REG(stack, i); + uint8_t type = STACK_TYPE(stack, i); + + if (reg == ZREG_NONE + && type != IS_UNKNOWN + && type != STACK_MEM_TYPE(stack, i)) { + if (!zend_jit_store_var_type(&dasm_state, i, type)) { + return 0; + } + SET_STACK_TYPE(stack, i, type, 1); + } + } } if (p->stop == ZEND_JIT_TRACE_STOP_LINK) { const void *timeout_exit_addr = NULL; diff --git a/ext/opcache/tests/jit/gh12512.phpt b/ext/opcache/tests/jit/gh12512.phpt new file mode 100644 index 0000000000000..35307d18cc61f --- /dev/null +++ b/ext/opcache/tests/jit/gh12512.phpt @@ -0,0 +1,41 @@ +--TEST-- +GH-12512: missing type store +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +--FILE-- + $val) { + if ($val === 2) { + unset($a[$key]); + } + } + return $ret; +} + +function foo($a, bool $b): bool { + if ($b) return true; + $n2 = count($a); + do { + $n = $n2; + $res = bar($a); + $n2 = count($a); + } while ($res === null && $n !== $n2); + + if ($res === null && $n === 0) { + return false; + } + return true; +} + +$a = [1,'a'=>5]; +bar($a); +foo([1,'a'=>5], true); +foo([1,'a'=>5], false); +foo([2,'a'=>5], false); +?> +DONE +--EXPECT-- +DONE diff --git a/ext/opcache/tests/jit/gh12512_2.phpt b/ext/opcache/tests/jit/gh12512_2.phpt new file mode 100644 index 0000000000000..67c5b091494c3 --- /dev/null +++ b/ext/opcache/tests/jit/gh12512_2.phpt @@ -0,0 +1,44 @@ +--TEST-- +GH-12512: missing type store +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +--FILE-- + $y; + } + if ($exit) { + return $n; + } + } + + return $n; +} +var_dump(foo([1,2,3,4,5,6,7,8], 1)); +var_dump(foo([1,2,3,4,5,6,7,8], 1)); +var_dump(foo([1,2,3,4,5,6,7,8], 0)); +?> +DONE +--EXPECT-- +int(0) +int(0) +int(0) +DONE From 86c7d3ed1f07cb6b4ddcbc1c12d48a7fc700f4a7 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 12 Nov 2023 18:43:35 +0100 Subject: [PATCH 14/92] Fix GH-12655: proc_open() does not take into account references in the descriptor array Closes GH-12658. --- NEWS | 2 ++ ext/standard/proc_open.c | 1 + .../tests/general_functions/gh12655.phpt | 22 +++++++++++++++++++ 3 files changed, 25 insertions(+) create mode 100644 ext/standard/tests/general_functions/gh12655.phpt diff --git a/NEWS b/NEWS index 22d900c51eb81..c22b54dfe42a8 100644 --- a/NEWS +++ b/NEWS @@ -12,6 +12,8 @@ PHP NEWS . Fix memory leak in syslog device handling. (danog) . Fixed bug GH-12621 (browscap segmentation fault when configured in the vhost). (nielsdos) + . Fixed bug GH-12655 (proc_open() does not take into account references + in the descriptor array). (nielsdos) - SQLite3: . Fixed bug GH-12633 (sqlite3_defensive.phpt fails with sqlite 3.44.0). diff --git a/ext/standard/proc_open.c b/ext/standard/proc_open.c index 53ec6faa1019e..866c7a3c896e2 100644 --- a/ext/standard/proc_open.c +++ b/ext/standard/proc_open.c @@ -1096,6 +1096,7 @@ PHP_FUNCTION(proc_open) descriptors[ndesc].index = (int)nindex; + ZVAL_DEREF(descitem); if (Z_TYPE_P(descitem) == IS_RESOURCE) { if (set_proc_descriptor_from_resource(descitem, &descriptors[ndesc], ndesc) == FAILURE) { goto exit_fail; diff --git a/ext/standard/tests/general_functions/gh12655.phpt b/ext/standard/tests/general_functions/gh12655.phpt new file mode 100644 index 0000000000000..c0235ee6ae6fb --- /dev/null +++ b/ext/standard/tests/general_functions/gh12655.phpt @@ -0,0 +1,22 @@ +--TEST-- +GH-12655 (proc_open(): Argument #2 ($descriptor_spec) must only contain arrays and streams [Descriptor item must be either an array or a File-Handle]) +--FILE-- + [ "pipe", "r" ], // stdin is a pipe that the child will read from + 1 => [ "pipe", "w" ], // stdout is a pipe that the child will write to + 2 => [ "pipe", "w" ], // stderr is a file to write to +]; + +foreach ( $descriptor_spec as $fd => &$d ) +{ + // don't do anything, just the fact that we used "&$d" will sink the ship! +} + +$proc = proc_open(PHP_BINARY, $descriptor_spec, $pipes); +echo $proc === false ? "FAILED\n" : "SUCCEEDED\n"; + +?> +--EXPECT-- +SUCCEEDED From 6625226074e1c534b10ad4cf405834d66e79b358 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Tue, 14 Nov 2023 09:10:53 +0100 Subject: [PATCH 15/92] fix GH-12661 (Inconsistency in ZipArchive::addGlob remove_path Option Behavior) --- ext/zip/php_zip.c | 2 +- ext/zip/tests/bug_gh12661.phpt | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 ext/zip/tests/bug_gh12661.phpt diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c index 96c3757a3740d..4dccdffbcdc42 100644 --- a/ext/zip/php_zip.c +++ b/ext/zip/php_zip.c @@ -1747,7 +1747,7 @@ static void php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAMETERS, int type) /* basename = php_basename(Z_STRVAL_P(zval_file), Z_STRLEN_P(zval_file), NULL, 0); file_stripped = ZSTR_VAL(basename); file_stripped_len = ZSTR_LEN(basename); - } else if (opts.remove_path && strstr(Z_STRVAL_P(zval_file), opts.remove_path) != NULL) { + } else if (opts.remove_path && !memcmp(Z_STRVAL_P(zval_file), opts.remove_path, opts.remove_path_len)) { if (IS_SLASH(Z_STRVAL_P(zval_file)[opts.remove_path_len])) { file_stripped = Z_STRVAL_P(zval_file) + opts.remove_path_len + 1; file_stripped_len = Z_STRLEN_P(zval_file) - opts.remove_path_len - 1; diff --git a/ext/zip/tests/bug_gh12661.phpt b/ext/zip/tests/bug_gh12661.phpt new file mode 100644 index 0000000000000..993299b8657f2 --- /dev/null +++ b/ext/zip/tests/bug_gh12661.phpt @@ -0,0 +1,25 @@ +--TEST-- +Bug GH-12661 (Inconsistency in ZipArchive::addGlob 'remove_path' Option Behavior) +--EXTENSIONS-- +zip +--FILE-- +open($file, ZipArchive::CREATE | ZipArchive::OVERWRITE); +$zip->addGlob(__FILE__, 0, ['remove_path' => 'bug_']); // unchanged (bug is not a prefix) +$zip->addGlob(__FILE__, 0, ['remove_path' => dirname(__DIR__)]); +verify_entries($zip, [__FILE__, basename(__DIR__) . DIRECTORY_SEPARATOR . basename(__FILE__)]); +$zip->close(); + +?> +Done +--CLEAN-- + +--EXPECT-- +Done From 0b5824e17c4036be080674ff79bc98074ee4c26e Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Tue, 14 Nov 2023 14:56:06 +0100 Subject: [PATCH 16/92] NEWS --- NEWS | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS b/NEWS index a69f1cefb2809..5139f2c4f0213 100644 --- a/NEWS +++ b/NEWS @@ -12,6 +12,10 @@ PHP NEWS . Fixed bug GH-12633 (sqlite3_defensive.phpt fails with sqlite 3.44.0). (SakiTakamachi) +- Zip: + . Fixed bug GH-12661 (Inconsistency in ZipArchive::addGlob remove_path Option + Behavior). (Remi) + 23 Nov 2023, PHP 8.1.26 - Core: From 2536cf78b8f91072a38a3628ad4723a742e332b9 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Tue, 14 Nov 2023 14:56:59 +0100 Subject: [PATCH 17/92] NEWS --- NEWS | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS b/NEWS index c22b54dfe42a8..a592ec6de97a1 100644 --- a/NEWS +++ b/NEWS @@ -19,6 +19,10 @@ PHP NEWS . Fixed bug GH-12633 (sqlite3_defensive.phpt fails with sqlite 3.44.0). (SakiTakamachi) +- Zip: + . Fixed bug GH-12661 (Inconsistency in ZipArchive::addGlob remove_path Option + Behavior). (Remi) + 23 Nov 2023, PHP 8.2.13 - Core: From 9b07b013fcec58c3568da74a00decfa8ce926209 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Tue, 14 Nov 2023 18:36:07 +0100 Subject: [PATCH 18/92] [skip ci] Further increase allowable atime deviation MSAN is slow in particular, leading to potentially higher deviations. --- ext/standard/tests/file/file.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/standard/tests/file/file.inc b/ext/standard/tests/file/file.inc index c53c217e970ac..c972784f9da36 100644 --- a/ext/standard/tests/file/file.inc +++ b/ext/standard/tests/file/file.inc @@ -611,7 +611,7 @@ function compare_stats($stat1, $stat2, $fields, $op = "==", $flag = false ) { if ( ! in_array( $fields[$index], $stat_time_diff_keys ) ) { $result = false; echo "Error: stat1 do not match with stat2 at key value: $fields[$index]\n"; - } elseif (abs($stat1[ $fields[$index] ] - $stat2[ $fields[$index] ]) > 1) { + } elseif (abs($stat1[ $fields[$index] ] - $stat2[ $fields[$index] ]) > 2) { $result = false; echo "Error: stat1 differs too much from stat2 at key value: $fields[$index]\n"; } From 6d5964098084bab1507b0b787b46bfcfd60a73a9 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 9 Nov 2023 11:53:55 +0100 Subject: [PATCH 19/92] Automatically mark tests as flaky Marking all of these tests as flaky is annoying, so attempt to recognize them automatically. Closes GH-12638 --- run-tests.php | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/run-tests.php b/run-tests.php index 19335cbf697a3..bb991aaf9872f 100755 --- a/run-tests.php +++ b/run-tests.php @@ -2804,10 +2804,30 @@ function run_test(string $php, $file, array $env): string return $restype[0] . 'ED'; } +function is_flaky(TestFile $test): bool +{ + if ($test->hasSection('FLAKY')) { + return true; + } + if (!$test->hasSection('FILE')) { + return false; + } + $file = $test->getSection('FILE'); + $flaky_functions = [ + 'disk_free_space', + 'hrtime', + 'microtime', + 'sleep', + 'usleep', + ]; + $regex = '(\b(' . implode('|', $flaky_functions) . ')\()i'; + return preg_match($regex, $file) === 1; +} + function error_may_be_retried(TestFile $test, string $output): bool { return preg_match('((timed out)|(connection refused)|(404: page not found)|(address already in use)|(mailbox already exists))i', $output) === 1 - || $test->hasSection('FLAKY'); + || is_flaky($test); } /** From 4f1103ef3b921ddf2e0df497b09829a3b4382a65 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Wed, 15 Nov 2023 20:15:44 +0100 Subject: [PATCH 20/92] Fix GH-12675: MEMORY_LEAK in phpdbg_prompt.c Have to use file_put_contents() instead of --FILE-- because we have to actually load it using the exec command, *and* have to make multiple files, and note that we can only load files relative from the current directory, so we can't rely on files being in the sapi/phpdbg/tests folder. Closes GH-12680. --- NEWS | 3 +++ sapi/phpdbg/phpdbg_prompt.c | 2 ++ sapi/phpdbg/tests/gh12675.phpt | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 37 insertions(+) create mode 100644 sapi/phpdbg/tests/gh12675.phpt diff --git a/NEWS b/NEWS index a592ec6de97a1..1f09639a2f136 100644 --- a/NEWS +++ b/NEWS @@ -8,6 +8,9 @@ PHP NEWS - PCRE: . Fixed bug GH-12628 (The gh11374 test fails on Alpinelinux). (nielsdos) +- PHPDBG: + . Fixed bug GH-12675 (MEMORY_LEAK in phpdbg_prompt.c). (nielsdos) + - Standard: . Fix memory leak in syslog device handling. (danog) . Fixed bug GH-12621 (browscap segmentation fault when configured in the diff --git a/sapi/phpdbg/phpdbg_prompt.c b/sapi/phpdbg/phpdbg_prompt.c index 2464e39e5683c..ffc40cb0c9686 100644 --- a/sapi/phpdbg/phpdbg_prompt.c +++ b/sapi/phpdbg/phpdbg_prompt.c @@ -408,6 +408,7 @@ PHPDBG_COMMAND(exec) /* {{{ */ if ((res_len != PHPDBG_G(exec_len)) || (memcmp(res, PHPDBG_G(exec), res_len) != SUCCESS)) { if (PHPDBG_G(in_execution)) { if (phpdbg_ask_user_permission("Do you really want to stop execution to set a new execution context?") == FAILURE) { + free(res); return FAILURE; } } @@ -441,6 +442,7 @@ PHPDBG_COMMAND(exec) /* {{{ */ phpdbg_compile(); } else { + free(res); phpdbg_notice("Execution context not changed"); } } else { diff --git a/sapi/phpdbg/tests/gh12675.phpt b/sapi/phpdbg/tests/gh12675.phpt new file mode 100644 index 0000000000000..167e68595df31 --- /dev/null +++ b/sapi/phpdbg/tests/gh12675.phpt @@ -0,0 +1,32 @@ +--TEST-- +GH-12675 (MEMORY_LEAK in phpdbg_prompt.c) +--INI-- +opcache.enable=0 +--PHPDBG-- +ev file_put_contents("gh12675_1.tmp", " 24 +prompt> 16 +prompt> [Cannot stat nonexistent.php, ensure the file exists] +prompt> [Set execution context: %sgh12675_1.tmp] +[Successful compilation of %sgh12675_1.tmp] +prompt> [Execution context not changed] +prompt> [Breakpoint #0 added at %sgh12675_1.tmp:2] +prompt> hi +[Breakpoint #0 at %sgh12675_1.tmp:2, hits: 1] +>00002: echo 2; +prompt> Do you really want to stop execution to set a new execution context? (type y or n): prompt> +--CLEAN-- + From f320c3561e09a02e2ad06cf5d604a836180d00d7 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Wed, 15 Nov 2023 20:27:02 +0100 Subject: [PATCH 21/92] Use __DIR__-relative path in tests Otherwise we can't run them from another directory, they'll fail instead. --- ext/exif/tests/bug78793.phpt | 2 +- ext/soap/tests/bug75306.phpt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ext/exif/tests/bug78793.phpt b/ext/exif/tests/bug78793.phpt index 93d728ff6d1cf..babbe927045d3 100644 --- a/ext/exif/tests/bug78793.phpt +++ b/ext/exif/tests/bug78793.phpt @@ -4,7 +4,7 @@ Bug #78793: Use-after-free in exif parsing under memory sanitizer exif --FILE-- WSDL_CACHE_NONE); // Need a warm-up for globals for ($i = 0; $i < 10; $i++) { - $client = new SoapClient("ext/soap/tests/test.wsdl", $options); + $client = new SoapClient(__DIR__ . "/test.wsdl", $options); } $usage = memory_get_usage(); for ($i = 0; $i < 10; $i++) { - $client = new SoapClient("ext/soap/tests/test.wsdl", $options); + $client = new SoapClient(__DIR__ . "/test.wsdl", $options); } $usage_delta = memory_get_usage() - $usage; var_dump($usage_delta); From b4208c8f9620d7772485f1522e7014d53c953279 Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Mon, 13 Nov 2023 14:42:26 +0000 Subject: [PATCH 22/92] Initialize syslog device in GINIT Closes GH-12663 --- ext/standard/basic_functions.c | 2 ++ ext/standard/syslog.c | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index cdffeebed66a2..ddaf1368410bc 100755 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -230,6 +230,8 @@ static void basic_globals_ctor(php_basic_globals *basic_globals_p) /* {{{ */ BG(page_uid) = -1; BG(page_gid) = -1; + + BG(syslog_device) = NULL; } /* }}} */ diff --git a/ext/standard/syslog.c b/ext/standard/syslog.c index 6ea10cef24711..9d392f212ecc7 100644 --- a/ext/standard/syslog.c +++ b/ext/standard/syslog.c @@ -90,7 +90,6 @@ PHP_MINIT_FUNCTION(syslog) /* AIX doesn't have LOG_PERROR */ REGISTER_LONG_CONSTANT("LOG_PERROR", LOG_PERROR, CONST_CS | CONST_PERSISTENT); /*log to stderr*/ #endif - BG(syslog_device)=NULL; return SUCCESS; } From a742010a0a3a89afa169b95e3ae8d107deb6508d Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 16 Nov 2023 14:13:38 +0100 Subject: [PATCH 23/92] Fix file test race condition 005_variation2.phpt creates files with special names, and filesize_variation5.phpt checks for filesize of inexistent files with special names. Create the files in a separate directory to avoid these tests clashing. Closes GH-12692 --- ext/standard/tests/file/005_variation2.phpt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ext/standard/tests/file/005_variation2.phpt b/ext/standard/tests/file/005_variation2.phpt index 55d1d6666098c..270a6cfbdd84c 100644 --- a/ext/standard/tests/file/005_variation2.phpt +++ b/ext/standard/tests/file/005_variation2.phpt @@ -28,6 +28,11 @@ function stat_fn( $filename ) { echo "*** Testing fileattime(), filemtime(), filectime() & touch() : usage variations ***\n"; echo "\n*** testing touch ***\n"; + +$dir = __DIR__ . '/005_variation2'; +mkdir($dir); +chdir($dir); + $b = touch(false); $c = touch(''); $d = touch(' '); @@ -47,6 +52,7 @@ stat_fn('|'); var_dump(unlink(' ')); var_dump(unlink('|')); +rmdir($dir); echo "Done"; ?> From 58712e06988de6fc343a02a8bc412b23f96d8672 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 16 Nov 2023 14:35:37 +0100 Subject: [PATCH 24/92] Retry tests on deadlock Closes GH-12693 --- run-tests.php | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/run-tests.php b/run-tests.php index bb991aaf9872f..bb422e41c0fe4 100755 --- a/run-tests.php +++ b/run-tests.php @@ -2824,9 +2824,23 @@ function is_flaky(TestFile $test): bool return preg_match($regex, $file) === 1; } +function is_flaky_output(string $output): bool +{ + $messages = [ + '404: page not found', + 'address already in use', + 'connection refused', + 'deadlock', + 'mailbox already exists', + 'timed out', + ]; + $regex = '(\b(' . implode('|', $messages) . ')\b)i'; + return preg_match($regex, $output) === 1; +} + function error_may_be_retried(TestFile $test, string $output): bool { - return preg_match('((timed out)|(connection refused)|(404: page not found)|(address already in use)|(mailbox already exists))i', $output) === 1 + return is_flaky_output($output) || is_flaky($test); } From d5c6633bd178f3cafe14e1b412d426c66b304fc4 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 16 Nov 2023 16:28:12 +0100 Subject: [PATCH 25/92] [skip ci] Fix more test tmp file conflicts --- ext/standard/tests/file/is_readable_basic.phpt | 2 +- ext/standard/tests/file/is_readable_error.phpt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/standard/tests/file/is_readable_basic.phpt b/ext/standard/tests/file/is_readable_basic.phpt index 7f1b85501a357..38d075439a3f2 100644 --- a/ext/standard/tests/file/is_readable_basic.phpt +++ b/ext/standard/tests/file/is_readable_basic.phpt @@ -15,7 +15,7 @@ require __DIR__.'/file.inc'; echo "*** Testing is_readable(): basic functionality ***\n"; // create a file -$filename = __DIR__."/is_readable.tmp"; +$filename = __DIR__."/is_readable_basic.tmp"; create_file($filename); $counter = 1; diff --git a/ext/standard/tests/file/is_readable_error.phpt b/ext/standard/tests/file/is_readable_error.phpt index 8df7ff92d526c..c013f7fbb7049 100644 --- a/ext/standard/tests/file/is_readable_error.phpt +++ b/ext/standard/tests/file/is_readable_error.phpt @@ -3,7 +3,7 @@ Test is_readable() function: error conditions --FILE-- From 708e9fadfd9c5432ff67dbc7f5117bd72415421c Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Fri, 17 Nov 2023 10:54:23 +0000 Subject: [PATCH 26/92] Skip slow tests on Travis Closes GH-12697 --- travis/test.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/travis/test.sh b/travis/test.sh index 8aaab2d13417d..c1617f782ab2d 100755 --- a/travis/test.sh +++ b/travis/test.sh @@ -4,6 +4,7 @@ set -ex # ARM64 CI reports nproc=32, which is excessive. if [ -z "$ARM64" ]; then export JOBS=$(nproc); else export JOBS=16; fi +export SKIP_SLOW_TESTS=1 export SKIP_IO_CAPTURE_TESTS=1 ./sapi/cli/php run-tests.php -P \ -g "FAIL,BORK,LEAK" --offline --show-diff --show-slow 1000 \ From c442a1f18e7f897a42dd8ac608a37958e6655a87 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Wed, 1 Mar 2023 02:19:29 +0100 Subject: [PATCH 27/92] Temporarily disable failing zlib tests on travis (#10738) --- ext/zlib/tests/gzcompress_basic1.phpt | 2 ++ ext/zlib/tests/gzdeflate_basic1.phpt | 2 ++ ext/zlib/tests/gzencode_basic1.phpt | 2 ++ 3 files changed, 6 insertions(+) diff --git a/ext/zlib/tests/gzcompress_basic1.phpt b/ext/zlib/tests/gzcompress_basic1.phpt index ec5f554153dab..b5ad22341ed74 100644 --- a/ext/zlib/tests/gzcompress_basic1.phpt +++ b/ext/zlib/tests/gzcompress_basic1.phpt @@ -2,6 +2,8 @@ Test gzcompress() function : basic functionality --EXTENSIONS-- zlib +--SKIPIF-- + --FILE-- --FILE-- --FILE-- Date: Thu, 16 Nov 2023 20:42:05 +0000 Subject: [PATCH 28/92] Fix bug #79945: Stream wrappers in imagecreatefrompng causes segfault Closes GH-12696 --- NEWS | 10 +++++++--- ext/gd/tests/bug79945.phpt | 22 ++++++++++++++++++++++ main/php_streams.h | 3 +++ main/streams/streams.c | 9 +++++++-- 4 files changed, 39 insertions(+), 5 deletions(-) create mode 100644 ext/gd/tests/bug79945.phpt diff --git a/NEWS b/NEWS index 1f09639a2f136..dff47b02fb671 100644 --- a/NEWS +++ b/NEWS @@ -11,6 +11,10 @@ PHP NEWS - PHPDBG: . Fixed bug GH-12675 (MEMORY_LEAK in phpdbg_prompt.c). (nielsdos) +- SQLite3: + . Fixed bug GH-12633 (sqlite3_defensive.phpt fails with sqlite 3.44.0). + (SakiTakamachi) + - Standard: . Fix memory leak in syslog device handling. (danog) . Fixed bug GH-12621 (browscap segmentation fault when configured in the @@ -18,9 +22,9 @@ PHP NEWS . Fixed bug GH-12655 (proc_open() does not take into account references in the descriptor array). (nielsdos) -- SQLite3: - . Fixed bug GH-12633 (sqlite3_defensive.phpt fails with sqlite 3.44.0). - (SakiTakamachi) +- Streams: + . Fixed bug #79945 (Stream wrappers in imagecreatefrompng causes segfault). + (Jakub Zelenka) - Zip: . Fixed bug GH-12661 (Inconsistency in ZipArchive::addGlob remove_path Option diff --git a/ext/gd/tests/bug79945.phpt b/ext/gd/tests/bug79945.phpt new file mode 100644 index 0000000000000..b985ddd48be31 --- /dev/null +++ b/ext/gd/tests/bug79945.phpt @@ -0,0 +1,22 @@ +--TEST-- +Bug #79945 (using php wrappers in imagecreatefrompng causes segmentation fault) +--EXTENSIONS-- +gd +--SKIPIF-- + +--FILE-- + +--CLEAN-- +--EXPECTF-- + +Warning: imagecreatefrompng(): "php://filter/read=convert.base64-encode/resource=%s" is not a valid PNG file in %s on line %d diff --git a/main/php_streams.h b/main/php_streams.h index e7cbc7369ed45..0837472d2f6b9 100644 --- a/main/php_streams.h +++ b/main/php_streams.h @@ -211,6 +211,9 @@ struct _php_stream { * PHP_STREAM_FCLOSE_XXX as appropriate */ uint8_t fclose_stdiocast:2; + /* whether stdio cast flushing is in progress */ + int8_t fclose_stdiocast_flush_in_progress:1; + char mode[16]; /* "rwb" etc. ala stdio */ uint32_t flags; /* PHP_STREAM_FLAG_XXX */ diff --git a/main/streams/streams.c b/main/streams/streams.c index 4cd211ad85fe5..e1399927b2783 100644 --- a/main/streams/streams.c +++ b/main/streams/streams.c @@ -1294,8 +1294,13 @@ PHPAPI zend_off_t _php_stream_tell(php_stream *stream) PHPAPI int _php_stream_seek(php_stream *stream, zend_off_t offset, int whence) { if (stream->fclose_stdiocast == PHP_STREAM_FCLOSE_FOPENCOOKIE) { - /* flush to commit data written to the fopencookie FILE* */ - fflush(stream->stdiocast); + /* flush can call seek internally so we need to prevent an infinite loop */ + if (!stream->fclose_stdiocast_flush_in_progress) { + stream->fclose_stdiocast_flush_in_progress = 1; + /* flush to commit data written to the fopencookie FILE* */ + fflush(stream->stdiocast); + stream->fclose_stdiocast_flush_in_progress = 0; + } } /* handle the case where we are in the buffer */ From 4da89d86ec4f21a1c6933cd0cb57fc08e75b4f6a Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Fri, 17 Nov 2023 13:33:51 +0000 Subject: [PATCH 29/92] Fix stream fclose_stdiocast_flush_in_progress type --- main/php_streams.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/php_streams.h b/main/php_streams.h index 0837472d2f6b9..17161d70ad59a 100644 --- a/main/php_streams.h +++ b/main/php_streams.h @@ -212,7 +212,7 @@ struct _php_stream { uint8_t fclose_stdiocast:2; /* whether stdio cast flushing is in progress */ - int8_t fclose_stdiocast_flush_in_progress:1; + uint8_t fclose_stdiocast_flush_in_progress:1; char mode[16]; /* "rwb" etc. ala stdio */ From 8a95e616b91ac0eeedba90a61e36e652919763f2 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Fri, 17 Nov 2023 19:45:40 +0100 Subject: [PATCH 30/92] Fix GH-12702: libxml2 2.12.0 issue building from src Fixes GH-12702. Co-authored-by: nono303 --- NEWS | 3 +++ ext/dom/document.c | 1 + ext/libxml/php_libxml.h | 1 + 3 files changed, 5 insertions(+) diff --git a/NEWS b/NEWS index dff47b02fb671..247a124e51293 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,9 @@ PHP NEWS - Intl: . Fixed bug GH-12635 (Test bug69398.phpt fails with ICU 74.1). (nielsdos) +- LibXML: + . Fixed bug GH-12702 (libxml2 2.12.0 issue building from src). (nono303) + - PCRE: . Fixed bug GH-12628 (The gh11374 test fails on Alpinelinux). (nielsdos) diff --git a/ext/dom/document.c b/ext/dom/document.c index 59f00897a69aa..8312d6c59399f 100644 --- a/ext/dom/document.c +++ b/ext/dom/document.c @@ -23,6 +23,7 @@ #if defined(HAVE_LIBXML) && defined(HAVE_DOM) #include "php_dom.h" #include +#include #ifdef LIBXML_SCHEMAS_ENABLED #include #include diff --git a/ext/libxml/php_libxml.h b/ext/libxml/php_libxml.h index af1cc7d6ac8c5..b484568bb1b0a 100644 --- a/ext/libxml/php_libxml.h +++ b/ext/libxml/php_libxml.h @@ -35,6 +35,7 @@ extern zend_module_entry libxml_module_entry; #include "zend_smart_str.h" #include +#include #define LIBXML_SAVE_NOEMPTYTAG 1<<2 From 3167d07603c2c76600a854163cd600b871c72df0 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Wed, 15 Nov 2023 21:15:02 +0100 Subject: [PATCH 31/92] Fix GH-12616: DOM: Removing XMLNS namespace node results in invalid default: prefix The namespace data is freed and set to NULL, but there remain references to the namespace declaration nodes. This (rightfully) confuses libxml2 because its invariants are broken. We also have to remove all remaining references from the subtree. This fixes the data corruption bug. Closes GH-12681. --- NEWS | 4 + ext/dom/element.c | 86 ++++++++++++++++++-- ext/dom/tests/gh12616_1.phpt | 36 +++++++++ ext/dom/tests/gh12616_2.phpt | 39 +++++++++ ext/dom/tests/gh12616_3.phpt | 152 +++++++++++++++++++++++++++++++++++ 5 files changed, 309 insertions(+), 8 deletions(-) create mode 100644 ext/dom/tests/gh12616_1.phpt create mode 100644 ext/dom/tests/gh12616_2.phpt create mode 100644 ext/dom/tests/gh12616_3.phpt diff --git a/NEWS b/NEWS index 247a124e51293..35bede4280638 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,10 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.2.14 +- DOM: + . Fixed bug GH-12616 (DOM: Removing XMLNS namespace node results in invalid + default: prefix). (nielsdos) + - Intl: . Fixed bug GH-12635 (Test bug69398.phpt fails with ICU 74.1). (nielsdos) diff --git a/ext/dom/element.c b/ext/dom/element.c index c630bec2b5007..f5733c5c48bf3 100644 --- a/ext/dom/element.c +++ b/ext/dom/element.c @@ -724,6 +724,83 @@ PHP_METHOD(DOMElement, setAttributeNS) } /* }}} end dom_element_set_attribute_ns */ +static void dom_remove_eliminated_ns_single_element(xmlNodePtr node, xmlNsPtr eliminatedNs) +{ + ZEND_ASSERT(node->type == XML_ELEMENT_NODE); + if (node->ns == eliminatedNs) { + node->ns = NULL; + } + + for (xmlAttrPtr attr = node->properties; attr != NULL; attr = attr->next) { + if (attr->ns == eliminatedNs) { + attr->ns = NULL; + } + } +} + +static void dom_remove_eliminated_ns(xmlNodePtr node, xmlNsPtr eliminatedNs) +{ + dom_remove_eliminated_ns_single_element(node, eliminatedNs); + + xmlNodePtr base = node; + node = node->children; + while (node != NULL) { + ZEND_ASSERT(node != base); + + if (node->type == XML_ELEMENT_NODE) { + dom_remove_eliminated_ns_single_element(node, eliminatedNs); + + if (node->children) { + node = node->children; + continue; + } + } + + if (node->next) { + node = node->next; + } else { + /* Go upwards, until we find a parent node with a next sibling, or until we hit the base. */ + do { + node = node->parent; + if (node == base) { + return; + } + } while (node->next == NULL); + node = node->next; + } + } +} + +static void dom_eliminate_ns(xmlNodePtr nodep, xmlNsPtr nsptr) +{ + if (nsptr->href != NULL) { + xmlFree((char *) nsptr->href); + nsptr->href = NULL; + } + if (nsptr->prefix != NULL) { + xmlFree((char *) nsptr->prefix); + nsptr->prefix = NULL; + } + + /* Remove it from the list and move it to the old ns list */ + xmlNsPtr current_ns = nodep->nsDef; + if (current_ns == nsptr) { + nodep->nsDef = nsptr->next; + } else { + do { + if (current_ns->next == nsptr) { + current_ns->next = nsptr->next; + break; + } + current_ns = current_ns->next; + } while (current_ns != NULL); + } + nsptr->next = NULL; + dom_set_old_ns(nodep->doc, nsptr); + + dom_remove_eliminated_ns(nodep, nsptr); +} + /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-ElRemAtNS Since: DOM Level 2 */ @@ -754,14 +831,7 @@ PHP_METHOD(DOMElement, removeAttributeNS) nsptr = dom_get_nsdecl(nodep, (xmlChar *)name); if (nsptr != NULL) { if (xmlStrEqual((xmlChar *)uri, nsptr->href)) { - if (nsptr->href != NULL) { - xmlFree((char *) nsptr->href); - nsptr->href = NULL; - } - if (nsptr->prefix != NULL) { - xmlFree((char *) nsptr->prefix); - nsptr->prefix = NULL; - } + dom_eliminate_ns(nodep, nsptr); } else { RETURN_NULL(); } diff --git a/ext/dom/tests/gh12616_1.phpt b/ext/dom/tests/gh12616_1.phpt new file mode 100644 index 0000000000000..408d871aee6f6 --- /dev/null +++ b/ext/dom/tests/gh12616_1.phpt @@ -0,0 +1,36 @@ +--TEST-- +GH-12616 (DOM: Removing XMLNS namespace node results in invalid default: prefix) +--EXTENSIONS-- +dom +--FILE-- +loadXML( + << + CHILDREN + + XML +); + +$doc->documentElement->removeAttributeNS('http://symfony.com/schema/dic/services', ''); +echo $doc->saveXML(); + +$new = new DOMDocument(); +$new->append( + $new->importNode($doc->documentElement, true) +); + +echo $new->saveXML(); + +?> +--EXPECT-- + + + CHILDREN + + + + CHILDREN + diff --git a/ext/dom/tests/gh12616_2.phpt b/ext/dom/tests/gh12616_2.phpt new file mode 100644 index 0000000000000..57138e4c45b3f --- /dev/null +++ b/ext/dom/tests/gh12616_2.phpt @@ -0,0 +1,39 @@ +--TEST-- +GH-12616 (DOM: Removing XMLNS namespace node results in invalid default: prefix) +--EXTENSIONS-- +dom +--FILE-- +loadXML( + << + + + + + XML +); + +$doc->documentElement->removeAttributeNS('http://symfony.com/schema/dic/services', 'symfony'); +$xpath = new DOMXPath($doc); +$xpath->registerNamespace('test', 'urn:test'); + +echo $doc->saveXML(); + +$result = $xpath->query('//container/services/test:service[@id="hello"]'); +var_dump($result); + +?> +--EXPECT-- + + + + + + +object(DOMNodeList)#4 (1) { + ["length"]=> + int(1) +} diff --git a/ext/dom/tests/gh12616_3.phpt b/ext/dom/tests/gh12616_3.phpt new file mode 100644 index 0000000000000..871a5e4607a30 --- /dev/null +++ b/ext/dom/tests/gh12616_3.phpt @@ -0,0 +1,152 @@ +--TEST-- +GH-12616 (DOM: Removing XMLNS namespace node results in invalid default: prefix) +--EXTENSIONS-- +dom +--FILE-- +loadXML( + << + + + + + + + + + + XML +); + +$doc->documentElement->firstElementChild->removeAttributeNS('http://symfony.com/schema/dic/services', 'x'); +echo $doc->saveXML(); + +$xpath = new DOMXPath($doc); + +echo "--- Namespaces of child1 ---\n"; + +foreach ($xpath->query("/container/child1/namespace::*") as $ns) { + var_dump($ns); +} + +echo "--- Namespaces of child1/foo (both nodes) ---\n"; + +foreach ($xpath->query("/container/child1/foo/namespace::*") as $ns) { + var_dump($ns); +} + +echo "--- Namespaces of child2 ---\n"; + +foreach ($xpath->query("/container/child2/namespace::*") as $ns) { + var_dump($ns); +} + +?> +--EXPECT-- + + + + + + + + + + + +--- Namespaces of child1 --- +object(DOMNameSpaceNode)#4 (8) { + ["nodeName"]=> + string(9) "xmlns:xml" + ["nodeValue"]=> + string(36) "http://www.w3.org/XML/1998/namespace" + ["nodeType"]=> + int(18) + ["prefix"]=> + string(3) "xml" + ["localName"]=> + string(3) "xml" + ["namespaceURI"]=> + string(36) "http://www.w3.org/XML/1998/namespace" + ["ownerDocument"]=> + string(22) "(object value omitted)" + ["parentNode"]=> + string(22) "(object value omitted)" +} +--- Namespaces of child1/foo (both nodes) --- +object(DOMNameSpaceNode)#5 (8) { + ["nodeName"]=> + string(9) "xmlns:xml" + ["nodeValue"]=> + string(36) "http://www.w3.org/XML/1998/namespace" + ["nodeType"]=> + int(18) + ["prefix"]=> + string(3) "xml" + ["localName"]=> + string(3) "xml" + ["namespaceURI"]=> + string(36) "http://www.w3.org/XML/1998/namespace" + ["ownerDocument"]=> + string(22) "(object value omitted)" + ["parentNode"]=> + string(22) "(object value omitted)" +} +object(DOMNameSpaceNode)#8 (8) { + ["nodeName"]=> + string(9) "xmlns:xml" + ["nodeValue"]=> + string(36) "http://www.w3.org/XML/1998/namespace" + ["nodeType"]=> + int(18) + ["prefix"]=> + string(3) "xml" + ["localName"]=> + string(3) "xml" + ["namespaceURI"]=> + string(36) "http://www.w3.org/XML/1998/namespace" + ["ownerDocument"]=> + string(22) "(object value omitted)" + ["parentNode"]=> + string(22) "(object value omitted)" +} +--- Namespaces of child2 --- +object(DOMNameSpaceNode)#9 (8) { + ["nodeName"]=> + string(9) "xmlns:xml" + ["nodeValue"]=> + string(36) "http://www.w3.org/XML/1998/namespace" + ["nodeType"]=> + int(18) + ["prefix"]=> + string(3) "xml" + ["localName"]=> + string(3) "xml" + ["namespaceURI"]=> + string(36) "http://www.w3.org/XML/1998/namespace" + ["ownerDocument"]=> + string(22) "(object value omitted)" + ["parentNode"]=> + string(22) "(object value omitted)" +} +object(DOMNameSpaceNode)#5 (8) { + ["nodeName"]=> + string(7) "xmlns:x" + ["nodeValue"]=> + string(38) "http://symfony.com/schema/dic/services" + ["nodeType"]=> + int(18) + ["prefix"]=> + string(1) "x" + ["localName"]=> + string(1) "x" + ["namespaceURI"]=> + string(38) "http://symfony.com/schema/dic/services" + ["ownerDocument"]=> + string(22) "(object value omitted)" + ["parentNode"]=> + string(22) "(object value omitted)" +} From f90b40416ffa731f19e8a9a9674ea4a8ab43fe5d Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Mon, 23 Oct 2023 13:51:03 +0100 Subject: [PATCH 32/92] Fix #50713: openssl_pkcs7_verify() may ignore untrusted CAs Closes GH-12499 --- NEWS | 4 ++ ext/openssl/openssl.c | 2 +- ext/openssl/tests/CertificateGenerator.inc | 82 +++++++++++----------- ext/openssl/tests/bug50713.phpt | 40 +++++++++++ 4 files changed, 87 insertions(+), 41 deletions(-) create mode 100644 ext/openssl/tests/bug50713.phpt diff --git a/NEWS b/NEWS index 35bede4280638..45805551eed2b 100644 --- a/NEWS +++ b/NEWS @@ -12,6 +12,10 @@ PHP NEWS - LibXML: . Fixed bug GH-12702 (libxml2 2.12.0 issue building from src). (nono303) +- OpenSSL: + . Fixed bug #50713 (openssl_pkcs7_verify() may ignore untrusted CAs). + (Jakub Zelenka) + - PCRE: . Fixed bug GH-12628 (The gh11374 test fails on Alpinelinux). (nielsdos) diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index 4fc22ef594f01..0f8adf013515c 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -5266,7 +5266,7 @@ PHP_FUNCTION(openssl_pkcs7_verify) signersfilename, signersfilename_len, 3, PHP_OPENSSL_BIO_MODE_W(PKCS7_BINARY)); if (certout) { int i; - signers = PKCS7_get0_signers(p7, NULL, (int)flags); + signers = PKCS7_get0_signers(p7, others, (int)flags); if (signers != NULL) { for (i = 0; i < sk_X509_num(signers); i++) { diff --git a/ext/openssl/tests/CertificateGenerator.inc b/ext/openssl/tests/CertificateGenerator.inc index c36718cd54844..12764c8b63d2c 100644 --- a/ext/openssl/tests/CertificateGenerator.inc +++ b/ext/openssl/tests/CertificateGenerator.inc @@ -85,8 +85,8 @@ class CertificateGenerator openssl_x509_export_to_file($this->ca, $file); } - public function saveNewCertAndKey( - $commonNameForCert, $certFile, $keyFile, $keyLength = null, $subjectAltName = null + private function generateCertAndKey( + $commonNameForCert, $file, $keyLength = null, $subjectAltName = null ) { $dn = [ 'countryName' => 'BY', @@ -117,51 +117,53 @@ $subjectAltNameConfig basicConstraints = CA:FALSE $subjectAltNameConfig CONFIG; - $configFile = $certFile . '.cnf'; + $configFile = $file . '.cnf'; file_put_contents($configFile, $configCode); - try { - $config = [ - 'config' => $configFile, - 'req_extensions' => 'v3_req', - 'x509_extensions' => 'usr_cert', - ]; - - $this->lastKey = self::generateKey($keyLength); - $csr = openssl_csr_new($dn, $this->lastKey, $config); - $this->lastCert = openssl_csr_sign( - $csr, - $this->ca, - $this->caKey, - /* days */ 2, - $config, - ); - if (!$this->lastCert) { - throw new Exception('Failed to create certificate'); - } - - $certText = ''; - openssl_x509_export($this->lastCert, $certText); - - $keyText = ''; - openssl_pkey_export($this->lastKey, $keyText, null, $config); - - if ($certFile === $keyFile) { - file_put_contents($certFile, $certText . PHP_EOL . $keyText); - } else { - file_put_contents($certFile, $certText); - file_put_contents($keyFile, $keyText); - } - } finally { - unlink($configFile); - } - } + $config = [ + 'config' => $configFile, + 'req_extensions' => 'v3_req', + 'x509_extensions' => 'usr_cert', + ]; + + $this->lastKey = self::generateKey($keyLength); + $csr = openssl_csr_new($dn, $this->lastKey, $config); + $this->lastCert = openssl_csr_sign( + $csr, + $this->ca, + $this->caKey, + /* days */ 2, + $config, + ); + return $config; + } public function saveNewCertAsFileWithKey( $commonNameForCert, $file, $keyLength = null, $subjectAltName = null ) { - $this->saveNewCertAndKey($commonNameForCert, $file, $file, $keyLength, $subjectAltName); + $config = $this->generateCertAndKey($commonNameForCert, $file, $keyLength, $subjectAltName); + + $certText = ''; + openssl_x509_export($this->lastCert, $certText); + + $keyText = ''; + openssl_pkey_export($this->lastKey, $keyText, null, $config); + + file_put_contents($file, $certText . PHP_EOL . $keyText); + + unlink($config['config']); + } + + public function saveNewCertAndKey( + $commonNameForCert, $certFile, $keyFile, $keyLength = null, $subjectAltName = null + ) { + $config = $this->generateCertAndKey($commonNameForCert, $certFile, $keyLength, $subjectAltName); + + openssl_x509_export_to_file($this->lastCert, $certFile); + openssl_pkey_export_to_file($this->lastKey, $keyFile, null, $config); + + unlink($config['config']); } public function getCertDigest($algo) diff --git a/ext/openssl/tests/bug50713.phpt b/ext/openssl/tests/bug50713.phpt new file mode 100644 index 0000000000000..95eff2e75f90a --- /dev/null +++ b/ext/openssl/tests/bug50713.phpt @@ -0,0 +1,40 @@ +--TEST-- +Bug #50713 (openssl_pkcs7_verify() may ignore untrusted CAs) +--EXTENSIONS-- +openssl +--FILE-- +saveCaCert($cacertFile); +$certificateGenerator->saveNewCertAndKey('bug50713', $certFile, $keyFile, 1024); + +var_dump(openssl_pkcs7_sign($inFile, $outFile, 'file://' . $certFile, 'file://' . $keyFile, [], PKCS7_NOCERTS)); +var_dump(openssl_pkcs7_verify($outFile, 0, $signersFile, [$cacertFile], $certFile)); +var_dump(strlen(file_get_contents($signersFile)) > 0); +?> +--CLEAN-- + +--EXPECT-- +bool(true) +bool(true) +bool(true) From 4d41dffb4f355872476bae561264c4796eef26b8 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 18 Nov 2023 23:50:53 +0100 Subject: [PATCH 33/92] Fix GH-12721: SplFileInfo::getFilename() segfault in combination with GlobIterator and no directory separator This broke in 7cd8879 and 9bae9ab. NULL is a perfectly valid return value that should be handled. Closes GH-12722. --- NEWS | 4 +++ ext/spl/spl_directory.c | 15 +++++++---- ext/spl/tests/gh12721.phpt | 51 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 5 deletions(-) create mode 100644 ext/spl/tests/gh12721.phpt diff --git a/NEWS b/NEWS index 45805551eed2b..3bf074b1e1b02 100644 --- a/NEWS +++ b/NEWS @@ -22,6 +22,10 @@ PHP NEWS - PHPDBG: . Fixed bug GH-12675 (MEMORY_LEAK in phpdbg_prompt.c). (nielsdos) +- SPL: + . Fixed bug GH-12721 (SplFileInfo::getFilename() segfault in combination + with GlobIterator and no directory separator). (nielsdos) + - SQLite3: . Fixed bug GH-12633 (sqlite3_defensive.phpt fails with sqlite 3.44.0). (SakiTakamachi) diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c index 0dcb34b6a6975..581183d38f49e 100644 --- a/ext/spl/spl_directory.c +++ b/ext/spl/spl_directory.c @@ -925,7 +925,6 @@ PHP_METHOD(SplFileInfo, getFilename) path = spl_filesystem_object_get_path(intern); - ZEND_ASSERT(path); if (path && ZSTR_LEN(path) && ZSTR_LEN(path) < ZSTR_LEN(intern->file_name)) { /* +1 to skip the trailing / of the path in the file name */ size_t path_len = ZSTR_LEN(path) + 1; @@ -933,7 +932,9 @@ PHP_METHOD(SplFileInfo, getFilename) } else { RETVAL_STR_COPY(intern->file_name); } - zend_string_release_ex(path, /* persistent */ false); + if (path) { + zend_string_release_ex(path, /* persistent */ false); + } } /* }}} */ @@ -973,14 +974,16 @@ PHP_METHOD(SplFileInfo, getExtension) path = spl_filesystem_object_get_path(intern); - if (ZSTR_LEN(path) && ZSTR_LEN(path) < ZSTR_LEN(intern->file_name)) { + if (path && ZSTR_LEN(path) && ZSTR_LEN(path) < ZSTR_LEN(intern->file_name)) { fname = ZSTR_VAL(intern->file_name) + ZSTR_LEN(path) + 1; flen = ZSTR_LEN(intern->file_name) - (ZSTR_LEN(path) + 1); } else { fname = ZSTR_VAL(intern->file_name); flen = ZSTR_LEN(intern->file_name); } - zend_string_release_ex(path, /* persistent */ false); + if (path) { + zend_string_release_ex(path, /* persistent */ false); + } ret = php_basename(fname, flen, NULL, 0); @@ -1052,7 +1055,9 @@ PHP_METHOD(SplFileInfo, getBasename) fname = ZSTR_VAL(intern->file_name); flen = ZSTR_LEN(intern->file_name); } - zend_string_release_ex(path, /* persistent */ false); + if (path) { + zend_string_release_ex(path, /* persistent */ false); + } RETURN_STR(php_basename(fname, flen, suffix, slen)); } diff --git a/ext/spl/tests/gh12721.phpt b/ext/spl/tests/gh12721.phpt new file mode 100644 index 0000000000000..4310afcdd933f --- /dev/null +++ b/ext/spl/tests/gh12721.phpt @@ -0,0 +1,51 @@ +--TEST-- +GH-12721 (SplFileInfo::getFilename() segfault in combination with GlobIterator and no directory separator) +--FILE-- +getFilename(), "\n"; + echo $fileInfo->getExtension(), "\n"; + echo $fileInfo->getBasename(), "\n"; + var_dump($fileInfo->getFileInfo()); +} + +echo "--- With slash ---\n"; + +foreach (new GlobIterator('./*.gh12721') as $fileInfo) { + echo $fileInfo->getFilename(), "\n"; + echo $fileInfo->getExtension(), "\n"; + echo $fileInfo->getBasename(), "\n"; + var_dump($fileInfo->getFileInfo()); +} + +?> +--CLEAN-- + +--EXPECTF-- +--- No slash --- +file1.gh12721 +gh12721 +file1.gh12721 +object(SplFileInfo)#4 (2) { + ["pathName":"SplFileInfo":private]=> + string(13) "file1.gh12721" + ["fileName":"SplFileInfo":private]=> + string(13) "file1.gh12721" +} +--- With slash --- +file1.gh12721 +gh12721 +file1.gh12721 +object(SplFileInfo)#3 (2) { + ["pathName":"SplFileInfo":private]=> + string(15) "%sfile1.gh12721" + ["fileName":"SplFileInfo":private]=> + string(13) "file1.gh12721" +} From ea52706a2a441db6e5dd024fe02fdaaa5de21b12 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Mon, 20 Nov 2023 11:56:06 +0100 Subject: [PATCH 34/92] Fix use-after-free of name in var-var with malicious error handler Fixes oss-fuzz #54325 Closes GH-12732 --- NEWS | 4 ++++ Zend/tests/oss_fuzz_54325.phpt | 19 +++++++++++++++++++ Zend/zend_vm_def.h | 7 +++++++ Zend/zend_vm_execute.h | 21 +++++++++++++++++++++ 4 files changed, 51 insertions(+) create mode 100644 Zend/tests/oss_fuzz_54325.phpt diff --git a/NEWS b/NEWS index 3bf074b1e1b02..5558c0661f451 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,10 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.2.14 +- Core: + . Fixed oss-fuzz #54325 (Use-after-free of name in var-var with malicious + error handler). (ilutov) + - DOM: . Fixed bug GH-12616 (DOM: Removing XMLNS namespace node results in invalid default: prefix). (nielsdos) diff --git a/Zend/tests/oss_fuzz_54325.phpt b/Zend/tests/oss_fuzz_54325.phpt new file mode 100644 index 0000000000000..d998acf1ffedb --- /dev/null +++ b/Zend/tests/oss_fuzz_54325.phpt @@ -0,0 +1,19 @@ +--TEST-- +oss-fuzz #54325: Fix use-after-free of name in var-var with malicious error handler +--FILE-- + +--EXPECT-- +string(23) "Undefined variable $oof" +object(stdClass)#2 (0) { +} diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 8ad2c6116d898..4ea88e56fa205 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -1748,6 +1748,10 @@ ZEND_VM_C_LABEL(fetch_this): } else if (type == BP_VAR_IS || type == BP_VAR_UNSET) { retval = &EG(uninitialized_zval); } else { + if (OP1_TYPE == IS_CV) { + /* Keep name alive in case an error handler tries to free it. */ + zend_string_addref(name); + } zend_error(E_WARNING, "Undefined %svariable $%s", (opline->extended_value & ZEND_FETCH_GLOBAL ? "global " : ""), ZSTR_VAL(name)); if (type == BP_VAR_RW && !EG(exception)) { @@ -1755,6 +1759,9 @@ ZEND_VM_C_LABEL(fetch_this): } else { retval = &EG(uninitialized_zval); } + if (OP1_TYPE == IS_CV) { + zend_string_release(name); + } } /* GLOBAL or $$name variable may be an INDIRECT pointer to CV */ } else if (Z_TYPE_P(retval) == IS_INDIRECT) { diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 22e9f5b62a8ae..447d43145c591 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -9859,6 +9859,10 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_ad } else if (type == BP_VAR_IS || type == BP_VAR_UNSET) { retval = &EG(uninitialized_zval); } else { + if (IS_CONST == IS_CV) { + /* Keep name alive in case an error handler tries to free it. */ + zend_string_addref(name); + } zend_error(E_WARNING, "Undefined %svariable $%s", (opline->extended_value & ZEND_FETCH_GLOBAL ? "global " : ""), ZSTR_VAL(name)); if (type == BP_VAR_RW && !EG(exception)) { @@ -9866,6 +9870,9 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_ad } else { retval = &EG(uninitialized_zval); } + if (IS_CONST == IS_CV) { + zend_string_release(name); + } } /* GLOBAL or $$name variable may be an INDIRECT pointer to CV */ } else if (Z_TYPE_P(retval) == IS_INDIRECT) { @@ -17667,6 +17674,10 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_ad } else if (type == BP_VAR_IS || type == BP_VAR_UNSET) { retval = &EG(uninitialized_zval); } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CV) { + /* Keep name alive in case an error handler tries to free it. */ + zend_string_addref(name); + } zend_error(E_WARNING, "Undefined %svariable $%s", (opline->extended_value & ZEND_FETCH_GLOBAL ? "global " : ""), ZSTR_VAL(name)); if (type == BP_VAR_RW && !EG(exception)) { @@ -17674,6 +17685,9 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_ad } else { retval = &EG(uninitialized_zval); } + if ((IS_TMP_VAR|IS_VAR) == IS_CV) { + zend_string_release(name); + } } /* GLOBAL or $$name variable may be an INDIRECT pointer to CV */ } else if (Z_TYPE_P(retval) == IS_INDIRECT) { @@ -47240,6 +47254,10 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_ad } else if (type == BP_VAR_IS || type == BP_VAR_UNSET) { retval = &EG(uninitialized_zval); } else { + if (IS_CV == IS_CV) { + /* Keep name alive in case an error handler tries to free it. */ + zend_string_addref(name); + } zend_error(E_WARNING, "Undefined %svariable $%s", (opline->extended_value & ZEND_FETCH_GLOBAL ? "global " : ""), ZSTR_VAL(name)); if (type == BP_VAR_RW && !EG(exception)) { @@ -47247,6 +47265,9 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_ad } else { retval = &EG(uninitialized_zval); } + if (IS_CV == IS_CV) { + zend_string_release(name); + } } /* GLOBAL or $$name variable may be an INDIRECT pointer to CV */ } else if (Z_TYPE_P(retval) == IS_INDIRECT) { From d8e866da04ec5883500332b3d31d5a684188463e Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Mon, 20 Nov 2023 12:37:32 +0100 Subject: [PATCH 35/92] Fix in-place modification of filename in php_message_handler_for_zend php_strip_url_passwd modifies url in-place. We cannot assume from php_message_handler_for_zend that data is a temporary, modifiable string. Fixes oss-fuzz #64209 Closes GH-12733 --- NEWS | 2 ++ Zend/tests/oss_fuzz_64209.phpt | 13 +++++++++++++ main/main.c | 21 +++++++++++++++------ 3 files changed, 30 insertions(+), 6 deletions(-) create mode 100644 Zend/tests/oss_fuzz_64209.phpt diff --git a/NEWS b/NEWS index 5558c0661f451..d2ed14804a5bf 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,8 @@ PHP NEWS - Core: . Fixed oss-fuzz #54325 (Use-after-free of name in var-var with malicious error handler). (ilutov) + . Fixed oss-fuzz #64209 (In-place modification of filename in + php_message_handler_for_zend). (ilutov) - DOM: . Fixed bug GH-12616 (DOM: Removing XMLNS namespace node results in invalid diff --git a/Zend/tests/oss_fuzz_64209.phpt b/Zend/tests/oss_fuzz_64209.phpt new file mode 100644 index 0000000000000..599ae258e5b2c --- /dev/null +++ b/Zend/tests/oss_fuzz_64209.phpt @@ -0,0 +1,13 @@ +--TEST-- +oss-fuzz #64209: Fix in-place modification of filename in php_message_handler_for_zend +--FILE-- + +--EXPECTF-- +Warning: require(://@): Failed to open stream: No such file or directory in %s on line %d + +Fatal error: Uncaught Error: Failed opening required '://@' (include_path='%s') in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/main/main.c b/main/main.c index 970d5f96c4c20..b2d03b4af8af4 100644 --- a/main/main.c +++ b/main/main.c @@ -1600,15 +1600,24 @@ static void php_free_request_globals(void) static ZEND_COLD void php_message_handler_for_zend(zend_long message, const void *data) { switch (message) { - case ZMSG_FAILED_INCLUDE_FOPEN: - php_error_docref("function.include", E_WARNING, "Failed opening '%s' for inclusion (include_path='%s')", php_strip_url_passwd((char *) data), STR_PRINT(PG(include_path))); + case ZMSG_FAILED_INCLUDE_FOPEN: { + char *tmp = estrdup((char *) data); + php_error_docref("function.include", E_WARNING, "Failed opening '%s' for inclusion (include_path='%s')", php_strip_url_passwd(tmp), STR_PRINT(PG(include_path))); + efree(tmp); break; - case ZMSG_FAILED_REQUIRE_FOPEN: - zend_throw_error(NULL, "Failed opening required '%s' (include_path='%s')", php_strip_url_passwd((char *) data), STR_PRINT(PG(include_path))); + } + case ZMSG_FAILED_REQUIRE_FOPEN: { + char *tmp = estrdup((char *) data); + zend_throw_error(NULL, "Failed opening required '%s' (include_path='%s')", php_strip_url_passwd(tmp), STR_PRINT(PG(include_path))); + efree(tmp); break; - case ZMSG_FAILED_HIGHLIGHT_FOPEN: - php_error_docref(NULL, E_WARNING, "Failed opening '%s' for highlighting", php_strip_url_passwd((char *) data)); + } + case ZMSG_FAILED_HIGHLIGHT_FOPEN: { + char *tmp = estrdup((char *) data); + php_error_docref(NULL, E_WARNING, "Failed opening '%s' for highlighting", php_strip_url_passwd(tmp)); + efree(tmp); break; + } case ZMSG_MEMORY_LEAK_DETECTED: case ZMSG_MEMORY_LEAK_REPEATED: #if ZEND_DEBUG From 6be4ba9f9008d5b6ac3f6012d1d37d42f05c1acf Mon Sep 17 00:00:00 2001 From: Muhammad Moinur Rahman Date: Sat, 18 Nov 2023 15:07:06 +0100 Subject: [PATCH 36/92] Add host_cpu type for FreeBSD In FreeBSD world x86_64 host type is identified as amd64 so add proper checks for FreeBSD amd64 hosts. Close GH-12736 --- ext/opcache/config.m4 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ext/opcache/config.m4 b/ext/opcache/config.m4 index 2a83fa2455974..0b923206282c4 100644 --- a/ext/opcache/config.m4 +++ b/ext/opcache/config.m4 @@ -29,7 +29,7 @@ if test "$PHP_OPCACHE" != "no"; then if test "$PHP_OPCACHE_JIT" = "yes"; then case $host_cpu in - i[[34567]]86*|x86*|aarch64) + i[[34567]]86*|x86*|aarch64|amd64) ;; *) AC_MSG_WARN([JIT not supported by host architecture]) @@ -48,7 +48,8 @@ if test "$PHP_OPCACHE" != "no"; then DASM_FLAGS="-D X64APPLE=1 -D X64=1" DASM_ARCH="x86" ;; - x86_64*) + *x86_64*|amd64-*-freebsd*) + IR_TARGET=IR_TARGET_X64 DASM_FLAGS="-D X64=1" DASM_ARCH="x86" ;; From 2d65d714a3bfbf7ebca8e958c417b356f99c6753 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 22 Nov 2023 13:19:10 +0300 Subject: [PATCH 37/92] Fixed GH-12748: Function JIT emits "could not convert to int" warning at the same time as invalid offset Error --- ext/opcache/jit/zend_jit_helpers.c | 3 ++- ext/opcache/tests/jit/gh12748.phpt | 35 ++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 ext/opcache/tests/jit/gh12748.phpt diff --git a/ext/opcache/jit/zend_jit_helpers.c b/ext/opcache/jit/zend_jit_helpers.c index 5a68e15588e36..95ff48dd4f9c1 100644 --- a/ext/opcache/jit/zend_jit_helpers.c +++ b/ext/opcache/jit/zend_jit_helpers.c @@ -1135,7 +1135,8 @@ static void ZEND_FASTCALL zend_jit_fetch_dim_str_is_helper(zend_string *str, zva goto try_string_offset; default: zend_jit_illegal_string_offset(dim); - break; + ZVAL_NULL(result); + return; } offset = zval_get_long_func(dim, /* is_strict */ false); diff --git a/ext/opcache/tests/jit/gh12748.phpt b/ext/opcache/tests/jit/gh12748.phpt new file mode 100644 index 0000000000000..d7580fdb9ab7c --- /dev/null +++ b/ext/opcache/tests/jit/gh12748.phpt @@ -0,0 +1,35 @@ +--TEST-- +GH-12748: Function JIT emits "could not convert to int" warning at the same time as invalid offset Error +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +--FILE-- +getMessage(), "\n"; +} +try { + echo "empty():\n"; + var_dump(empty($container[new stdClass()])); +} catch (\Throwable $e) { + echo $e->getMessage(), "\n"; +} +try { + echo "Coalesce():\n"; + var_dump($container[new stdClass()] ?? 'default'); +} catch (\Throwable $e) { + echo $e->getMessage(), "\n"; +} +?> +--EXPECT-- +isset(): +bool(false) +empty(): +bool(true) +Coalesce(): +Cannot access offset of type stdClass on string From 6641cd159ead068bfa3327668771b8292c87474e Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 11 Nov 2023 14:15:23 +0100 Subject: [PATCH 38/92] Fix GH-12635: Test bug69398.phpt fails with ICU 74.1 ICU 74.1 contains new locale data that breaks the test. Split the test based on the version number to resolve the issue. Closes GH-12653. --- NEWS | 3 +++ ext/intl/tests/bug69398-icu74.1.phpt | 19 +++++++++++++++++++ ext/intl/tests/bug69398.phpt | 5 ++++- 3 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 ext/intl/tests/bug69398-icu74.1.phpt diff --git a/NEWS b/NEWS index 5139f2c4f0213..2dda841f6574b 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.1.27 +- Intl: + . Fixed bug GH-12635 (Test bug69398.phpt fails with ICU 74.1). (nielsdos) + - PCRE: . Fixed bug GH-12628 (The gh11374 test fails on Alpinelinux). (nielsdos) diff --git a/ext/intl/tests/bug69398-icu74.1.phpt b/ext/intl/tests/bug69398-icu74.1.phpt new file mode 100644 index 0000000000000..cf8ce39d1e270 --- /dev/null +++ b/ext/intl/tests/bug69398-icu74.1.phpt @@ -0,0 +1,19 @@ +--TEST-- +IntlDateFormatter::formatObject(): returns wrong value when time style is NONE. +--EXTENSIONS-- +intl +--SKIPIF-- + +--FILE-- +setTime($millitimestamp); +echo IntlDateFormatter::formatObject($date, array(IntlDateFormatter::SHORT, IntlDateFormatter::NONE), 'vi_VN'), "\n"; +echo IntlDateFormatter::formatObject ($date, array(IntlDateFormatter::SHORT, IntlDateFormatter::NONE), 'ko_KR'), "\n"; +?> +--EXPECT-- +4/4/15 +15. 4. 4. diff --git a/ext/intl/tests/bug69398.phpt b/ext/intl/tests/bug69398.phpt index 02c4b7daeff9f..075dd5f4bd0c8 100644 --- a/ext/intl/tests/bug69398.phpt +++ b/ext/intl/tests/bug69398.phpt @@ -3,7 +3,10 @@ IntlDateFormatter::formatObject(): returns wrong value when time style is NONE. --EXTENSIONS-- intl --SKIPIF-- -= 51.1.2'); ?> += 0) die('skip for ICU >= 74.1'); +?> --FILE-- Date: Wed, 8 Nov 2023 20:06:18 +0100 Subject: [PATCH 39/92] Fix GH-12621: browscap segmentation fault when configured in the vhost The temporary HashTable has a destructor that releases the string held by the entry's value. However, browscap_intern_str(_ci) only incremented the refcount for the reference created by the return value. As the HashTable is only used during parsing, we don't need to manage the reference count of the value anyway, so get rid of the destructor. This is triggerable in two cases: - When using php_admin_value to set the ini at the activation stage - When running out of space for the opcache-interned strings Closes GH-12634. --- NEWS | 2 ++ ext/standard/browscap.c | 10 ++++---- sapi/fpm/tests/gh12621.phpt | 46 +++++++++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 6 deletions(-) create mode 100644 sapi/fpm/tests/gh12621.phpt diff --git a/NEWS b/NEWS index 2dda841f6574b..73fa39d796700 100644 --- a/NEWS +++ b/NEWS @@ -10,6 +10,8 @@ PHP NEWS - Standard: . Fix memory leak in syslog device handling. (danog) + . Fixed bug GH-12621 (browscap segmentation fault when configured in the + vhost). (nielsdos) - SQLite3: . Fixed bug GH-12633 (sqlite3_defensive.phpt fails with sqlite 3.44.0). diff --git a/ext/standard/browscap.c b/ext/standard/browscap.c index 53504098fb85a..222681915122d 100644 --- a/ext/standard/browscap.c +++ b/ext/standard/browscap.c @@ -228,7 +228,7 @@ static zend_string *browscap_intern_str( } else { interned = zend_string_copy(str); if (persistent) { - interned = zend_new_interned_string(str); + interned = zend_new_interned_string(interned); } zend_hash_add_new_ptr(&ctx->str_interned, interned, interned); } @@ -397,10 +397,6 @@ static void php_browscap_parser_cb(zval *arg1, zval *arg2, zval *arg3, int callb } /* }}} */ -static void str_interned_dtor(zval *zv) { - zend_string_release(Z_STR_P(zv)); -} - static int browscap_read_file(char *filename, browser_data *browdata, int persistent) /* {{{ */ { zend_file_handle fh; @@ -430,7 +426,9 @@ static int browscap_read_file(char *filename, browser_data *browdata, int persis ctx.bdata = browdata; ctx.current_entry = NULL; ctx.current_section_name = NULL; - zend_hash_init(&ctx.str_interned, 8, NULL, str_interned_dtor, persistent); + /* No dtor because we don't inc the refcount for the reference stored within the hash table's entry value + * as the hash table is only temporary anyway. */ + zend_hash_init(&ctx.str_interned, 8, NULL, NULL, persistent); zend_parse_ini_file(&fh, persistent, ZEND_INI_SCANNER_RAW, (zend_ini_parser_cb_t) php_browscap_parser_cb, &ctx); diff --git a/sapi/fpm/tests/gh12621.phpt b/sapi/fpm/tests/gh12621.phpt new file mode 100644 index 0000000000000..0ee64fbe415bd --- /dev/null +++ b/sapi/fpm/tests/gh12621.phpt @@ -0,0 +1,46 @@ +--TEST-- +GH-12621 (browscap segmentation fault when configured with php_admin_value) +--SKIPIF-- + +--FILE-- +browser_name_pattern; +var_dump(\$cv); +EOT; + +$tester = new FPM\Tester($cfg, $code); +$tester->start(); +$tester->expectLogStartNotices(); +echo $tester + ->request() + ->getBody(); +$tester->terminate(); +$tester->close(); + +?> +--EXPECT-- +string(14) "*Konqueror/2.*" +--CLEAN-- + From db8c91ae9fc871018b032dbd9695ae617e15a7de Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Fri, 10 Nov 2023 12:42:17 +0100 Subject: [PATCH 40/92] Fix undeclared variable in stat tests Closes GH-12645 --- ext/standard/tests/file/file.inc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/standard/tests/file/file.inc b/ext/standard/tests/file/file.inc index d4ad02a363bd5..0901069717a16 100644 --- a/ext/standard/tests/file/file.inc +++ b/ext/standard/tests/file/file.inc @@ -590,9 +590,9 @@ $all_stat_keys = array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, "rdev", "size", "atime", "mtime", "ctime", "blksize", "blocks"); -$stat_time_diff_keys = array(8, 'atime'); - function compare_stats($stat1, $stat2, $fields, $op = "==", $flag = false ) { + $stat_time_diff_keys = array(8, 'atime'); + // dump the stat if requested if ( $flag == true ) { var_dump($stat1); From f7f9401cc842824bccc3c79873d6e9f9dfe92997 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 9 Nov 2023 20:44:30 +0100 Subject: [PATCH 41/92] Disable -fsanitize=function on Clang 17 Closes GH-12642 --- configure.ac | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/configure.ac b/configure.ac index 0c5304b9e4822..91cb9e2fe4c34 100644 --- a/configure.ac +++ b/configure.ac @@ -1534,6 +1534,23 @@ if test "$PHP_UNDEFINED_SANITIZER" = "yes"; then AX_CHECK_COMPILE_FLAG([-fsanitize=undefined], [ CFLAGS="$CFLAGS -fsanitize=undefined" CXXFLAGS="$CXXFLAGS -fsanitize=undefined" + + dnl Clang 17 adds stricter function pointer compatibility checks where pointer args cannot be + dnl cast to void*. In that case, set -fno-sanitize=function. + OLD_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -fno-sanitize-recover=undefined" + AC_RUN_IFELSE([AC_LANG_SOURCE([[ +void foo(char *string) {} +int main(void) { + void (*f)(void *) = (void (*)(void *))foo; + f("foo"); +} + ]])],,[ubsan_needs_no_function=yes],) + CFLAGS="$OLD_CFLAGS" + if test "$ubsan_needs_no_function" = yes; then + CFLAGS="$CFLAGS -fno-sanitize=function" + CXXFLAGS="$CFLAGS -fno-sanitize=function" + fi ], [AC_MSG_ERROR([UndefinedBehaviorSanitizer is not available])]) fi From fe34dd1b494a43b33451ceb5e449148d1e62ac84 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Sun, 12 Nov 2023 14:06:02 +0100 Subject: [PATCH 42/92] Fix astat imperciseness excemption in test --- ext/standard/tests/file/file.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/standard/tests/file/file.inc b/ext/standard/tests/file/file.inc index 0901069717a16..c53c217e970ac 100644 --- a/ext/standard/tests/file/file.inc +++ b/ext/standard/tests/file/file.inc @@ -608,7 +608,7 @@ function compare_stats($stat1, $stat2, $fields, $op = "==", $flag = false ) { { case "==": if ( $stat1[ $fields[$index] ] != $stat2[ $fields[$index] ] ) { - if ( ! in_array( $index, $stat_time_diff_keys ) ) { + if ( ! in_array( $fields[$index], $stat_time_diff_keys ) ) { $result = false; echo "Error: stat1 do not match with stat2 at key value: $fields[$index]\n"; } elseif (abs($stat1[ $fields[$index] ] - $stat2[ $fields[$index] ]) > 1) { From c376f9943fd1146a8468b81c206e39cef07a9257 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 12 Nov 2023 18:43:35 +0100 Subject: [PATCH 43/92] Fix GH-12655: proc_open() does not take into account references in the descriptor array Closes GH-12658. --- NEWS | 2 ++ ext/standard/proc_open.c | 1 + .../tests/general_functions/gh12655.phpt | 22 +++++++++++++++++++ 3 files changed, 25 insertions(+) create mode 100644 ext/standard/tests/general_functions/gh12655.phpt diff --git a/NEWS b/NEWS index 73fa39d796700..33d604bc45779 100644 --- a/NEWS +++ b/NEWS @@ -12,6 +12,8 @@ PHP NEWS . Fix memory leak in syslog device handling. (danog) . Fixed bug GH-12621 (browscap segmentation fault when configured in the vhost). (nielsdos) + . Fixed bug GH-12655 (proc_open() does not take into account references + in the descriptor array). (nielsdos) - SQLite3: . Fixed bug GH-12633 (sqlite3_defensive.phpt fails with sqlite 3.44.0). diff --git a/ext/standard/proc_open.c b/ext/standard/proc_open.c index a57e66bd97954..3f8eaafd6d281 100644 --- a/ext/standard/proc_open.c +++ b/ext/standard/proc_open.c @@ -1096,6 +1096,7 @@ PHP_FUNCTION(proc_open) descriptors[ndesc].index = (int)nindex; + ZVAL_DEREF(descitem); if (Z_TYPE_P(descitem) == IS_RESOURCE) { if (set_proc_descriptor_from_resource(descitem, &descriptors[ndesc], ndesc) == FAILURE) { goto exit_fail; diff --git a/ext/standard/tests/general_functions/gh12655.phpt b/ext/standard/tests/general_functions/gh12655.phpt new file mode 100644 index 0000000000000..c0235ee6ae6fb --- /dev/null +++ b/ext/standard/tests/general_functions/gh12655.phpt @@ -0,0 +1,22 @@ +--TEST-- +GH-12655 (proc_open(): Argument #2 ($descriptor_spec) must only contain arrays and streams [Descriptor item must be either an array or a File-Handle]) +--FILE-- + [ "pipe", "r" ], // stdin is a pipe that the child will read from + 1 => [ "pipe", "w" ], // stdout is a pipe that the child will write to + 2 => [ "pipe", "w" ], // stderr is a file to write to +]; + +foreach ( $descriptor_spec as $fd => &$d ) +{ + // don't do anything, just the fact that we used "&$d" will sink the ship! +} + +$proc = proc_open(PHP_BINARY, $descriptor_spec, $pipes); +echo $proc === false ? "FAILED\n" : "SUCCEEDED\n"; + +?> +--EXPECT-- +SUCCEEDED From 28c312c9948cecf10670a0be245ee21d25e3417f Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Tue, 14 Nov 2023 18:36:07 +0100 Subject: [PATCH 44/92] [skip ci] Further increase allowable atime deviation MSAN is slow in particular, leading to potentially higher deviations. --- ext/standard/tests/file/file.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/standard/tests/file/file.inc b/ext/standard/tests/file/file.inc index c53c217e970ac..c972784f9da36 100644 --- a/ext/standard/tests/file/file.inc +++ b/ext/standard/tests/file/file.inc @@ -611,7 +611,7 @@ function compare_stats($stat1, $stat2, $fields, $op = "==", $flag = false ) { if ( ! in_array( $fields[$index], $stat_time_diff_keys ) ) { $result = false; echo "Error: stat1 do not match with stat2 at key value: $fields[$index]\n"; - } elseif (abs($stat1[ $fields[$index] ] - $stat2[ $fields[$index] ]) > 1) { + } elseif (abs($stat1[ $fields[$index] ] - $stat2[ $fields[$index] ]) > 2) { $result = false; echo "Error: stat1 differs too much from stat2 at key value: $fields[$index]\n"; } From 9bdd0f0de95d0db93b46af89042f3c9b4dfef972 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 9 Nov 2023 11:53:55 +0100 Subject: [PATCH 45/92] Automatically mark tests as flaky Marking all of these tests as flaky is annoying, so attempt to recognize them automatically. Closes GH-12638 --- run-tests.php | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/run-tests.php b/run-tests.php index 404fd3e457a6a..ad69de76b9a48 100755 --- a/run-tests.php +++ b/run-tests.php @@ -2873,10 +2873,30 @@ function run_test(string $php, $file, array $env): string return $restype[0] . 'ED'; } +function is_flaky(TestFile $test): bool +{ + if ($test->hasSection('FLAKY')) { + return true; + } + if (!$test->hasSection('FILE')) { + return false; + } + $file = $test->getSection('FILE'); + $flaky_functions = [ + 'disk_free_space', + 'hrtime', + 'microtime', + 'sleep', + 'usleep', + ]; + $regex = '(\b(' . implode('|', $flaky_functions) . ')\()i'; + return preg_match($regex, $file) === 1; +} + function error_may_be_retried(TestFile $test, string $output): bool { return preg_match('((timed out)|(connection refused)|(404: page not found)|(address already in use)|(mailbox already exists))i', $output) === 1 - || $test->hasSection('FLAKY'); + || is_flaky($test); } /** From df2af7ff6583aad069f24d647e08d226c8ce6dcb Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Wed, 15 Nov 2023 20:15:44 +0100 Subject: [PATCH 46/92] Fix GH-12675: MEMORY_LEAK in phpdbg_prompt.c Have to use file_put_contents() instead of --FILE-- because we have to actually load it using the exec command, *and* have to make multiple files, and note that we can only load files relative from the current directory, so we can't rely on files being in the sapi/phpdbg/tests folder. Closes GH-12680. --- NEWS | 3 +++ sapi/phpdbg/phpdbg_prompt.c | 2 ++ sapi/phpdbg/tests/gh12675.phpt | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 37 insertions(+) create mode 100644 sapi/phpdbg/tests/gh12675.phpt diff --git a/NEWS b/NEWS index 33d604bc45779..f8a9a54289f5e 100644 --- a/NEWS +++ b/NEWS @@ -8,6 +8,9 @@ PHP NEWS - PCRE: . Fixed bug GH-12628 (The gh11374 test fails on Alpinelinux). (nielsdos) +- PHPDBG: + . Fixed bug GH-12675 (MEMORY_LEAK in phpdbg_prompt.c). (nielsdos) + - Standard: . Fix memory leak in syslog device handling. (danog) . Fixed bug GH-12621 (browscap segmentation fault when configured in the diff --git a/sapi/phpdbg/phpdbg_prompt.c b/sapi/phpdbg/phpdbg_prompt.c index 4c50653ce66f9..8ca6d83c78c2b 100644 --- a/sapi/phpdbg/phpdbg_prompt.c +++ b/sapi/phpdbg/phpdbg_prompt.c @@ -408,6 +408,7 @@ PHPDBG_COMMAND(exec) /* {{{ */ if ((res_len != PHPDBG_G(exec_len)) || (memcmp(res, PHPDBG_G(exec), res_len) != SUCCESS)) { if (PHPDBG_G(in_execution)) { if (phpdbg_ask_user_permission("Do you really want to stop execution to set a new execution context?") == FAILURE) { + free(res); return FAILURE; } } @@ -441,6 +442,7 @@ PHPDBG_COMMAND(exec) /* {{{ */ phpdbg_compile(); } else { + free(res); phpdbg_notice("Execution context not changed"); } } else { diff --git a/sapi/phpdbg/tests/gh12675.phpt b/sapi/phpdbg/tests/gh12675.phpt new file mode 100644 index 0000000000000..167e68595df31 --- /dev/null +++ b/sapi/phpdbg/tests/gh12675.phpt @@ -0,0 +1,32 @@ +--TEST-- +GH-12675 (MEMORY_LEAK in phpdbg_prompt.c) +--INI-- +opcache.enable=0 +--PHPDBG-- +ev file_put_contents("gh12675_1.tmp", " 24 +prompt> 16 +prompt> [Cannot stat nonexistent.php, ensure the file exists] +prompt> [Set execution context: %sgh12675_1.tmp] +[Successful compilation of %sgh12675_1.tmp] +prompt> [Execution context not changed] +prompt> [Breakpoint #0 added at %sgh12675_1.tmp:2] +prompt> hi +[Breakpoint #0 at %sgh12675_1.tmp:2, hits: 1] +>00002: echo 2; +prompt> Do you really want to stop execution to set a new execution context? (type y or n): prompt> +--CLEAN-- + From 4f5ba054ba98d4c80cb98cfb40f44be3df9243f3 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Wed, 15 Nov 2023 20:27:02 +0100 Subject: [PATCH 47/92] Use __DIR__-relative path in tests Otherwise we can't run them from another directory, they'll fail instead. --- ext/exif/tests/bug78793.phpt | 2 +- ext/soap/tests/bug75306.phpt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ext/exif/tests/bug78793.phpt b/ext/exif/tests/bug78793.phpt index 93d728ff6d1cf..babbe927045d3 100644 --- a/ext/exif/tests/bug78793.phpt +++ b/ext/exif/tests/bug78793.phpt @@ -4,7 +4,7 @@ Bug #78793: Use-after-free in exif parsing under memory sanitizer exif --FILE-- WSDL_CACHE_NONE); // Need a warm-up for globals for ($i = 0; $i < 10; $i++) { - $client = new SoapClient("ext/soap/tests/test.wsdl", $options); + $client = new SoapClient(__DIR__ . "/test.wsdl", $options); } $usage = memory_get_usage(); for ($i = 0; $i < 10; $i++) { - $client = new SoapClient("ext/soap/tests/test.wsdl", $options); + $client = new SoapClient(__DIR__ . "/test.wsdl", $options); } $usage_delta = memory_get_usage() - $usage; var_dump($usage_delta); From e1e140f2f2db45f6ecc8bbe72b9408b61d763e04 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 16 Nov 2023 14:13:38 +0100 Subject: [PATCH 48/92] Fix file test race condition 005_variation2.phpt creates files with special names, and filesize_variation5.phpt checks for filesize of inexistent files with special names. Create the files in a separate directory to avoid these tests clashing. Closes GH-12692 --- ext/standard/tests/file/005_variation2.phpt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ext/standard/tests/file/005_variation2.phpt b/ext/standard/tests/file/005_variation2.phpt index 55d1d6666098c..270a6cfbdd84c 100644 --- a/ext/standard/tests/file/005_variation2.phpt +++ b/ext/standard/tests/file/005_variation2.phpt @@ -28,6 +28,11 @@ function stat_fn( $filename ) { echo "*** Testing fileattime(), filemtime(), filectime() & touch() : usage variations ***\n"; echo "\n*** testing touch ***\n"; + +$dir = __DIR__ . '/005_variation2'; +mkdir($dir); +chdir($dir); + $b = touch(false); $c = touch(''); $d = touch(' '); @@ -47,6 +52,7 @@ stat_fn('|'); var_dump(unlink(' ')); var_dump(unlink('|')); +rmdir($dir); echo "Done"; ?> From 231263749655591b6e91b693c372ec903c99bd4b Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 16 Nov 2023 14:35:37 +0100 Subject: [PATCH 49/92] Retry tests on deadlock Closes GH-12693 --- run-tests.php | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/run-tests.php b/run-tests.php index ad69de76b9a48..39621a39aa666 100755 --- a/run-tests.php +++ b/run-tests.php @@ -2893,9 +2893,23 @@ function is_flaky(TestFile $test): bool return preg_match($regex, $file) === 1; } +function is_flaky_output(string $output): bool +{ + $messages = [ + '404: page not found', + 'address already in use', + 'connection refused', + 'deadlock', + 'mailbox already exists', + 'timed out', + ]; + $regex = '(\b(' . implode('|', $messages) . ')\b)i'; + return preg_match($regex, $output) === 1; +} + function error_may_be_retried(TestFile $test, string $output): bool { - return preg_match('((timed out)|(connection refused)|(404: page not found)|(address already in use)|(mailbox already exists))i', $output) === 1 + return is_flaky_output($output) || is_flaky($test); } From 05ba4615241f247e4acda3cda693be605647e02e Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 16 Nov 2023 16:28:12 +0100 Subject: [PATCH 50/92] [skip ci] Fix more test tmp file conflicts --- ext/standard/tests/file/is_readable_basic.phpt | 2 +- ext/standard/tests/file/is_readable_error.phpt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/standard/tests/file/is_readable_basic.phpt b/ext/standard/tests/file/is_readable_basic.phpt index 7f1b85501a357..38d075439a3f2 100644 --- a/ext/standard/tests/file/is_readable_basic.phpt +++ b/ext/standard/tests/file/is_readable_basic.phpt @@ -15,7 +15,7 @@ require __DIR__.'/file.inc'; echo "*** Testing is_readable(): basic functionality ***\n"; // create a file -$filename = __DIR__."/is_readable.tmp"; +$filename = __DIR__."/is_readable_basic.tmp"; create_file($filename); $counter = 1; diff --git a/ext/standard/tests/file/is_readable_error.phpt b/ext/standard/tests/file/is_readable_error.phpt index 8df7ff92d526c..c013f7fbb7049 100644 --- a/ext/standard/tests/file/is_readable_error.phpt +++ b/ext/standard/tests/file/is_readable_error.phpt @@ -3,7 +3,7 @@ Test is_readable() function: error conditions --FILE-- From e41cbd2174c0331dd3214febbac99c0c0d7190ed Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Fri, 17 Nov 2023 10:54:23 +0000 Subject: [PATCH 51/92] Skip slow tests on Travis Closes GH-12697 --- travis/test.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/travis/test.sh b/travis/test.sh index 13f5c8bd7b53b..51e02dbab0c6c 100755 --- a/travis/test.sh +++ b/travis/test.sh @@ -4,6 +4,7 @@ set -ex # ARM64 CI reports nproc=32, which is excessive. if [ -z "$ARM64" ]; then export JOBS=$(nproc); else export JOBS=16; fi +export SKIP_SLOW_TESTS=1 export SKIP_IO_CAPTURE_TESTS=1 ./sapi/cli/php run-tests.php -P \ -g "FAIL,XFAIL,BORK,WARN,LEAK,SKIP" --offline --show-diff --show-slow 1000 \ From 0b754fc48c691e655cdaa954015a94f9fead8c6f Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Wed, 1 Mar 2023 02:19:29 +0100 Subject: [PATCH 52/92] Temporarily disable failing zlib tests on travis (#10738) --- ext/zlib/tests/gzcompress_basic1.phpt | 2 ++ ext/zlib/tests/gzdeflate_basic1.phpt | 2 ++ ext/zlib/tests/gzencode_basic1.phpt | 2 ++ 3 files changed, 6 insertions(+) diff --git a/ext/zlib/tests/gzcompress_basic1.phpt b/ext/zlib/tests/gzcompress_basic1.phpt index ec5f554153dab..b5ad22341ed74 100644 --- a/ext/zlib/tests/gzcompress_basic1.phpt +++ b/ext/zlib/tests/gzcompress_basic1.phpt @@ -2,6 +2,8 @@ Test gzcompress() function : basic functionality --EXTENSIONS-- zlib +--SKIPIF-- + --FILE-- --FILE-- --FILE-- Date: Thu, 16 Nov 2023 20:42:05 +0000 Subject: [PATCH 53/92] Fix bug #79945: Stream wrappers in imagecreatefrompng causes segfault Closes GH-12696 --- NEWS | 10 +++++++--- ext/gd/tests/bug79945.phpt | 22 ++++++++++++++++++++++ main/php_streams.h | 3 +++ main/streams/streams.c | 9 +++++++-- 4 files changed, 39 insertions(+), 5 deletions(-) create mode 100644 ext/gd/tests/bug79945.phpt diff --git a/NEWS b/NEWS index f8a9a54289f5e..8c2485d1a6549 100644 --- a/NEWS +++ b/NEWS @@ -11,6 +11,10 @@ PHP NEWS - PHPDBG: . Fixed bug GH-12675 (MEMORY_LEAK in phpdbg_prompt.c). (nielsdos) +- SQLite3: + . Fixed bug GH-12633 (sqlite3_defensive.phpt fails with sqlite 3.44.0). + (SakiTakamachi) + - Standard: . Fix memory leak in syslog device handling. (danog) . Fixed bug GH-12621 (browscap segmentation fault when configured in the @@ -18,9 +22,9 @@ PHP NEWS . Fixed bug GH-12655 (proc_open() does not take into account references in the descriptor array). (nielsdos) -- SQLite3: - . Fixed bug GH-12633 (sqlite3_defensive.phpt fails with sqlite 3.44.0). - (SakiTakamachi) +- Streams: + . Fixed bug #79945 (Stream wrappers in imagecreatefrompng causes segfault). + (Jakub Zelenka) - Zip: . Fixed bug GH-12661 (Inconsistency in ZipArchive::addGlob remove_path Option diff --git a/ext/gd/tests/bug79945.phpt b/ext/gd/tests/bug79945.phpt new file mode 100644 index 0000000000000..b985ddd48be31 --- /dev/null +++ b/ext/gd/tests/bug79945.phpt @@ -0,0 +1,22 @@ +--TEST-- +Bug #79945 (using php wrappers in imagecreatefrompng causes segmentation fault) +--EXTENSIONS-- +gd +--SKIPIF-- + +--FILE-- + +--CLEAN-- +--EXPECTF-- + +Warning: imagecreatefrompng(): "php://filter/read=convert.base64-encode/resource=%s" is not a valid PNG file in %s on line %d diff --git a/main/php_streams.h b/main/php_streams.h index ca8d9c034740f..c9a17f22dabdf 100644 --- a/main/php_streams.h +++ b/main/php_streams.h @@ -206,6 +206,9 @@ struct _php_stream { * PHP_STREAM_FCLOSE_XXX as appropriate */ uint8_t fclose_stdiocast:2; + /* whether stdio cast flushing is in progress */ + int8_t fclose_stdiocast_flush_in_progress:1; + char mode[16]; /* "rwb" etc. ala stdio */ uint32_t flags; /* PHP_STREAM_FLAG_XXX */ diff --git a/main/streams/streams.c b/main/streams/streams.c index 9359ed2fcccdd..634c0d5834880 100644 --- a/main/streams/streams.c +++ b/main/streams/streams.c @@ -1291,8 +1291,13 @@ PHPAPI zend_off_t _php_stream_tell(php_stream *stream) PHPAPI int _php_stream_seek(php_stream *stream, zend_off_t offset, int whence) { if (stream->fclose_stdiocast == PHP_STREAM_FCLOSE_FOPENCOOKIE) { - /* flush to commit data written to the fopencookie FILE* */ - fflush(stream->stdiocast); + /* flush can call seek internally so we need to prevent an infinite loop */ + if (!stream->fclose_stdiocast_flush_in_progress) { + stream->fclose_stdiocast_flush_in_progress = 1; + /* flush to commit data written to the fopencookie FILE* */ + fflush(stream->stdiocast); + stream->fclose_stdiocast_flush_in_progress = 0; + } } /* handle the case where we are in the buffer */ From e43ffb5023432091b38391d4034de0c8c213bf2d Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Fri, 17 Nov 2023 13:33:51 +0000 Subject: [PATCH 54/92] Fix stream fclose_stdiocast_flush_in_progress type --- main/php_streams.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/php_streams.h b/main/php_streams.h index c9a17f22dabdf..adf1f812736f0 100644 --- a/main/php_streams.h +++ b/main/php_streams.h @@ -207,7 +207,7 @@ struct _php_stream { uint8_t fclose_stdiocast:2; /* whether stdio cast flushing is in progress */ - int8_t fclose_stdiocast_flush_in_progress:1; + uint8_t fclose_stdiocast_flush_in_progress:1; char mode[16]; /* "rwb" etc. ala stdio */ From 6a76e5d0a2dcf46b4ab74cc3ffcbfeb860c4fdb3 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Fri, 17 Nov 2023 19:45:40 +0100 Subject: [PATCH 55/92] Fix GH-12702: libxml2 2.12.0 issue building from src Fixes GH-12702. Co-authored-by: nono303 --- NEWS | 3 +++ ext/dom/document.c | 1 + ext/libxml/php_libxml.h | 1 + 3 files changed, 5 insertions(+) diff --git a/NEWS b/NEWS index 8c2485d1a6549..60696c704feae 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,9 @@ PHP NEWS - Intl: . Fixed bug GH-12635 (Test bug69398.phpt fails with ICU 74.1). (nielsdos) +- LibXML: + . Fixed bug GH-12702 (libxml2 2.12.0 issue building from src). (nono303) + - PCRE: . Fixed bug GH-12628 (The gh11374 test fails on Alpinelinux). (nielsdos) diff --git a/ext/dom/document.c b/ext/dom/document.c index 59f00897a69aa..8312d6c59399f 100644 --- a/ext/dom/document.c +++ b/ext/dom/document.c @@ -23,6 +23,7 @@ #if defined(HAVE_LIBXML) && defined(HAVE_DOM) #include "php_dom.h" #include +#include #ifdef LIBXML_SCHEMAS_ENABLED #include #include diff --git a/ext/libxml/php_libxml.h b/ext/libxml/php_libxml.h index c0775a07f5dcc..a1011f0b17858 100644 --- a/ext/libxml/php_libxml.h +++ b/ext/libxml/php_libxml.h @@ -35,6 +35,7 @@ extern zend_module_entry libxml_module_entry; #include "zend_smart_str.h" #include +#include #define LIBXML_SAVE_NOEMPTYTAG 1<<2 From 243fa9c1431e03c23f6d681a89d35621c2e3a38f Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Wed, 15 Nov 2023 21:15:02 +0100 Subject: [PATCH 56/92] Fix GH-12616: DOM: Removing XMLNS namespace node results in invalid default: prefix The namespace data is freed and set to NULL, but there remain references to the namespace declaration nodes. This (rightfully) confuses libxml2 because its invariants are broken. We also have to remove all remaining references from the subtree. This fixes the data corruption bug. Closes GH-12681. --- NEWS | 4 + ext/dom/element.c | 86 ++++++++++++++++++-- ext/dom/tests/gh12616_1.phpt | 36 +++++++++ ext/dom/tests/gh12616_2.phpt | 39 +++++++++ ext/dom/tests/gh12616_3.phpt | 152 +++++++++++++++++++++++++++++++++++ 5 files changed, 309 insertions(+), 8 deletions(-) create mode 100644 ext/dom/tests/gh12616_1.phpt create mode 100644 ext/dom/tests/gh12616_2.phpt create mode 100644 ext/dom/tests/gh12616_3.phpt diff --git a/NEWS b/NEWS index 60696c704feae..32d4375d54595 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,10 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.1.27 +- DOM: + . Fixed bug GH-12616 (DOM: Removing XMLNS namespace node results in invalid + default: prefix). (nielsdos) + - Intl: . Fixed bug GH-12635 (Test bug69398.phpt fails with ICU 74.1). (nielsdos) diff --git a/ext/dom/element.c b/ext/dom/element.c index c630bec2b5007..f5733c5c48bf3 100644 --- a/ext/dom/element.c +++ b/ext/dom/element.c @@ -724,6 +724,83 @@ PHP_METHOD(DOMElement, setAttributeNS) } /* }}} end dom_element_set_attribute_ns */ +static void dom_remove_eliminated_ns_single_element(xmlNodePtr node, xmlNsPtr eliminatedNs) +{ + ZEND_ASSERT(node->type == XML_ELEMENT_NODE); + if (node->ns == eliminatedNs) { + node->ns = NULL; + } + + for (xmlAttrPtr attr = node->properties; attr != NULL; attr = attr->next) { + if (attr->ns == eliminatedNs) { + attr->ns = NULL; + } + } +} + +static void dom_remove_eliminated_ns(xmlNodePtr node, xmlNsPtr eliminatedNs) +{ + dom_remove_eliminated_ns_single_element(node, eliminatedNs); + + xmlNodePtr base = node; + node = node->children; + while (node != NULL) { + ZEND_ASSERT(node != base); + + if (node->type == XML_ELEMENT_NODE) { + dom_remove_eliminated_ns_single_element(node, eliminatedNs); + + if (node->children) { + node = node->children; + continue; + } + } + + if (node->next) { + node = node->next; + } else { + /* Go upwards, until we find a parent node with a next sibling, or until we hit the base. */ + do { + node = node->parent; + if (node == base) { + return; + } + } while (node->next == NULL); + node = node->next; + } + } +} + +static void dom_eliminate_ns(xmlNodePtr nodep, xmlNsPtr nsptr) +{ + if (nsptr->href != NULL) { + xmlFree((char *) nsptr->href); + nsptr->href = NULL; + } + if (nsptr->prefix != NULL) { + xmlFree((char *) nsptr->prefix); + nsptr->prefix = NULL; + } + + /* Remove it from the list and move it to the old ns list */ + xmlNsPtr current_ns = nodep->nsDef; + if (current_ns == nsptr) { + nodep->nsDef = nsptr->next; + } else { + do { + if (current_ns->next == nsptr) { + current_ns->next = nsptr->next; + break; + } + current_ns = current_ns->next; + } while (current_ns != NULL); + } + nsptr->next = NULL; + dom_set_old_ns(nodep->doc, nsptr); + + dom_remove_eliminated_ns(nodep, nsptr); +} + /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-ElRemAtNS Since: DOM Level 2 */ @@ -754,14 +831,7 @@ PHP_METHOD(DOMElement, removeAttributeNS) nsptr = dom_get_nsdecl(nodep, (xmlChar *)name); if (nsptr != NULL) { if (xmlStrEqual((xmlChar *)uri, nsptr->href)) { - if (nsptr->href != NULL) { - xmlFree((char *) nsptr->href); - nsptr->href = NULL; - } - if (nsptr->prefix != NULL) { - xmlFree((char *) nsptr->prefix); - nsptr->prefix = NULL; - } + dom_eliminate_ns(nodep, nsptr); } else { RETURN_NULL(); } diff --git a/ext/dom/tests/gh12616_1.phpt b/ext/dom/tests/gh12616_1.phpt new file mode 100644 index 0000000000000..408d871aee6f6 --- /dev/null +++ b/ext/dom/tests/gh12616_1.phpt @@ -0,0 +1,36 @@ +--TEST-- +GH-12616 (DOM: Removing XMLNS namespace node results in invalid default: prefix) +--EXTENSIONS-- +dom +--FILE-- +loadXML( + << + CHILDREN + + XML +); + +$doc->documentElement->removeAttributeNS('http://symfony.com/schema/dic/services', ''); +echo $doc->saveXML(); + +$new = new DOMDocument(); +$new->append( + $new->importNode($doc->documentElement, true) +); + +echo $new->saveXML(); + +?> +--EXPECT-- + + + CHILDREN + + + + CHILDREN + diff --git a/ext/dom/tests/gh12616_2.phpt b/ext/dom/tests/gh12616_2.phpt new file mode 100644 index 0000000000000..57138e4c45b3f --- /dev/null +++ b/ext/dom/tests/gh12616_2.phpt @@ -0,0 +1,39 @@ +--TEST-- +GH-12616 (DOM: Removing XMLNS namespace node results in invalid default: prefix) +--EXTENSIONS-- +dom +--FILE-- +loadXML( + << + + + + + XML +); + +$doc->documentElement->removeAttributeNS('http://symfony.com/schema/dic/services', 'symfony'); +$xpath = new DOMXPath($doc); +$xpath->registerNamespace('test', 'urn:test'); + +echo $doc->saveXML(); + +$result = $xpath->query('//container/services/test:service[@id="hello"]'); +var_dump($result); + +?> +--EXPECT-- + + + + + + +object(DOMNodeList)#4 (1) { + ["length"]=> + int(1) +} diff --git a/ext/dom/tests/gh12616_3.phpt b/ext/dom/tests/gh12616_3.phpt new file mode 100644 index 0000000000000..871a5e4607a30 --- /dev/null +++ b/ext/dom/tests/gh12616_3.phpt @@ -0,0 +1,152 @@ +--TEST-- +GH-12616 (DOM: Removing XMLNS namespace node results in invalid default: prefix) +--EXTENSIONS-- +dom +--FILE-- +loadXML( + << + + + + + + + + + + XML +); + +$doc->documentElement->firstElementChild->removeAttributeNS('http://symfony.com/schema/dic/services', 'x'); +echo $doc->saveXML(); + +$xpath = new DOMXPath($doc); + +echo "--- Namespaces of child1 ---\n"; + +foreach ($xpath->query("/container/child1/namespace::*") as $ns) { + var_dump($ns); +} + +echo "--- Namespaces of child1/foo (both nodes) ---\n"; + +foreach ($xpath->query("/container/child1/foo/namespace::*") as $ns) { + var_dump($ns); +} + +echo "--- Namespaces of child2 ---\n"; + +foreach ($xpath->query("/container/child2/namespace::*") as $ns) { + var_dump($ns); +} + +?> +--EXPECT-- + + + + + + + + + + + +--- Namespaces of child1 --- +object(DOMNameSpaceNode)#4 (8) { + ["nodeName"]=> + string(9) "xmlns:xml" + ["nodeValue"]=> + string(36) "http://www.w3.org/XML/1998/namespace" + ["nodeType"]=> + int(18) + ["prefix"]=> + string(3) "xml" + ["localName"]=> + string(3) "xml" + ["namespaceURI"]=> + string(36) "http://www.w3.org/XML/1998/namespace" + ["ownerDocument"]=> + string(22) "(object value omitted)" + ["parentNode"]=> + string(22) "(object value omitted)" +} +--- Namespaces of child1/foo (both nodes) --- +object(DOMNameSpaceNode)#5 (8) { + ["nodeName"]=> + string(9) "xmlns:xml" + ["nodeValue"]=> + string(36) "http://www.w3.org/XML/1998/namespace" + ["nodeType"]=> + int(18) + ["prefix"]=> + string(3) "xml" + ["localName"]=> + string(3) "xml" + ["namespaceURI"]=> + string(36) "http://www.w3.org/XML/1998/namespace" + ["ownerDocument"]=> + string(22) "(object value omitted)" + ["parentNode"]=> + string(22) "(object value omitted)" +} +object(DOMNameSpaceNode)#8 (8) { + ["nodeName"]=> + string(9) "xmlns:xml" + ["nodeValue"]=> + string(36) "http://www.w3.org/XML/1998/namespace" + ["nodeType"]=> + int(18) + ["prefix"]=> + string(3) "xml" + ["localName"]=> + string(3) "xml" + ["namespaceURI"]=> + string(36) "http://www.w3.org/XML/1998/namespace" + ["ownerDocument"]=> + string(22) "(object value omitted)" + ["parentNode"]=> + string(22) "(object value omitted)" +} +--- Namespaces of child2 --- +object(DOMNameSpaceNode)#9 (8) { + ["nodeName"]=> + string(9) "xmlns:xml" + ["nodeValue"]=> + string(36) "http://www.w3.org/XML/1998/namespace" + ["nodeType"]=> + int(18) + ["prefix"]=> + string(3) "xml" + ["localName"]=> + string(3) "xml" + ["namespaceURI"]=> + string(36) "http://www.w3.org/XML/1998/namespace" + ["ownerDocument"]=> + string(22) "(object value omitted)" + ["parentNode"]=> + string(22) "(object value omitted)" +} +object(DOMNameSpaceNode)#5 (8) { + ["nodeName"]=> + string(7) "xmlns:x" + ["nodeValue"]=> + string(38) "http://symfony.com/schema/dic/services" + ["nodeType"]=> + int(18) + ["prefix"]=> + string(1) "x" + ["localName"]=> + string(1) "x" + ["namespaceURI"]=> + string(38) "http://symfony.com/schema/dic/services" + ["ownerDocument"]=> + string(22) "(object value omitted)" + ["parentNode"]=> + string(22) "(object value omitted)" +} From 2b4a47ccec5e2feea8f04b2d5607d57a5d4a4520 Mon Sep 17 00:00:00 2001 From: Ben Ramsey Date: Wed, 22 Nov 2023 20:25:29 -0600 Subject: [PATCH 57/92] Merge changes to CertificateGenerator.inc from PHP-8.2 This pulls only the changes made to CertificateGenerator.inc in the PHP-8.2 branch from commit 505e8d2a04b258d9982e8994e14f5e75be5e1cf8. Co-authored-by: Jakub Zelenka --- ext/openssl/tests/CertificateGenerator.inc | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/ext/openssl/tests/CertificateGenerator.inc b/ext/openssl/tests/CertificateGenerator.inc index 4783353a4709c..c36718cd54844 100644 --- a/ext/openssl/tests/CertificateGenerator.inc +++ b/ext/openssl/tests/CertificateGenerator.inc @@ -85,8 +85,8 @@ class CertificateGenerator openssl_x509_export_to_file($this->ca, $file); } - public function saveNewCertAsFileWithKey( - $commonNameForCert, $file, $keyLength = null, $subjectAltName = null + public function saveNewCertAndKey( + $commonNameForCert, $certFile, $keyFile, $keyLength = null, $subjectAltName = null ) { $dn = [ 'countryName' => 'BY', @@ -117,7 +117,7 @@ $subjectAltNameConfig basicConstraints = CA:FALSE $subjectAltNameConfig CONFIG; - $configFile = $file . '.cnf'; + $configFile = $certFile . '.cnf'; file_put_contents($configFile, $configCode); try { @@ -146,12 +146,24 @@ CONFIG; $keyText = ''; openssl_pkey_export($this->lastKey, $keyText, null, $config); - file_put_contents($file, $certText . PHP_EOL . $keyText); + if ($certFile === $keyFile) { + file_put_contents($certFile, $certText . PHP_EOL . $keyText); + } else { + file_put_contents($certFile, $certText); + file_put_contents($keyFile, $keyText); + } } finally { unlink($configFile); } } + + public function saveNewCertAsFileWithKey( + $commonNameForCert, $file, $keyLength = null, $subjectAltName = null + ) { + $this->saveNewCertAndKey($commonNameForCert, $file, $file, $keyLength, $subjectAltName); + } + public function getCertDigest($algo) { return openssl_x509_fingerprint($this->lastCert, $algo); From 55e0748487f99e8bb60b8c4fd4f6e9c3857c8cf3 Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Mon, 23 Oct 2023 13:51:03 +0100 Subject: [PATCH 58/92] Fix #50713: openssl_pkcs7_verify() may ignore untrusted CAs Closes GH-12499 --- NEWS | 4 ++ ext/openssl/openssl.c | 2 +- ext/openssl/tests/CertificateGenerator.inc | 82 +++++++++++----------- ext/openssl/tests/bug50713.phpt | 40 +++++++++++ 4 files changed, 87 insertions(+), 41 deletions(-) create mode 100644 ext/openssl/tests/bug50713.phpt diff --git a/NEWS b/NEWS index 32d4375d54595..d79d0e4fe225d 100644 --- a/NEWS +++ b/NEWS @@ -12,6 +12,10 @@ PHP NEWS - LibXML: . Fixed bug GH-12702 (libxml2 2.12.0 issue building from src). (nono303) +- OpenSSL: + . Fixed bug #50713 (openssl_pkcs7_verify() may ignore untrusted CAs). + (Jakub Zelenka) + - PCRE: . Fixed bug GH-12628 (The gh11374 test fails on Alpinelinux). (nielsdos) diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index 31baa2d0e0250..a6a05fe03db50 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -5382,7 +5382,7 @@ PHP_FUNCTION(openssl_pkcs7_verify) signersfilename, signersfilename_len, 3, PHP_OPENSSL_BIO_MODE_W(PKCS7_BINARY)); if (certout) { int i; - signers = PKCS7_get0_signers(p7, NULL, (int)flags); + signers = PKCS7_get0_signers(p7, others, (int)flags); if (signers != NULL) { for (i = 0; i < sk_X509_num(signers); i++) { diff --git a/ext/openssl/tests/CertificateGenerator.inc b/ext/openssl/tests/CertificateGenerator.inc index c36718cd54844..12764c8b63d2c 100644 --- a/ext/openssl/tests/CertificateGenerator.inc +++ b/ext/openssl/tests/CertificateGenerator.inc @@ -85,8 +85,8 @@ class CertificateGenerator openssl_x509_export_to_file($this->ca, $file); } - public function saveNewCertAndKey( - $commonNameForCert, $certFile, $keyFile, $keyLength = null, $subjectAltName = null + private function generateCertAndKey( + $commonNameForCert, $file, $keyLength = null, $subjectAltName = null ) { $dn = [ 'countryName' => 'BY', @@ -117,51 +117,53 @@ $subjectAltNameConfig basicConstraints = CA:FALSE $subjectAltNameConfig CONFIG; - $configFile = $certFile . '.cnf'; + $configFile = $file . '.cnf'; file_put_contents($configFile, $configCode); - try { - $config = [ - 'config' => $configFile, - 'req_extensions' => 'v3_req', - 'x509_extensions' => 'usr_cert', - ]; - - $this->lastKey = self::generateKey($keyLength); - $csr = openssl_csr_new($dn, $this->lastKey, $config); - $this->lastCert = openssl_csr_sign( - $csr, - $this->ca, - $this->caKey, - /* days */ 2, - $config, - ); - if (!$this->lastCert) { - throw new Exception('Failed to create certificate'); - } - - $certText = ''; - openssl_x509_export($this->lastCert, $certText); - - $keyText = ''; - openssl_pkey_export($this->lastKey, $keyText, null, $config); - - if ($certFile === $keyFile) { - file_put_contents($certFile, $certText . PHP_EOL . $keyText); - } else { - file_put_contents($certFile, $certText); - file_put_contents($keyFile, $keyText); - } - } finally { - unlink($configFile); - } - } + $config = [ + 'config' => $configFile, + 'req_extensions' => 'v3_req', + 'x509_extensions' => 'usr_cert', + ]; + + $this->lastKey = self::generateKey($keyLength); + $csr = openssl_csr_new($dn, $this->lastKey, $config); + $this->lastCert = openssl_csr_sign( + $csr, + $this->ca, + $this->caKey, + /* days */ 2, + $config, + ); + return $config; + } public function saveNewCertAsFileWithKey( $commonNameForCert, $file, $keyLength = null, $subjectAltName = null ) { - $this->saveNewCertAndKey($commonNameForCert, $file, $file, $keyLength, $subjectAltName); + $config = $this->generateCertAndKey($commonNameForCert, $file, $keyLength, $subjectAltName); + + $certText = ''; + openssl_x509_export($this->lastCert, $certText); + + $keyText = ''; + openssl_pkey_export($this->lastKey, $keyText, null, $config); + + file_put_contents($file, $certText . PHP_EOL . $keyText); + + unlink($config['config']); + } + + public function saveNewCertAndKey( + $commonNameForCert, $certFile, $keyFile, $keyLength = null, $subjectAltName = null + ) { + $config = $this->generateCertAndKey($commonNameForCert, $certFile, $keyLength, $subjectAltName); + + openssl_x509_export_to_file($this->lastCert, $certFile); + openssl_pkey_export_to_file($this->lastKey, $keyFile, null, $config); + + unlink($config['config']); } public function getCertDigest($algo) diff --git a/ext/openssl/tests/bug50713.phpt b/ext/openssl/tests/bug50713.phpt new file mode 100644 index 0000000000000..95eff2e75f90a --- /dev/null +++ b/ext/openssl/tests/bug50713.phpt @@ -0,0 +1,40 @@ +--TEST-- +Bug #50713 (openssl_pkcs7_verify() may ignore untrusted CAs) +--EXTENSIONS-- +openssl +--FILE-- +saveCaCert($cacertFile); +$certificateGenerator->saveNewCertAndKey('bug50713', $certFile, $keyFile, 1024); + +var_dump(openssl_pkcs7_sign($inFile, $outFile, 'file://' . $certFile, 'file://' . $keyFile, [], PKCS7_NOCERTS)); +var_dump(openssl_pkcs7_verify($outFile, 0, $signersFile, [$cacertFile], $certFile)); +var_dump(strlen(file_get_contents($signersFile)) > 0); +?> +--CLEAN-- + +--EXPECT-- +bool(true) +bool(true) +bool(true) From 1fdcfa4ebe842531f2b403d45a92012c83125ba1 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Mon, 20 Nov 2023 11:56:06 +0100 Subject: [PATCH 59/92] Fix use-after-free of name in var-var with malicious error handler Fixes oss-fuzz #54325 Closes GH-12732 --- NEWS | 4 ++++ Zend/tests/oss_fuzz_54325.phpt | 19 +++++++++++++++++++ Zend/zend_vm_def.h | 7 +++++++ Zend/zend_vm_execute.h | 21 +++++++++++++++++++++ 4 files changed, 51 insertions(+) create mode 100644 Zend/tests/oss_fuzz_54325.phpt diff --git a/NEWS b/NEWS index d79d0e4fe225d..92b6027c4fdfb 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,10 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.1.27 +- Core: + . Fixed oss-fuzz #54325 (Use-after-free of name in var-var with malicious + error handler). (ilutov) + - DOM: . Fixed bug GH-12616 (DOM: Removing XMLNS namespace node results in invalid default: prefix). (nielsdos) diff --git a/Zend/tests/oss_fuzz_54325.phpt b/Zend/tests/oss_fuzz_54325.phpt new file mode 100644 index 0000000000000..d998acf1ffedb --- /dev/null +++ b/Zend/tests/oss_fuzz_54325.phpt @@ -0,0 +1,19 @@ +--TEST-- +oss-fuzz #54325: Fix use-after-free of name in var-var with malicious error handler +--FILE-- + +--EXPECT-- +string(23) "Undefined variable $oof" +object(stdClass)#2 (0) { +} diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 90704993bb253..fd5b7242ba645 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -1748,6 +1748,10 @@ ZEND_VM_C_LABEL(fetch_this): } else if (type == BP_VAR_IS || type == BP_VAR_UNSET) { retval = &EG(uninitialized_zval); } else { + if (OP1_TYPE == IS_CV) { + /* Keep name alive in case an error handler tries to free it. */ + zend_string_addref(name); + } zend_error(E_WARNING, "Undefined %svariable $%s", (opline->extended_value & ZEND_FETCH_GLOBAL ? "global " : ""), ZSTR_VAL(name)); if (type == BP_VAR_RW && !EG(exception)) { @@ -1755,6 +1759,9 @@ ZEND_VM_C_LABEL(fetch_this): } else { retval = &EG(uninitialized_zval); } + if (OP1_TYPE == IS_CV) { + zend_string_release(name); + } } /* GLOBAL or $$name variable may be an INDIRECT pointer to CV */ } else if (Z_TYPE_P(retval) == IS_INDIRECT) { diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 530fd7d3e117c..bc098148541fb 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -9755,6 +9755,10 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_ad } else if (type == BP_VAR_IS || type == BP_VAR_UNSET) { retval = &EG(uninitialized_zval); } else { + if (IS_CONST == IS_CV) { + /* Keep name alive in case an error handler tries to free it. */ + zend_string_addref(name); + } zend_error(E_WARNING, "Undefined %svariable $%s", (opline->extended_value & ZEND_FETCH_GLOBAL ? "global " : ""), ZSTR_VAL(name)); if (type == BP_VAR_RW && !EG(exception)) { @@ -9762,6 +9766,9 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_ad } else { retval = &EG(uninitialized_zval); } + if (IS_CONST == IS_CV) { + zend_string_release(name); + } } /* GLOBAL or $$name variable may be an INDIRECT pointer to CV */ } else if (Z_TYPE_P(retval) == IS_INDIRECT) { @@ -17560,6 +17567,10 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_ad } else if (type == BP_VAR_IS || type == BP_VAR_UNSET) { retval = &EG(uninitialized_zval); } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CV) { + /* Keep name alive in case an error handler tries to free it. */ + zend_string_addref(name); + } zend_error(E_WARNING, "Undefined %svariable $%s", (opline->extended_value & ZEND_FETCH_GLOBAL ? "global " : ""), ZSTR_VAL(name)); if (type == BP_VAR_RW && !EG(exception)) { @@ -17567,6 +17578,9 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_ad } else { retval = &EG(uninitialized_zval); } + if ((IS_TMP_VAR|IS_VAR) == IS_CV) { + zend_string_release(name); + } } /* GLOBAL or $$name variable may be an INDIRECT pointer to CV */ } else if (Z_TYPE_P(retval) == IS_INDIRECT) { @@ -47008,6 +47022,10 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_ad } else if (type == BP_VAR_IS || type == BP_VAR_UNSET) { retval = &EG(uninitialized_zval); } else { + if (IS_CV == IS_CV) { + /* Keep name alive in case an error handler tries to free it. */ + zend_string_addref(name); + } zend_error(E_WARNING, "Undefined %svariable $%s", (opline->extended_value & ZEND_FETCH_GLOBAL ? "global " : ""), ZSTR_VAL(name)); if (type == BP_VAR_RW && !EG(exception)) { @@ -47015,6 +47033,9 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_ad } else { retval = &EG(uninitialized_zval); } + if (IS_CV == IS_CV) { + zend_string_release(name); + } } /* GLOBAL or $$name variable may be an INDIRECT pointer to CV */ } else if (Z_TYPE_P(retval) == IS_INDIRECT) { From daa38dd63e6837ec7e3ecdecf7e7be7b13628f16 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Mon, 20 Nov 2023 12:37:32 +0100 Subject: [PATCH 60/92] Fix in-place modification of filename in php_message_handler_for_zend php_strip_url_passwd modifies url in-place. We cannot assume from php_message_handler_for_zend that data is a temporary, modifiable string. Fixes oss-fuzz #64209 Closes GH-12733 --- NEWS | 2 ++ Zend/tests/oss_fuzz_64209.phpt | 13 +++++++++++++ main/main.c | 21 +++++++++++++++------ 3 files changed, 30 insertions(+), 6 deletions(-) create mode 100644 Zend/tests/oss_fuzz_64209.phpt diff --git a/NEWS b/NEWS index 92b6027c4fdfb..b8d860bd3d9ad 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,8 @@ PHP NEWS - Core: . Fixed oss-fuzz #54325 (Use-after-free of name in var-var with malicious error handler). (ilutov) + . Fixed oss-fuzz #64209 (In-place modification of filename in + php_message_handler_for_zend). (ilutov) - DOM: . Fixed bug GH-12616 (DOM: Removing XMLNS namespace node results in invalid diff --git a/Zend/tests/oss_fuzz_64209.phpt b/Zend/tests/oss_fuzz_64209.phpt new file mode 100644 index 0000000000000..599ae258e5b2c --- /dev/null +++ b/Zend/tests/oss_fuzz_64209.phpt @@ -0,0 +1,13 @@ +--TEST-- +oss-fuzz #64209: Fix in-place modification of filename in php_message_handler_for_zend +--FILE-- + +--EXPECTF-- +Warning: require(://@): Failed to open stream: No such file or directory in %s on line %d + +Fatal error: Uncaught Error: Failed opening required '://@' (include_path='%s') in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/main/main.c b/main/main.c index 4868d2df40039..9c62aa914eb00 100644 --- a/main/main.c +++ b/main/main.c @@ -1585,15 +1585,24 @@ static void php_free_request_globals(void) static ZEND_COLD void php_message_handler_for_zend(zend_long message, const void *data) { switch (message) { - case ZMSG_FAILED_INCLUDE_FOPEN: - php_error_docref("function.include", E_WARNING, "Failed opening '%s' for inclusion (include_path='%s')", php_strip_url_passwd((char *) data), STR_PRINT(PG(include_path))); + case ZMSG_FAILED_INCLUDE_FOPEN: { + char *tmp = estrdup((char *) data); + php_error_docref("function.include", E_WARNING, "Failed opening '%s' for inclusion (include_path='%s')", php_strip_url_passwd(tmp), STR_PRINT(PG(include_path))); + efree(tmp); break; - case ZMSG_FAILED_REQUIRE_FOPEN: - zend_throw_error(NULL, "Failed opening required '%s' (include_path='%s')", php_strip_url_passwd((char *) data), STR_PRINT(PG(include_path))); + } + case ZMSG_FAILED_REQUIRE_FOPEN: { + char *tmp = estrdup((char *) data); + zend_throw_error(NULL, "Failed opening required '%s' (include_path='%s')", php_strip_url_passwd(tmp), STR_PRINT(PG(include_path))); + efree(tmp); break; - case ZMSG_FAILED_HIGHLIGHT_FOPEN: - php_error_docref(NULL, E_WARNING, "Failed opening '%s' for highlighting", php_strip_url_passwd((char *) data)); + } + case ZMSG_FAILED_HIGHLIGHT_FOPEN: { + char *tmp = estrdup((char *) data); + php_error_docref(NULL, E_WARNING, "Failed opening '%s' for highlighting", php_strip_url_passwd(tmp)); + efree(tmp); break; + } case ZMSG_MEMORY_LEAK_DETECTED: case ZMSG_MEMORY_LEAK_REPEATED: #if ZEND_DEBUG From fafa34d9cdfe5bd5f4a8ba58b63ae40434468d85 Mon Sep 17 00:00:00 2001 From: Muhammad Moinur Rahman Date: Sat, 18 Nov 2023 15:07:06 +0100 Subject: [PATCH 61/92] Add host_cpu type for FreeBSD In FreeBSD world x86_64 host type is identified as amd64 so add proper checks for FreeBSD amd64 hosts. Close GH-12736 --- ext/opcache/config.m4 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ext/opcache/config.m4 b/ext/opcache/config.m4 index 2a83fa2455974..0b923206282c4 100644 --- a/ext/opcache/config.m4 +++ b/ext/opcache/config.m4 @@ -29,7 +29,7 @@ if test "$PHP_OPCACHE" != "no"; then if test "$PHP_OPCACHE_JIT" = "yes"; then case $host_cpu in - i[[34567]]86*|x86*|aarch64) + i[[34567]]86*|x86*|aarch64|amd64) ;; *) AC_MSG_WARN([JIT not supported by host architecture]) @@ -48,7 +48,8 @@ if test "$PHP_OPCACHE" != "no"; then DASM_FLAGS="-D X64APPLE=1 -D X64=1" DASM_ARCH="x86" ;; - x86_64*) + *x86_64*|amd64-*-freebsd*) + IR_TARGET=IR_TARGET_X64 DASM_FLAGS="-D X64=1" DASM_ARCH="x86" ;; From 87107f86884d9e717a4f2caee84c0f540abddc1a Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 22 Nov 2023 13:19:10 +0300 Subject: [PATCH 62/92] Fixed GH-12748: Function JIT emits "could not convert to int" warning at the same time as invalid offset Error --- ext/opcache/jit/zend_jit_helpers.c | 3 ++- ext/opcache/tests/jit/gh12748.phpt | 35 ++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 ext/opcache/tests/jit/gh12748.phpt diff --git a/ext/opcache/jit/zend_jit_helpers.c b/ext/opcache/jit/zend_jit_helpers.c index fc52986ea197e..de40449e4095e 100644 --- a/ext/opcache/jit/zend_jit_helpers.c +++ b/ext/opcache/jit/zend_jit_helpers.c @@ -1135,7 +1135,8 @@ static void ZEND_FASTCALL zend_jit_fetch_dim_str_is_helper(zend_string *str, zva goto try_string_offset; default: zend_jit_illegal_string_offset(dim); - break; + ZVAL_NULL(result); + return; } offset = zval_get_long_func(dim, /* is_strict */ false); diff --git a/ext/opcache/tests/jit/gh12748.phpt b/ext/opcache/tests/jit/gh12748.phpt new file mode 100644 index 0000000000000..d7580fdb9ab7c --- /dev/null +++ b/ext/opcache/tests/jit/gh12748.phpt @@ -0,0 +1,35 @@ +--TEST-- +GH-12748: Function JIT emits "could not convert to int" warning at the same time as invalid offset Error +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +--FILE-- +getMessage(), "\n"; +} +try { + echo "empty():\n"; + var_dump(empty($container[new stdClass()])); +} catch (\Throwable $e) { + echo $e->getMessage(), "\n"; +} +try { + echo "Coalesce():\n"; + var_dump($container[new stdClass()] ?? 'default'); +} catch (\Throwable $e) { + echo $e->getMessage(), "\n"; +} +?> +--EXPECT-- +isset(): +bool(false) +empty(): +bool(true) +Coalesce(): +Cannot access offset of type stdClass on string From 28dabaab2f57d05d87ff3935f562c63f1026c2f5 Mon Sep 17 00:00:00 2001 From: Derick Rethans Date: Thu, 23 Nov 2023 16:06:00 +0000 Subject: [PATCH 63/92] Import timelib 2022.10 --- ext/date/lib/parse_date.c | 233 +++++++++++++++++++------------------ ext/date/lib/parse_date.re | 25 ++-- ext/date/lib/timelib.c | 24 ++-- ext/date/lib/timelib.h | 6 +- 4 files changed, 159 insertions(+), 129 deletions(-) diff --git a/ext/date/lib/parse_date.c b/ext/date/lib/parse_date.c index 0b19c4fa4e993..a53fdc215472c 100644 --- a/ext/date/lib/parse_date.c +++ b/ext/date/lib/parse_date.c @@ -1,4 +1,4 @@ -/* Generated by re2c 1.0.3 on Thu Aug 3 09:42:12 2023 */ +/* Generated by re2c 1.0.3 on Thu Nov 23 16:02:28 2023 */ #line 1 "ext/date/lib/parse_date.re" /* * The MIT License (MIT) @@ -713,6 +713,17 @@ static const timelib_relunit* timelib_lookup_relunit(const char **ptr) return value; } +static void add_with_overflow(Scanner *s, timelib_sll *e, timelib_sll amount, int multiplier) +{ +#if defined(__has_builtin) && __has_builtin(__builtin_saddll_overflow) + if (__builtin_saddll_overflow(*e, amount * multiplier, e)) { + add_error(s, TIMELIB_ERR_NUMBER_OUT_OF_RANGE, "Number out of range"); + } +#else + *e += (amount * multiplier); +#endif +} + /** * The time_part parameter is a flag. It can be TIMELIB_TIME_PART_KEEP in case * the time portion should not be reset to midnight, or @@ -728,13 +739,13 @@ static void timelib_set_relative(const char **ptr, timelib_sll amount, int behav } switch (relunit->unit) { - case TIMELIB_MICROSEC: s->time->relative.us += amount * relunit->multiplier; break; - case TIMELIB_SECOND: s->time->relative.s += amount * relunit->multiplier; break; - case TIMELIB_MINUTE: s->time->relative.i += amount * relunit->multiplier; break; - case TIMELIB_HOUR: s->time->relative.h += amount * relunit->multiplier; break; - case TIMELIB_DAY: s->time->relative.d += amount * relunit->multiplier; break; - case TIMELIB_MONTH: s->time->relative.m += amount * relunit->multiplier; break; - case TIMELIB_YEAR: s->time->relative.y += amount * relunit->multiplier; break; + case TIMELIB_MICROSEC: add_with_overflow(s, &s->time->relative.us, amount, relunit->multiplier); break; + case TIMELIB_SECOND: add_with_overflow(s, &s->time->relative.s, amount, relunit->multiplier); break; + case TIMELIB_MINUTE: add_with_overflow(s, &s->time->relative.i, amount, relunit->multiplier); break; + case TIMELIB_HOUR: add_with_overflow(s, &s->time->relative.h, amount, relunit->multiplier); break; + case TIMELIB_DAY: add_with_overflow(s, &s->time->relative.d, amount, relunit->multiplier); break; + case TIMELIB_MONTH: add_with_overflow(s, &s->time->relative.m, amount, relunit->multiplier); break; + case TIMELIB_YEAR: add_with_overflow(s, &s->time->relative.y, amount, relunit->multiplier); break; case TIMELIB_WEEKDAY: TIMELIB_HAVE_WEEKDAY_RELATIVE(); @@ -1003,11 +1014,11 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) std: s->tok = cursor; s->len = 0; -#line 1136 "ext/date/lib/parse_date.re" +#line 1147 "ext/date/lib/parse_date.re" -#line 1011 "" +#line 1022 "" { YYCTYPE yych; unsigned int yyaccept = 0; @@ -1188,23 +1199,23 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) YYDEBUG(2, *YYCURSOR); ++YYCURSOR; YYDEBUG(3, *YYCURSOR); -#line 1969 "ext/date/lib/parse_date.re" +#line 1980 "ext/date/lib/parse_date.re" { s->pos = cursor; s->line++; goto std; } -#line 1197 "" +#line 1208 "" yy4: YYDEBUG(4, *YYCURSOR); ++YYCURSOR; yy5: YYDEBUG(5, *YYCURSOR); -#line 1975 "ext/date/lib/parse_date.re" +#line 1986 "ext/date/lib/parse_date.re" { add_error(s, TIMELIB_ERR_UNEXPECTED_CHARACTER, "Unexpected character"); goto std; } -#line 1208 "" +#line 1219 "" yy6: YYDEBUG(6, *YYCURSOR); yyaccept = 0; @@ -1219,11 +1230,11 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) if (yych <= '9') goto yy58; yy8: YYDEBUG(8, *YYCURSOR); -#line 1964 "ext/date/lib/parse_date.re" +#line 1975 "ext/date/lib/parse_date.re" { goto std; } -#line 1227 "" +#line 1238 "" yy9: YYDEBUG(9, *YYCURSOR); yych = *++YYCURSOR; @@ -1257,11 +1268,11 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) YYDEBUG(11, *YYCURSOR); ++YYCURSOR; YYDEBUG(12, *YYCURSOR); -#line 1959 "ext/date/lib/parse_date.re" +#line 1970 "ext/date/lib/parse_date.re" { goto std; } -#line 1265 "" +#line 1276 "" yy13: YYDEBUG(13, *YYCURSOR); yyaccept = 1; @@ -1762,7 +1773,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy20: YYDEBUG(20, *YYCURSOR); -#line 1874 "ext/date/lib/parse_date.re" +#line 1885 "ext/date/lib/parse_date.re" { int tz_not_found; DEBUG_OUTPUT("tzcorrection | tz"); @@ -1776,7 +1787,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_TIMEZONE; } -#line 1780 "" +#line 1791 "" yy21: YYDEBUG(21, *YYCURSOR); yych = *++YYCURSOR; @@ -3581,7 +3592,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy81: YYDEBUG(81, *YYCURSOR); -#line 1621 "ext/date/lib/parse_date.re" +#line 1632 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("datenoyearrev"); TIMELIB_INIT; @@ -3592,7 +3603,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_DATE_TEXT; } -#line 3596 "" +#line 3607 "" yy82: YYDEBUG(82, *YYCURSOR); yych = *++YYCURSOR; @@ -4107,7 +4118,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } if (yych == '.') goto yy289; YYDEBUG(114, *YYCURSOR); -#line 1196 "ext/date/lib/parse_date.re" +#line 1207 "ext/date/lib/parse_date.re" { timelib_ull i; @@ -4132,7 +4143,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 4136 "" +#line 4147 "" yy115: YYDEBUG(115, *YYCURSOR); ++YYCURSOR; @@ -5858,7 +5869,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy177: YYDEBUG(177, *YYCURSOR); -#line 1362 "ext/date/lib/parse_date.re" +#line 1373 "ext/date/lib/parse_date.re" { int tz_not_found; DEBUG_OUTPUT("timetiny24 | timeshort24 | timelong24 | iso8601long"); @@ -5885,7 +5896,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_TIME24_WITH_ZONE; } -#line 5889 "" +#line 5900 "" yy178: YYDEBUG(178, *YYCURSOR); yyaccept = 4; @@ -6914,7 +6925,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy224: YYDEBUG(224, *YYCURSOR); -#line 1456 "ext/date/lib/parse_date.re" +#line 1467 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("americanshort | american"); @@ -6929,7 +6940,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_AMERICAN; } -#line 6933 "" +#line 6944 "" yy225: YYDEBUG(225, *YYCURSOR); yyaccept = 5; @@ -7172,7 +7183,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) if (yych <= '9') goto yy431; yy251: YYDEBUG(251, *YYCURSOR); -#line 1538 "ext/date/lib/parse_date.re" +#line 1549 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("datefull"); @@ -7186,7 +7197,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_DATE_FULL; } -#line 7190 "" +#line 7201 "" yy252: YYDEBUG(252, *YYCURSOR); yyaccept = 3; @@ -7300,7 +7311,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) if (yych == 'e') goto yy440; yy260: YYDEBUG(260, *YYCURSOR); -#line 1943 "ext/date/lib/parse_date.re" +#line 1954 "ext/date/lib/parse_date.re" { timelib_ull i; DEBUG_OUTPUT("relative"); @@ -7315,7 +7326,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 7319 "" +#line 7330 "" yy261: YYDEBUG(261, *YYCURSOR); yych = *++YYCURSOR; @@ -7761,7 +7772,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) if (yych <= '9') goto yy471; yy290: YYDEBUG(290, *YYCURSOR); -#line 1222 "ext/date/lib/parse_date.re" +#line 1233 "ext/date/lib/parse_date.re" { timelib_sll i; timelib_ull us; @@ -7800,7 +7811,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 7804 "" +#line 7815 "" yy291: YYDEBUG(291, *YYCURSOR); yych = *++YYCURSOR; @@ -7825,7 +7836,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy293: YYDEBUG(293, *YYCURSOR); -#line 1784 "ext/date/lib/parse_date.re" +#line 1795 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("ago"); TIMELIB_INIT; @@ -7845,7 +7856,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_AGO; } -#line 7849 "" +#line 7860 "" yy294: YYDEBUG(294, *YYCURSOR); yyaccept = 7; @@ -7884,7 +7895,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy295: YYDEBUG(295, *YYCURSOR); -#line 1864 "ext/date/lib/parse_date.re" +#line 1875 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("monthtext"); TIMELIB_INIT; @@ -7893,7 +7904,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_DATE_TEXT; } -#line 7897 "" +#line 7908 "" yy296: YYDEBUG(296, *YYCURSOR); yyaccept = 7; @@ -8468,7 +8479,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy315: YYDEBUG(315, *YYCURSOR); -#line 1805 "ext/date/lib/parse_date.re" +#line 1816 "ext/date/lib/parse_date.re" { const timelib_relunit* relunit; DEBUG_OUTPUT("daytext"); @@ -8485,7 +8496,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_WEEKDAY; } -#line 8489 "" +#line 8500 "" yy316: YYDEBUG(316, *YYCURSOR); yych = *++YYCURSOR; @@ -8753,7 +8764,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy325: YYDEBUG(325, *YYCURSOR); -#line 1607 "ext/date/lib/parse_date.re" +#line 1618 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("datetextual | datenoyear"); @@ -8766,7 +8777,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_DATE_TEXT; } -#line 8770 "" +#line 8781 "" yy326: YYDEBUG(326, *YYCURSOR); yyaccept = 10; @@ -9460,7 +9471,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy351: YYDEBUG(351, *YYCURSOR); -#line 1153 "ext/date/lib/parse_date.re" +#line 1164 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("now"); TIMELIB_INIT; @@ -9468,7 +9479,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 9472 "" +#line 9483 "" yy352: YYDEBUG(352, *YYCURSOR); yyaccept = 2; @@ -10971,7 +10982,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy420: YYDEBUG(420, *YYCURSOR); -#line 1390 "ext/date/lib/parse_date.re" +#line 1401 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("gnunocolon"); TIMELIB_INIT; @@ -10993,7 +11004,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_GNU_NOCOLON; } -#line 10997 "" +#line 11008 "" yy421: YYDEBUG(421, *YYCURSOR); yyaccept = 13; @@ -11074,7 +11085,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy422: YYDEBUG(422, *YYCURSOR); -#line 1775 "ext/date/lib/parse_date.re" +#line 1786 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("year4"); TIMELIB_INIT; @@ -11082,7 +11093,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_CLF; } -#line 11086 "" +#line 11097 "" yy423: YYDEBUG(423, *YYCURSOR); yyaccept = 3; @@ -11689,7 +11700,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) YYDEBUG(456, *YYCURSOR); ++YYCURSOR; YYDEBUG(457, *YYCURSOR); -#line 1324 "ext/date/lib/parse_date.re" +#line 1335 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("timetiny12 | timeshort12 | timelong12"); TIMELIB_INIT; @@ -11706,7 +11717,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_TIME12; } -#line 11710 "" +#line 11721 "" yy458: YYDEBUG(458, *YYCURSOR); yych = *++YYCURSOR; @@ -13033,7 +13044,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy526: YYDEBUG(526, *YYCURSOR); -#line 1162 "ext/date/lib/parse_date.re" +#line 1173 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("noon"); TIMELIB_INIT; @@ -13044,7 +13055,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 13048 "" +#line 13059 "" yy527: YYDEBUG(527, *YYCURSOR); yyaccept = 2; @@ -14090,7 +14101,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy567: YYDEBUG(567, *YYCURSOR); -#line 1524 "ext/date/lib/parse_date.re" +#line 1535 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("gnudateshort"); @@ -14103,7 +14114,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_ISO_DATE; } -#line 14107 "" +#line 14118 "" yy568: YYDEBUG(568, *YYCURSOR); yyaccept = 15; @@ -14554,7 +14565,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy600: YYDEBUG(600, *YYCURSOR); -#line 1593 "ext/date/lib/parse_date.re" +#line 1604 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("datenodayrev"); @@ -14567,7 +14578,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_DATE_NO_DAY; } -#line 14571 "" +#line 14582 "" yy601: YYDEBUG(601, *YYCURSOR); yych = *++YYCURSOR; @@ -15942,7 +15953,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) YYDEBUG(696, *YYCURSOR); ++YYCURSOR; YYDEBUG(697, *YYCURSOR); -#line 1579 "ext/date/lib/parse_date.re" +#line 1590 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("datenoday"); @@ -15955,7 +15966,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_DATE_NO_DAY; } -#line 15959 "" +#line 15970 "" yy698: YYDEBUG(698, *YYCURSOR); yych = *++YYCURSOR; @@ -16516,7 +16527,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy722: YYDEBUG(722, *YYCURSOR); -#line 1174 "ext/date/lib/parse_date.re" +#line 1185 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("midnight | today"); TIMELIB_INIT; @@ -16525,7 +16536,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 16529 "" +#line 16540 "" yy723: YYDEBUG(723, *YYCURSOR); yych = *++YYCURSOR; @@ -16835,7 +16846,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) if (yych <= '9') goto yy897; yy739: YYDEBUG(739, *YYCURSOR); -#line 1565 "ext/date/lib/parse_date.re" +#line 1576 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("pointed date YY"); @@ -16848,7 +16859,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_DATE_FULL_POINTED; } -#line 16852 "" +#line 16863 "" yy740: YYDEBUG(740, *YYCURSOR); yyaccept = 15; @@ -16960,7 +16971,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy752: YYDEBUG(752, *YYCURSOR); -#line 1510 "ext/date/lib/parse_date.re" +#line 1521 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("gnudateshorter"); @@ -16973,7 +16984,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_ISO_DATE; } -#line 16977 "" +#line 16988 "" yy753: YYDEBUG(753, *YYCURSOR); yyaccept = 18; @@ -17222,7 +17233,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy777: YYDEBUG(777, *YYCURSOR); -#line 1436 "ext/date/lib/parse_date.re" +#line 1447 "ext/date/lib/parse_date.re" { int tz_not_found; DEBUG_OUTPUT("iso8601nocolon"); @@ -17241,7 +17252,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_ISO_NOCOLON; } -#line 17245 "" +#line 17256 "" yy778: YYDEBUG(778, *YYCURSOR); yyaccept = 19; @@ -18469,7 +18480,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy849: YYDEBUG(849, *YYCURSOR); -#line 1913 "ext/date/lib/parse_date.re" +#line 1924 "ext/date/lib/parse_date.re" { int tz_not_found; DEBUG_OUTPUT("dateshortwithtimeshort | dateshortwithtimelong | dateshortwithtimelongtz"); @@ -18498,7 +18509,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_SHORTDATE_WITH_TIME; } -#line 18502 "" +#line 18513 "" yy850: YYDEBUG(850, *YYCURSOR); yyaccept = 20; @@ -19542,7 +19553,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy926: YYDEBUG(926, *YYCURSOR); -#line 1671 "ext/date/lib/parse_date.re" +#line 1682 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("pgydotd"); @@ -19555,7 +19566,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_PG_YEARDAY; } -#line 19559 "" +#line 19570 "" yy927: YYDEBUG(927, *YYCURSOR); yyaccept = 21; @@ -19809,7 +19820,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) if (yych <= '7') goto yy1059; yy942: YYDEBUG(942, *YYCURSOR); -#line 1704 "ext/date/lib/parse_date.re" +#line 1715 "ext/date/lib/parse_date.re" { timelib_sll w, d; DEBUG_OUTPUT("isoweek"); @@ -19827,7 +19838,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_ISO_WEEK; } -#line 19831 "" +#line 19842 "" yy943: YYDEBUG(943, *YYCURSOR); yych = *++YYCURSOR; @@ -20303,7 +20314,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) if (yych == 'e') goto yy1094; yy982: YYDEBUG(982, *YYCURSOR); -#line 1847 "ext/date/lib/parse_date.re" +#line 1858 "ext/date/lib/parse_date.re" { timelib_sll i; int behavior = 0; @@ -20319,7 +20330,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 20323 "" +#line 20334 "" yy983: YYDEBUG(983, *YYCURSOR); yych = *++YYCURSOR; @@ -20666,7 +20677,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) YYDEBUG(1020, *YYCURSOR); ++YYCURSOR; YYDEBUG(1021, *YYCURSOR); -#line 1553 "ext/date/lib/parse_date.re" +#line 1564 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("pointed date YYYY"); TIMELIB_INIT; @@ -20677,7 +20688,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_DATE_FULL_POINTED; } -#line 20681 "" +#line 20692 "" yy1022: YYDEBUG(1022, *YYCURSOR); ++YYCURSOR; @@ -20706,7 +20717,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy1025: YYDEBUG(1025, *YYCURSOR); -#line 1484 "ext/date/lib/parse_date.re" +#line 1495 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("iso8601date2"); @@ -20719,7 +20730,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_ISO_DATE; } -#line 20723 "" +#line 20734 "" yy1026: YYDEBUG(1026, *YYCURSOR); yyaccept = 15; @@ -20939,7 +20950,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy1043: YYDEBUG(1043, *YYCURSOR); -#line 1472 "ext/date/lib/parse_date.re" +#line 1483 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("iso8601date4 | iso8601date2 | iso8601dateslash | dateslash"); TIMELIB_INIT; @@ -20950,7 +20961,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_ISO_DATE; } -#line 20954 "" +#line 20965 "" yy1044: YYDEBUG(1044, *YYCURSOR); yyaccept = 26; @@ -21065,7 +21076,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy1048: YYDEBUG(1048, *YYCURSOR); -#line 1633 "ext/date/lib/parse_date.re" +#line 1644 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("datenocolon"); TIMELIB_INIT; @@ -21076,7 +21087,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_DATE_NOCOLON; } -#line 21080 "" +#line 21091 "" yy1049: YYDEBUG(1049, *YYCURSOR); yych = *++YYCURSOR; @@ -21146,7 +21157,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) YYDEBUG(1059, *YYCURSOR); ++YYCURSOR; YYDEBUG(1060, *YYCURSOR); -#line 1685 "ext/date/lib/parse_date.re" +#line 1696 "ext/date/lib/parse_date.re" { timelib_sll w, d; DEBUG_OUTPUT("isoweekday"); @@ -21164,7 +21175,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_ISO_WEEK; } -#line 21168 "" +#line 21179 "" yy1061: YYDEBUG(1061, *YYCURSOR); yych = *++YYCURSOR; @@ -21227,7 +21238,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) if (yych <= '9') goto yy1143; yy1070: YYDEBUG(1070, *YYCURSOR); -#line 1723 "ext/date/lib/parse_date.re" +#line 1734 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("pgtextshort"); @@ -21240,7 +21251,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_PG_TEXT; } -#line 21244 "" +#line 21255 "" yy1071: YYDEBUG(1071, *YYCURSOR); yych = *++YYCURSOR; @@ -21713,7 +21724,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) ++YYCURSOR; yy1107: YYDEBUG(1107, *YYCURSOR); -#line 1184 "ext/date/lib/parse_date.re" +#line 1195 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("tomorrow"); TIMELIB_INIT; @@ -21724,7 +21735,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 21728 "" +#line 21739 "" yy1108: YYDEBUG(1108, *YYCURSOR); yyaccept = 28; @@ -22061,7 +22072,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) YYDEBUG(1140, *YYCURSOR); ++YYCURSOR; YYDEBUG(1141, *YYCURSOR); -#line 1737 "ext/date/lib/parse_date.re" +#line 1748 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("pgtextreverse"); @@ -22074,7 +22085,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_PG_TEXT; } -#line 22078 "" +#line 22089 "" yy1142: YYDEBUG(1142, *YYCURSOR); ++YYCURSOR; @@ -22118,7 +22129,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy1145: YYDEBUG(1145, *YYCURSOR); -#line 1279 "ext/date/lib/parse_date.re" +#line 1290 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("backof | frontof"); TIMELIB_INIT; @@ -22140,7 +22151,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_LF_DAY_OF_MONTH; } -#line 22144 "" +#line 22155 "" yy1146: YYDEBUG(1146, *YYCURSOR); yyaccept = 29; @@ -22464,7 +22475,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy1172: YYDEBUG(1172, *YYCURSOR); -#line 1823 "ext/date/lib/parse_date.re" +#line 1834 "ext/date/lib/parse_date.re" { timelib_sll i; int behavior = 0; @@ -22487,7 +22498,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 22491 "" +#line 22502 "" yy1173: YYDEBUG(1173, *YYCURSOR); yych = *++YYCURSOR; @@ -22499,7 +22510,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) ++YYCURSOR; yy1175: YYDEBUG(1175, *YYCURSOR); -#line 1141 "ext/date/lib/parse_date.re" +#line 1152 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("yesterday"); TIMELIB_INIT; @@ -22510,7 +22521,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 22514 "" +#line 22525 "" yy1176: YYDEBUG(1176, *YYCURSOR); yyaccept = 31; @@ -23003,7 +23014,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) YYDEBUG(1222, *YYCURSOR); ++YYCURSOR; YYDEBUG(1223, *YYCURSOR); -#line 1889 "ext/date/lib/parse_date.re" +#line 1900 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("dateshortwithtimeshort12 | dateshortwithtimelong12"); TIMELIB_INIT; @@ -23026,7 +23037,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_SHORTDATE_WITH_TIME; } -#line 23030 "" +#line 23041 "" yy1224: YYDEBUG(1224, *YYCURSOR); yych = *++YYCURSOR; @@ -23528,7 +23539,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) YYDEBUG(1268, *YYCURSOR); ++YYCURSOR; YYDEBUG(1269, *YYCURSOR); -#line 1302 "ext/date/lib/parse_date.re" +#line 1313 "ext/date/lib/parse_date.re" { timelib_sll i; int behavior = 0; @@ -23549,7 +23560,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_WEEK_DAY_OF_MONTH; } -#line 23553 "" +#line 23564 "" yy1270: YYDEBUG(1270, *YYCURSOR); yyaccept = 24; @@ -23596,7 +23607,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) YYDEBUG(1273, *YYCURSOR); ++YYCURSOR; YYDEBUG(1274, *YYCURSOR); -#line 1262 "ext/date/lib/parse_date.re" +#line 1273 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("firstdayof | lastdayof"); TIMELIB_INIT; @@ -23612,12 +23623,12 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_LF_DAY_OF_MONTH; } -#line 23616 "" +#line 23627 "" yy1275: YYDEBUG(1275, *YYCURSOR); ++YYCURSOR; YYDEBUG(1276, *YYCURSOR); -#line 1498 "ext/date/lib/parse_date.re" +#line 1509 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("iso8601datex"); TIMELIB_INIT; @@ -23628,7 +23639,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_ISO_DATE; } -#line 23632 "" +#line 23643 "" yy1277: YYDEBUG(1277, *YYCURSOR); yych = *++YYCURSOR; @@ -23731,7 +23742,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) YYDEBUG(1290, *YYCURSOR); ++YYCURSOR; YYDEBUG(1291, *YYCURSOR); -#line 1342 "ext/date/lib/parse_date.re" +#line 1353 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("mssqltime"); TIMELIB_INIT; @@ -23750,7 +23761,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_TIME24_WITH_ZONE; } -#line 23754 "" +#line 23765 "" yy1292: YYDEBUG(1292, *YYCURSOR); yych = *++YYCURSOR; @@ -24174,7 +24185,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) if (yych <= '9') goto yy1331; yy1329: YYDEBUG(1329, *YYCURSOR); -#line 1645 "ext/date/lib/parse_date.re" +#line 1656 "ext/date/lib/parse_date.re" { int tz_not_found; DEBUG_OUTPUT("xmlrpc | xmlrpcnocolon | soap | wddx | exif"); @@ -24199,7 +24210,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_XMLRPC_SOAP; } -#line 24203 "" +#line 24214 "" yy1330: YYDEBUG(1330, *YYCURSOR); yych = *++YYCURSOR; @@ -24569,7 +24580,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) if (yych <= ':') goto yy1383; yy1375: YYDEBUG(1375, *YYCURSOR); -#line 1751 "ext/date/lib/parse_date.re" +#line 1762 "ext/date/lib/parse_date.re" { int tz_not_found; DEBUG_OUTPUT("clf"); @@ -24592,7 +24603,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_CLF; } -#line 24596 "" +#line 24607 "" yy1376: YYDEBUG(1376, *YYCURSOR); yyaccept = 33; @@ -24824,7 +24835,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) if (yych == ':') goto yy1286; goto yy1329; } -#line 1979 "ext/date/lib/parse_date.re" +#line 1990 "ext/date/lib/parse_date.re" } diff --git a/ext/date/lib/parse_date.re b/ext/date/lib/parse_date.re index 3159ff7fa8cac..5d259ed4e2c75 100644 --- a/ext/date/lib/parse_date.re +++ b/ext/date/lib/parse_date.re @@ -711,6 +711,17 @@ static const timelib_relunit* timelib_lookup_relunit(const char **ptr) return value; } +static void add_with_overflow(Scanner *s, timelib_sll *e, timelib_sll amount, int multiplier) +{ +#if defined(__has_builtin) && __has_builtin(__builtin_saddll_overflow) + if (__builtin_saddll_overflow(*e, amount * multiplier, e)) { + add_error(s, TIMELIB_ERR_NUMBER_OUT_OF_RANGE, "Number out of range"); + } +#else + *e += (amount * multiplier); +#endif +} + /** * The time_part parameter is a flag. It can be TIMELIB_TIME_PART_KEEP in case * the time portion should not be reset to midnight, or @@ -726,13 +737,13 @@ static void timelib_set_relative(const char **ptr, timelib_sll amount, int behav } switch (relunit->unit) { - case TIMELIB_MICROSEC: s->time->relative.us += amount * relunit->multiplier; break; - case TIMELIB_SECOND: s->time->relative.s += amount * relunit->multiplier; break; - case TIMELIB_MINUTE: s->time->relative.i += amount * relunit->multiplier; break; - case TIMELIB_HOUR: s->time->relative.h += amount * relunit->multiplier; break; - case TIMELIB_DAY: s->time->relative.d += amount * relunit->multiplier; break; - case TIMELIB_MONTH: s->time->relative.m += amount * relunit->multiplier; break; - case TIMELIB_YEAR: s->time->relative.y += amount * relunit->multiplier; break; + case TIMELIB_MICROSEC: add_with_overflow(s, &s->time->relative.us, amount, relunit->multiplier); break; + case TIMELIB_SECOND: add_with_overflow(s, &s->time->relative.s, amount, relunit->multiplier); break; + case TIMELIB_MINUTE: add_with_overflow(s, &s->time->relative.i, amount, relunit->multiplier); break; + case TIMELIB_HOUR: add_with_overflow(s, &s->time->relative.h, amount, relunit->multiplier); break; + case TIMELIB_DAY: add_with_overflow(s, &s->time->relative.d, amount, relunit->multiplier); break; + case TIMELIB_MONTH: add_with_overflow(s, &s->time->relative.m, amount, relunit->multiplier); break; + case TIMELIB_YEAR: add_with_overflow(s, &s->time->relative.y, amount, relunit->multiplier); break; case TIMELIB_WEEKDAY: TIMELIB_HAVE_WEEKDAY_RELATIVE(); diff --git a/ext/date/lib/timelib.c b/ext/date/lib/timelib.c index d42c69bbd6f06..6473a2798a80e 100644 --- a/ext/date/lib/timelib.c +++ b/ext/date/lib/timelib.c @@ -187,14 +187,22 @@ timelib_long timelib_date_to_int(timelib_time *d, int *error) void timelib_decimal_hour_to_hms(double h, int *hour, int *min, int *sec) { - if (h > 0) { - *hour = floor(h); - *min = floor((h - *hour) * 60); - *sec = (h - *hour - ((float) *min / 60)) * 3600; - } else { - *hour = ceil(h); - *min = 0 - ceil((h - *hour) * 60); - *sec = 0 - (h - *hour - ((float) *min / -60)) * 3600; + bool swap = false; + int seconds; + + if (h < 0) { + swap = true; + h = fabs(h); + } + + *hour = floor(h); + seconds = floor((h - *hour) * 3600); + + *min = seconds / 60; + *sec = seconds % 60; + + if (swap) { + *hour = 0 - *hour; } } diff --git a/ext/date/lib/timelib.h b/ext/date/lib/timelib.h index a532bf60356c7..4582fcfd46917 100644 --- a/ext/date/lib/timelib.h +++ b/ext/date/lib/timelib.h @@ -30,9 +30,9 @@ # include "timelib_config.h" #endif -#define TIMELIB_VERSION 202209 -#define TIMELIB_EXTENDED_VERSION 20220901 -#define TIMELIB_ASCII_VERSION "2022.09" +#define TIMELIB_VERSION 202210 +#define TIMELIB_EXTENDED_VERSION 20221001 +#define TIMELIB_ASCII_VERSION "2022.10" #include #include From 73246bac003a95efa8175f05fe219825f8540c83 Mon Sep 17 00:00:00 2001 From: Derick Rethans Date: Thu, 23 Nov 2023 16:18:34 +0000 Subject: [PATCH 64/92] Update NEWS --- NEWS | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS b/NEWS index d2ed14804a5bf..39670fa94f958 100644 --- a/NEWS +++ b/NEWS @@ -8,6 +8,10 @@ PHP NEWS . Fixed oss-fuzz #64209 (In-place modification of filename in php_message_handler_for_zend). (ilutov) +- Date: + . Fixed improbably integer overflow while parsing really large (or small) + Unix timestamps. (Derick) + - DOM: . Fixed bug GH-12616 (DOM: Removing XMLNS namespace node results in invalid default: prefix). (nielsdos) From 8d2df86b060657bb10e1e9a8692c8972b4cc2083 Mon Sep 17 00:00:00 2001 From: Florian Engelhardt Date: Sat, 25 Nov 2023 00:54:02 +0100 Subject: [PATCH 65/92] Fix invalid opline in OOM handlers within ZEND_FUNC_GET_ARGS and ZEND_BIND_STATIC (#12768) * fix segfault in `ZEND_BIND_STATIC` In case a `ZEND_BIND_STATIC` is being executed, while the current chunk is full, the `zend_array_dup()` call will trigger a OOM in ZendMM which will crash, as the opline might be a dangling pointer. * add missing test * `assert()`ing seems easier than trying to make the compiler to not optimize * moved from function call to INI setting, so we can use this in other places as well * make `assert()` work no NDEBUG builds * document magic number * fix segfault in `ZEND_FUNC_GET_ARGS` In case a `ZEND_FUNC_GET_ARGS` is being executed, while the current chunk is full, the `zend_new_array()` call will trigger a OOM in ZendMM which will crash, as the opline might be a dangling pointer. --------- Co-authored-by: Florian Engelhardt --- Zend/zend_vm_def.h | 4 +- Zend/zend_vm_execute.h | 5 +- ext/zend_test/php_test.h | 3 + ext/zend_test/test.c | 77 +++++++++++++++++++++ ext/zend_test/tests/opline_dangling.phpt | 33 +++++++++ ext/zend_test/tests/opline_dangling_02.phpt | 36 ++++++++++ 6 files changed, 156 insertions(+), 2 deletions(-) create mode 100644 ext/zend_test/tests/opline_dangling.phpt create mode 100644 ext/zend_test/tests/opline_dangling_02.phpt diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index fd5b7242ba645..a6f86a9eab6f7 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -8788,6 +8788,8 @@ ZEND_VM_HANDLER(183, ZEND_BIND_STATIC, CV, UNUSED, REF) variable_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W); + SAVE_OPLINE(); + ht = ZEND_MAP_PTR_GET(EX(func)->op_array.static_variables_ptr); if (!ht) { ht = zend_array_dup(EX(func)->op_array.static_variables); @@ -8797,7 +8799,6 @@ ZEND_VM_HANDLER(183, ZEND_BIND_STATIC, CV, UNUSED, REF) value = (zval*)((char*)ht->arData + (opline->extended_value & ~(ZEND_BIND_REF|ZEND_BIND_IMPLICIT|ZEND_BIND_EXPLICIT))); - SAVE_OPLINE(); if (opline->extended_value & ZEND_BIND_REF) { if (Z_TYPE_P(value) == IS_CONSTANT_AST) { if (UNEXPECTED(zval_update_constant_ex(value, EX(func)->op_array.scope) != SUCCESS)) { @@ -9250,6 +9251,7 @@ ZEND_VM_HANDLER(172, ZEND_FUNC_GET_ARGS, UNUSED|CONST, UNUSED) } if (result_size) { + SAVE_OPLINE(); uint32_t first_extra_arg = EX(func)->op_array.num_args; ht = zend_new_array(result_size); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index bc098148541fb..5ee1c2c94daf5 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -10700,6 +10700,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FUNC_GET_ARGS_SPEC_CONST_UNUSE } if (result_size) { + SAVE_OPLINE(); uint32_t first_extra_arg = EX(func)->op_array.num_args; ht = zend_new_array(result_size); @@ -36064,6 +36065,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FUNC_GET_ARGS_SPEC_UNUSED_UNUS } if (result_size) { + SAVE_OPLINE(); uint32_t first_extra_arg = EX(func)->op_array.num_args; ht = zend_new_array(result_size); @@ -48471,6 +48473,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BIND_STATIC_SPEC_CV_UNUSED_HAN variable_ptr = EX_VAR(opline->op1.var); + SAVE_OPLINE(); + ht = ZEND_MAP_PTR_GET(EX(func)->op_array.static_variables_ptr); if (!ht) { ht = zend_array_dup(EX(func)->op_array.static_variables); @@ -48480,7 +48484,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BIND_STATIC_SPEC_CV_UNUSED_HAN value = (zval*)((char*)ht->arData + (opline->extended_value & ~(ZEND_BIND_REF|ZEND_BIND_IMPLICIT|ZEND_BIND_EXPLICIT))); - SAVE_OPLINE(); if (opline->extended_value & ZEND_BIND_REF) { if (Z_TYPE_P(value) == IS_CONSTANT_AST) { if (UNEXPECTED(zval_update_constant_ex(value, EX(func)->op_array.scope) != SUCCESS)) { diff --git a/ext/zend_test/php_test.h b/ext/zend_test/php_test.h index 05f658e91bdb6..9d0ca087ce6f7 100644 --- a/ext/zend_test/php_test.h +++ b/ext/zend_test/php_test.h @@ -52,6 +52,9 @@ ZEND_BEGIN_MODULE_GLOBALS(zend_test) HashTable global_weakmap; int replace_zend_execute_ex; int register_passes; + int observe_opline_in_zendmm; + zend_mm_heap* zend_orig_heap; + zend_mm_heap* zend_test_heap; zend_test_fiber *active_fiber; ZEND_END_MODULE_GLOBALS(zend_test) diff --git a/ext/zend_test/test.c b/ext/zend_test/test.c index 2f3ff6d9009e6..c2a6bd18a5433 100644 --- a/ext/zend_test/test.c +++ b/ext/zend_test/test.c @@ -30,8 +30,15 @@ #include "zend_interfaces.h" #include "zend_weakrefs.h" #include "Zend/Optimizer/zend_optimizer.h" +#include "Zend/zend_alloc.h" #include "test_arginfo.h" +// `php.h` sets `NDEBUG` when not `PHP_DEBUG` which will make `assert()` from +// assert.h a no-op. In order to have `assert()` working on NDEBUG builds, we +// undefine `NDEBUG` and re-include assert.h +#undef NDEBUG +#include "assert.h" + #if defined(HAVE_LIBXML) && !defined(PHP_WIN32) # include # include @@ -364,6 +371,68 @@ static ZEND_FUNCTION(zend_test_crash) php_printf("%s", invalid); } +static bool has_opline(zend_execute_data *execute_data) +{ + return execute_data + && execute_data->func + && ZEND_USER_CODE(execute_data->func->type) + && execute_data->opline + ; +} + +void * zend_test_custom_malloc(size_t len) +{ + if (has_opline(EG(current_execute_data))) { + assert(EG(current_execute_data)->opline->lineno != (uint32_t)-1); + } + return _zend_mm_alloc(ZT_G(zend_orig_heap), len ZEND_FILE_LINE_EMPTY_CC ZEND_FILE_LINE_EMPTY_CC); +} + +void zend_test_custom_free(void *ptr) +{ + if (has_opline(EG(current_execute_data))) { + assert(EG(current_execute_data)->opline->lineno != (uint32_t)-1); + } + _zend_mm_free(ZT_G(zend_orig_heap), ptr ZEND_FILE_LINE_EMPTY_CC ZEND_FILE_LINE_EMPTY_CC); +} + +void * zend_test_custom_realloc(void * ptr, size_t len) +{ + if (has_opline(EG(current_execute_data))) { + assert(EG(current_execute_data)->opline->lineno != (uint32_t)-1); + } + return _zend_mm_realloc(ZT_G(zend_orig_heap), ptr, len ZEND_FILE_LINE_EMPTY_CC ZEND_FILE_LINE_EMPTY_CC); +} + +static PHP_INI_MH(OnUpdateZendTestObserveOplineInZendMM) +{ + if (new_value == NULL) { + return FAILURE; + } + + int int_value = zend_ini_parse_bool(new_value); + + if (int_value == 1) { + // `zend_mm_heap` is a private struct, so we have not way to find the + // actual size, but 4096 bytes should be enough + ZT_G(zend_test_heap) = malloc(4096); + memset(ZT_G(zend_test_heap), 0, 4096); + zend_mm_set_custom_handlers( + ZT_G(zend_test_heap), + zend_test_custom_malloc, + zend_test_custom_free, + zend_test_custom_realloc + ); + ZT_G(zend_orig_heap) = zend_mm_get_heap(); + zend_mm_set_heap(ZT_G(zend_test_heap)); + } else if (ZT_G(zend_test_heap)) { + free(ZT_G(zend_test_heap)); + ZT_G(zend_test_heap) = NULL; + zend_mm_set_heap(ZT_G(zend_orig_heap)); + } + return OnUpdateBool(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); +} + static ZEND_FUNCTION(zend_test_is_pcre_bundled) { ZEND_PARSE_PARAMETERS_NONE(); @@ -558,6 +627,7 @@ static ZEND_METHOD(ZendTestChildClassWithMethodWithParameterAttribute, override) PHP_INI_BEGIN() STD_PHP_INI_BOOLEAN("zend_test.replace_zend_execute_ex", "0", PHP_INI_SYSTEM, OnUpdateBool, replace_zend_execute_ex, zend_zend_test_globals, zend_test_globals) STD_PHP_INI_BOOLEAN("zend_test.register_passes", "0", PHP_INI_SYSTEM, OnUpdateBool, register_passes, zend_zend_test_globals, zend_test_globals) + STD_PHP_INI_BOOLEAN("zend_test.observe_opline_in_zendmm", "0", PHP_INI_ALL, OnUpdateZendTestObserveOplineInZendMM, observe_opline_in_zendmm, zend_zend_test_globals, zend_test_globals) PHP_INI_END() void (*old_zend_execute_ex)(zend_execute_data *execute_data); @@ -700,6 +770,13 @@ PHP_RSHUTDOWN_FUNCTION(zend_test) zend_weakrefs_hash_del(&ZT_G(global_weakmap), (zend_object *)(uintptr_t)objptr); } ZEND_HASH_FOREACH_END(); zend_hash_destroy(&ZT_G(global_weakmap)); + + if (ZT_G(zend_test_heap)) { + free(ZT_G(zend_test_heap)); + ZT_G(zend_test_heap) = NULL; + zend_mm_set_heap(ZT_G(zend_orig_heap)); + } + return SUCCESS; } diff --git a/ext/zend_test/tests/opline_dangling.phpt b/ext/zend_test/tests/opline_dangling.phpt new file mode 100644 index 0000000000000..b411223cecf76 --- /dev/null +++ b/ext/zend_test/tests/opline_dangling.phpt @@ -0,0 +1,33 @@ +--TEST-- +possible segfault in `ZEND_BIND_STATIC` +--DESCRIPTION-- +https://github.com/php/php-src/pull/12758 +--EXTENSIONS-- +zend_test +--INI-- +zend_test.observe_opline_in_zendmm=1 +--FILE-- + +--EXPECT-- +int(1) +string(1) "x" +int(1) +int(5) +Done. diff --git a/ext/zend_test/tests/opline_dangling_02.phpt b/ext/zend_test/tests/opline_dangling_02.phpt new file mode 100644 index 0000000000000..1537bc68c181a --- /dev/null +++ b/ext/zend_test/tests/opline_dangling_02.phpt @@ -0,0 +1,36 @@ +--TEST-- +possible segfault in `ZEND_FUNC_GET_ARGS` +--DESCRIPTION-- +--EXTENSIONS-- +zend_test +--INI-- +zend_test.observe_opline_in_zendmm=1 +--FILE-- + +--EXPECT-- +int(1) +string(1) "x" +int(1) +array(2) { + [0]=> + string(6) "string" + [1]=> + int(0) +} +Done. From 1305ea23cee98e91092641c0ec39f17e09f29882 Mon Sep 17 00:00:00 2001 From: Bob Weinand Date: Sat, 25 Nov 2023 00:57:22 +0100 Subject: [PATCH 66/92] Add NEWS entry for GH-12768 --- NEWS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NEWS b/NEWS index b8d860bd3d9ad..a528a8f878fa9 100644 --- a/NEWS +++ b/NEWS @@ -7,6 +7,8 @@ PHP NEWS error handler). (ilutov) . Fixed oss-fuzz #64209 (In-place modification of filename in php_message_handler_for_zend). (ilutov) + . Fixed bug GH-12758 / GH-12768 (Invalid opline in OOM handlers within + ZEND_FUNC_GET_ARGS and ZEND_BIND_STATIC). (Florian Engelhardt) - DOM: . Fixed bug GH-12616 (DOM: Removing XMLNS namespace node results in invalid From d404e1d1ee675102e25be5975949030d959821d7 Mon Sep 17 00:00:00 2001 From: Bob Weinand Date: Sat, 25 Nov 2023 18:44:45 +0100 Subject: [PATCH 67/92] USE_ZEND_ALLOC=1 in tests with zend_test.observe_opline_in_zendmm=1 --- ext/zend_test/tests/opline_dangling.phpt | 2 ++ ext/zend_test/tests/opline_dangling_02.phpt | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/ext/zend_test/tests/opline_dangling.phpt b/ext/zend_test/tests/opline_dangling.phpt index b411223cecf76..3b27b544ca34f 100644 --- a/ext/zend_test/tests/opline_dangling.phpt +++ b/ext/zend_test/tests/opline_dangling.phpt @@ -4,6 +4,8 @@ possible segfault in `ZEND_BIND_STATIC` https://github.com/php/php-src/pull/12758 --EXTENSIONS-- zend_test +--ENV-- +USE_ZEND_ALLOC=1 --INI-- zend_test.observe_opline_in_zendmm=1 --FILE-- diff --git a/ext/zend_test/tests/opline_dangling_02.phpt b/ext/zend_test/tests/opline_dangling_02.phpt index 1537bc68c181a..585a9c8395b59 100644 --- a/ext/zend_test/tests/opline_dangling_02.phpt +++ b/ext/zend_test/tests/opline_dangling_02.phpt @@ -1,8 +1,9 @@ --TEST-- possible segfault in `ZEND_FUNC_GET_ARGS` ---DESCRIPTION-- --EXTENSIONS-- zend_test +--ENV-- +USE_ZEND_ALLOC=1 --INI-- zend_test.observe_opline_in_zendmm=1 --FILE-- From 7e7817bc2f82570bbc510a2bf5e4e0ec09dbc774 Mon Sep 17 00:00:00 2001 From: Mikhail Galanin Date: Fri, 25 Aug 2023 16:43:01 +0100 Subject: [PATCH 68/92] Avoid using uninitialised struct Closes GH-12046. --- NEWS | 3 +++ ext/mysqlnd/mysqlnd_result.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index a528a8f878fa9..d0cb95eee4ae6 100644 --- a/NEWS +++ b/NEWS @@ -20,6 +20,9 @@ PHP NEWS - LibXML: . Fixed bug GH-12702 (libxml2 2.12.0 issue building from src). (nono303) +- MySQLnd: + . Avoid using uninitialised struct. (mikhainin) + - OpenSSL: . Fixed bug #50713 (openssl_pkcs7_verify() may ignore untrusted CAs). (Jakub Zelenka) diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c index b1a400499781a..68a0255ee0550 100644 --- a/ext/mysqlnd/mysqlnd_result.c +++ b/ext/mysqlnd/mysqlnd_result.c @@ -346,8 +346,8 @@ mysqlnd_query_read_result_set_header(MYSQLND_CONN_DATA * conn, MYSQLND_STMT * s) } MYSQLND_INC_CONN_STATISTIC(conn->stats, statistic); } + PACKET_FREE(&fields_eof); } while (0); - PACKET_FREE(&fields_eof); break; /* switch break */ } } while (0); From 6a914cb7a50fafbda38a4d8acce3a06b97dbd994 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Mon, 27 Nov 2023 13:25:11 +0100 Subject: [PATCH 69/92] Fix GH-12791: Possible dereference of NULL in MySQLnd debug code Closes GH-12794. --- NEWS | 2 ++ ext/mysqlnd/mysqlnd_result.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 0a39d3f286d61..1a8f3412b3acc 100644 --- a/NEWS +++ b/NEWS @@ -26,6 +26,8 @@ PHP NEWS - MySQLnd: . Avoid using uninitialised struct. (mikhainin) + . Fixed bug GH-12791 (Possible dereference of NULL in MySQLnd debug code). + (nielsdos) - OpenSSL: . Fixed bug #50713 (openssl_pkcs7_verify() may ignore untrusted CAs). diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c index f96ca410b2323..0331518d7d3d6 100644 --- a/ext/mysqlnd/mysqlnd_result.c +++ b/ext/mysqlnd/mysqlnd_result.c @@ -735,8 +735,8 @@ MYSQLND_METHOD(mysqlnd_res, store_result_fetch_data)(MYSQLND_CONN_DATA * const c UPSERT_STATUS_GET_SERVER_STATUS(conn->upsert_status)); free_end: PACKET_FREE(&row_packet); + DBG_INF_FMT("rows=%llu", (unsigned long long)set->row_count); end: - DBG_INF_FMT("rows=%llu", (unsigned long long)result->stored_data->row_count); DBG_RETURN(ret); } /* }}} */ From ed8b9018696f27997cfd582d5fe6569f9c75ee40 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Mon, 27 Nov 2023 16:04:41 +0000 Subject: [PATCH 70/92] jit: fixed "Uninitialized string offset" warning being emitted at the same time as invalid offset Error --- NEWS | 4 ++++ ext/opcache/jit/zend_jit_helpers.c | 3 +++ ext/opcache/tests/jit/gh12723-A.phpt | 20 ++++++++++++++++++++ 3 files changed, 27 insertions(+) create mode 100644 ext/opcache/tests/jit/gh12723-A.phpt diff --git a/NEWS b/NEWS index 1a8f3412b3acc..2bc78b317abbd 100644 --- a/NEWS +++ b/NEWS @@ -29,6 +29,10 @@ PHP NEWS . Fixed bug GH-12791 (Possible dereference of NULL in MySQLnd debug code). (nielsdos) +- Opcache: + . Fixed JIT bug (Function JIT emits "Uninitialized string offset" warning + at the same time as invalid offset Error). (Girgias) + - OpenSSL: . Fixed bug #50713 (openssl_pkcs7_verify() may ignore untrusted CAs). (Jakub Zelenka) diff --git a/ext/opcache/jit/zend_jit_helpers.c b/ext/opcache/jit/zend_jit_helpers.c index 95ff48dd4f9c1..a838a73582389 100644 --- a/ext/opcache/jit/zend_jit_helpers.c +++ b/ext/opcache/jit/zend_jit_helpers.c @@ -1106,6 +1106,9 @@ static zend_string* ZEND_FASTCALL zend_jit_fetch_dim_str_r_helper(zend_string *s } else { offset = Z_LVAL_P(dim); } + if (UNEXPECTED(EG(exception) != NULL)) { + return ZSTR_EMPTY_ALLOC(); + } return zend_jit_fetch_dim_str_offset(str, offset); } diff --git a/ext/opcache/tests/jit/gh12723-A.phpt b/ext/opcache/tests/jit/gh12723-A.phpt new file mode 100644 index 0000000000000..f30453e8c0a37 --- /dev/null +++ b/ext/opcache/tests/jit/gh12723-A.phpt @@ -0,0 +1,20 @@ +--TEST-- +GH-12723: Function JIT emits "Uninitialized string offset" warning at the same time as invalid offset Error +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +--FILE-- +getMessage(), "\n"; +} + +?> +--EXPECT-- +Cannot access offset of type array on string From 126a255d66d3c2b2161bce8c20eb2d09bbf0b690 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Mon, 27 Nov 2023 16:19:35 +0000 Subject: [PATCH 71/92] jit: fixed JIT "Attempt to assign property of non-object" warning emitted at the same time as Error is being thrown --- NEWS | 2 ++ ext/opcache/jit/zend_jit_helpers.c | 4 +++- ext/opcache/tests/jit/gh12723-B.phpt | 19 +++++++++++++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 ext/opcache/tests/jit/gh12723-B.phpt diff --git a/NEWS b/NEWS index 2bc78b317abbd..0cc4d64783b71 100644 --- a/NEWS +++ b/NEWS @@ -32,6 +32,8 @@ PHP NEWS - Opcache: . Fixed JIT bug (Function JIT emits "Uninitialized string offset" warning at the same time as invalid offset Error). (Girgias) + . Fixed JIT bug (JIT emits "Attempt to assign property of non-object" + warning at the same time as Error is being thrown). (Girgias) - OpenSSL: . Fixed bug #50713 (openssl_pkcs7_verify() may ignore untrusted CAs). diff --git a/ext/opcache/jit/zend_jit_helpers.c b/ext/opcache/jit/zend_jit_helpers.c index a838a73582389..69c7ca3a537c4 100644 --- a/ext/opcache/jit/zend_jit_helpers.c +++ b/ext/opcache/jit/zend_jit_helpers.c @@ -1591,7 +1591,9 @@ static void ZEND_FASTCALL zend_jit_assign_dim_op_helper(zval *container, zval *d } zval_ptr_dtor(&res); } else { - zend_error(E_WARNING, "Attempt to assign property of non-object"); + /* Exception is thrown in this case */ + GC_DELREF(obj); + return; } if (UNEXPECTED(GC_DELREF(obj) == 0)) { zend_objects_store_del(obj); diff --git a/ext/opcache/tests/jit/gh12723-B.phpt b/ext/opcache/tests/jit/gh12723-B.phpt new file mode 100644 index 0000000000000..9f5ae7a19ff16 --- /dev/null +++ b/ext/opcache/tests/jit/gh12723-B.phpt @@ -0,0 +1,19 @@ +--TEST-- +GH-12723: JIT emits "Attempt to assign property of non-object" warning at the same time as Error is being thrown +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +--FILE-- +getMessage(), "\n"; +} + +?> +--EXPECT-- +Cannot use object of type stdClass as array From 3f57bd80f68fdff067b45f3d717dcf340b972635 Mon Sep 17 00:00:00 2001 From: ddv Date: Fri, 24 Nov 2023 14:39:07 +0500 Subject: [PATCH 72/92] Fix phpGH-12763: PGSQL pg_untrace(): Argument #1 ($connection) must be of type resource or null, PgSql\Connection given. --- NEWS | 3 +++ ext/pgsql/pgsql.c | 2 +- ext/pgsql/tests/gh12763.phpt | 23 +++++++++++++++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 ext/pgsql/tests/gh12763.phpt diff --git a/NEWS b/NEWS index d0cb95eee4ae6..aaf852a8ad2cc 100644 --- a/NEWS +++ b/NEWS @@ -30,6 +30,9 @@ PHP NEWS - PCRE: . Fixed bug GH-12628 (The gh11374 test fails on Alpinelinux). (nielsdos) +- PGSQL: + . Fixed bug GH-12763 wrong argument type for pg_untrace. (degtyarov) + - PHPDBG: . Fixed bug GH-12675 (MEMORY_LEAK in phpdbg_prompt.c). (nielsdos) diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c index 66f09382fc32e..9f04f2c843b9c 100644 --- a/ext/pgsql/pgsql.c +++ b/ext/pgsql/pgsql.c @@ -2286,7 +2286,7 @@ PHP_FUNCTION(pg_untrace) PGconn *pgsql; pgsql_link_handle *link; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "|r!", &pgsql_link) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "|O!", &pgsql_link, pgsql_link_ce) == FAILURE) { RETURN_THROWS(); } diff --git a/ext/pgsql/tests/gh12763.phpt b/ext/pgsql/tests/gh12763.phpt new file mode 100644 index 0000000000000..a9bc0d18cfe56 --- /dev/null +++ b/ext/pgsql/tests/gh12763.phpt @@ -0,0 +1,23 @@ +--TEST-- +Bug #GH12763 (pg_untrace(): Argument #1 ($connection) must be of type resource or null, PgSql\Connection given) +--EXTENSIONS-- +pgsql +--SKIPIF-- + +--FILE-- + +--EXPECT-- +OK From d8ef868b92b9c7ae811639d8c6cc9b58aa402a98 Mon Sep 17 00:00:00 2001 From: Alex Dowad Date: Sun, 26 Nov 2023 17:17:28 +0200 Subject: [PATCH 73/92] Return value of mb_get_info can be NULL This has been the case at least since PHP 5.4. Thanks to Girgias for pointing it out. It appears that there are several global variables internal to mbstring which can be queried via mb_get_info() and which could be NULL, but at the very least, we know that "mbstring.http_input" is one of them. --- Zend/Optimizer/zend_func_infos.h | 2 +- ext/mbstring/mbstring.stub.php | 4 ++-- ext/mbstring/mbstring_arginfo.h | 4 ++-- ext/mbstring/tests/mb_get_info_http_input.phpt | 10 ++++++++++ 4 files changed, 15 insertions(+), 5 deletions(-) create mode 100644 ext/mbstring/tests/mb_get_info_http_input.phpt diff --git a/Zend/Optimizer/zend_func_infos.h b/Zend/Optimizer/zend_func_infos.h index 10f8d950ee094..3aefdf53df072 100644 --- a/Zend/Optimizer/zend_func_infos.h +++ b/Zend/Optimizer/zend_func_infos.h @@ -235,7 +235,7 @@ static const func_info_t func_infos[] = { F1("mb_convert_variables", MAY_BE_STRING|MAY_BE_FALSE), F1("mb_encode_numericentity", MAY_BE_STRING), F1("mb_decode_numericentity", MAY_BE_STRING), - F1("mb_get_info", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_LONG|MAY_BE_ARRAY_OF_STRING|MAY_BE_ARRAY_OF_ARRAY|MAY_BE_STRING|MAY_BE_LONG|MAY_BE_FALSE), + F1("mb_get_info", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_LONG|MAY_BE_ARRAY_OF_STRING|MAY_BE_ARRAY_OF_ARRAY|MAY_BE_STRING|MAY_BE_LONG|MAY_BE_FALSE|MAY_BE_NULL), #if defined(HAVE_MBREGEX) F1("mb_regex_encoding", MAY_BE_STRING|MAY_BE_BOOL), #endif diff --git a/ext/mbstring/mbstring.stub.php b/ext/mbstring/mbstring.stub.php index 0d04e34bc7823..77d3fee67aab5 100644 --- a/ext/mbstring/mbstring.stub.php +++ b/ext/mbstring/mbstring.stub.php @@ -171,10 +171,10 @@ function mb_decode_numericentity(string $string, array $map, ?string $encoding = function mb_send_mail(string $to, string $subject, string $message, array|string $additional_headers = [], ?string $additional_params = null): bool {} /** - * @return array|string|int|false + * @return array|string|int|false|null * @refcount 1 */ -function mb_get_info(string $type = "all"): array|string|int|false {} +function mb_get_info(string $type = "all"): array|string|int|false|null {} function mb_check_encoding(array|string|null $value = null, ?string $encoding = null): bool {} diff --git a/ext/mbstring/mbstring_arginfo.h b/ext/mbstring/mbstring_arginfo.h index 3bf10789e0d6c..924c6864e54dc 100644 --- a/ext/mbstring/mbstring_arginfo.h +++ b/ext/mbstring/mbstring_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 0c9ac8888b8332557f7098cfb9d259757af8b3c6 */ + * Stub hash: 131af756402aecb88d2265f2a3d25aa5c66a7185 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_mb_language, 0, 0, MAY_BE_STRING|MAY_BE_BOOL) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, language, IS_STRING, 1, "null") @@ -177,7 +177,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_mb_send_mail, 0, 3, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, additional_params, IS_STRING, 1, "null") ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_mb_get_info, 0, 0, MAY_BE_ARRAY|MAY_BE_STRING|MAY_BE_LONG|MAY_BE_FALSE) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_mb_get_info, 0, 0, MAY_BE_ARRAY|MAY_BE_STRING|MAY_BE_LONG|MAY_BE_FALSE|MAY_BE_NULL) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, type, IS_STRING, 0, "\"all\"") ZEND_END_ARG_INFO() diff --git a/ext/mbstring/tests/mb_get_info_http_input.phpt b/ext/mbstring/tests/mb_get_info_http_input.phpt new file mode 100644 index 0000000000000..5cfac7a833679 --- /dev/null +++ b/ext/mbstring/tests/mb_get_info_http_input.phpt @@ -0,0 +1,10 @@ +--TEST-- +mb_get_info("http_input") can return null +--EXTENSIONS-- +mbstring +--FILE-- + +--EXPECT-- +NULL From e94ab0461cfe948c39ca6aff4377eacc14e7d096 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Mon, 27 Nov 2023 21:37:21 +0000 Subject: [PATCH 74/92] Align error messages between normal VM and JIT for RW when using object as array (#12799) --- Zend/zend_execute.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 89610f84b5efc..0df529203c1b9 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -1417,9 +1417,9 @@ static ZEND_COLD void zend_verify_missing_return_type(const zend_function *zf) zend_verify_return_error(zf, NULL); } -static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_use_object_as_array(void) +static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_use_object_as_array(const zend_object *object) { - zend_throw_error(NULL, "Cannot use object as array"); + zend_throw_error(NULL, "Cannot use object of type %s as array", ZSTR_VAL(object->ce->name)); } static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_illegal_offset(void) @@ -1487,7 +1487,7 @@ static zend_never_inline void zend_binary_assign_op_obj_dim(zend_object *obj, zv } zval_ptr_dtor(&res); } else { - zend_use_object_as_array(); + zend_use_object_as_array(obj); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } From ace91ddd7305f865364ba42620963c165e0b7be9 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Tue, 21 Nov 2023 10:58:15 +0100 Subject: [PATCH 75/92] Reduce parallelism on frequently crashing jobs Some jobs on GA apparently consume a lot of CPU resources, possibly hindering communication between master and runner. This only seems to happen on Linux+ASAN and macOS. For these jobs, keep one core idle. Closes GH-12742 --- .github/actions/test-linux/action.yml | 5 ++++- .github/actions/test-macos/action.yml | 2 +- .github/workflows/nightly.yml | 1 + 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/actions/test-linux/action.yml b/.github/actions/test-linux/action.yml index f6d726a2f71dd..a56ed2823d7ac 100644 --- a/.github/actions/test-linux/action.yml +++ b/.github/actions/test-linux/action.yml @@ -9,6 +9,9 @@ inputs: jitType: default: 'disable' required: false + idleCpu: + default: 'false' + required: false runs: using: composite steps: @@ -36,7 +39,7 @@ runs: sapi/cli/php run-tests.php -P -q ${{ inputs.runTestsParameters }} \ -d opcache.jit=${{ inputs.jitType }} \ -d opcache.jit_buffer_size=16M \ - -j$(/usr/bin/nproc) \ + ${{ inputs.idleCpu == 'true' && '-j$(($(/usr/bin/nproc) - 1))' || '-j$(/usr/bin/nproc)' }} \ -g FAIL,BORK,LEAK,XLEAK \ --no-progress \ --offline \ diff --git a/.github/actions/test-macos/action.yml b/.github/actions/test-macos/action.yml index 63bccece39ed0..0090f6a1cb337 100644 --- a/.github/actions/test-macos/action.yml +++ b/.github/actions/test-macos/action.yml @@ -21,7 +21,7 @@ runs: sapi/cli/php run-tests.php -P -q ${{ inputs.runTestsParameters }} \ -d opcache.jit=${{ inputs.jitType }} \ -d opcache.jit_buffer_size=16M \ - -j$(sysctl -n hw.ncpu) \ + -j$(($(sysctl -n hw.ncpu) - 1)) \ -g FAIL,BORK,LEAK,XLEAK \ --no-progress \ --offline \ diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index dae430f225bae..a8fdd0a867bec 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -82,6 +82,7 @@ jobs: testArtifacts: ${{ matrix.branch.name }}_${{ matrix.name }}_${{ matrix.debug && 'DEBUG' || 'RELEASE' }}_${{ matrix.zts && 'ZTS' || 'NTS' }} runTestsParameters: >- ${{ matrix.run_tests_parameters }} + idleCpu: ${{ matrix.asan && 'true' || 'false' }} - name: Test Tracing JIT uses: ./.github/actions/test-linux with: From 39a813d9ca6c9186aad23876e4b05c4a7d8e64ea Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 28 Nov 2023 21:19:57 +0300 Subject: [PATCH 76/92] Fixed GH-12812: Integer string in variable used as offset produces wrong undefined array key warning (#12817) * Fixed GH-12812: Integer string in variable used as offset produces wrong undefined array key warning * Fixed register names --- ext/opcache/jit/zend_jit_arm64.dasc | 75 +++---------------- ext/opcache/jit/zend_jit_disasm.c | 2 + ext/opcache/jit/zend_jit_internal.h | 2 + ext/opcache/jit/zend_jit_vm_helpers.c | 37 ++++++++++ ext/opcache/jit/zend_jit_x86.dasc | 100 +++----------------------- ext/opcache/tests/jit/gh12812.phpt | 29 ++++++++ 6 files changed, 86 insertions(+), 159 deletions(-) create mode 100644 ext/opcache/tests/jit/gh12812.phpt diff --git a/ext/opcache/jit/zend_jit_arm64.dasc b/ext/opcache/jit/zend_jit_arm64.dasc index d40aaf904727e..d4e67b6c5a4a6 100644 --- a/ext/opcache/jit/zend_jit_arm64.dasc +++ b/ext/opcache/jit/zend_jit_arm64.dasc @@ -2023,39 +2023,10 @@ static int zend_jit_undefined_offset_ex_stub(dasm_State **Dst) static int zend_jit_undefined_offset_stub(dasm_State **Dst) { |->undefined_offset: -#ifdef __APPLE__ - | stp x29, x30, [sp, # -16]! - | mov x29, sp -#endif - | //sub r4, 8 - | ldr REG0, EX->opline - | ldr REG1w, OP:REG0->result.var - | add REG1, REG1, FP - | SET_Z_TYPE_INFO REG1, IS_NULL, TMP1w - | ldrb REG1w, OP:REG0->op2_type - | cmp REG1w, #IS_CONST - | bne >2 - | ldrsw REG1, OP:REG0->op2.constant - | add REG0, REG0, REG1 - | b >3 - |2: - | ldr REG0w, OP:REG0->op2.var - | add REG0, REG0, FP - |3: - | mov CARG1, #E_WARNING - | LOAD_ADDR CARG2, "Undefined array key " ZEND_LONG_FMT - | ldr CARG3, [REG0] -#ifdef __APPLE__ - | str CARG3, [sp, #-16]! - | EXT_CALL zend_error, REG0 - | add sp, sp, #16 - | ldp x29, x30, [sp], #16 - | ret -#else - | EXT_JMP zend_error, REG0 // tail call - | //add r4, 8 // stack alignment - | //ret -#endif + || if (!GCC_GLOBAL_REGS) { + | mov FCARG1x, FP + || } + | EXT_JMP zend_jit_undefined_long_key, REG0 return 1; } @@ -2072,40 +2043,10 @@ static int zend_jit_undefined_index_ex_stub(dasm_State **Dst) static int zend_jit_undefined_index_stub(dasm_State **Dst) { |->undefined_index: -#ifdef __APPLE__ - | stp x29, x30, [sp, # -16]! - | mov x29, sp -#endif - | //sub r4, 8 - | ldr REG0, EX->opline - | ldr REG1w, OP:REG0->result.var - | add REG1, REG1, FP - | SET_Z_TYPE_INFO REG1, IS_NULL, TMP1w - | ldrb REG1w, OP:REG0->op2_type - | cmp REG1w, #IS_CONST - | bne >2 - | ldrsw REG1, OP:REG0->op2.constant - | add REG0, REG0, REG1 - | b >3 - |2: - | ldr REG0w, OP:REG0->op2.var - | add REG0, REG0, FP - |3: - | mov CARG1, #E_WARNING - | LOAD_ADDR CARG2, "Undefined array key \"%s\"" - | ldr CARG3, [REG0] - | add CARG3, CARG3, #offsetof(zend_string, val) -#ifdef __APPLE__ - | str CARG3, [sp, #-16]! - | EXT_CALL zend_error, REG0 - | add sp, sp, #16 - | ldp x29, x30, [sp], #16 - | ret -#else - | EXT_JMP zend_error, REG0 // tail call - | //add r4, 8 - | //ret -#endif + || if (!GCC_GLOBAL_REGS) { + | mov FCARG1x, FP + || } + | EXT_JMP zend_jit_undefined_string_key, REG0 return 1; } diff --git a/ext/opcache/jit/zend_jit_disasm.c b/ext/opcache/jit/zend_jit_disasm.c index f470cb9a96855..c49a0df863aed 100644 --- a/ext/opcache/jit/zend_jit_disasm.c +++ b/ext/opcache/jit/zend_jit_disasm.c @@ -655,6 +655,8 @@ static int zend_jit_disasm_init(void) REGISTER_HELPER(zend_jit_vm_stack_free_args_helper); REGISTER_HELPER(zend_jit_copy_extra_args_helper); REGISTER_HELPER(zend_jit_deprecated_helper); + REGISTER_HELPER(zend_jit_undefined_long_key); + REGISTER_HELPER(zend_jit_undefined_string_key); REGISTER_HELPER(zend_jit_assign_const_to_typed_ref); REGISTER_HELPER(zend_jit_assign_tmp_to_typed_ref); REGISTER_HELPER(zend_jit_assign_var_to_typed_ref); diff --git a/ext/opcache/jit/zend_jit_internal.h b/ext/opcache/jit/zend_jit_internal.h index 544bcdd1f245b..92f6fb7b11dc5 100644 --- a/ext/opcache/jit/zend_jit_internal.h +++ b/ext/opcache/jit/zend_jit_internal.h @@ -328,6 +328,8 @@ ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_loop_counter_helper(ZEND_OPCODE_H void ZEND_FASTCALL zend_jit_copy_extra_args_helper(EXECUTE_DATA_D); bool ZEND_FASTCALL zend_jit_deprecated_helper(OPLINE_D); +void ZEND_FASTCALL zend_jit_undefined_long_key(EXECUTE_DATA_D); +void ZEND_FASTCALL zend_jit_undefined_string_key(EXECUTE_DATA_D); zend_constant* ZEND_FASTCALL zend_jit_get_constant(const zval *key, uint32_t flags); zend_constant* ZEND_FASTCALL zend_jit_check_constant(const zval *key); diff --git a/ext/opcache/jit/zend_jit_vm_helpers.c b/ext/opcache/jit/zend_jit_vm_helpers.c index 5342731fc81b7..ff7fbd87546eb 100644 --- a/ext/opcache/jit/zend_jit_vm_helpers.c +++ b/ext/opcache/jit/zend_jit_vm_helpers.c @@ -199,6 +199,43 @@ bool ZEND_FASTCALL zend_jit_deprecated_helper(OPLINE_D) return 1; } +void ZEND_FASTCALL zend_jit_undefined_long_key(EXECUTE_DATA_D) +{ + const zend_op *opline = EX(opline); + zval *result = EX_VAR(opline->result.var); + zval *dim; + + ZVAL_NULL(result); + if (opline->op2_type == IS_CONST) { + dim = RT_CONSTANT(opline, opline->op2); + } else { + dim = EX_VAR(opline->op2.var); + } + ZEND_ASSERT(Z_TYPE_P(dim) == IS_LONG); + zend_error(E_WARNING, "Undefined array key " ZEND_LONG_FMT, Z_LVAL_P(dim)); +} + +void ZEND_FASTCALL zend_jit_undefined_string_key(EXECUTE_DATA_D) +{ + const zend_op *opline = EX(opline); + zval *result = EX_VAR(opline->result.var); + zval *dim; + zend_ulong lval; + + ZVAL_NULL(result); + if (opline->op2_type == IS_CONST) { + dim = RT_CONSTANT(opline, opline->op2); + } else { + dim = EX_VAR(opline->op2.var); + } + ZEND_ASSERT(Z_TYPE_P(dim) == IS_STRING); + if (ZEND_HANDLE_NUMERIC(Z_STR_P(dim), lval)) { + zend_error(E_WARNING, "Undefined array key " ZEND_LONG_FMT, lval); + } else { + zend_error(E_WARNING, "Undefined array key \"%s\"", Z_STRVAL_P(dim)); + } +} + ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_profile_helper(ZEND_OPCODE_HANDLER_ARGS) { zend_op_array *op_array = (zend_op_array*)EX(func); diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index b441b3dc966f1..d881b466dd962 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -1966,50 +1966,10 @@ static int zend_jit_undefined_offset_ex_stub(dasm_State **Dst) static int zend_jit_undefined_offset_stub(dasm_State **Dst) { |->undefined_offset: - |.if X64WIN - | sub r4, 0x28 - |.elif X64 - | sub r4, 8 - |.else - | sub r4, 12 - |.endif - | mov r0, EX->opline - | mov ecx, dword OP:r0->result.var - | cmp byte OP:r0->op2_type, IS_CONST - | SET_Z_TYPE_INFO FP + r1, IS_NULL - | jne >2 - |.if X64 - | movsxd r1, dword OP:r0->op2.constant - | add r0, r1 - |.else - | mov r0, aword OP:r0->op2.zv - |.endif - | jmp >3 - |2: - | mov eax, dword OP:r0->op2.var - | add r0, FP - |3: - |.if X64WIN - | mov CARG1, E_WARNING - | LOAD_ADDR CARG2, "Undefined array key " ZEND_LONG_FMT - | mov CARG3, aword [r0] - | EXT_CALL zend_error, r0 - | add r4, 0x28 // stack alignment - |.elif X64 - | mov CARG1, E_WARNING - | LOAD_ADDR CARG2, "Undefined array key " ZEND_LONG_FMT - | mov CARG3, aword [r0] - | EXT_CALL zend_error, r0 - | add r4, 8 // stack alignment - |.else - | sub r4, 4 - | push aword [r0] - | push "Undefined array key " ZEND_LONG_FMT - | push E_WARNING - | EXT_CALL zend_error, r0 - | add r4, 28 - |.endif - | ret + || if (!GCC_GLOBAL_REGS) { + | mov FCARG1a, FP + || } + | EXT_JMP zend_jit_undefined_long_key, r0 return 1; } @@ -2026,54 +1986,10 @@ static int zend_jit_undefined_index_ex_stub(dasm_State **Dst) static int zend_jit_undefined_index_stub(dasm_State **Dst) { |->undefined_index: - |.if X64WIN - | sub r4, 0x28 - |.elif X64 - | sub r4, 8 - |.else - | sub r4, 12 - |.endif - | mov r0, EX->opline - | mov ecx, dword OP:r0->result.var - | cmp byte OP:r0->op2_type, IS_CONST - | SET_Z_TYPE_INFO FP + r1, IS_NULL - | jne >2 - |.if X64 - | movsxd r1, dword OP:r0->op2.constant - | add r0, r1 - |.else - | mov r0, aword OP:r0->op2.zv - |.endif - | jmp >3 - |2: - | mov eax, dword OP:r0->op2.var - | add r0, FP - |3: - |.if X64WIN - | mov CARG1, E_WARNING - | LOAD_ADDR CARG2, "Undefined array key \"%s\"" - | mov CARG3, aword [r0] - | add CARG3, offsetof(zend_string, val) - | EXT_CALL zend_error, r0 - | add r4, 0x28 - |.elif X64 - | mov CARG1, E_WARNING - | LOAD_ADDR CARG2, "Undefined array key \"%s\"" - | mov CARG3, aword [r0] - | add CARG3, offsetof(zend_string, val) - | EXT_CALL zend_error, r0 - | add r4, 8 - |.else - | sub r4, 4 - | mov r0, aword [r0] - | add r0, offsetof(zend_string, val) - | push r0 - | push "Undefined array key \"%s\"" - | push E_WARNING - | EXT_CALL zend_error, r0 - | add r4, 28 - |.endif - | ret + || if (!GCC_GLOBAL_REGS) { + | mov FCARG1a, FP + || } + | EXT_JMP zend_jit_undefined_string_key, r0 return 1; } diff --git a/ext/opcache/tests/jit/gh12812.phpt b/ext/opcache/tests/jit/gh12812.phpt new file mode 100644 index 0000000000000..267abf2aae064 --- /dev/null +++ b/ext/opcache/tests/jit/gh12812.phpt @@ -0,0 +1,29 @@ +--TEST-- +GH-12812: JIT: Integer string in variable used as offset produces wrong undefined array key warning +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +--FILE-- +getMessage(), "\n"; +} +try { + var_dump($container[$dimension]); +} catch (\Throwable $e) { + echo $e->getMessage(), "\n"; +} + +?> +--EXPECTF-- +Warning: Undefined array key 7 in %s on line %d +NULL + +Warning: Undefined array key 7 in %s on line %d +NULL From 423a1e586e186d1df7838216a88b63b67f37afea Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 28 Nov 2023 22:49:39 +0300 Subject: [PATCH 77/92] Fixed GH-8251: Narrowing occurred during type inference of ZEND_FETCH_DIM_W --- Zend/Optimizer/zend_inference.c | 4 +--- ext/opcache/tests/opt/inference_023.phpt | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 ext/opcache/tests/opt/inference_023.phpt diff --git a/Zend/Optimizer/zend_inference.c b/Zend/Optimizer/zend_inference.c index ae04094f12f09..549287efa2db0 100644 --- a/Zend/Optimizer/zend_inference.c +++ b/Zend/Optimizer/zend_inference.c @@ -3682,9 +3682,7 @@ static zend_always_inline zend_result _zend_update_type_info( UPDATE_SSA_TYPE(tmp, ssa_op->op1_def); } else { /* invalid key type */ - tmp = (tmp & (MAY_BE_RC1|MAY_BE_RCN|MAY_BE_ARRAY)) | - (t1 & ~(MAY_BE_RC1|MAY_BE_RCN|MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE)); - UPDATE_SSA_TYPE(tmp, ssa_op->op1_def); + return SUCCESS; } COPY_SSA_OBJ_TYPE(ssa_op->op1_use, ssa_op->op1_def); } diff --git a/ext/opcache/tests/opt/inference_023.phpt b/ext/opcache/tests/opt/inference_023.phpt new file mode 100644 index 0000000000000..0949972796eb9 --- /dev/null +++ b/ext/opcache/tests/opt/inference_023.phpt @@ -0,0 +1,24 @@ +--TEST-- +Type inference 023: FETCH_DIM_W +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.optimization_level=-1 +--FILE-- += 0) { + $a[$n]->x = 2; + } + $n++; + $a[$n] = new stdClass(); + $a[$n]->x = 1; + } +} +?> +DONE +--EXPECT-- +DONE From 752192700f8d4f2512e58e3d279dd9f5c80687e3 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Wed, 29 Nov 2023 00:27:17 +0100 Subject: [PATCH 78/92] [skip ci] Skip resource intensive tidy test on GA --- ext/tidy/tests/parsing_file_too_large.phpt | 1 + 1 file changed, 1 insertion(+) diff --git a/ext/tidy/tests/parsing_file_too_large.phpt b/ext/tidy/tests/parsing_file_too_large.phpt index 25829bf4e9595..46196c0a5fdce 100644 --- a/ext/tidy/tests/parsing_file_too_large.phpt +++ b/ext/tidy/tests/parsing_file_too_large.phpt @@ -7,6 +7,7 @@ tidy if (PHP_INT_SIZE != 8) die("skip this test is for 64bit platform only"); if (getenv("SKIP_SLOW_TESTS")) die("skip slow test"); if (getenv("SKIP_ASAN")) die("skip too big for asan"); +if (getenv("GITHUB_ACTIONS")) die("skip potentially crashes on GitHub actions"); ?> --CONFLICTS-- all From 706e51ad8a85c888ada4491e90bf421d34af5c4e Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Wed, 29 Nov 2023 00:36:46 +0100 Subject: [PATCH 79/92] Fix travis_wait It seems travis_wait is broken. Output skipped tests to avoid the timeout. Closes GH-12822 --- .travis.yml | 2 +- travis/test.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 6c51e13a0fab5..9f764251afffc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -85,7 +85,7 @@ before_script: # Run PHPs run-tests.php script: - - travis_wait 60 ./travis/test.sh -d opcache.jit_buffer_size=16M -d opcache.jit=tracing + - ./travis/test.sh -d opcache.jit_buffer_size=16M -d opcache.jit=tracing - sapi/cli/php -d extension_dir=`pwd`/modules -r 'dl("zend_test");' after_success: diff --git a/travis/test.sh b/travis/test.sh index c1617f782ab2d..92253042751e4 100755 --- a/travis/test.sh +++ b/travis/test.sh @@ -7,7 +7,7 @@ if [ -z "$ARM64" ]; then export JOBS=$(nproc); else export JOBS=16; fi export SKIP_SLOW_TESTS=1 export SKIP_IO_CAPTURE_TESTS=1 ./sapi/cli/php run-tests.php -P \ - -g "FAIL,BORK,LEAK" --offline --show-diff --show-slow 1000 \ + -g "FAIL,SKIP,BORK,LEAK" --offline --show-diff --show-slow 1000 \ --no-progress \ --set-timeout 120 -j$JOBS \ -d extension=`pwd`/modules/zend_test.so \ From 061058a9b1bbd90d27d97d79aebcf2b5029767b0 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Wed, 29 Nov 2023 20:49:29 +0100 Subject: [PATCH 80/92] Test fixes for libxml2 2.12.0 --- NEWS | 1 + ext/dom/tests/DOMDocument_loadXML_error1.phpt | 4 +++ .../DOMDocument_loadXML_error1_gte2_12.phpt | 26 ++++++++++++++++ .../DOMDocument_loadXML_error2_gte2_11.phpt | 2 +- .../DOMDocument_loadXML_error2_gte2_12.phpt | 30 +++++++++++++++++++ ext/dom/tests/DOMDocument_load_error1.phpt | 4 +++ .../DOMDocument_load_error1_gte2_12.phpt | 26 ++++++++++++++++ .../DOMDocument_load_error2_gte2_11.phpt | 2 +- .../DOMDocument_load_error2_gte2_12.phpt | 30 +++++++++++++++++++ ext/xml/tests/bug81351.phpt | 4 +-- ext/xml/tests/xml_error_string_basic.phpt | 6 ++-- 11 files changed, 128 insertions(+), 7 deletions(-) create mode 100644 ext/dom/tests/DOMDocument_loadXML_error1_gte2_12.phpt create mode 100644 ext/dom/tests/DOMDocument_loadXML_error2_gte2_12.phpt create mode 100644 ext/dom/tests/DOMDocument_load_error1_gte2_12.phpt create mode 100644 ext/dom/tests/DOMDocument_load_error2_gte2_12.phpt diff --git a/NEWS b/NEWS index 1dac798eba6d3..898f1b9e22f67 100644 --- a/NEWS +++ b/NEWS @@ -23,6 +23,7 @@ PHP NEWS - LibXML: . Fixed bug GH-12702 (libxml2 2.12.0 issue building from src). (nono303) + . Fixed test failures for libxml2 2.12.0. (nielsdos) - MySQLnd: . Avoid using uninitialised struct. (mikhainin) diff --git a/ext/dom/tests/DOMDocument_loadXML_error1.phpt b/ext/dom/tests/DOMDocument_loadXML_error1.phpt index 14d99e4ed9ad9..2af3217bd6c6a 100644 --- a/ext/dom/tests/DOMDocument_loadXML_error1.phpt +++ b/ext/dom/tests/DOMDocument_loadXML_error1.phpt @@ -1,5 +1,9 @@ --TEST-- Test DOMDocument::loadXML() detects not-well formed XML +--SKIPIF-- += 21200) die('skip libxml2 test variant for version < 2.12'); +?> --DESCRIPTION-- This test verifies the method detects an opening and ending tag mismatch Environment variables used in the test: diff --git a/ext/dom/tests/DOMDocument_loadXML_error1_gte2_12.phpt b/ext/dom/tests/DOMDocument_loadXML_error1_gte2_12.phpt new file mode 100644 index 0000000000000..e1ded0ffadd7f --- /dev/null +++ b/ext/dom/tests/DOMDocument_loadXML_error1_gte2_12.phpt @@ -0,0 +1,26 @@ +--TEST-- +Test DOMDocument::loadXML() detects not-well formed XML +--SKIPIF-- += 2.12'); +?> +--DESCRIPTION-- +This test verifies the method detects an opening and ending tag mismatch +Environment variables used in the test: +- XML_FILE: the xml file to load +- LOAD_OPTIONS: the second parameter to pass to the method +- EXPECTED_RESULT: the expected result +--CREDITS-- +Antonio Diaz Ruiz +--EXTENSIONS-- +dom +--ENV-- +XML_FILE=/not_well_formed.xml +LOAD_OPTIONS=0 +EXPECTED_RESULT=0 +--FILE_EXTERNAL-- +domdocumentloadxml_test_method.inc +--EXPECTF-- +Warning: DOMDocument::load%r(XML){0,1}%r(): Opening and ending tag mismatch: title line 5 and book %s + +Warning: DOMDocument::load%r(XML){0,1}%r(): %rexpected '>'|Opening and ending tag mismatch: book line (4|5) and books%r %s diff --git a/ext/dom/tests/DOMDocument_loadXML_error2_gte2_11.phpt b/ext/dom/tests/DOMDocument_loadXML_error2_gte2_11.phpt index ff5ceb3fbed53..f52d3348138c5 100644 --- a/ext/dom/tests/DOMDocument_loadXML_error2_gte2_11.phpt +++ b/ext/dom/tests/DOMDocument_loadXML_error2_gte2_11.phpt @@ -2,7 +2,7 @@ Test DOMDocument::loadXML() detects not-well formed XML --SKIPIF-- = 2.11'); +if (LIBXML_VERSION < 21100 || LIBXML_VERSION >= 21200) die('skip libxml2 test variant for version >= 2.11 && <= 2.12'); ?> --DESCRIPTION-- This test verifies the method detects attributes values not closed between " or ' diff --git a/ext/dom/tests/DOMDocument_loadXML_error2_gte2_12.phpt b/ext/dom/tests/DOMDocument_loadXML_error2_gte2_12.phpt new file mode 100644 index 0000000000000..6a3ff5841f565 --- /dev/null +++ b/ext/dom/tests/DOMDocument_loadXML_error2_gte2_12.phpt @@ -0,0 +1,30 @@ +--TEST-- +Test DOMDocument::loadXML() detects not-well formed XML +--SKIPIF-- += 2.12'); +?> +--DESCRIPTION-- +This test verifies the method detects attributes values not closed between " or ' +Environment variables used in the test: +- XML_FILE: the xml file to load +- LOAD_OPTIONS: the second parameter to pass to the method +- EXPECTED_RESULT: the expected result +--CREDITS-- +Antonio Diaz Ruiz +--EXTENSIONS-- +dom +--ENV-- +XML_FILE=/not_well_formed2.xml +LOAD_OPTIONS=0 +EXPECTED_RESULT=0 +--FILE_EXTERNAL-- +domdocumentloadxml_test_method.inc +--EXPECTF-- +Warning: DOMDocument::loadXML(): AttValue: " or ' expected in Entity, line: 4 in %s on line %d + +Warning: DOMDocument::loadXML(): internal error: xmlParseStartTag: problem parsing attributes in Entity, line: 4 in %s on line %d + +Warning: DOMDocument::loadXML(): Couldn't find end of Start Tag book line 4 in Entity, line: 4 in %s on line %d + +Warning: DOMDocument::loadXML(): Opening and ending tag mismatch: books line 3 and book in Entity, line: 7 in %s on line %d diff --git a/ext/dom/tests/DOMDocument_load_error1.phpt b/ext/dom/tests/DOMDocument_load_error1.phpt index f736b0a0e81c6..2da8c0cd18b4e 100644 --- a/ext/dom/tests/DOMDocument_load_error1.phpt +++ b/ext/dom/tests/DOMDocument_load_error1.phpt @@ -1,5 +1,9 @@ --TEST-- Test DOMDocument::load() detects not-well formed XML +--SKIPIF-- += 21200) die('skip libxml2 test variant for version < 2.12'); +?> --DESCRIPTION-- This test verifies the method detects an opening and ending tag mismatch Environment variables used in the test: diff --git a/ext/dom/tests/DOMDocument_load_error1_gte2_12.phpt b/ext/dom/tests/DOMDocument_load_error1_gte2_12.phpt new file mode 100644 index 0000000000000..183c8406fdfc8 --- /dev/null +++ b/ext/dom/tests/DOMDocument_load_error1_gte2_12.phpt @@ -0,0 +1,26 @@ +--TEST-- +Test DOMDocument::load() detects not-well formed XML +--SKIPIF-- += 2.12'); +?> +--DESCRIPTION-- +This test verifies the method detects an opening and ending tag mismatch +Environment variables used in the test: +- XML_FILE: the xml file to load +- LOAD_OPTIONS: the second parameter to pass to the method +- EXPECTED_RESULT: the expected result +--CREDITS-- +Antonio Diaz Ruiz +--EXTENSIONS-- +dom +--ENV-- +XML_FILE=/not_well_formed.xml +LOAD_OPTIONS=0 +EXPECTED_RESULT=0 +--FILE_EXTERNAL-- +domdocumentload_test_method.inc +--EXPECTF-- +Warning: DOMDocument::load%r(XML){0,1}%r(): Opening and ending tag mismatch: title line 5 and book %s + +Warning: DOMDocument::load%r(XML){0,1}%r(): %rexpected '>'|Opening and ending tag mismatch: book line (4|5) and books%r %s diff --git a/ext/dom/tests/DOMDocument_load_error2_gte2_11.phpt b/ext/dom/tests/DOMDocument_load_error2_gte2_11.phpt index 32b6bf161142e..4d9f992b3bafd 100644 --- a/ext/dom/tests/DOMDocument_load_error2_gte2_11.phpt +++ b/ext/dom/tests/DOMDocument_load_error2_gte2_11.phpt @@ -2,7 +2,7 @@ Test DOMDocument::load() detects not-well formed --SKIPIF-- = 2.11'); +if (LIBXML_VERSION < 21100 || LIBXML_VERSION >= 21200) die('skip libxml2 test variant for version >= 2.11 && <= 2.12'); ?> --DESCRIPTION-- This test verifies the method detects attributes values not closed between " or ' diff --git a/ext/dom/tests/DOMDocument_load_error2_gte2_12.phpt b/ext/dom/tests/DOMDocument_load_error2_gte2_12.phpt new file mode 100644 index 0000000000000..4fadf41736124 --- /dev/null +++ b/ext/dom/tests/DOMDocument_load_error2_gte2_12.phpt @@ -0,0 +1,30 @@ +--TEST-- +Test DOMDocument::load() detects not-well formed +--SKIPIF-- += 2.12'); +?> +--DESCRIPTION-- +This test verifies the method detects attributes values not closed between " or ' +Environment variables used in the test: +- XML_FILE: the xml file to load +- LOAD_OPTIONS: the second parameter to pass to the method +- EXPECTED_RESULT: the expected result +--CREDITS-- +Antonio Diaz Ruiz +--EXTENSIONS-- +dom +--ENV-- +XML_FILE=/not_well_formed2.xml +LOAD_OPTIONS=0 +EXPECTED_RESULT=0 +--FILE_EXTERNAL-- +domdocumentload_test_method.inc +--EXPECTF-- +Warning: DOMDocument::load(): AttValue: " or ' expected in %s on line %d + +Warning: DOMDocument::load(): internal error: xmlParseStartTag: problem parsing attributes in %s on line %d + +Warning: DOMDocument::load(): Couldn't find end of Start Tag book line 4 in %s on line %d + +Warning: DOMDocument::load(): Opening and ending tag mismatch: books line 3 and book in %s on line %d diff --git a/ext/xml/tests/bug81351.phpt b/ext/xml/tests/bug81351.phpt index 78aea041046f7..7380a9a937008 100644 --- a/ext/xml/tests/bug81351.phpt +++ b/ext/xml/tests/bug81351.phpt @@ -21,6 +21,6 @@ $code = xml_get_error_code($parser); $error = xml_error_string($code); echo "xml_parse returned $success, xml_get_error_code = $code, xml_error_string = $error\r\n"; ?> ---EXPECT-- +--EXPECTF-- xml_parse returned 1, xml_get_error_code = 0, xml_error_string = No error -xml_parse returned 0, xml_get_error_code = 5, xml_error_string = Invalid document end +%rxml_parse returned 0, xml_get_error_code = 5, xml_error_string = Invalid document end|xml_parse returned 0, xml_get_error_code = 77, xml_error_string = Tag not finished%r diff --git a/ext/xml/tests/xml_error_string_basic.phpt b/ext/xml/tests/xml_error_string_basic.phpt index 86dede1730f7e..a23ec8741d592 100644 --- a/ext/xml/tests/xml_error_string_basic.phpt +++ b/ext/xml/tests/xml_error_string_basic.phpt @@ -21,9 +21,9 @@ foreach ($xmls as $xml) { xml_parser_free($xml_parser); } ?> ---EXPECT-- -int(5) -string(20) "Invalid document end" +--EXPECTF-- +int(%r5|77%r) +string(%d) %r"Invalid document end"|"Tag not finished"%r int(47) string(35) "Processing Instruction not finished" int(57) From bedf1083f34a301f3fc94102a10ed0cae2780344 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 30 Nov 2023 20:26:24 +0100 Subject: [PATCH 81/92] Add missing NULL pointer checks related to the previous call frame --- Zend/zend_builtin_functions.c | 6 +++--- ext/standard/basic_functions.c | 2 +- ..._functions_without_previous_call_frame_01.phpt | 15 +++++++++++++++ ..._functions_without_previous_call_frame_02.phpt | 15 +++++++++++++++ ..._functions_without_previous_call_frame_03.phpt | 15 +++++++++++++++ ..._functions_without_previous_call_frame_04.phpt | 15 +++++++++++++++ 6 files changed, 64 insertions(+), 4 deletions(-) create mode 100644 ext/standard/tests/general_functions/register_shutdown_functions_without_previous_call_frame_01.phpt create mode 100644 ext/standard/tests/general_functions/register_shutdown_functions_without_previous_call_frame_02.phpt create mode 100644 ext/standard/tests/general_functions/register_shutdown_functions_without_previous_call_frame_03.phpt create mode 100644 ext/standard/tests/general_functions/register_shutdown_functions_without_previous_call_frame_04.phpt diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index 5cebbbc560894..9c4b836caface 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -154,7 +154,7 @@ ZEND_FUNCTION(func_num_args) ZEND_PARSE_PARAMETERS_NONE(); - if (ZEND_CALL_INFO(ex) & ZEND_CALL_CODE) { + if (ex && (ZEND_CALL_INFO(ex) & ZEND_CALL_CODE)) { zend_throw_error(NULL, "func_num_args() must be called from a function context"); RETURN_THROWS(); } @@ -185,7 +185,7 @@ ZEND_FUNCTION(func_get_arg) } ex = EX(prev_execute_data); - if (ZEND_CALL_INFO(ex) & ZEND_CALL_CODE) { + if (ex && (ZEND_CALL_INFO(ex) & ZEND_CALL_CODE)) { zend_throw_error(NULL, "func_get_arg() cannot be called from the global scope"); RETURN_THROWS(); } @@ -223,7 +223,7 @@ ZEND_FUNCTION(func_get_args) ZEND_PARSE_PARAMETERS_NONE(); - if (ZEND_CALL_INFO(ex) & ZEND_CALL_CODE) { + if (ex && (ZEND_CALL_INFO(ex) & ZEND_CALL_CODE)) { zend_throw_error(NULL, "func_get_args() cannot be called from the global scope"); RETURN_THROWS(); } diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index c3ad0aad9de15..3517b514420d5 100755 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -1541,7 +1541,7 @@ PHP_FUNCTION(forward_static_call) Z_PARAM_VARIADIC('*', fci.params, fci.param_count) ZEND_PARSE_PARAMETERS_END(); - if (!EX(prev_execute_data)->func->common.scope) { + if (!EX(prev_execute_data) || !EX(prev_execute_data)->func->common.scope) { zend_throw_error(NULL, "Cannot call forward_static_call() when no class scope is active"); RETURN_THROWS(); } diff --git a/ext/standard/tests/general_functions/register_shutdown_functions_without_previous_call_frame_01.phpt b/ext/standard/tests/general_functions/register_shutdown_functions_without_previous_call_frame_01.phpt new file mode 100644 index 0000000000000..ee102894cb779 --- /dev/null +++ b/ext/standard/tests/general_functions/register_shutdown_functions_without_previous_call_frame_01.phpt @@ -0,0 +1,15 @@ +--TEST-- +register_shutdown_function() without a previous call frame 01 +--FILE-- + +Done +--EXPECT-- +Done + +Fatal error: Uncaught Error: Cannot call forward_static_call() when no class scope is active in [no active file]:0 +Stack trace: +#0 [internal function]: forward_static_call('hash_hkdf') +#1 {main} + thrown in [no active file] on line 0 diff --git a/ext/standard/tests/general_functions/register_shutdown_functions_without_previous_call_frame_02.phpt b/ext/standard/tests/general_functions/register_shutdown_functions_without_previous_call_frame_02.phpt new file mode 100644 index 0000000000000..69826ac562e25 --- /dev/null +++ b/ext/standard/tests/general_functions/register_shutdown_functions_without_previous_call_frame_02.phpt @@ -0,0 +1,15 @@ +--TEST-- +register_shutdown_function() without a previous call frame 02 +--FILE-- + +Done +--EXPECT-- +Done + +Fatal error: Uncaught Error: Cannot call func_get_args() dynamically in [no active file]:0 +Stack trace: +#0 [internal function]: func_get_args() +#1 {main} + thrown in [no active file] on line 0 diff --git a/ext/standard/tests/general_functions/register_shutdown_functions_without_previous_call_frame_03.phpt b/ext/standard/tests/general_functions/register_shutdown_functions_without_previous_call_frame_03.phpt new file mode 100644 index 0000000000000..dd847b2bb0b6a --- /dev/null +++ b/ext/standard/tests/general_functions/register_shutdown_functions_without_previous_call_frame_03.phpt @@ -0,0 +1,15 @@ +--TEST-- +register_shutdown_function() without a previous call frame 03 +--FILE-- + +Done +--EXPECT-- +Done + +Fatal error: Uncaught Error: Cannot call func_num_args() dynamically in [no active file]:0 +Stack trace: +#0 [internal function]: func_num_args() +#1 {main} + thrown in [no active file] on line 0 diff --git a/ext/standard/tests/general_functions/register_shutdown_functions_without_previous_call_frame_04.phpt b/ext/standard/tests/general_functions/register_shutdown_functions_without_previous_call_frame_04.phpt new file mode 100644 index 0000000000000..220af3a67ff97 --- /dev/null +++ b/ext/standard/tests/general_functions/register_shutdown_functions_without_previous_call_frame_04.phpt @@ -0,0 +1,15 @@ +--TEST-- +register_shutdown_function() without a previous call frame 04 +--FILE-- + +Done +--EXPECT-- +Done + +Fatal error: Uncaught ArgumentCountError: func_get_arg() expects exactly 1 argument, 0 given in [no active file]:0 +Stack trace: +#0 [internal function]: func_get_arg() +#1 {main} + thrown in [no active file] on line 0 From 9a69bb2d582ed127fb2a82273e9f9b9d6d6e4612 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 30 Nov 2023 20:27:07 +0100 Subject: [PATCH 82/92] Add missing NULL checks for spl autoload table Closes GH-12840. --- NEWS | 1 + ext/spl/php_spl.c | 6 ++++-- .../spl_autoload_unregister_without_registrations.phpt | 10 ++++++++++ 3 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 ext/spl/tests/spl_autoload_unregister_without_registrations.phpt diff --git a/NEWS b/NEWS index 898f1b9e22f67..e3f6d8d8c4a24 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,7 @@ PHP NEWS php_message_handler_for_zend). (ilutov) . Fixed bug GH-12758 / GH-12768 (Invalid opline in OOM handlers within ZEND_FUNC_GET_ARGS and ZEND_BIND_STATIC). (Florian Engelhardt) + . Fix various missing NULL checks. (nielsdos, dstogov) - Date: . Fixed improbably integer overflow while parsing really large (or small) diff --git a/ext/spl/php_spl.c b/ext/spl/php_spl.c index 710b2f97ffb9a..715b10c456dea 100644 --- a/ext/spl/php_spl.c +++ b/ext/spl/php_spl.c @@ -585,8 +585,10 @@ PHP_FUNCTION(spl_autoload_unregister) if (fcc.function_handler && zend_string_equals_literal( fcc.function_handler->common.function_name, "spl_autoload_call")) { - /* Don't destroy the hash table, as we might be iterating over it right now. */ - zend_hash_clean(spl_autoload_functions); + if (spl_autoload_functions) { + /* Don't destroy the hash table, as we might be iterating over it right now. */ + zend_hash_clean(spl_autoload_functions); + } RETURN_TRUE; } diff --git a/ext/spl/tests/spl_autoload_unregister_without_registrations.phpt b/ext/spl/tests/spl_autoload_unregister_without_registrations.phpt new file mode 100644 index 0000000000000..0a7ca5a1352fd --- /dev/null +++ b/ext/spl/tests/spl_autoload_unregister_without_registrations.phpt @@ -0,0 +1,10 @@ +--TEST-- +spl_autoload_unregister("spl_autoload_call") without registrations +--FILE-- + +Done +--EXPECT-- +bool(true) +Done From 1e55c9760178f9d5e1de8b251537b3e8ccf44feb Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Fri, 1 Dec 2023 17:08:16 +0300 Subject: [PATCH 83/92] Fixed type inference Fixes oss-fuzz #64577, #64579, #64589 --- Zend/Optimizer/zend_inference.c | 3 ++- ext/opcache/tests/opt/inference_024.phpt | 23 +++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 ext/opcache/tests/opt/inference_024.phpt diff --git a/Zend/Optimizer/zend_inference.c b/Zend/Optimizer/zend_inference.c index 549287efa2db0..16edb2cc82e46 100644 --- a/Zend/Optimizer/zend_inference.c +++ b/Zend/Optimizer/zend_inference.c @@ -3673,7 +3673,8 @@ static zend_always_inline zend_result _zend_update_type_info( tmp &= ~MAY_BE_ARRAY_EMPTY; } } - if (((tmp & MAY_BE_ARRAY) && (tmp & MAY_BE_ARRAY_KEY_ANY)) + if (!(tmp & MAY_BE_ARRAY) + || (tmp & MAY_BE_ARRAY_KEY_ANY) || opline->opcode == ZEND_FETCH_DIM_FUNC_ARG || opline->opcode == ZEND_FETCH_DIM_R || opline->opcode == ZEND_FETCH_DIM_IS diff --git a/ext/opcache/tests/opt/inference_024.phpt b/ext/opcache/tests/opt/inference_024.phpt new file mode 100644 index 0000000000000..a34ac5c1ece51 --- /dev/null +++ b/ext/opcache/tests/opt/inference_024.phpt @@ -0,0 +1,23 @@ +--TEST-- +Type inference 024: FETCH_DIM_W +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.optimization_level=-1 +--FILE-- + +DONE +--EXPECT-- +DONE From df259f88daaf7df5673fd78a0a1b76a1d831d0a2 Mon Sep 17 00:00:00 2001 From: Patrick Prasse Date: Fri, 17 Nov 2023 16:32:23 +0000 Subject: [PATCH 84/92] Fix bug GH-12705: Segmentation fault in fpm_status_export_to_zval Closes GH-12706 --- NEWS | 4 ++++ sapi/fpm/fpm/fpm_status.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index aaf852a8ad2cc..903b836806cac 100644 --- a/NEWS +++ b/NEWS @@ -14,6 +14,10 @@ PHP NEWS . Fixed bug GH-12616 (DOM: Removing XMLNS namespace node results in invalid default: prefix). (nielsdos) +- FPM: + . Fixed bug GH-12705 (Segmentation fault in fpm_status_export_to_zval). + (Patrick Prasse) + - Intl: . Fixed bug GH-12635 (Test bug69398.phpt fails with ICU 74.1). (nielsdos) diff --git a/sapi/fpm/fpm/fpm_status.c b/sapi/fpm/fpm/fpm_status.c index f0d869444afce..f698753cf4c65 100644 --- a/sapi/fpm/fpm/fpm_status.c +++ b/sapi/fpm/fpm/fpm_status.c @@ -56,7 +56,7 @@ int fpm_status_export_to_zval(zval *status) scoreboard_p = fpm_scoreboard_acquire(NULL, 1); if (!scoreboard_p) { - zlog(ZLOG_NOTICE, "[pool %s] status: scoreboard already in use.", scoreboard_p->pool); + zlog(ZLOG_NOTICE, "[pool (unknown)] status: scoreboard already in use."); return -1; } From f203edd3c537b5f106eaeaaad8afbe59a5095a97 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 30 Nov 2023 13:41:07 +0100 Subject: [PATCH 85/92] Fix leak of call->extra_named_params on internal __call Fixes GH-12835 Closes GH-12836 --- NEWS | 2 ++ Zend/zend_vm_def.h | 3 +++ Zend/zend_vm_execute.h | 6 +++++ ext/zend_test/test.c | 21 +++++++++++++++++ ext/zend_test/test.stub.php | 5 ++++ ext/zend_test/test_arginfo.h | 24 +++++++++++++++++++- ext/zend_test/tests/internal_magic_call.phpt | 23 +++++++++++++++++++ 7 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 ext/zend_test/tests/internal_magic_call.phpt diff --git a/NEWS b/NEWS index e10ed67f6051e..56aa5d51bb2ad 100644 --- a/NEWS +++ b/NEWS @@ -10,6 +10,8 @@ PHP NEWS . Fixed bug GH-12758 / GH-12768 (Invalid opline in OOM handlers within ZEND_FUNC_GET_ARGS and ZEND_BIND_STATIC). (Florian Engelhardt) . Fix various missing NULL checks. (nielsdos, dstogov) + . Fixed bug GH-12835 (Leak of call->extra_named_params on internal __call). + (ilutov) - Date: . Fixed improbably integer overflow while parsing really large (or small) diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 342fe6fb5ba98..2a48b9c3713bb 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -8783,6 +8783,9 @@ ZEND_VM_HANDLER(158, ZEND_CALL_TRAMPOLINE, ANY, ANY, SPEC(OBSERVER)) EG(current_execute_data) = call->prev_execute_data; zend_vm_stack_free_args(call); + if (UNEXPECTED(call_info & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) { + zend_free_extra_named_params(call->extra_named_params); + } if (ret == &retval) { zval_ptr_dtor(ret); } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 7387164a6d3d4..3bc01a597fa6c 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -3457,6 +3457,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_HANDLER(Z EG(current_execute_data) = call->prev_execute_data; zend_vm_stack_free_args(call); + if (UNEXPECTED(call_info & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) { + zend_free_extra_named_params(call->extra_named_params); + } if (ret == &retval) { zval_ptr_dtor(ret); } @@ -3598,6 +3601,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_OBSERVER_ EG(current_execute_data) = call->prev_execute_data; zend_vm_stack_free_args(call); + if (UNEXPECTED(call_info & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) { + zend_free_extra_named_params(call->extra_named_params); + } if (ret == &retval) { zval_ptr_dtor(ret); } diff --git a/ext/zend_test/test.c b/ext/zend_test/test.c index 41cca5ae6e61a..901cd8e3063da 100644 --- a/ext/zend_test/test.c +++ b/ext/zend_test/test.c @@ -65,6 +65,7 @@ static zend_class_entry *zend_test_ns2_ns_foo_class; static zend_class_entry *zend_test_unit_enum; static zend_class_entry *zend_test_string_enum; static zend_class_entry *zend_test_int_enum; +static zend_class_entry *zend_test_magic_call; static zend_object_handlers zend_test_class_handlers; static ZEND_FUNCTION(zend_test_func) @@ -802,6 +803,24 @@ static ZEND_METHOD(ZendTestForbidDynamicCall, callStatic) zend_forbid_dynamic_call(); } +static ZEND_METHOD(_ZendTestMagicCall, __call) +{ + zend_string *name; + zval *arguments; + + ZEND_PARSE_PARAMETERS_START(2, 2) + Z_PARAM_STR(name) + Z_PARAM_ARRAY(arguments) + ZEND_PARSE_PARAMETERS_END(); + + zval name_zv; + ZVAL_STR(&name_zv, name); + + zend_string_addref(name); + Z_TRY_ADDREF_P(arguments); + RETURN_ARR(zend_new_pair(&name_zv, arguments)); +} + PHP_INI_BEGIN() STD_PHP_INI_BOOLEAN("zend_test.replace_zend_execute_ex", "0", PHP_INI_SYSTEM, OnUpdateBool, replace_zend_execute_ex, zend_zend_test_globals, zend_test_globals) STD_PHP_INI_BOOLEAN("zend_test.register_passes", "0", PHP_INI_SYSTEM, OnUpdateBool, register_passes, zend_zend_test_globals, zend_test_globals) @@ -914,6 +933,8 @@ PHP_MINIT_FUNCTION(zend_test) zend_test_string_enum = register_class_ZendTestStringEnum(); zend_test_int_enum = register_class_ZendTestIntEnum(); + zend_test_magic_call = register_class__ZendTestMagicCall(); + zend_register_functions(NULL, ext_function_legacy, NULL, EG(current_module)->type); // Loading via dl() not supported with the observer API diff --git a/ext/zend_test/test.stub.php b/ext/zend_test/test.stub.php index d877dac726d52..cf8ac50bd0629 100644 --- a/ext/zend_test/test.stub.php +++ b/ext/zend_test/test.stub.php @@ -47,6 +47,11 @@ public function returnsThrowable(): Throwable {} static public function variadicTest(string|Iterator ...$elements) : static {} } + class _ZendTestMagicCall + { + public function __call(string $name, array $args): mixed {} + } + class _ZendTestChildClass extends _ZendTestClass { public function returnsThrowable(): Exception {} diff --git a/ext/zend_test/test_arginfo.h b/ext/zend_test/test_arginfo.h index 34f56f3d95040..70439ff726164 100644 --- a/ext/zend_test/test_arginfo.h +++ b/ext/zend_test/test_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: a272e1920e36041da1c20eaf3afe1d6032164d24 */ + * Stub hash: 420711ec6f040d38bde450a169bf1186f8531191 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_array_return, 0, 0, IS_ARRAY, 0) ZEND_END_ARG_INFO() @@ -142,6 +142,11 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class__ZendTestClass_variadicTes ZEND_ARG_VARIADIC_OBJ_TYPE_MASK(0, elements, Iterator, MAY_BE_STRING) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class__ZendTestMagicCall___call, 0, 2, IS_MIXED, 0) + ZEND_ARG_TYPE_INFO(0, name, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, args, IS_ARRAY, 0) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class__ZendTestChildClass_returnsThrowable, 0, 0, Exception, 0) ZEND_END_ARG_INFO() @@ -220,6 +225,7 @@ static ZEND_METHOD(_ZendTestClass, __toString); static ZEND_METHOD(_ZendTestClass, returnsStatic); static ZEND_METHOD(_ZendTestClass, returnsThrowable); static ZEND_METHOD(_ZendTestClass, variadicTest); +static ZEND_METHOD(_ZendTestMagicCall, __call); static ZEND_METHOD(_ZendTestChildClass, returnsThrowable); static ZEND_METHOD(_ZendTestTrait, testMethod); static ZEND_METHOD(ZendTestParameterAttribute, __construct); @@ -296,6 +302,12 @@ static const zend_function_entry class__ZendTestClass_methods[] = { }; +static const zend_function_entry class__ZendTestMagicCall_methods[] = { + ZEND_ME(_ZendTestMagicCall, __call, arginfo_class__ZendTestMagicCall___call, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + + static const zend_function_entry class__ZendTestChildClass_methods[] = { ZEND_ME(_ZendTestChildClass, returnsThrowable, arginfo_class__ZendTestChildClass_returnsThrowable, ZEND_ACC_PUBLIC) ZEND_FE_END @@ -486,6 +498,16 @@ static zend_class_entry *register_class__ZendTestClass(zend_class_entry *class_e return class_entry; } +static zend_class_entry *register_class__ZendTestMagicCall(void) +{ + zend_class_entry ce, *class_entry; + + INIT_CLASS_ENTRY(ce, "_ZendTestMagicCall", class__ZendTestMagicCall_methods); + class_entry = zend_register_internal_class_ex(&ce, NULL); + + return class_entry; +} + static zend_class_entry *register_class__ZendTestChildClass(zend_class_entry *class_entry__ZendTestClass) { zend_class_entry ce, *class_entry; diff --git a/ext/zend_test/tests/internal_magic_call.phpt b/ext/zend_test/tests/internal_magic_call.phpt new file mode 100644 index 0000000000000..2139ddeb5004a --- /dev/null +++ b/ext/zend_test/tests/internal_magic_call.phpt @@ -0,0 +1,23 @@ +--TEST-- +GH-12835: call->extra_named_params leaks on internal __call +--EXTENSIONS-- +zend_test +--FILE-- +test('a', 'b', c: 'c')); +?> +--EXPECT-- +array(2) { + [0]=> + string(4) "test" + [1]=> + array(3) { + [0]=> + string(1) "a" + [1]=> + string(1) "b" + ["c"]=> + string(1) "c" + } +} From 4eee81b50944033b6f0a1069d64229df6414271d Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 30 Nov 2023 20:43:50 +0100 Subject: [PATCH 86/92] Fix GH-12838: [SOAP] Temporary WSDL cache files not being deleted If there are two users that can execute the script that caches a WSDL, but the script is owned by a single user, then the caching code will name the cached file with the file owner username and a hash of the uri. When one of the two tries to rename the file created by the other process, this does not work because it has no permission to do so. This then leaves temporary files floating in the temp directory. To fix the immediate problem, unlink the file after rename has failed. On the long term, this has to be fixed by taking the username of the process instead of the username of the file owner. Closes GH-12841. --- NEWS | 4 ++++ ext/soap/php_sdl.c | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 56aa5d51bb2ad..ceda8d103caa8 100644 --- a/NEWS +++ b/NEWS @@ -56,6 +56,10 @@ PHP NEWS - PHPDBG: . Fixed bug GH-12675 (MEMORY_LEAK in phpdbg_prompt.c). (nielsdos) +- SOAP: + . Fixed bug GH-12838 ([SOAP] Temporary WSDL cache files not being deleted). + (nielsdos) + - SPL: . Fixed bug GH-12721 (SplFileInfo::getFilename() segfault in combination with GlobIterator and no directory separator). (nielsdos) diff --git a/ext/soap/php_sdl.c b/ext/soap/php_sdl.c index 5c833dc45cf04..749f5a5685ec2 100644 --- a/ext/soap/php_sdl.c +++ b/ext/soap/php_sdl.c @@ -2381,7 +2381,9 @@ static void add_sdl_to_cache(const char *fn, const char *uri, time_t t, sdlPtr s /* Make sure that incomplete files (e.g. due to disk space issues, see bug #66150) are not utilised. */ if (valid_file) { /* This is allowed to fail, this means that another process was raced to create the file. */ - (void) VCWD_RENAME(ZSTR_VAL(temp_file_path), fn); + if (VCWD_RENAME(ZSTR_VAL(temp_file_path), fn) < 0) { + VCWD_UNLINK(ZSTR_VAL(temp_file_path)); + } } smart_str_free(&buf); From 0a39890c967aa57225bb6bdf4821aff7a3a3c082 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Fri, 1 Dec 2023 18:03:35 +0100 Subject: [PATCH 87/92] Fix libxml2 2.12 build due to API breaks See https://github.com/php/php-src/actions/runs/7062192818/job/19225478601 --- ext/libxml/libxml.c | 14 ++++++++++---- ext/soap/php_sdl.c | 2 +- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/ext/libxml/libxml.c b/ext/libxml/libxml.c index 22eb1901b8909..1de693892b7aa 100644 --- a/ext/libxml/libxml.c +++ b/ext/libxml/libxml.c @@ -472,7 +472,11 @@ static void _php_libxml_free_error(void *ptr) xmlResetError((xmlErrorPtr) ptr); } -static void _php_list_set_error_structure(xmlErrorPtr error, const char *msg) +#if LIBXML_VERSION >= 21200 +static void _php_list_set_error_structure(const xmlError *error, const char *msg) +#else +static void _php_list_set_error_structure(xmlError *error, const char *msg) +#endif { xmlError error_copy; int ret; @@ -725,7 +729,11 @@ PHP_LIBXML_API void php_libxml_ctx_warning(void *ctx, const char *msg, ...) va_end(args); } +#if LIBXML_VERSION >= 21200 +PHP_LIBXML_API void php_libxml_structured_error_handler(void *userData, const xmlError *error) +#else PHP_LIBXML_API void php_libxml_structured_error_handler(void *userData, xmlErrorPtr error) +#endif { _php_list_set_error_structure(error, NULL); @@ -957,11 +965,9 @@ PHP_FUNCTION(libxml_use_internal_errors) /* {{{ Retrieve last error from libxml */ PHP_FUNCTION(libxml_get_last_error) { - xmlErrorPtr error; - ZEND_PARSE_PARAMETERS_NONE(); - error = xmlGetLastError(); + const xmlError *error = xmlGetLastError(); if (error) { object_init_ex(return_value, libxmlerror_class_entry); diff --git a/ext/soap/php_sdl.c b/ext/soap/php_sdl.c index 749f5a5685ec2..b731114775ad7 100644 --- a/ext/soap/php_sdl.c +++ b/ext/soap/php_sdl.c @@ -332,7 +332,7 @@ static void load_wsdl_ex(zval *this_ptr, char *struri, sdlCtx *ctx, int include) sdl_restore_uri_credentials(ctx); if (!wsdl) { - xmlErrorPtr xmlErrorPtr = xmlGetLastError(); + const xmlError *xmlErrorPtr = xmlGetLastError(); if (xmlErrorPtr) { soap_error2(E_ERROR, "Parsing WSDL: Couldn't load from '%s' : %s", struri, xmlErrorPtr->message); From ac8a58fab1b756e2b07f9621c4050cb30afc89ed Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 2 Dec 2023 16:20:15 +0100 Subject: [PATCH 88/92] Fix GH-9348: FTP & SSL session reuse The issue referenced here doesn't contain a reproducer, but I recently received an email of a user with the exact same problem. I was able to recreate the scenario locally using vsftpd and setting `require_ssl_reuse=YES` in the vsftpd configuration. It turns out that our session resumption code is broken. It only works a single time: the first time a data connection opens. Subsequent data connections fail to reuse the session. This is because on every data connection a new session is negotiated, but the current code always tries to reuse the (stale) session of the control connection. To fix this, we use SSL_CTX_sess_set_new_cb() to setup a callback that gets called every time a new session is negotiated. We take a strong reference using SSL_get1_session() and store it in the ftpbuf_t struct. Every time we open a data connection we'll take that session. This works because every control connection has at most a single associated data connection. Also disable internal session caching storage to not fill the cache up with useless sessions. There is no phpt for this because PHP does not support enforcing SSL session reuse. It is however testable manually by setting up vsftpd and setting the `require_ssl_reuse=YES` function from before. Closes GH-12851. --- NEWS | 3 +++ ext/ftp/ftp.c | 27 ++++++++++++++++++++++++--- ext/ftp/ftp.h | 1 + 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index ceda8d103caa8..30c1054e3cea4 100644 --- a/NEWS +++ b/NEWS @@ -24,6 +24,9 @@ PHP NEWS - FPM: . Fixed bug GH-12705 (Segmentation fault in fpm_status_export_to_zval). (Patrick Prasse) + +- FTP: + . Fixed bug GH-9348 (FTP & SSL session reuse). (nielsdos) - Intl: . Fixed bug GH-12635 (Test bug69398.phpt fails with ICU 74.1). (nielsdos) diff --git a/ext/ftp/ftp.c b/ext/ftp/ftp.c index 85cfd0a90cdf6..54326889042fb 100644 --- a/ext/ftp/ftp.c +++ b/ext/ftp/ftp.c @@ -167,6 +167,9 @@ ftp_close(ftpbuf_t *ftp) if (ftp == NULL) { return NULL; } + if (ftp->last_ssl_session) { + SSL_SESSION_free(ftp->last_ssl_session); + } if (ftp->data) { data_close(ftp, ftp->data); } @@ -229,6 +232,20 @@ ftp_quit(ftpbuf_t *ftp) } /* }}} */ +static int ftp_ssl_new_session_cb(SSL *ssl, SSL_SESSION *sess) +{ + ftpbuf_t *ftp = SSL_get_app_data(ssl); + + /* Technically there can be multiple sessions per connection, but we only care about the most recent one. */ + if (ftp->last_ssl_session) { + SSL_SESSION_free(ftp->last_ssl_session); + } + ftp->last_ssl_session = SSL_get1_session(ssl); + + /* Return 0 as we are not using OpenSSL's session cache. */ + return 0; +} + /* {{{ ftp_login */ int ftp_login(ftpbuf_t *ftp, const char *user, const size_t user_len, const char *pass, const size_t pass_len) @@ -279,10 +296,13 @@ ftp_login(ftpbuf_t *ftp, const char *user, const size_t user_len, const char *pa #endif SSL_CTX_set_options(ctx, ssl_ctx_options); - /* allow SSL to re-use sessions */ - SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_BOTH); + /* Allow SSL to re-use sessions. + * We're relying on our own session storage as only at most one session will ever be active per FTP connection. */ + SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_BOTH | SSL_SESS_CACHE_NO_INTERNAL); + SSL_CTX_sess_set_new_cb(ctx, ftp_ssl_new_session_cb); ftp->ssl_handle = SSL_new(ctx); + SSL_set_app_data(ftp->ssl_handle, ftp); /* Needed for ftp_ssl_new_session_cb */ SSL_CTX_free(ctx); if (ftp->ssl_handle == NULL) { @@ -1789,7 +1809,7 @@ data_accept(databuf_t *data, ftpbuf_t *ftp) } /* get the session from the control connection so we can re-use it */ - session = SSL_get_session(ftp->ssl_handle); + session = ftp->last_ssl_session; if (session == NULL) { php_error_docref(NULL, E_WARNING, "data_accept: failed to retrieve the existing SSL session"); SSL_free(data->ssl_handle); @@ -1797,6 +1817,7 @@ data_accept(databuf_t *data, ftpbuf_t *ftp) } /* and set it on the data connection */ + SSL_set_app_data(data->ssl_handle, ftp); /* Needed for ftp_ssl_new_session_cb */ res = SSL_set_session(data->ssl_handle, session); if (res == 0) { php_error_docref(NULL, E_WARNING, "data_accept: failed to set the existing SSL session"); diff --git a/ext/ftp/ftp.h b/ext/ftp/ftp.h index 9b50ea71ff5d5..5e96351ebdaee 100644 --- a/ext/ftp/ftp.h +++ b/ext/ftp/ftp.h @@ -82,6 +82,7 @@ typedef struct ftpbuf int old_ssl; /* old mode = forced data encryption */ SSL *ssl_handle; /* handle for control connection */ int ssl_active; /* ssl active on control conn */ + SSL_SESSION *last_ssl_session; /* last negotiated session */ #endif } ftpbuf_t; From 8387f2dfd491ba44a31462ffd30c61aa94af54fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Kocsis?= Date: Sun, 3 Dec 2023 08:59:21 +0100 Subject: [PATCH 89/92] Fix the default value of $fetchMode in PDO::pgsqlGetNotify() --- NEWS | 3 +++ ext/pdo_pgsql/pgsql_driver.stub.php | 2 +- ext/pdo_pgsql/pgsql_driver_arginfo.h | 4 ++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index 30c1054e3cea4..dcae26e449021 100644 --- a/NEWS +++ b/NEWS @@ -53,6 +53,9 @@ PHP NEWS - PCRE: . Fixed bug GH-12628 (The gh11374 test fails on Alpinelinux). (nielsdos) +- PDO PGSQL: + . Fixed the default value of $fetchMode in PDO::pgsqlGetNotify() (kocsismate) + - PGSQL: . Fixed bug GH-12763 wrong argument type for pg_untrace. (degtyarov) diff --git a/ext/pdo_pgsql/pgsql_driver.stub.php b/ext/pdo_pgsql/pgsql_driver.stub.php index 4206dbea636b9..cf3504fbbfb83 100644 --- a/ext/pdo_pgsql/pgsql_driver.stub.php +++ b/ext/pdo_pgsql/pgsql_driver.stub.php @@ -29,7 +29,7 @@ public function pgsqlLOBOpen(string $oid, string $mode = "rb") {} public function pgsqlLOBUnlink(string $oid): bool {} /** @tentative-return-type */ - public function pgsqlGetNotify(int $fetchMode = PDO::FETCH_USE_DEFAULT, int $timeoutMilliseconds = 0): array|false {} + public function pgsqlGetNotify(int $fetchMode = PDO::FETCH_DEFAULT, int $timeoutMilliseconds = 0): array|false {} /** @tentative-return-type */ public function pgsqlGetPid(): int {} diff --git a/ext/pdo_pgsql/pgsql_driver_arginfo.h b/ext/pdo_pgsql/pgsql_driver_arginfo.h index 3f84d4d8e5b9d..a1c51dc0c491f 100644 --- a/ext/pdo_pgsql/pgsql_driver_arginfo.h +++ b/ext/pdo_pgsql/pgsql_driver_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: b30fa6327876dc1090ee5397253c935e4566a8fe */ + * Stub hash: 9bb79af98dbb7c171fd9533aeabece4937a06cd2 */ ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_PDO_PGSql_Ext_pgsqlCopyFromArray, 0, 2, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, tableName, IS_STRING, 0) @@ -39,7 +39,7 @@ ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_PDO_PGSql_Ext_pg ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_MASK_EX(arginfo_class_PDO_PGSql_Ext_pgsqlGetNotify, 0, 0, MAY_BE_ARRAY|MAY_BE_FALSE) - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, fetchMode, IS_LONG, 0, "PDO::FETCH_USE_DEFAULT") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, fetchMode, IS_LONG, 0, "PDO::FETCH_DEFAULT") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, timeoutMilliseconds, IS_LONG, 0, "0") ZEND_END_ARG_INFO() From 4f934cb7f7cf65f17f01b8be472dedf269ad6030 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Mon, 4 Dec 2023 15:48:51 +0100 Subject: [PATCH 90/92] Fix compilation of ftp without openssl Closes GH-12866 --- ext/ftp/ftp.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ext/ftp/ftp.c b/ext/ftp/ftp.c index 54326889042fb..dd1f9d6654ced 100644 --- a/ext/ftp/ftp.c +++ b/ext/ftp/ftp.c @@ -167,9 +167,11 @@ ftp_close(ftpbuf_t *ftp) if (ftp == NULL) { return NULL; } +#ifdef HAVE_FTP_SSL if (ftp->last_ssl_session) { SSL_SESSION_free(ftp->last_ssl_session); } +#endif if (ftp->data) { data_close(ftp, ftp->data); } @@ -232,6 +234,7 @@ ftp_quit(ftpbuf_t *ftp) } /* }}} */ +#ifdef HAVE_FTP_SSL static int ftp_ssl_new_session_cb(SSL *ssl, SSL_SESSION *sess) { ftpbuf_t *ftp = SSL_get_app_data(ssl); @@ -245,6 +248,7 @@ static int ftp_ssl_new_session_cb(SSL *ssl, SSL_SESSION *sess) /* Return 0 as we are not using OpenSSL's session cache. */ return 0; } +#endif /* {{{ ftp_login */ int From 8f6610ce8871c1065682db84264fd3450a5db342 Mon Sep 17 00:00:00 2001 From: Patrick Allaert Date: Tue, 5 Dec 2023 15:04:57 +0100 Subject: [PATCH 91/92] PHP-8.1 is now for PHP 8.1.28-dev (If released one day!) --- NEWS | 5 ++++- Zend/zend.h | 2 +- configure.ac | 2 +- main/php_version.h | 6 +++--- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/NEWS b/NEWS index 903b836806cac..8373c66329af5 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? ????, PHP 8.1.27 +?? ??? ????, PHP 8.1.28 + + +21 Dec 2023, PHP 8.1.27 - Core: . Fixed oss-fuzz #54325 (Use-after-free of name in var-var with malicious diff --git a/Zend/zend.h b/Zend/zend.h index 3c320ddc88cac..2bba956fe4744 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -20,7 +20,7 @@ #ifndef ZEND_H #define ZEND_H -#define ZEND_VERSION "4.1.27-dev" +#define ZEND_VERSION "4.1.28-dev" #define ZEND_ENGINE_3 diff --git a/configure.ac b/configure.ac index 91cb9e2fe4c34..90e1f8e8a6588 100644 --- a/configure.ac +++ b/configure.ac @@ -17,7 +17,7 @@ dnl Basic autoconf initialization, generation of config.nice. dnl ---------------------------------------------------------------------------- AC_PREREQ([2.68]) -AC_INIT([PHP],[8.1.27-dev],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) +AC_INIT([PHP],[8.1.28-dev],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) AC_CONFIG_SRCDIR([main/php_version.h]) AC_CONFIG_AUX_DIR([build]) AC_PRESERVE_HELP_ORDER diff --git a/main/php_version.h b/main/php_version.h index 64e387dec6834..59842b5307cb7 100644 --- a/main/php_version.h +++ b/main/php_version.h @@ -2,7 +2,7 @@ /* edit configure.ac to change version number */ #define PHP_MAJOR_VERSION 8 #define PHP_MINOR_VERSION 1 -#define PHP_RELEASE_VERSION 27 +#define PHP_RELEASE_VERSION 28 #define PHP_EXTRA_VERSION "-dev" -#define PHP_VERSION "8.1.27-dev" -#define PHP_VERSION_ID 80127 +#define PHP_VERSION "8.1.28-dev" +#define PHP_VERSION_ID 80128 From f652d223e96fb960916d68072bbe5d6740db435e Mon Sep 17 00:00:00 2001 From: Pierrick Charron Date: Wed, 20 Dec 2023 01:23:20 -0500 Subject: [PATCH 92/92] Prepare PHP 8.2.14 --- NEWS | 4 ++-- Zend/zend.h | 2 +- configure.ac | 2 +- main/php_version.h | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/NEWS b/NEWS index dcae26e449021..7c7bdaf0d6933 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,6 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? ????, PHP 8.2.14 +21 Dec 2023, PHP 8.2.14 - Core: . Fixed oss-fuzz #54325 (Use-after-free of name in var-var with malicious @@ -27,7 +27,7 @@ PHP NEWS - FTP: . Fixed bug GH-9348 (FTP & SSL session reuse). (nielsdos) - + - Intl: . Fixed bug GH-12635 (Test bug69398.phpt fails with ICU 74.1). (nielsdos) diff --git a/Zend/zend.h b/Zend/zend.h index 7dd0ed1071feb..526bbf078fa7b 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -20,7 +20,7 @@ #ifndef ZEND_H #define ZEND_H -#define ZEND_VERSION "4.2.14-dev" +#define ZEND_VERSION "4.2.14" #define ZEND_ENGINE_3 diff --git a/configure.ac b/configure.ac index dd3464216108f..d11f13f854096 100644 --- a/configure.ac +++ b/configure.ac @@ -17,7 +17,7 @@ dnl Basic autoconf initialization, generation of config.nice. dnl ---------------------------------------------------------------------------- AC_PREREQ([2.68]) -AC_INIT([PHP],[8.2.14-dev],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) +AC_INIT([PHP],[8.2.14],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) AC_CONFIG_SRCDIR([main/php_version.h]) AC_CONFIG_AUX_DIR([build]) AC_PRESERVE_HELP_ORDER diff --git a/main/php_version.h b/main/php_version.h index 87eb6ba3b3ac7..79f6f7b3ae87f 100644 --- a/main/php_version.h +++ b/main/php_version.h @@ -3,6 +3,6 @@ #define PHP_MAJOR_VERSION 8 #define PHP_MINOR_VERSION 2 #define PHP_RELEASE_VERSION 14 -#define PHP_EXTRA_VERSION "-dev" -#define PHP_VERSION "8.2.14-dev" +#define PHP_EXTRA_VERSION "" +#define PHP_VERSION "8.2.14" #define PHP_VERSION_ID 80214