From 7f26661993d1605f1b6e17cdc24ad6114e983ae4 Mon Sep 17 00:00:00 2001 From: Ben Ramsey Date: Tue, 16 Aug 2022 10:45:29 -0500 Subject: [PATCH 01/61] PHP-8.1 is now for PHP 8.1.11-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 3a5d072854716..d473b05a08238 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,10 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? ????, PHP 8.1.10 +?? ??? ????, PHP 8.1.11 + + + +01 Sep 2022, PHP 8.1.10 - Core: . Fixed --CGI-- support of run-tests.php. (cmb) diff --git a/Zend/zend.h b/Zend/zend.h index 001bf329b9e49..632869a9b37d3 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -20,7 +20,7 @@ #ifndef ZEND_H #define ZEND_H -#define ZEND_VERSION "4.1.10-dev" +#define ZEND_VERSION "4.1.11-dev" #define ZEND_ENGINE_3 diff --git a/configure.ac b/configure.ac index 485062e32a8f1..75021f30b983e 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.10-dev],[https://bugs.php.net],[php],[https://www.php.net]) +AC_INIT([PHP],[8.1.11-dev],[https://bugs.php.net],[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 218f92c2fc14b..baf7b8c6b1893 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 10 +#define PHP_RELEASE_VERSION 11 #define PHP_EXTRA_VERSION "-dev" -#define PHP_VERSION "8.1.10-dev" -#define PHP_VERSION_ID 80110 +#define PHP_VERSION "8.1.11-dev" +#define PHP_VERSION_ID 80111 From 371367ce3e0cd941b4eb1c42f33c590e645f4ca3 Mon Sep 17 00:00:00 2001 From: Alex Dowad Date: Thu, 7 Apr 2022 07:57:22 +0200 Subject: [PATCH 02/61] Reintroduce legacy 'SJIS-win' text encoding in mbstring In e2459857af, I combined mbstring's "SJIS-win" text encoding into CP932. This was done after doing some testing which appeared to show that the mappings for "SJIS-win" were the same as those for "CP932". Later, it was found that there was actually a small difference prior to e2459857af when converting Unicode to CP932. The mappings for the following two codepoints were different: CP932 SJIS-win U+203E 0x7E 0x81 0x50 U+00A5 0x5C 0x81 0x8F As shown, mbstring's "CP932" mapped Unicode's 'OVERLINE' and 'YEN SIGN' to the ASCII bytes which have conflicting uses in most legacy Japanese text encodings. "SJIS-win" mapped these to equivalent JIS X 0208 fullwidth characters. Since e2459867af was not intended to cause any user-visible change in behavior, I am rolling back the merge of "CP932" and "SJIS-win". It seems doubtful whether these two text encodings should be kept separate or merged in a future release. An extensive discussion of the related historical background and compatibility issues involved can be found in this GitHub thread: https://github.com/php/php-src/issues/8308 --- ext/mbstring/libmbfl/filters/mbfilter_cp932.c | 95 ++++++++++++++++--- ext/mbstring/libmbfl/filters/mbfilter_cp932.h | 5 + ext/mbstring/libmbfl/mbfl/mbfl_encoding.c | 1 + ext/mbstring/libmbfl/mbfl/mbfl_encoding.h | 1 + ext/mbstring/tests/cp932_encoding.phpt | 46 +++++++-- .../mb_internal_encoding_variation2.phpt | 4 +- 6 files changed, 130 insertions(+), 22 deletions(-) diff --git a/ext/mbstring/libmbfl/filters/mbfilter_cp932.c b/ext/mbstring/libmbfl/filters/mbfilter_cp932.c index 10559b593be60..62bf1942193c9 100644 --- a/ext/mbstring/libmbfl/filters/mbfilter_cp932.c +++ b/ext/mbstring/libmbfl/filters/mbfilter_cp932.c @@ -27,6 +27,36 @@ * */ +/* CP932 is Microsoft's version of Shift-JIS. + * + * What we call "SJIS-win" is a variant of CP932 which maps U+00A5 + * and U+203E the same way as eucJP-win; namely, instead of mapping + * U+00A5 (YEN SIGN) to 0x5C and U+203E (OVERLINE) to 0x7E, + * these codepoints are mapped to appropriate JIS X 0208 characters. + * + * When converting from Shift-JIS to Unicode, there is no difference + * between CP932 and "SJIS-win". + * + * Additional facts: + * + * • In the libmbfl library which formed the base for mbstring, "CP932" and + * "SJIS-win" were originally aliases. The differing mappings were added in + * December 2002. The libmbfl author later stated that this was done so that + * "CP932" would comply with a certain specification, while "SJIS-win" would + * maintain the existing mappings. He does not remember which specification + * it was. + * • The WHATWG specification for "Shift_JIS" (followed by web browsers) + * agrees with our mappings for "CP932". + * • Microsoft Windows' "best-fit" mappings for CP932 (via the + * WideCharToMultiByte API) convert U+00A5 to 0x5C, which also agrees with + * our mappings for "CP932". + * • glibc's iconv converts U+203E to CP932 0x7E, which again agrees with + * our mappings for "CP932". + * • When converting Shift-JIS to CP932, the conversion goes through Unicode. + * Shift-JIS 0x7E converts to U+203E, so mapping U+203E to 0x7E means that + * 0x7E will go to 0x7E when converting Shift-JIS to CP932. + */ + #include "mbfilter.h" #include "mbfilter_cp932.h" @@ -54,7 +84,8 @@ static const unsigned char mblen_table_sjis[] = { /* 0x80-0x9f,0xE0-0xFF */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 }; -static const char *mbfl_encoding_cp932_aliases[] = {"MS932", "Windows-31J", "MS_Kanji", "SJIS-win", "SJIS-ms", "SJIS-open", NULL}; +static const char *mbfl_encoding_cp932_aliases[] = {"MS932", "Windows-31J", "MS_Kanji", NULL}; +static const char *mbfl_encoding_sjiswin_aliases[] = {"SJIS-ms", "SJIS-open", NULL}; const mbfl_encoding mbfl_encoding_cp932 = { mbfl_no_encoding_cp932, @@ -87,6 +118,37 @@ const struct mbfl_convert_vtbl vtbl_wchar_cp932 = { NULL, }; +const mbfl_encoding mbfl_encoding_sjiswin = { + mbfl_no_encoding_sjiswin, + "SJIS-win", + "Shift_JIS", + mbfl_encoding_sjiswin_aliases, + mblen_table_sjis, + MBFL_ENCTYPE_GL_UNSAFE, + &vtbl_sjiswin_wchar, + &vtbl_wchar_sjiswin +}; + +const struct mbfl_convert_vtbl vtbl_sjiswin_wchar = { + mbfl_no_encoding_sjiswin, + mbfl_no_encoding_wchar, + mbfl_filt_conv_common_ctor, + NULL, + mbfl_filt_conv_cp932_wchar, + mbfl_filt_conv_cp932_wchar_flush, + NULL, +}; + +const struct mbfl_convert_vtbl vtbl_wchar_sjiswin = { + mbfl_no_encoding_wchar, + mbfl_no_encoding_sjiswin, + mbfl_filt_conv_common_ctor, + NULL, + mbfl_filt_conv_wchar_sjiswin, + mbfl_filt_conv_common_flush, + NULL, +}; + #define CK(statement) do { if ((statement) < 0) return (-1); } while (0) #define SJIS_ENCODE(c1,c2,s1,s2) \ @@ -132,12 +194,7 @@ const struct mbfl_convert_vtbl vtbl_wchar_cp932 = { } \ } while (0) - -/* - * SJIS-win => wchar - */ -int -mbfl_filt_conv_cp932_wchar(int c, mbfl_convert_filter *filter) +int mbfl_filt_conv_cp932_wchar(int c, mbfl_convert_filter *filter) { int c1, s, s1, s2, w; @@ -224,11 +281,7 @@ static int mbfl_filt_conv_cp932_wchar_flush(mbfl_convert_filter *filter) return 0; } -/* - * wchar => SJIS-win - */ -int -mbfl_filt_conv_wchar_cp932(int c, mbfl_convert_filter *filter) +int mbfl_filt_conv_wchar_cp932(int c, mbfl_convert_filter *filter) { int c1, c2, s1, s2; @@ -236,6 +289,8 @@ mbfl_filt_conv_wchar_cp932(int c, mbfl_convert_filter *filter) s2 = 0; if (c >= ucs_a1_jis_table_min && c < ucs_a1_jis_table_max) { s1 = ucs_a1_jis_table[c - ucs_a1_jis_table_min]; + } else if (c == 0x203E) { + s1 = 0x7E; } else if (c >= ucs_a2_jis_table_min && c < ucs_a2_jis_table_max) { s1 = ucs_a2_jis_table[c - ucs_a2_jis_table_min]; } else if (c >= ucs_i_jis_table_min && c < ucs_i_jis_table_max) { @@ -251,7 +306,7 @@ mbfl_filt_conv_wchar_cp932(int c, mbfl_convert_filter *filter) } if (s1 <= 0) { if (c == 0xa5) { /* YEN SIGN */ - s1 = 0x216F; /* FULLWIDTH YEN SIGN */ + s1 = 0x5C; } else if (c == 0xff3c) { /* FULLWIDTH REVERSE SOLIDUS */ s1 = 0x2140; } else if (c == 0x2225) { /* PARALLEL TO */ @@ -310,3 +365,17 @@ mbfl_filt_conv_wchar_cp932(int c, mbfl_convert_filter *filter) return 0; } + +int mbfl_filt_conv_wchar_sjiswin(int c, mbfl_convert_filter *filter) +{ + if (c == 0xA5) { + CK((*filter->output_function)(0x81, filter->data)); + CK((*filter->output_function)(0x8F, filter->data)); + } else if (c == 0x203E) { + CK((*filter->output_function)(0x81, filter->data)); + CK((*filter->output_function)(0x50, filter->data)); + } else { + return mbfl_filt_conv_wchar_cp932(c, filter); + } + return 0; +} diff --git a/ext/mbstring/libmbfl/filters/mbfilter_cp932.h b/ext/mbstring/libmbfl/filters/mbfilter_cp932.h index 031276ddf1470..8dce3ab9e91d8 100644 --- a/ext/mbstring/libmbfl/filters/mbfilter_cp932.h +++ b/ext/mbstring/libmbfl/filters/mbfilter_cp932.h @@ -36,7 +36,12 @@ extern const mbfl_encoding mbfl_encoding_cp932; extern const struct mbfl_convert_vtbl vtbl_cp932_wchar; extern const struct mbfl_convert_vtbl vtbl_wchar_cp932; +extern const mbfl_encoding mbfl_encoding_sjiswin; +extern const struct mbfl_convert_vtbl vtbl_sjiswin_wchar; +extern const struct mbfl_convert_vtbl vtbl_wchar_sjiswin; + int mbfl_filt_conv_cp932_wchar(int c, mbfl_convert_filter *filter); int mbfl_filt_conv_wchar_cp932(int c, mbfl_convert_filter *filter); +int mbfl_filt_conv_wchar_sjiswin(int c, mbfl_convert_filter *filter); #endif /* MBFL_MBFILTER_CP932_H */ diff --git a/ext/mbstring/libmbfl/mbfl/mbfl_encoding.c b/ext/mbstring/libmbfl/mbfl/mbfl_encoding.c index f298eab6df238..2495f7447aa3a 100644 --- a/ext/mbstring/libmbfl/mbfl/mbfl_encoding.c +++ b/ext/mbstring/libmbfl/mbfl/mbfl_encoding.c @@ -121,6 +121,7 @@ static const mbfl_encoding *mbfl_encoding_ptr_list[] = { &mbfl_encoding_utf8_kddi_b, &mbfl_encoding_utf8_sb, &mbfl_encoding_cp932, + &mbfl_encoding_sjiswin, &mbfl_encoding_cp51932, &mbfl_encoding_jis, &mbfl_encoding_2022jp, diff --git a/ext/mbstring/libmbfl/mbfl/mbfl_encoding.h b/ext/mbstring/libmbfl/mbfl/mbfl_encoding.h index c99b42dcc6eab..09505d7238245 100644 --- a/ext/mbstring/libmbfl/mbfl/mbfl_encoding.h +++ b/ext/mbstring/libmbfl/mbfl/mbfl_encoding.h @@ -74,6 +74,7 @@ enum mbfl_no_encoding { mbfl_no_encoding_sjis_mac, mbfl_no_encoding_sjis2004, mbfl_no_encoding_cp932, + mbfl_no_encoding_sjiswin, mbfl_no_encoding_cp51932, mbfl_no_encoding_jis, mbfl_no_encoding_2022jp, diff --git a/ext/mbstring/tests/cp932_encoding.phpt b/ext/mbstring/tests/cp932_encoding.phpt index ff7bd9cfcdc28..df700f20286a5 100644 --- a/ext/mbstring/tests/cp932_encoding.phpt +++ b/ext/mbstring/tests/cp932_encoding.phpt @@ -1,5 +1,5 @@ --TEST-- -Exhaustive test of CP932 encoding verification and conversion +Exhaustive test of CP932 encoding verification and conversion (including 'SJIS-win' variant) --EXTENSIONS-- mbstring --SKIPIF-- @@ -34,8 +34,10 @@ for ($i = 0xF0; $i <= 0xF9; $i++) { $fromUnicode["\x00\xA2"] = "\x81\x91"; /* U+00A3 is POUND SIGN; convert to FULLWIDTH POUND SIGN */ $fromUnicode["\x00\xA3"] = "\x81\x92"; -/* U+00A5 is YEN SIGN; convert to FULLWIDTH YEN SIGN */ -$fromUnicode["\x00\xA5"] = "\x81\x8F"; +/* U+00A5 is YEN SIGN; convert to 0x5C, which has conflicting uses + * (either as backslash or as Yen sign) */ +$fromUnicode["\x00\xA5"] = "\x5C"; + /* We map the JIS X 0208 FULLWIDTH TILDE to U+FF5E (FULLWIDTH TILDE) * But when converting Unicode to CP932, we also accept U+301C (WAVE DASH) */ @@ -51,12 +53,13 @@ $fromUnicode["\x20\x16"] = "\x81\x61"; * but when converting Unicode to CP932, we also accept U+00AC (NOT SIGN) */ $fromUnicode["\x00\xAC"] = "\x81\xCA"; -/* U+203E is OVERLINE; convert to JIS X 0208 FULLWIDTH MACRON */ -$fromUnicode["\x20\x3E"] = "\x81\x50"; - -/* U+00AF is MACRON; it can also go to FULLWIDTH MACRON */ +/* U+00AF is MACRON; convert to FULLWIDTH MACRON */ $fromUnicode["\x00\xAF"] = "\x81\x50"; +/* U+203E is OVERLINE; convert to 0x7E, which has conflicting uses + * (either as tilde or as overline) */ +$fromUnicode["\x20\x3E"] = "\x7E"; + findInvalidChars($validChars, $invalidChars, $truncated, array_fill_keys(range(0x81, 0x9F), 2) + array_fill_keys(range(0xE0, 0xFC), 2)); findInvalidChars($fromUnicode, $invalidCodepoints, $unused, array_fill_keys(range(0, 0xFF), 2)); @@ -106,12 +109,38 @@ echo "CP932 verification and conversion works on all invalid characters\n"; convertAllInvalidChars($invalidCodepoints, $fromUnicode, 'UTF-16BE', 'CP932', '%'); echo "Unicode -> CP932 conversion works on all invalid codepoints\n"; +/* Now test 'SJIS-win' variant of CP932, which is really CP932 but with + * two different mappings + * Instead of mapping U+00A5 and U+203E to the single bytes 0x5C and 07E + * (which have conflicting uses), 'SJIS-win' maps them to appropriate + * JIS X 0208 characters */ + +/* U+00A5 is YEN SIGN; convert to FULLWIDTH YEN SIGN */ +$fromUnicode["\x00\xA5"] = "\x81\x8F"; +/* U+203E is OVERLINE; convert to JIS X 0208 FULLWIDTH MACRON */ +$fromUnicode["\x20\x3E"] = "\x81\x50"; + +testAllValidChars($validChars, 'SJIS-win', 'UTF-16BE'); +foreach ($nonInvertible as $cp932 => $unicode) + testValidString($cp932, $unicode, 'SJIS-win', 'UTF-16BE', false); +echo "SJIS-win verification and conversion works on all valid characters\n"; + +testAllInvalidChars($invalidChars, $validChars, 'SJIS-win', 'UTF-16BE', "\x00%"); +echo "SJIS-win verification and conversion works on all invalid characters\n"; + +convertAllInvalidChars($invalidCodepoints, $fromUnicode, 'UTF-16BE', 'SJIS-win', '%'); +echo "Unicode -> SJIS-win conversion works on all invalid codepoints\n"; + // Test "long" illegal character markers mb_substitute_character("long"); convertInvalidString("\x80", "%", "CP932", "UTF-8"); convertInvalidString("\xEA", "%", "CP932", "UTF-8"); convertInvalidString("\x81\x20", "%", "CP932", "UTF-8"); convertInvalidString("\xEA\xA9", "%", "CP932", "UTF-8"); +convertInvalidString("\x80", "%", "SJIS-win", "UTF-8"); +convertInvalidString("\xEA", "%", "SJIS-win", "UTF-8"); +convertInvalidString("\x81\x20", "%", "SJIS-win", "UTF-8"); +convertInvalidString("\xEA\xA9", "%", "SJIS-win", "UTF-8"); echo "Done!\n"; ?> @@ -119,4 +148,7 @@ echo "Done!\n"; CP932 verification and conversion works on all valid characters CP932 verification and conversion works on all invalid characters Unicode -> CP932 conversion works on all invalid codepoints +SJIS-win verification and conversion works on all valid characters +SJIS-win verification and conversion works on all invalid characters +Unicode -> SJIS-win conversion works on all invalid codepoints Done! diff --git a/ext/mbstring/tests/mb_internal_encoding_variation2.phpt b/ext/mbstring/tests/mb_internal_encoding_variation2.phpt index 842d8d519cf06..dab306b12a2b8 100644 --- a/ext/mbstring/tests/mb_internal_encoding_variation2.phpt +++ b/ext/mbstring/tests/mb_internal_encoding_variation2.phpt @@ -176,10 +176,10 @@ string(9) "eucJP-win" -- Iteration 20 -- string(9) "eucJP-win" bool(true) -string(5) "CP932" +string(8) "SJIS-win" -- Iteration 21 -- -string(5) "CP932" +string(8) "SJIS-win" bool(true) string(11) "ISO-2022-JP" From 7c6316ad1c7ce95551f9a2477d04930efb7274d5 Mon Sep 17 00:00:00 2001 From: Gabriel Caruso Date: Wed, 17 Aug 2022 11:56:42 +0200 Subject: [PATCH 03/61] Prepare for 8.0.24 --- NEWS | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index caf69a2627f8e..50901b3926a97 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? 2022, PHP 8.0.23 +?? ??? 2022, PHP 8.0.24 + + +01 Sep 2022, PHP 8.0.23 - Core: . Fixed incorrect double to long casting in latest clang. (zeriyoshi) From 84dcf578b155d82e0c0c02611c9299f74f17173f Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Mon, 15 Aug 2022 12:05:19 +0100 Subject: [PATCH 04/61] Fix GH-9339: OpenSSL oid_file path check warning contains uninitialized path --- NEWS | 4 ++++ ext/openssl/openssl.c | 6 +++--- ext/openssl/tests/gh9339.phpt | 25 +++++++++++++++++++++++++ 3 files changed, 32 insertions(+), 3 deletions(-) create mode 100644 ext/openssl/tests/gh9339.phpt diff --git a/NEWS b/NEWS index 50901b3926a97..3c68c6cd1390b 100644 --- a/NEWS +++ b/NEWS @@ -20,6 +20,10 @@ PHP NEWS . Fixed bug GH-9033 (Loading blacklist file can fail due to negative length). (cmb) +- OpenSSL: + . Fixed bug GH-9339 (OpenSSL oid_file path check warning contains + uninitialized path). (Jakub Zelenka) + - PDO_SQLite: . Fixed bug GH-9032 (SQLite3 authorizer crashes on NULL values). (cmb) diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index f791cfa856031..208776e330151 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -506,15 +506,15 @@ static bool php_openssl_check_path_ex( error_msg = "must not contain any null bytes"; error_type = E_ERROR; } else if (expand_filepath(fs_file_path, real_path) == NULL) { - error_msg = "The argument must be a valid file path"; + error_msg = "must be a valid file path"; } if (error_msg != NULL) { if (arg_num == 0) { const char *option_title = option_name ? option_name : "unknown"; const char *option_label = is_from_array ? "array item" : "option"; - php_error_docref(NULL, E_WARNING, "Path '%s' for %s %s %s", - real_path, option_title, option_label, error_msg); + php_error_docref(NULL, E_WARNING, "Path for %s %s %s", + option_title, option_label, error_msg); } else if (is_from_array && option_name != NULL) { php_openssl_check_path_error( arg_num, error_type, "option %s array item %s", option_name, error_msg); diff --git a/ext/openssl/tests/gh9339.phpt b/ext/openssl/tests/gh9339.phpt new file mode 100644 index 0000000000000..9e4adbccce7f6 --- /dev/null +++ b/ext/openssl/tests/gh9339.phpt @@ -0,0 +1,25 @@ +--TEST-- +GH-9339: oid_file path check warning contains uninitialized path +--SKIPIF-- + +--FILE-- + $configFile ]); +?> +--CLEAN-- + +--EXPECTF-- + +Warning: openssl_pkey_new(): Path for oid_file option must be a valid file path in %s on line %d From 72da41871907ce803b227b21f1edeef334b48c4c Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Wed, 17 Aug 2022 14:20:57 +0200 Subject: [PATCH 05/61] Fix GH-9316: $http_response_header is wrong for long status line MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While the reason-phrase in a HTTP response status line is usually short, there is no actual limit specified by the RFCs. As such, we must not assume that the line fits into the buffer (which is currently 128 bytes large). Since there is no real need to present the complete status line, we simply read and discard the rest of a long line. Co-authored-by: Tim Düsterhus Closes GH-9319. --- NEWS | 3 +++ ext/standard/http_fopen_wrapper.c | 4 +++ ext/standard/tests/http/gh9316.phpt | 38 +++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+) create mode 100644 ext/standard/tests/http/gh9316.phpt diff --git a/NEWS b/NEWS index 3c68c6cd1390b..d38ab8a422564 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? 2022, PHP 8.0.24 +- Streams: + . Fixed bug GH-9316 ($http_response_header is wrong for long status line). + (cmb, timwolla) 01 Sep 2022, PHP 8.0.23 diff --git a/ext/standard/http_fopen_wrapper.c b/ext/standard/http_fopen_wrapper.c index da822d9160f67..45677c396acf2 100644 --- a/ext/standard/http_fopen_wrapper.c +++ b/ext/standard/http_fopen_wrapper.c @@ -717,6 +717,10 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, if (tmp_line_len >= 1 &&tmp_line[tmp_line_len - 1] == '\r') { --tmp_line_len; } + } else { + // read and discard rest of status line + char *line = php_stream_get_line(stream, NULL, 0, NULL); + efree(line); } ZVAL_STRINGL(&http_response, tmp_line, tmp_line_len); zend_hash_next_index_insert(Z_ARRVAL_P(response_header), &http_response); diff --git a/ext/standard/tests/http/gh9316.phpt b/ext/standard/tests/http/gh9316.phpt new file mode 100644 index 0000000000000..126e1bb7bf72f --- /dev/null +++ b/ext/standard/tests/http/gh9316.phpt @@ -0,0 +1,38 @@ +--TEST-- +Bug GH-9316 ($http_response_header is wrong for long status line) +--SKIPIF-- + +--INI-- +allow_url_fopen=1 +--FILE-- + $pid, 'uri' => $uri] = http_server($responses, $output); + +for ($i = 0; $i < count($responses); ++$i) { + $f = @fopen($uri, "r"); + var_dump($http_response_header); + fclose($f); +} + +http_server_kill($pid); + +--EXPECT-- +array(2) { + [0]=> + string(126) "HTTP/1.1 200 Some very long reason-phrase to test that this is properly handled by our code without adding a new header like " + [1]=> + string(12) "Good: Header" +} +array(2) { + [0]=> + string(13) "HTTP/1.1 200 " + [1]=> + string(12) "Good: Header" +} From 1d4300d87076410c7af784a8034fccd2badb0204 Mon Sep 17 00:00:00 2001 From: NathanFreeman <1056159381@qq.com> Date: Sat, 30 Jul 2022 17:13:28 +0800 Subject: [PATCH 06/61] Fix bug #79451: Using DOMDocument->replaceChild on doctype causes double free Closes GH-9201 --- NEWS | 4 ++++ ext/dom/node.c | 20 +++++++++++++++----- ext/dom/tests/bug79451.phpt | 20 ++++++++++++++++++++ 3 files changed, 39 insertions(+), 5 deletions(-) create mode 100644 ext/dom/tests/bug79451.phpt diff --git a/NEWS b/NEWS index d38ab8a422564..28734647d612c 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,10 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? 2022, PHP 8.0.24 +- DOM: + . Fixed bug #79451 (Using DOMDocument->replaceChild on doctype causes + double free) (NathanFreeman) + - Streams: . Fixed bug GH-9316 ($http_response_header is wrong for long status line). (cmb, timwolla) diff --git a/ext/dom/node.c b/ext/dom/node.c index a6f88b5c0f1bb..6d86a46918baa 100644 --- a/ext/dom/node.c +++ b/ext/dom/node.c @@ -20,6 +20,7 @@ #endif #include "php.h" + #if defined(HAVE_LIBXML) && defined(HAVE_DOM) #include "php_dom.h" @@ -1001,6 +1002,7 @@ PHP_METHOD(DOMNode, replaceChild) xmlNodePtr children, newchild, oldchild, nodep; dom_object *intern, *newchildobj, *oldchildobj; int foundoldchild = 0, stricterror; + bool replacedoctype = false; int ret; @@ -1063,13 +1065,21 @@ PHP_METHOD(DOMNode, replaceChild) dom_reconcile_ns(nodep->doc, newchild); } } else if (oldchild != newchild) { + xmlDtdPtr intSubset = xmlGetIntSubset(nodep->doc); + replacedoctype = (intSubset == (xmlDtd *) oldchild); + if (newchild->doc == NULL && nodep->doc != NULL) { xmlSetTreeDoc(newchild, nodep->doc); newchildobj->document = intern->document; php_libxml_increment_doc_ref((php_libxml_node_object *)newchildobj, NULL); } + xmlReplaceNode(oldchild, newchild); dom_reconcile_ns(nodep->doc, newchild); + + if (replacedoctype) { + nodep->doc->intSubset = (xmlDtd *) newchild; + } } DOM_RET_OBJ(oldchild, &ret, intern); return; @@ -1668,7 +1678,7 @@ static void dom_canonicalization(INTERNAL_FUNCTION_PARAMETERS, int mode) /* {{{ buf = xmlAllocOutputBuffer(NULL); } - if (buf != NULL) { + if (buf != NULL) { ret = xmlC14NDocSaveTo(docp, nodeset, exclusive, inclusive_ns_prefixes, with_comments, buf); } @@ -1683,9 +1693,9 @@ static void dom_canonicalization(INTERNAL_FUNCTION_PARAMETERS, int mode) /* {{{ xmlXPathFreeContext(ctxp); } - if (buf == NULL || ret < 0) { - RETVAL_FALSE; - } else { + if (buf == NULL || ret < 0) { + RETVAL_FALSE; + } else { if (mode == 0) { #ifdef LIBXML2_NEW_BUFFER ret = xmlOutputBufferGetSize(buf); @@ -1702,7 +1712,7 @@ static void dom_canonicalization(INTERNAL_FUNCTION_PARAMETERS, int mode) /* {{{ RETVAL_EMPTY_STRING(); } } - } + } if (buf) { int bytes; diff --git a/ext/dom/tests/bug79451.phpt b/ext/dom/tests/bug79451.phpt new file mode 100644 index 0000000000000..cb0b072482a3a --- /dev/null +++ b/ext/dom/tests/bug79451.phpt @@ -0,0 +1,20 @@ +--TEST-- +Bug #79451 (Using DOMDocument->replaceChild on doctype causes double free) +--SKIPIF-- + +--FILE-- +loadHTML("

hello

"); +$impl = new \DOMImplementation(); +$dt = $impl->createDocumentType("html_replace", "", ""); +$dom->replaceChild($dt, $dom->doctype); + +var_dump($dom->doctype->name); +echo $dom->saveXML(); +?> +--EXPECTF-- +string(12) "html_replace" + + +

hello

From 410e5d48a3b3d6f70beb31246df440a348b36bef Mon Sep 17 00:00:00 2001 From: Tim Starling Date: Fri, 19 Aug 2022 14:30:55 +1000 Subject: [PATCH 07/61] Fix GCC 9.4 uninitialized variable warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ext/opcache/zend_accelerator_blacklist.c:295:4: error: ‘blacklist_path_length’ may be used uninitialized in this function [-Werror=maybe-uninitialized] --- ext/opcache/zend_accelerator_blacklist.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/opcache/zend_accelerator_blacklist.c b/ext/opcache/zend_accelerator_blacklist.c index f0e3b69ae5fb3..aee8755f9dc94 100644 --- a/ext/opcache/zend_accelerator_blacklist.c +++ b/ext/opcache/zend_accelerator_blacklist.c @@ -241,7 +241,7 @@ static void zend_accel_blacklist_loadone(zend_blacklist *blacklist, char *filena { char buf[MAXPATHLEN + 1], real_path[MAXPATHLEN + 1], *blacklist_path = NULL; FILE *fp; - int path_length, blacklist_path_length; + int path_length, blacklist_path_length = 0; if ((fp = fopen(filename, "r")) == NULL) { zend_accel_error(ACCEL_LOG_WARNING, "Cannot load blacklist file: %s\n", filename); From ba029fce6898cb50fd619b934e190ecf16b48835 Mon Sep 17 00:00:00 2001 From: Tim Starling Date: Fri, 19 Aug 2022 14:09:07 +1000 Subject: [PATCH 08/61] Fix GH-9323: crash when the VM enters userspace code via the GC Closes GH-9323 --- NEWS | 4 ++++ Zend/zend_vm_def.h | 3 ++- Zend/zend_vm_execute.h | 12 +++++++++++- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index 28734647d612c..b45dce71fc5fb 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,10 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? 2022, PHP 8.0.24 +- Core: + . Fixed bug GH-9323 (Crash in ZEND_RETURN/GC/zend_call_function) + (Tim Starling) + - DOM: . Fixed bug #79451 (Using DOMDocument->replaceChild on doctype causes double free) (NathanFreeman) diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 1b4ef0d084652..d1aea77e8f974 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -4299,6 +4299,7 @@ ZEND_VM_INLINE_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY, SPEC(OBSERVER)) zend_refcounted *ref = Z_COUNTED_P(retval_ptr); ZVAL_COPY_VALUE(return_value, retval_ptr); if (GC_MAY_LEAK(ref)) { + SAVE_OPLINE(); gc_possible_root(ref); } ZVAL_NULL(retval_ptr); @@ -8304,8 +8305,8 @@ ZEND_VM_C_LABEL(check_indirect): zend_refcounted *garbage = Z_COUNTED_P(variable_ptr); ZVAL_REF(variable_ptr, ref); + SAVE_OPLINE(); if (GC_DELREF(garbage) == 0) { - SAVE_OPLINE(); rc_dtor_func(garbage); if (UNEXPECTED(EG(exception))) { ZVAL_NULL(variable_ptr); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 0daa7b9e507f0..5e41f9f88b739 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -4073,6 +4073,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_CONST_ zend_refcounted *ref = Z_COUNTED_P(retval_ptr); ZVAL_COPY_VALUE(return_value, retval_ptr); if (GC_MAY_LEAK(ref)) { + SAVE_OPLINE(); gc_possible_root(ref); } ZVAL_NULL(retval_ptr); @@ -4150,6 +4151,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_OBSER zend_refcounted *ref = Z_COUNTED_P(retval_ptr); ZVAL_COPY_VALUE(return_value, retval_ptr); if (GC_MAY_LEAK(ref)) { + SAVE_OPLINE(); gc_possible_root(ref); } ZVAL_NULL(retval_ptr); @@ -18585,6 +18587,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HA zend_refcounted *ref = Z_COUNTED_P(retval_ptr); ZVAL_COPY_VALUE(return_value, retval_ptr); if (GC_MAY_LEAK(ref)) { + SAVE_OPLINE(); gc_possible_root(ref); } ZVAL_NULL(retval_ptr); @@ -21200,6 +21203,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_VAR_HA zend_refcounted *ref = Z_COUNTED_P(retval_ptr); ZVAL_COPY_VALUE(return_value, retval_ptr); if (GC_MAY_LEAK(ref)) { + SAVE_OPLINE(); gc_possible_root(ref); } ZVAL_NULL(retval_ptr); @@ -37947,6 +37951,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_CV_HAN zend_refcounted *ref = Z_COUNTED_P(retval_ptr); ZVAL_COPY_VALUE(return_value, retval_ptr); if (GC_MAY_LEAK(ref)) { + SAVE_OPLINE(); gc_possible_root(ref); } ZVAL_NULL(retval_ptr); @@ -42680,8 +42685,8 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BIND_GLOBAL_SPEC_C zend_refcounted *garbage = Z_COUNTED_P(variable_ptr); ZVAL_REF(variable_ptr, ref); + SAVE_OPLINE(); if (GC_DELREF(garbage) == 0) { - SAVE_OPLINE(); rc_dtor_func(garbage); if (UNEXPECTED(EG(exception))) { ZVAL_NULL(variable_ptr); @@ -55390,6 +55395,7 @@ ZEND_API void execute_ex(zend_execute_data *ex) zend_refcounted *ref = Z_COUNTED_P(retval_ptr); ZVAL_COPY_VALUE(return_value, retval_ptr); if (GC_MAY_LEAK(ref)) { + SAVE_OPLINE(); gc_possible_root(ref); } ZVAL_NULL(retval_ptr); @@ -55468,6 +55474,7 @@ ZEND_API void execute_ex(zend_execute_data *ex) zend_refcounted *ref = Z_COUNTED_P(retval_ptr); ZVAL_COPY_VALUE(return_value, retval_ptr); if (GC_MAY_LEAK(ref)) { + SAVE_OPLINE(); gc_possible_root(ref); } ZVAL_NULL(retval_ptr); @@ -57001,6 +57008,7 @@ ZEND_API void execute_ex(zend_execute_data *ex) zend_refcounted *ref = Z_COUNTED_P(retval_ptr); ZVAL_COPY_VALUE(return_value, retval_ptr); if (GC_MAY_LEAK(ref)) { + SAVE_OPLINE(); gc_possible_root(ref); } ZVAL_NULL(retval_ptr); @@ -57306,6 +57314,7 @@ ZEND_API void execute_ex(zend_execute_data *ex) zend_refcounted *ref = Z_COUNTED_P(retval_ptr); ZVAL_COPY_VALUE(return_value, retval_ptr); if (GC_MAY_LEAK(ref)) { + SAVE_OPLINE(); gc_possible_root(ref); } ZVAL_NULL(retval_ptr); @@ -58427,6 +58436,7 @@ ZEND_API void execute_ex(zend_execute_data *ex) zend_refcounted *ref = Z_COUNTED_P(retval_ptr); ZVAL_COPY_VALUE(return_value, retval_ptr); if (GC_MAY_LEAK(ref)) { + SAVE_OPLINE(); gc_possible_root(ref); } ZVAL_NULL(retval_ptr); From 5739dd00308ac3d49e4b6d40d5bffc9afcf82ec8 Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Fri, 19 Aug 2022 13:17:57 +0100 Subject: [PATCH 09/61] Fix bad merge --- ext/dom/node.c | 44 -------------------------------------------- 1 file changed, 44 deletions(-) diff --git a/ext/dom/node.c b/ext/dom/node.c index e85cdddaf5274..c228eb07af6a2 100644 --- a/ext/dom/node.c +++ b/ext/dom/node.c @@ -1044,51 +1044,7 @@ PHP_METHOD(DOMNode, replaceChild) RETURN_FALSE; } -<<<<<<< HEAD if (oldchild->parent != nodep) { -======= - /* check for the old child and whether the new child is already a child */ - while (children) { - if (children == oldchild) { - foundoldchild = 1; - break; - } - children = children->next; - } - - if (foundoldchild) { - if (newchild->type == XML_DOCUMENT_FRAG_NODE) { - xmlNodePtr prevsib, nextsib; - prevsib = oldchild->prev; - nextsib = oldchild->next; - - xmlUnlinkNode(oldchild); - - newchild = _php_dom_insert_fragment(nodep, prevsib, nextsib, newchild, intern, newchildobj); - if (newchild) { - dom_reconcile_ns(nodep->doc, newchild); - } - } else if (oldchild != newchild) { - xmlDtdPtr intSubset = xmlGetIntSubset(nodep->doc); - replacedoctype = (intSubset == (xmlDtd *) oldchild); - - if (newchild->doc == NULL && nodep->doc != NULL) { - xmlSetTreeDoc(newchild, nodep->doc); - newchildobj->document = intern->document; - php_libxml_increment_doc_ref((php_libxml_node_object *)newchildobj, NULL); - } - - xmlReplaceNode(oldchild, newchild); - dom_reconcile_ns(nodep->doc, newchild); - - if (replacedoctype) { - nodep->doc->intSubset = (xmlDtd *) newchild; - } - } - DOM_RET_OBJ(oldchild, &ret, intern); - return; - } else { ->>>>>>> PHP-8.0 php_dom_throw_error(NOT_FOUND_ERR, stricterror); RETURN_FALSE; } From d6831e9a5c9a868d639ba6989d310c424361b64b Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Fri, 19 Aug 2022 13:54:54 +0100 Subject: [PATCH 10/61] Revert Fixed bug #79451 The fix for 8.1 and above is not identical and I don't know how to fix without breaking the whole build apparently --- NEWS | 4 ---- ext/dom/node.c | 20 +++++--------------- 2 files changed, 5 insertions(+), 19 deletions(-) diff --git a/NEWS b/NEWS index b45dce71fc5fb..d0372e385befc 100644 --- a/NEWS +++ b/NEWS @@ -6,10 +6,6 @@ PHP NEWS . Fixed bug GH-9323 (Crash in ZEND_RETURN/GC/zend_call_function) (Tim Starling) -- DOM: - . Fixed bug #79451 (Using DOMDocument->replaceChild on doctype causes - double free) (NathanFreeman) - - Streams: . Fixed bug GH-9316 ($http_response_header is wrong for long status line). (cmb, timwolla) diff --git a/ext/dom/node.c b/ext/dom/node.c index 6d86a46918baa..a6f88b5c0f1bb 100644 --- a/ext/dom/node.c +++ b/ext/dom/node.c @@ -20,7 +20,6 @@ #endif #include "php.h" - #if defined(HAVE_LIBXML) && defined(HAVE_DOM) #include "php_dom.h" @@ -1002,7 +1001,6 @@ PHP_METHOD(DOMNode, replaceChild) xmlNodePtr children, newchild, oldchild, nodep; dom_object *intern, *newchildobj, *oldchildobj; int foundoldchild = 0, stricterror; - bool replacedoctype = false; int ret; @@ -1065,21 +1063,13 @@ PHP_METHOD(DOMNode, replaceChild) dom_reconcile_ns(nodep->doc, newchild); } } else if (oldchild != newchild) { - xmlDtdPtr intSubset = xmlGetIntSubset(nodep->doc); - replacedoctype = (intSubset == (xmlDtd *) oldchild); - if (newchild->doc == NULL && nodep->doc != NULL) { xmlSetTreeDoc(newchild, nodep->doc); newchildobj->document = intern->document; php_libxml_increment_doc_ref((php_libxml_node_object *)newchildobj, NULL); } - xmlReplaceNode(oldchild, newchild); dom_reconcile_ns(nodep->doc, newchild); - - if (replacedoctype) { - nodep->doc->intSubset = (xmlDtd *) newchild; - } } DOM_RET_OBJ(oldchild, &ret, intern); return; @@ -1678,7 +1668,7 @@ static void dom_canonicalization(INTERNAL_FUNCTION_PARAMETERS, int mode) /* {{{ buf = xmlAllocOutputBuffer(NULL); } - if (buf != NULL) { + if (buf != NULL) { ret = xmlC14NDocSaveTo(docp, nodeset, exclusive, inclusive_ns_prefixes, with_comments, buf); } @@ -1693,9 +1683,9 @@ static void dom_canonicalization(INTERNAL_FUNCTION_PARAMETERS, int mode) /* {{{ xmlXPathFreeContext(ctxp); } - if (buf == NULL || ret < 0) { - RETVAL_FALSE; - } else { + if (buf == NULL || ret < 0) { + RETVAL_FALSE; + } else { if (mode == 0) { #ifdef LIBXML2_NEW_BUFFER ret = xmlOutputBufferGetSize(buf); @@ -1712,7 +1702,7 @@ static void dom_canonicalization(INTERNAL_FUNCTION_PARAMETERS, int mode) /* {{{ RETVAL_EMPTY_STRING(); } } - } + } if (buf) { int bytes; From 52e312afb8dfb6cd34d3e50a5dd487167be8637d Mon Sep 17 00:00:00 2001 From: David Carlier Date: Fri, 19 Aug 2022 16:55:51 +0100 Subject: [PATCH 11/61] opcache jit fix message format for OpenBSD. like macOs it requires `ll`. Closes #9380. --- ext/opcache/jit/libudis86/udint.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/opcache/jit/libudis86/udint.h b/ext/opcache/jit/libudis86/udint.h index 734f0eaa82db1..0bf493c182bb6 100644 --- a/ext/opcache/jit/libudis86/udint.h +++ b/ext/opcache/jit/libudis86/udint.h @@ -79,7 +79,7 @@ #if defined(_MSC_VER) || defined(__BORLANDC__) # define FMT64 "I64" #else -# if defined(__APPLE__) +# if defined(__APPLE__) || defined(__OpenBSD__) # define FMT64 "ll" # elif defined(__amd64__) || defined(__x86_64__) # define FMT64 "l" From 6027d441c1d650cad0c74e5d973a782f4b9c7516 Mon Sep 17 00:00:00 2001 From: NathanFreeman <1056159381@qq.com> Date: Thu, 4 Aug 2022 16:04:41 +0200 Subject: [PATCH 12/61] Fix #79451: DOMDocument->replaceChild on doctype causes double free We have to reset intSubset if replacing doctype with another doctype node. Closes GH-9201. Closes GH-9376. --- NEWS | 4 ++++ ext/dom/node.c | 10 ++++++++++ 2 files changed, 14 insertions(+) diff --git a/NEWS b/NEWS index d0372e385befc..2f93cb9808a1b 100644 --- a/NEWS +++ b/NEWS @@ -6,6 +6,10 @@ PHP NEWS . Fixed bug GH-9323 (Crash in ZEND_RETURN/GC/zend_call_function) (Tim Starling) +- DOM: + . Fixed bug #79451 (DOMDocument->replaceChild on doctype causes double free). + (Nathan Freeman) + - Streams: . Fixed bug GH-9316 ($http_response_header is wrong for long status line). (cmb, timwolla) diff --git a/ext/dom/node.c b/ext/dom/node.c index a6f88b5c0f1bb..a469ce28f77b5 100644 --- a/ext/dom/node.c +++ b/ext/dom/node.c @@ -20,6 +20,7 @@ #endif #include "php.h" + #if defined(HAVE_LIBXML) && defined(HAVE_DOM) #include "php_dom.h" @@ -1001,6 +1002,7 @@ PHP_METHOD(DOMNode, replaceChild) xmlNodePtr children, newchild, oldchild, nodep; dom_object *intern, *newchildobj, *oldchildobj; int foundoldchild = 0, stricterror; + bool replacedoctype = false; int ret; @@ -1063,13 +1065,21 @@ PHP_METHOD(DOMNode, replaceChild) dom_reconcile_ns(nodep->doc, newchild); } } else if (oldchild != newchild) { + xmlDtdPtr intSubset = xmlGetIntSubset(nodep->doc); + replacedoctype = (intSubset == (xmlDtd *) oldchild); + if (newchild->doc == NULL && nodep->doc != NULL) { xmlSetTreeDoc(newchild, nodep->doc); newchildobj->document = intern->document; php_libxml_increment_doc_ref((php_libxml_node_object *)newchildobj, NULL); } + xmlReplaceNode(oldchild, newchild); dom_reconcile_ns(nodep->doc, newchild); + + if (replacedoctype) { + nodep->doc->intSubset = (xmlDtd *) newchild; + } } DOM_RET_OBJ(oldchild, &ret, intern); return; From 305892580efc063fb3c2ddfb4c8d254c7d1ffb5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Vo=C5=99=C3=AD=C5=A1ek?= Date: Tue, 19 Jul 2022 12:05:10 +0200 Subject: [PATCH 13/61] Fix pdo_oci tests for PHP 8.0 --- ext/pdo/tests/bug_73234.phpt | 5 ++ ext/pdo/tests/gh8626.phpt | 5 ++ ...i_stream_2a.phpt => pdo_oci_stream_2.phpt} | 53 +++++++++++++- ext/pdo_oci/tests/pdo_oci_stream_2b.phpt | 70 ------------------- 4 files changed, 62 insertions(+), 71 deletions(-) rename ext/pdo_oci/tests/{pdo_oci_stream_2a.phpt => pdo_oci_stream_2.phpt} (60%) delete mode 100644 ext/pdo_oci/tests/pdo_oci_stream_2b.phpt diff --git a/ext/pdo/tests/bug_73234.phpt b/ext/pdo/tests/bug_73234.phpt index 451cc4849c42a..e3e3c0b2b8090 100644 --- a/ext/pdo/tests/bug_73234.phpt +++ b/ext/pdo/tests/bug_73234.phpt @@ -7,6 +7,11 @@ $dir = getenv('REDIR_TEST_DIR'); if (false == $dir) die('skip no driver'); require_once $dir . 'pdo_test.inc'; PDOTest::skip(); + +$db = PDOTest::factory(); +if ($db->getAttribute(PDO::ATTR_DRIVER_NAME) == 'oci') { + die("xfail PDO::PARAM_NULL is not honored by OCI driver, related with bug #81586"); +} ?> --FILE-- getAttribute(PDO::ATTR_DRIVER_NAME) == 'oci') { + die("xfail OCI driver errorInfo is inconsistent with other PDO drivers"); +} ?> --FILE-- exec("drop table pdo_oci_stream_2"); +$db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false); // Let's use streams + +// Since each column only has one lob descriptor, the last row is +// shown twice because the lob descriptor for each column is reused in +// the stream + +$i = 0; +$j = 9; +$a_val = ord('a'); +foreach($db->query("select data1 as d4_1, data2 as d4_2 from pdo_oci_stream_2 order by id") as $row) { + $a = $row['d4_1']; + $a1 = $row['d4_2']; + + $str1 = stream_get_contents($a); + $str2 = stream_get_contents($a1); + + $str1len = strlen($str1); + $str2len = strlen($str2); + + $b = ord($str1[0]); + $b1 = ord($str2[0]); + + if (($b != ($a_val + $i)) && ($str1len != (4086 + $i)) && + ($b1 != ($a_val + $j)) && ($str2len != (4086 + $j))) { + printf("There is a bug!\n"); + printf("Col1:\n"); + printf("a_val = %d\n", $a_val); + printf("b = %d\n", $b); + printf("i = %d\n", $i); + printf("str1len = %d\n", $str1len); + + printf("Col2:\n"); + printf("a_val = %d\n", $a_val); + printf("b1 = %d\n", $b1); + printf("j = %d\n", $j); + printf("str2len = %d\n", $str1len); + + } + $i++; + if ($i>9) + $i = 0; + $j--; + if ($j<0) + $j = 9; +} +echo "Fetch operation done!\n"; + +/* Cleanup */ +$db->exec("drop table pdo_oci_stream_2"); + ?> --EXPECT-- Inserting 1000 Records ... Done +Fetch operation done! diff --git a/ext/pdo_oci/tests/pdo_oci_stream_2b.phpt b/ext/pdo_oci/tests/pdo_oci_stream_2b.phpt deleted file mode 100644 index de09c4872883b..0000000000000 --- a/ext/pdo_oci/tests/pdo_oci_stream_2b.phpt +++ /dev/null @@ -1,70 +0,0 @@ ---TEST-- -PDO OCI: Fetches 1K records from a table that contains 1 number and 2 LOB columns (stress test) ---SKIPIF-- - ---FILE-- -setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false); // Let's use streams - -// Since each column only has one lob descriptor, the last row is -// shown twice because the lob descriptor for each column is reused in -// the stream - -$i = 0; -$j = 9; -$a_val = ord('a'); -foreach($db->query("select data1 as d4_1, data2 as d4_2 from pdo_oci_stream_2 order by id") as $row) { - $a = $row['d4_1']; - $a1 = $row['d4_2']; - - $str1 = stream_get_contents($a); - $str2 = stream_get_contents($a1); - - $str1len = strlen($str1); - $str2len = strlen($str2); - - $b = ord($str1[0]); - $b1 = ord($str2[0]); - - if (($b != ($a_val + $i)) && ($str1len != (4086 + $i)) && - ($b1 != ($a_val + $j)) && ($str2len != (4086 + $j))) { - printf("There is a bug!\n"); - printf("Col1:\n"); - printf("a_val = %d\n", $a_val); - printf("b = %d\n", $b); - printf("i = %d\n", $i); - printf("str1len = %d\n", $str1len); - - printf("Col2:\n"); - printf("a_val = %d\n", $a_val); - printf("b1 = %d\n", $b1); - printf("j = %d\n", $j); - printf("str2len = %d\n", $str1len); - - } - $i++; - if ($i>9) - $i = 0; - $j--; - if ($j<0) - $j = 9; -} -echo "Fetch operation done!\n"; - -/* Cleanup */ -$db->exec("drop table pdo_oci_stream_2"); - -?> ---EXPECT-- -Fetch operation done! From bb341210f53b7597a8a4821efdee9ce59810f2ed Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Fri, 19 Aug 2022 16:26:26 +0200 Subject: [PATCH 14/61] Fix GH-9361: Segmentation fault on script exit Using a lot of memory may overflow some `int` calculations; to avoid that we make sure that the operands are promoted to `size_t`. This issue has been analyzed by @chschneider. Closes GH-9379. --- NEWS | 2 ++ Zend/zend_alloc_sizes.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 2f93cb9808a1b..21d5d334a4e4c 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,8 @@ PHP NEWS - Core: . Fixed bug GH-9323 (Crash in ZEND_RETURN/GC/zend_call_function) (Tim Starling) + . Fixed bug GH-9361 (Segmentation fault on script exit #9379). (cmb, + Christian Schneider) - DOM: . Fixed bug #79451 (DOMDocument->replaceChild on doctype causes double free). diff --git a/Zend/zend_alloc_sizes.h b/Zend/zend_alloc_sizes.h index 9f1c00eaad568..502b982a50522 100644 --- a/Zend/zend_alloc_sizes.h +++ b/Zend/zend_alloc_sizes.h @@ -19,7 +19,7 @@ #ifndef ZEND_ALLOC_SIZES_H #define ZEND_ALLOC_SIZES_H -#define ZEND_MM_CHUNK_SIZE (2 * 1024 * 1024) /* 2 MB */ +#define ZEND_MM_CHUNK_SIZE ((size_t) (2 * 1024 * 1024)) /* 2 MB */ #define ZEND_MM_PAGE_SIZE (4 * 1024) /* 4 KB */ #define ZEND_MM_PAGES (ZEND_MM_CHUNK_SIZE / ZEND_MM_PAGE_SIZE) /* 512 */ #define ZEND_MM_FIRST_PAGE (1) From c9c51eb1f15117517384ba4e1707af326b3a161b Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 22 Aug 2022 15:38:41 +0300 Subject: [PATCH 15/61] Tracing JIT: Fix incorrect guard elimination Fixes oss-fuzz #49917 --- ext/opcache/jit/zend_jit_trace.c | 48 ++++++++++++++++++++++++++---- ext/opcache/tests/jit/add_014.phpt | 25 ++++++++++++++++ 2 files changed, 68 insertions(+), 5 deletions(-) create mode 100644 ext/opcache/tests/jit/add_014.phpt diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c index 2890f7ebfd75c..47463fc682ca2 100644 --- a/ext/opcache/jit/zend_jit_trace.c +++ b/ext/opcache/jit/zend_jit_trace.c @@ -981,6 +981,9 @@ static int is_checked_guard(const zend_ssa *tssa, const zend_op **ssa_opcodes, u && (tssa->var_info[tssa->ops[idx].op1_use].type & MAY_BE_STRING)) { return 0; } + if (!(tssa->var_info[tssa->ops[idx].op1_use].type & (MAY_BE_LONG|MAY_BE_DOUBLE))) { + return 0; + } return 1; } else if (opline->opcode == ZEND_ASSIGN_OP && (opline->extended_value == ZEND_ADD @@ -991,6 +994,17 @@ static int is_checked_guard(const zend_ssa *tssa, const zend_op **ssa_opcodes, u && (tssa->var_info[tssa->ops[idx].op2_use].type & MAY_BE_REF)) { return 0; } + if (!(tssa->var_info[tssa->ops[idx].op1_use].type & (MAY_BE_LONG|MAY_BE_DOUBLE))) { + return 0; + } + if (opline->op2_type == IS_CONST) { + zval *zv = RT_CONSTANT(opline, opline->op2); + if (Z_TYPE_P(zv) != IS_LONG && Z_TYPE_P(zv) != IS_DOUBLE) { + return 0; + } + } else if (!(tssa->var_info[tssa->ops[idx].op2_use].type & (MAY_BE_LONG|MAY_BE_DOUBLE))) { + return 0; + } return 1; } } @@ -998,11 +1012,7 @@ static int is_checked_guard(const zend_ssa *tssa, const zend_op **ssa_opcodes, u const zend_op *opline = ssa_opcodes[idx]; if (opline->opcode == ZEND_ADD || opline->opcode == ZEND_SUB - || opline->opcode == ZEND_MUL - || opline->opcode == ZEND_PRE_DEC - || opline->opcode == ZEND_PRE_INC - || opline->opcode == ZEND_POST_DEC - || opline->opcode == ZEND_POST_INC) { + || opline->opcode == ZEND_MUL) { if ((opline->op1_type & (IS_VAR|IS_CV)) && tssa->ops[idx].op1_use >= 0 && (tssa->var_info[tssa->ops[idx].op1_use].type & MAY_BE_REF)) { @@ -1013,6 +1023,34 @@ static int is_checked_guard(const zend_ssa *tssa, const zend_op **ssa_opcodes, u && (tssa->var_info[tssa->ops[idx].op2_use].type & MAY_BE_REF)) { return 0; } + if (opline->op1_type == IS_CONST) { + zval *zv = RT_CONSTANT(opline, opline->op1); + if (Z_TYPE_P(zv) != IS_LONG && Z_TYPE_P(zv) != IS_DOUBLE) { + return 0; + } + } else if (!(tssa->var_info[tssa->ops[idx].op1_use].type & (MAY_BE_LONG|MAY_BE_DOUBLE))) { + return 0; + } + if (opline->op2_type == IS_CONST) { + zval *zv = RT_CONSTANT(opline, opline->op2); + if (Z_TYPE_P(zv) != IS_LONG && Z_TYPE_P(zv) != IS_DOUBLE) { + return 0; + } + } else if (!(tssa->var_info[tssa->ops[idx].op2_use].type & (MAY_BE_LONG|MAY_BE_DOUBLE))) { + return 0; + } + } else if (opline->opcode == ZEND_PRE_DEC + || opline->opcode == ZEND_PRE_INC + || opline->opcode == ZEND_POST_DEC + || opline->opcode == ZEND_POST_INC) { + if ((opline->op1_type & (IS_VAR|IS_CV)) + && tssa->ops[idx].op1_use >= 0 + && (tssa->var_info[tssa->ops[idx].op1_use].type & MAY_BE_REF)) { + return 0; + } + if (!(tssa->var_info[tssa->ops[idx].op1_use].type & (MAY_BE_LONG|MAY_BE_DOUBLE))) { + return 0; + } return 1; } } diff --git a/ext/opcache/tests/jit/add_014.phpt b/ext/opcache/tests/jit/add_014.phpt new file mode 100644 index 0000000000000..b7691c770334c --- /dev/null +++ b/ext/opcache/tests/jit/add_014.phpt @@ -0,0 +1,25 @@ +--TEST-- +JIT ADD: 014 incorrect guard elimination +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit_buffer_size=1M +--FILE-- +> 4 - $j++; + if ($j > 14) break; + } +} +try { + @test(); +} catch (Throwable $e) { + echo $e->getMessage() . "\n"; +} +?> +--EXPECT-- +Bit shift by negative number From 73c2d79fc5a517340cc629c053c6ce0d096afaf7 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 22 Aug 2022 17:47:07 +0300 Subject: [PATCH 16/61] Fix memory leaks Fixes oss-fuzz #50078 --- .../named_params/call_user_func_array_variadic.phpt | 13 +++++++++++++ Zend/zend_compile.c | 4 +++- 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 Zend/tests/named_params/call_user_func_array_variadic.phpt diff --git a/Zend/tests/named_params/call_user_func_array_variadic.phpt b/Zend/tests/named_params/call_user_func_array_variadic.phpt new file mode 100644 index 0000000000000..89a8f7cb10e33 --- /dev/null +++ b/Zend/tests/named_params/call_user_func_array_variadic.phpt @@ -0,0 +1,13 @@ +--TEST-- +call_user_func_array() with extra named parameters +--FILE-- + 1); +call_user_func_array("array_multisort", $args); +?> +--EXPECTF-- +Fatal error: Uncaught ArgumentCountError: array_multisort() expects at least 1 argument, 0 given in %scall_user_func_array_variadic.php:3 +Stack trace: +#0 %scall_user_func_array_variadic.php(3): array_multisort(: 1) +#1 {main} + thrown in %scall_user_func_array_variadic.php on line 3 diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index cf43dd852a7c6..cde1758ffc4e2 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -3860,6 +3860,7 @@ static void zend_compile_init_user_func(zend_ast *name_ast, uint32_t num_args, z zend_result zend_compile_func_cufa(znode *result, zend_ast_list *args, zend_string *lcname) /* {{{ */ { znode arg_node; + zend_op *opline; if (args->children != 2) { return FAILURE; @@ -3901,7 +3902,8 @@ zend_result zend_compile_func_cufa(znode *result, zend_ast_list *args, zend_stri zend_compile_expr(&arg_node, args->child[1]); zend_emit_op(NULL, ZEND_SEND_ARRAY, &arg_node, NULL); zend_emit_op(NULL, ZEND_CHECK_UNDEF_ARGS, NULL, NULL); - zend_emit_op(result, ZEND_DO_FCALL, NULL, NULL); + opline = zend_emit_op(result, ZEND_DO_FCALL, NULL, NULL); + opline->extended_value = ZEND_FCALL_MAY_HAVE_EXTRA_NAMED_PARAMS; return SUCCESS; } From fd74ee7e909c66f09d8d904a5438b275a13e8738 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 22 Aug 2022 19:53:33 +0300 Subject: [PATCH 17/61] JIT: Make code generation to be consistent with register allocation Fixes ext/opcache/tests/jit/add_014.phpt with opcache.jit=1205 --- ext/opcache/jit/zend_jit_x86.dasc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index 37450f9c28c19..dfe3b6aa78d7f 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -8781,7 +8781,7 @@ static int zend_jit_bool_jmpznz(dasm_State **Dst, const zend_op *opline, uint32_ } } - if ((op1_info & MAY_BE_ANY) == MAY_BE_DOUBLE) { + if ((op1_info & (MAY_BE_ANY-(MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG))) == MAY_BE_DOUBLE) { |2: if (CAN_USE_AVX()) { | vxorps xmm0, xmm0, xmm0 From 95befc786ae89afc5b9b6c6d26fa26883e50ebf0 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 22 Aug 2022 21:11:39 +0300 Subject: [PATCH 18/61] Fix type inference Fixes oss-fuzz #50272 --- Zend/Optimizer/zend_inference.c | 3 +++ ext/opcache/tests/opt/inference_015.phpt | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 ext/opcache/tests/opt/inference_015.phpt diff --git a/Zend/Optimizer/zend_inference.c b/Zend/Optimizer/zend_inference.c index 5dec2dd24a3db..dc73ffb6f416b 100644 --- a/Zend/Optimizer/zend_inference.c +++ b/Zend/Optimizer/zend_inference.c @@ -1951,6 +1951,9 @@ static uint32_t assign_dim_array_result_type( tmp |= MAY_BE_ARRAY_KEY_STRING; if (dim_op_type != IS_CONST) { // FIXME: numeric string + if (arr_type & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE)) { + tmp |= MAY_BE_ARRAY_PACKED; + } tmp |= MAY_BE_HASH_ONLY(arr_type) ? MAY_BE_ARRAY_NUMERIC_HASH : MAY_BE_ARRAY_KEY_LONG; } } diff --git a/ext/opcache/tests/opt/inference_015.phpt b/ext/opcache/tests/opt/inference_015.phpt new file mode 100644 index 0000000000000..e64c02225b32f --- /dev/null +++ b/ext/opcache/tests/opt/inference_015.phpt @@ -0,0 +1,19 @@ +--TEST-- +Type inference 015: ASSIGN_DIM_OP +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.optimization_level=-1 +--FILE-- + +DONE +--EXPECT-- +DONE From 2db2cab6adb95707e3bf671d8e6c3c19623c64c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Vo=C5=99=C3=AD=C5=A1ek?= Date: Wed, 24 Aug 2022 14:34:01 +0200 Subject: [PATCH 19/61] Fix pdo_oci tests for PHP 8.1 Closes GH-9051 --- ext/pdo/tests/pdo_039.phpt | 14 ++++++++++++-- ext/pdo_oci/tests/pdo_oci_quote1.phpt | 11 +---------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/ext/pdo/tests/pdo_039.phpt b/ext/pdo/tests/pdo_039.phpt index ecde2428769cc..5004fc40d651d 100644 --- a/ext/pdo/tests/pdo_039.phpt +++ b/ext/pdo/tests/pdo_039.phpt @@ -28,19 +28,29 @@ if ($pass === false) $pass = NULL; $conn = new PDO($dsn, $user, $pass, $attr); -$query = 'SELECT 1'; +var_dump($conn->errorCode()); +$query = 'SELECT 1'; +if ($conn->getAttribute(PDO::ATTR_DRIVER_NAME) === 'oci') { + $query .= ' FROM DUAL'; +} var_dump($conn->errorCode()); -$stmt = $conn->prepare($query); var_dump($conn->errorCode()); +$stmt = $conn->prepare($query); +var_dump($conn->errorCode()); var_dump($stmt->errorCode()); + $stmt->execute(); var_dump($stmt->errorCode()); +var_dump($stmt->errorCode()); ?> --EXPECT-- NULL string(5) "00000" +string(5) "00000" +string(5) "00000" NULL string(5) "00000" +string(5) "00000" diff --git a/ext/pdo_oci/tests/pdo_oci_quote1.phpt b/ext/pdo_oci/tests/pdo_oci_quote1.phpt index 024625a181fc4..ea2a5468dbd5b 100644 --- a/ext/pdo_oci/tests/pdo_oci_quote1.phpt +++ b/ext/pdo_oci/tests/pdo_oci_quote1.phpt @@ -21,7 +21,7 @@ $stmt = $db->prepare('select * from poq_tab'); // The intent is that the fetched data be identical to the unquoted string. // Remember!: use bind variables instead of PDO->quote() -$a = array(null, "", "a", "ab", "abc", "ab'cd", "a\b\n", "'", "''", "a'", "'z", "a''b", '"'); +$a = array("", "a", "ab", "abc", "ab'cd", "a\b\n", "'", "''", "a'", "'z", "a''b", '"'); foreach ($a as $u) { $q = $db->quote($u); echo "Unquoted : "; @@ -42,15 +42,6 @@ echo "Done\n"; ?> --EXPECT-- -Unquoted : NULL -Quoted : string(2) "''" -array(1) { - [0]=> - array(1) { - ["t"]=> - NULL - } -} Unquoted : string(0) "" Quoted : string(2) "''" array(1) { From c19116ff09fda3afd93f5ebfad11086e3c96d406 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Vo=C5=99=C3=AD=C5=A1ek?= Date: Wed, 24 Aug 2022 15:21:37 +0200 Subject: [PATCH 20/61] Test oci8 & pdo_oci in CI Closes GH-8348 --- .github/actions/apt-x64/action.yml | 7 ++++++- .github/actions/install-linux/action.yml | 2 ++ .github/actions/{mssql => setup-mssql}/action.yml | 2 +- .github/actions/setup-oracle/action.yml | 13 +++++++++++++ .github/actions/setup-x64/action.yml | 2 +- .github/actions/test-linux/action.yml | 6 ++++++ .github/workflows/nightly.yml | 6 ++++-- .github/workflows/push.yml | 6 ++++-- 8 files changed, 37 insertions(+), 7 deletions(-) rename .github/actions/{mssql => setup-mssql}/action.yml (91%) create mode 100644 .github/actions/setup-oracle/action.yml diff --git a/.github/actions/apt-x64/action.yml b/.github/actions/apt-x64/action.yml index a5b0db49e8270..abae59c8fdea4 100644 --- a/.github/actions/apt-x64/action.yml +++ b/.github/actions/apt-x64/action.yml @@ -5,6 +5,7 @@ runs: - shell: bash run: | set -x + sudo apt-get update sudo apt-get install \ bison \ @@ -58,11 +59,15 @@ runs: libjpeg-dev \ libpng-dev \ libfreetype6-dev + mkdir /opt/oracle wget -nv https://download.oracle.com/otn_software/linux/instantclient/instantclient-basiclite-linuxx64.zip unzip instantclient-basiclite-linuxx64.zip && rm instantclient-basiclite-linuxx64.zip wget -nv https://download.oracle.com/otn_software/linux/instantclient/instantclient-sdk-linuxx64.zip unzip instantclient-sdk-linuxx64.zip && rm instantclient-sdk-linuxx64.zip mv instantclient_*_* /opt/oracle/instantclient - # Interferes with libldap2 headers. + # interferes with libldap2 headers rm /opt/oracle/instantclient/sdk/include/ldap.h + # fix debug build warning: zend_signal: handler was replaced for signal (2) after startup + echo DISABLE_INTERRUPT=on > /opt/oracle/instantclient/network/admin/sqlnet.ora + sudo sh -c 'echo /opt/oracle/instantclient >/etc/ld.so.conf.d/oracle-instantclient.conf && ldconfig' diff --git a/.github/actions/install-linux/action.yml b/.github/actions/install-linux/action.yml index e0f6726dbd1d3..7ac2ae4c4fcb1 100644 --- a/.github/actions/install-linux/action.yml +++ b/.github/actions/install-linux/action.yml @@ -10,3 +10,5 @@ runs: sudo chmod 777 /etc/php.d echo mysqli.default_socket=/var/run/mysqld/mysqld.sock > /etc/php.d/mysqli.ini echo pdo_mysql.default_socket=/var/run/mysqld/mysqld.sock > /etc/php.d/pdo_mysql.ini + echo extension=oci8.so > /etc/php.d/oci8.ini + echo extension=pdo_oci.so > /etc/php.d/pdo_oci.ini diff --git a/.github/actions/mssql/action.yml b/.github/actions/setup-mssql/action.yml similarity index 91% rename from .github/actions/mssql/action.yml rename to .github/actions/setup-mssql/action.yml index 894380644c1ea..c069744a21b59 100644 --- a/.github/actions/mssql/action.yml +++ b/.github/actions/setup-mssql/action.yml @@ -1,4 +1,4 @@ -name: Create mssql container +name: Create MSSQL container runs: using: composite steps: diff --git a/.github/actions/setup-oracle/action.yml b/.github/actions/setup-oracle/action.yml new file mode 100644 index 0000000000000..11c16fe93d525 --- /dev/null +++ b/.github/actions/setup-oracle/action.yml @@ -0,0 +1,13 @@ +name: Create Oracle container +runs: + using: composite + steps: + - shell: bash + run: | + set -x + docker run \ + -e "ORACLE_PASSWORD=pass" \ + -p 1521:1521 \ + --name oracle \ + -h oracle \ + -d gvenzl/oracle-xe:slim diff --git a/.github/actions/setup-x64/action.yml b/.github/actions/setup-x64/action.yml index 6cec51d4c8079..bb014bfe9de11 100644 --- a/.github/actions/setup-x64/action.yml +++ b/.github/actions/setup-x64/action.yml @@ -17,7 +17,7 @@ runs: docker exec sql1 /opt/mssql-tools/bin/sqlcmd -S 127.0.0.1 -U SA -P "" -Q "create login pdo_test with password='password', check_policy=off; create user pdo_test for login pdo_test; grant alter, control to pdo_test;" sudo locale-gen de_DE - ./.github/scripts/setup-slapd.sh + ./.github/scripts/setup-slapd.sh &>/dev/null sudo cp ext/snmp/tests/snmpd.conf /etc/snmp sudo cp ext/snmp/tests/bigtest /etc/snmp diff --git a/.github/actions/test-linux/action.yml b/.github/actions/test-linux/action.yml index c7dab609820dd..7db8fa58900d3 100644 --- a/.github/actions/test-linux/action.yml +++ b/.github/actions/test-linux/action.yml @@ -17,6 +17,12 @@ runs: export PDO_DBLIB_TEST_DSN="dblib:host=127.0.0.1;dbname=master;version=7.0" export PDO_DBLIB_TEST_USER="pdo_test" export PDO_DBLIB_TEST_PASS="password" + export PHP_OCI8_TEST_USER="system" + export PHP_OCI8_TEST_PASS="pass" + export PHP_OCI8_TEST_DB="localhost/XEPDB1" + export PDO_OCI_TEST_USER="system" + export PDO_OCI_TEST_PASS="pass" + export PDO_OCI_TEST_DSN="oci:dbname=localhost/XEPDB1;charset=AL32UTF8" export SKIP_IO_CAPTURE_TESTS=1 sapi/cli/php run-tests.php -P -q ${{ inputs.runTestsParameters }} \ -j$(/usr/bin/nproc) \ diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 33c9335ef72da..b5e28b2fdd8f9 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -47,8 +47,10 @@ jobs: uses: actions/checkout@v2 with: ref: ${{ matrix.branch.ref }} - - name: Create mssql container - uses: ./.github/actions/mssql + - name: Create MSSQL container + uses: ./.github/actions/setup-mssql + - name: Create Oracle container + uses: ./.github/actions/setup-oracle - name: apt uses: ./.github/actions/apt-x64 - name: ./configure diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index bd05e60d89572..520a701a0de43 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -32,8 +32,10 @@ jobs: steps: - name: git checkout uses: actions/checkout@v2 - - name: Create mssql container - uses: ./.github/actions/mssql + - name: Create MSSQL container + uses: ./.github/actions/setup-mssql + - name: Create Oracle container + uses: ./.github/actions/setup-oracle - name: apt uses: ./.github/actions/apt-x64 - name: ./configure From f59754694eaebc75cba569f6f3e9b1a503d68b9a Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Wed, 24 Aug 2022 14:13:20 +0200 Subject: [PATCH 21/61] xmlRelaxNGCleanupTypes() is deprecated as of libxml2 2.10.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The documentation[1] suggest to call `xmlCleanupParser()` instead, but we are not doing that for reasons[2]. Thus, we do no longer call `xmlRelaxNGCleanupTypes()` for libxml2 ≥ 2.10.0. [1] [2] Closes GH-9417. --- ext/libxml/libxml.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/libxml/libxml.c b/ext/libxml/libxml.c index 2b2089a2d7b7c..73486ae253f84 100644 --- a/ext/libxml/libxml.c +++ b/ext/libxml/libxml.c @@ -772,7 +772,7 @@ PHP_LIBXML_API void php_libxml_initialize(void) PHP_LIBXML_API void php_libxml_shutdown(void) { if (_php_libxml_initialized) { -#ifdef LIBXML_SCHEMAS_ENABLED +#if defined(LIBXML_SCHEMAS_ENABLED) && LIBXML_VERSION < 21000 xmlRelaxNGCleanupTypes(); #endif /* xmlCleanupParser(); */ From be4dd60c55f5e2837124c2889bffe3784e4f712a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Vo=C5=99=C3=AD=C5=A1ek?= Date: Thu, 25 Aug 2022 14:35:39 +0200 Subject: [PATCH 22/61] Fix oci8/pdo_oci random test failures when run in parallel Closes GH-9424. --- ext/oci8/tests/CONFLICTS | 1 + ext/pdo_oci/tests/CONFLICTS | 1 + 2 files changed, 2 insertions(+) create mode 100644 ext/oci8/tests/CONFLICTS create mode 100644 ext/pdo_oci/tests/CONFLICTS diff --git a/ext/oci8/tests/CONFLICTS b/ext/oci8/tests/CONFLICTS new file mode 100644 index 0000000000000..176b41ab8bb6f --- /dev/null +++ b/ext/oci8/tests/CONFLICTS @@ -0,0 +1 @@ +oci8 diff --git a/ext/pdo_oci/tests/CONFLICTS b/ext/pdo_oci/tests/CONFLICTS new file mode 100644 index 0000000000000..176b41ab8bb6f --- /dev/null +++ b/ext/pdo_oci/tests/CONFLICTS @@ -0,0 +1 @@ +oci8 From 34d9e089c2124a7b101596fdf21402f66262b984 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Vo=C5=99=C3=AD=C5=A1ek?= Date: Fri, 26 Aug 2022 10:20:41 +0200 Subject: [PATCH 23/61] Fix GH-8348 for nightly --- .github/workflows/nightly.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index b5e28b2fdd8f9..38d85d2b7224e 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -160,8 +160,10 @@ jobs: steps: - name: git checkout uses: actions/checkout@v2 - - name: Create mssql container - uses: ./.github/actions/mssql + - name: Create MSSQL container + uses: ./.github/actions/setup-mssql + - name: Create Oracle container + uses: ./.github/actions/setup-oracle - name: apt uses: ./.github/actions/apt-x64 - name: Install gcovr From f86629569ced0816a8d51c32b8b23fda23f2804e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Vo=C5=99=C3=AD=C5=A1ek?= Date: Fri, 26 Aug 2022 13:14:35 +0200 Subject: [PATCH 24/61] Fix pdo_dblib ext test conflicts when run in parallel Closes GH-9430. --- ext/pdo_dblib/tests/CONFLICTS | 1 + 1 file changed, 1 insertion(+) create mode 100644 ext/pdo_dblib/tests/CONFLICTS diff --git a/ext/pdo_dblib/tests/CONFLICTS b/ext/pdo_dblib/tests/CONFLICTS new file mode 100644 index 0000000000000..7980e46ba3fa6 --- /dev/null +++ b/ext/pdo_dblib/tests/CONFLICTS @@ -0,0 +1 @@ +pdo_dblib From e2a5428ca08ad10c0f08a686e974af774b4d1b18 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Mon, 18 Jul 2022 07:51:02 +0100 Subject: [PATCH 25/61] FPM fix strict prototype warnings. Closes GH-8986. --- sapi/fpm/fpm/events/devpoll.c | 8 +++----- sapi/fpm/fpm/events/devpoll.h | 2 +- sapi/fpm/fpm/events/epoll.c | 8 +++----- sapi/fpm/fpm/events/epoll.h | 2 +- sapi/fpm/fpm/events/poll.c | 11 ++++------- sapi/fpm/fpm/events/poll.h | 2 +- sapi/fpm/fpm/events/port.c | 5 ++--- sapi/fpm/fpm/events/port.h | 2 +- sapi/fpm/fpm/events/select.c | 3 +-- sapi/fpm/fpm/events/select.h | 2 +- sapi/fpm/fpm/fpm_children.c | 9 +++------ sapi/fpm/fpm/fpm_children.h | 4 ++-- sapi/fpm/fpm/fpm_clock.c | 9 +++------ sapi/fpm/fpm/fpm_clock.h | 2 +- sapi/fpm/fpm/fpm_conf.c | 15 +++++---------- sapi/fpm/fpm/fpm_conf.h | 4 ++-- sapi/fpm/fpm/fpm_env.c | 6 ++---- sapi/fpm/fpm/fpm_env.h | 4 ++-- sapi/fpm/fpm/fpm_events.c | 9 +++------ sapi/fpm/fpm/fpm_events.h | 6 +++--- sapi/fpm/fpm/fpm_php.c | 24 ++++++++---------------- sapi/fpm/fpm/fpm_php.h | 4 ++-- sapi/fpm/fpm/fpm_process_ctl.c | 21 +++++++-------------- sapi/fpm/fpm/fpm_process_ctl.h | 6 +++--- sapi/fpm/fpm/fpm_request.c | 18 ++++++------------ sapi/fpm/fpm/fpm_request.h | 10 +++++----- sapi/fpm/fpm/fpm_scoreboard.c | 9 +++------ sapi/fpm/fpm/fpm_scoreboard.h | 6 +++--- sapi/fpm/fpm/fpm_shm.c | 3 +-- sapi/fpm/fpm/fpm_shm.h | 2 +- sapi/fpm/fpm/fpm_signals.c | 21 +++++++-------------- sapi/fpm/fpm/fpm_signals.h | 14 +++++++------- sapi/fpm/fpm/fpm_sockets.c | 3 +-- sapi/fpm/fpm/fpm_sockets.h | 2 +- sapi/fpm/fpm/fpm_stdio.c | 12 ++++-------- sapi/fpm/fpm/fpm_stdio.h | 6 +++--- sapi/fpm/fpm/fpm_systemd.c | 6 ++---- sapi/fpm/fpm/fpm_systemd.h | 2 +- sapi/fpm/fpm/fpm_trace_mach.c | 3 +-- sapi/fpm/fpm/fpm_unix.c | 3 +-- sapi/fpm/fpm/fpm_unix.h | 2 +- sapi/fpm/fpm/fpm_worker_pool.c | 6 ++---- sapi/fpm/fpm/fpm_worker_pool.h | 4 ++-- 43 files changed, 116 insertions(+), 184 deletions(-) diff --git a/sapi/fpm/fpm/events/devpoll.c b/sapi/fpm/fpm/events/devpoll.c index 0d165fe2fc8b4..322a57f6161b1 100644 --- a/sapi/fpm/fpm/events/devpoll.c +++ b/sapi/fpm/fpm/events/devpoll.c @@ -29,7 +29,7 @@ #include static int fpm_event_devpoll_init(int max); -static int fpm_event_devpoll_clean(); +static int fpm_event_devpoll_clean(void); static int fpm_event_devpoll_wait(struct fpm_event_queue_s *queue, unsigned long int timeout); static int fpm_event_devpoll_add(struct fpm_event_s *ev); static int fpm_event_devpoll_remove(struct fpm_event_s *ev); @@ -51,7 +51,7 @@ static int npollfds = 0; #endif /* HAVE_DEVPOLL */ -struct fpm_event_module_s *fpm_event_devpoll_module() /* {{{ */ +struct fpm_event_module_s *fpm_event_devpoll_module(void) { #ifdef HAVE_DEVPOLL return &devpoll_module; @@ -59,7 +59,6 @@ struct fpm_event_module_s *fpm_event_devpoll_module() /* {{{ */ return NULL; #endif /* HAVE_DEVPOLL */ } -/* }}} */ #ifdef HAVE_DEVPOLL @@ -113,7 +112,7 @@ static int fpm_event_devpoll_init(int max) /* {{{ */ /* * Clean the module */ -static int fpm_event_devpoll_clean() /* {{{ */ +static int fpm_event_devpoll_clean(void) { /* close /dev/poll if open */ if (dpfd > -1) { @@ -136,7 +135,6 @@ static int fpm_event_devpoll_clean() /* {{{ */ npollfds = 0; return 0; } -/* }}} */ /* * wait for events or timeout diff --git a/sapi/fpm/fpm/events/devpoll.h b/sapi/fpm/fpm/events/devpoll.h index b05a456924367..bac6c008b54f4 100644 --- a/sapi/fpm/fpm/events/devpoll.h +++ b/sapi/fpm/fpm/events/devpoll.h @@ -20,6 +20,6 @@ #include "../fpm_config.h" #include "../fpm_events.h" -struct fpm_event_module_s *fpm_event_devpoll_module(); +struct fpm_event_module_s *fpm_event_devpoll_module(void); #endif /* FPM_EVENTS_DEVPOLL_H */ diff --git a/sapi/fpm/fpm/events/epoll.c b/sapi/fpm/fpm/events/epoll.c index 9973ac0ddcef1..dbed786623089 100644 --- a/sapi/fpm/fpm/events/epoll.c +++ b/sapi/fpm/fpm/events/epoll.c @@ -25,7 +25,7 @@ #include static int fpm_event_epoll_init(int max); -static int fpm_event_epoll_clean(); +static int fpm_event_epoll_clean(void); static int fpm_event_epoll_wait(struct fpm_event_queue_s *queue, unsigned long int timeout); static int fpm_event_epoll_add(struct fpm_event_s *ev); static int fpm_event_epoll_remove(struct fpm_event_s *ev); @@ -46,7 +46,7 @@ static int epollfd = -1; #endif /* HAVE_EPOLL */ -struct fpm_event_module_s *fpm_event_epoll_module() /* {{{ */ +struct fpm_event_module_s *fpm_event_epoll_module(void) { #ifdef HAVE_EPOLL return &epoll_module; @@ -54,7 +54,6 @@ struct fpm_event_module_s *fpm_event_epoll_module() /* {{{ */ return NULL; #endif /* HAVE_EPOLL */ } -/* }}} */ #ifdef HAVE_EPOLL @@ -92,7 +91,7 @@ static int fpm_event_epoll_init(int max) /* {{{ */ /* * Clean the module */ -static int fpm_event_epoll_clean() /* {{{ */ +static int fpm_event_epoll_clean(void) { /* free epollfds */ if (epollfds) { @@ -108,7 +107,6 @@ static int fpm_event_epoll_clean() /* {{{ */ return 0; } -/* }}} */ /* * wait for events or timeout diff --git a/sapi/fpm/fpm/events/epoll.h b/sapi/fpm/fpm/events/epoll.h index 2469cbeaee30b..4f90249604a2d 100644 --- a/sapi/fpm/fpm/events/epoll.h +++ b/sapi/fpm/fpm/events/epoll.h @@ -20,6 +20,6 @@ #include "../fpm_config.h" #include "../fpm_events.h" -struct fpm_event_module_s *fpm_event_epoll_module(); +struct fpm_event_module_s *fpm_event_epoll_module(void); #endif /* FPM_EVENTS_EPOLL_H */ diff --git a/sapi/fpm/fpm/events/poll.c b/sapi/fpm/fpm/events/poll.c index 0363c2ece10a4..41e64277d8e18 100644 --- a/sapi/fpm/fpm/events/poll.c +++ b/sapi/fpm/fpm/events/poll.c @@ -26,7 +26,7 @@ #include static int fpm_event_poll_init(int max); -static int fpm_event_poll_clean(); +static int fpm_event_poll_clean(void); static int fpm_event_poll_wait(struct fpm_event_queue_s *queue, unsigned long int timeout); static int fpm_event_poll_add(struct fpm_event_s *ev); static int fpm_event_poll_remove(struct fpm_event_s *ev); @@ -50,7 +50,7 @@ static int next_free_slot = 0; /* * return the module configuration */ -struct fpm_event_module_s *fpm_event_poll_module() /* {{{ */ +struct fpm_event_module_s *fpm_event_poll_module(void) { #ifdef HAVE_POLL return &poll_module; @@ -58,14 +58,13 @@ struct fpm_event_module_s *fpm_event_poll_module() /* {{{ */ return NULL; #endif /* HAVE_POLL */ } -/* }}} */ #ifdef HAVE_POLL /* * Init the module */ -static int fpm_event_poll_init(int max) /* {{{ */ +static int fpm_event_poll_init(int max) { int i; @@ -99,12 +98,11 @@ static int fpm_event_poll_init(int max) /* {{{ */ npollfds = max; return 0; } -/* }}} */ /* * Clean the module */ -static int fpm_event_poll_clean() /* {{{ */ +static int fpm_event_poll_clean(void) { /* free pollfds */ if (pollfds) { @@ -121,7 +119,6 @@ static int fpm_event_poll_clean() /* {{{ */ npollfds = 0; return 0; } -/* }}} */ /* * wait for events or timeout diff --git a/sapi/fpm/fpm/events/poll.h b/sapi/fpm/fpm/events/poll.h index 371ecf1604972..3248b2a0dafaa 100644 --- a/sapi/fpm/fpm/events/poll.h +++ b/sapi/fpm/fpm/events/poll.h @@ -20,6 +20,6 @@ #include "../fpm_config.h" #include "../fpm_events.h" -struct fpm_event_module_s *fpm_event_poll_module(); +struct fpm_event_module_s *fpm_event_poll_module(void); #endif /* FPM_EVENTS_POLL_H */ diff --git a/sapi/fpm/fpm/events/port.c b/sapi/fpm/fpm/events/port.c index 4006c01712b8e..5266973c4aa13 100644 --- a/sapi/fpm/fpm/events/port.c +++ b/sapi/fpm/fpm/events/port.c @@ -26,7 +26,7 @@ #include static int fpm_event_port_init(int max); -static int fpm_event_port_clean(); +static int fpm_event_port_clean(void); static int fpm_event_port_wait(struct fpm_event_queue_s *queue, unsigned long int timeout); static int fpm_event_port_add(struct fpm_event_s *ev); static int fpm_event_port_remove(struct fpm_event_s *ev); @@ -90,7 +90,7 @@ static int fpm_event_port_init(int max) /* {{{ */ /* * Clean the module */ -static int fpm_event_port_clean() /* {{{ */ +static int fpm_event_port_clean(void) { if (pfd > -1) { close(pfd); @@ -105,7 +105,6 @@ static int fpm_event_port_clean() /* {{{ */ nevents = 0; return 0; } -/* }}} */ /* * wait for events or timeout diff --git a/sapi/fpm/fpm/events/port.h b/sapi/fpm/fpm/events/port.h index ced1d05c82dcb..641d390c55684 100644 --- a/sapi/fpm/fpm/events/port.h +++ b/sapi/fpm/fpm/events/port.h @@ -20,6 +20,6 @@ #include "../fpm_config.h" #include "../fpm_events.h" -struct fpm_event_module_s *fpm_event_port_module(); +struct fpm_event_module_s *fpm_event_port_module(void); #endif /* FPM_EVENTS_PORT_H */ diff --git a/sapi/fpm/fpm/events/select.c b/sapi/fpm/fpm/events/select.c index 61b33c55695da..f0f61f7d442d7 100644 --- a/sapi/fpm/fpm/events/select.c +++ b/sapi/fpm/fpm/events/select.c @@ -53,7 +53,7 @@ static fd_set fds; /* * return the module configuration */ -struct fpm_event_module_s *fpm_event_select_module() /* {{{ */ +struct fpm_event_module_s *fpm_event_select_module(void) { #ifdef HAVE_SELECT return &select_module; @@ -61,7 +61,6 @@ struct fpm_event_module_s *fpm_event_select_module() /* {{{ */ return NULL; #endif /* HAVE_SELECT */ } -/* }}} */ #ifdef HAVE_SELECT diff --git a/sapi/fpm/fpm/events/select.h b/sapi/fpm/fpm/events/select.h index 7fc6d017a3c14..f8cd1e6d60ca6 100644 --- a/sapi/fpm/fpm/events/select.h +++ b/sapi/fpm/fpm/events/select.h @@ -20,6 +20,6 @@ #include "../fpm_config.h" #include "../fpm_events.h" -struct fpm_event_module_s *fpm_event_select_module(); +struct fpm_event_module_s *fpm_event_select_module(void); #endif /* FPM_EVENTS_SELECT_H */ diff --git a/sapi/fpm/fpm/fpm_children.c b/sapi/fpm/fpm/fpm_children.c index 0aab23043a943..fdaeb89d2bf3d 100644 --- a/sapi/fpm/fpm/fpm_children.c +++ b/sapi/fpm/fpm/fpm_children.c @@ -38,7 +38,7 @@ static void fpm_children_cleanup(int which, void *arg) /* {{{ */ } /* }}} */ -static struct fpm_child_s *fpm_child_alloc() /* {{{ */ +static struct fpm_child_s *fpm_child_alloc(void) { struct fpm_child_s *ret; @@ -52,7 +52,6 @@ static struct fpm_child_s *fpm_child_alloc() /* {{{ */ ret->scoreboard_i = -1; return ret; } -/* }}} */ static void fpm_child_free(struct fpm_child_s *child) /* {{{ */ { @@ -177,7 +176,7 @@ int fpm_children_free(struct fpm_child_s *child) /* {{{ */ } /* }}} */ -void fpm_children_bury() /* {{{ */ +void fpm_children_bury(void) { int status; pid_t pid; @@ -303,7 +302,6 @@ void fpm_children_bury() /* {{{ */ } } } -/* }}} */ static struct fpm_child_s *fpm_resources_prepare(struct fpm_worker_pool_s *wp) /* {{{ */ { @@ -472,7 +470,7 @@ int fpm_children_create_initial(struct fpm_worker_pool_s *wp) /* {{{ */ } /* }}} */ -int fpm_children_init_main() /* {{{ */ +int fpm_children_init_main(void) { if (fpm_global_config.emergency_restart_threshold && fpm_global_config.emergency_restart_interval) { @@ -492,4 +490,3 @@ int fpm_children_init_main() /* {{{ */ return 0; } -/* }}} */ diff --git a/sapi/fpm/fpm/fpm_children.h b/sapi/fpm/fpm/fpm_children.h index 9d9c1fa7cb31f..5ae4e2062e468 100644 --- a/sapi/fpm/fpm/fpm_children.h +++ b/sapi/fpm/fpm/fpm_children.h @@ -12,8 +12,8 @@ int fpm_children_create_initial(struct fpm_worker_pool_s *wp); int fpm_children_free(struct fpm_child_s *child); -void fpm_children_bury(); -int fpm_children_init_main(); +void fpm_children_bury(void); +int fpm_children_init_main(void); int fpm_children_make(struct fpm_worker_pool_s *wp, int in_event_loop, int nb_to_spawn, int is_debug); struct fpm_child_s; diff --git a/sapi/fpm/fpm/fpm_clock.c b/sapi/fpm/fpm/fpm_clock.c index cd0bb7320c5cb..dc5f394f0b24b 100644 --- a/sapi/fpm/fpm/fpm_clock.c +++ b/sapi/fpm/fpm/fpm_clock.c @@ -15,7 +15,7 @@ static int monotonic_works; -int fpm_clock_init() /* {{{ */ +int fpm_clock_init(void) { struct timespec ts; @@ -27,7 +27,6 @@ int fpm_clock_init() /* {{{ */ return 0; } -/* }}} */ int fpm_clock_get(struct timeval *tv) /* {{{ */ { @@ -59,7 +58,7 @@ static clock_serv_t mach_clock; /* this code borrowed from here: http://lists.apple.com/archives/Darwin-development/2002/Mar/msg00746.html */ /* mach_clock also should be re-initialized in child process after fork */ -int fpm_clock_init() /* {{{ */ +int fpm_clock_init(void) { kern_return_t ret; mach_timespec_t aTime; @@ -81,7 +80,6 @@ int fpm_clock_init() /* {{{ */ return 0; } -/* }}} */ int fpm_clock_get(struct timeval *tv) /* {{{ */ { @@ -104,11 +102,10 @@ int fpm_clock_get(struct timeval *tv) /* {{{ */ #else /* no clock */ -int fpm_clock_init() /* {{{ */ +int fpm_clock_init(void) { return 0; } -/* }}} */ int fpm_clock_get(struct timeval *tv) /* {{{ */ { diff --git a/sapi/fpm/fpm/fpm_clock.h b/sapi/fpm/fpm/fpm_clock.h index cf92521dcc3b2..1bf38ff63ef80 100644 --- a/sapi/fpm/fpm/fpm_clock.h +++ b/sapi/fpm/fpm/fpm_clock.h @@ -5,7 +5,7 @@ #include -int fpm_clock_init(); +int fpm_clock_init(void); int fpm_clock_get(struct timeval *tv); #endif diff --git a/sapi/fpm/fpm/fpm_conf.c b/sapi/fpm/fpm/fpm_conf.c index 31336292d528b..7818cea47af76 100644 --- a/sapi/fpm/fpm/fpm_conf.c +++ b/sapi/fpm/fpm/fpm_conf.c @@ -591,7 +591,7 @@ static char *fpm_conf_set_array(zval *key, zval *value, void **config, int conve } /* }}} */ -static void *fpm_worker_pool_config_alloc() /* {{{ */ +static void *fpm_worker_pool_config_alloc(void) { struct fpm_worker_pool_s *wp; @@ -632,7 +632,6 @@ static void *fpm_worker_pool_config_alloc() /* {{{ */ current_wp = wp; return wp->config; } -/* }}} */ int fpm_worker_pool_config_free(struct fpm_worker_pool_config_s *wpc) /* {{{ */ { @@ -792,7 +791,7 @@ static int fpm_evaluate_full_path(char **path, struct fpm_worker_pool_s *wp, cha } /* }}} */ -static int fpm_conf_process_all_pools() /* {{{ */ +static int fpm_conf_process_all_pools(void) { struct fpm_worker_pool_s *wp, *wp2; @@ -1186,9 +1185,8 @@ static int fpm_conf_process_all_pools() /* {{{ */ } return 0; } -/* }}} */ -int fpm_conf_unlink_pid() /* {{{ */ +int fpm_conf_unlink_pid(void) { if (fpm_global_config.pid_file) { if (0 > unlink(fpm_global_config.pid_file)) { @@ -1198,9 +1196,8 @@ int fpm_conf_unlink_pid() /* {{{ */ } return 0; } -/* }}} */ -int fpm_conf_write_pid() /* {{{ */ +int fpm_conf_write_pid(void) { int fd; @@ -1227,7 +1224,6 @@ int fpm_conf_write_pid() /* {{{ */ } return 0; } -/* }}} */ static int fpm_conf_post_process(int force_daemon) /* {{{ */ { @@ -1654,7 +1650,7 @@ int fpm_conf_load_ini_file(char *filename) /* {{{ */ } /* }}} */ -static void fpm_conf_dump() /* {{{ */ +static void fpm_conf_dump(void) { struct fpm_worker_pool_s *wp; @@ -1757,7 +1753,6 @@ static void fpm_conf_dump() /* {{{ */ zlog(ZLOG_NOTICE, " "); } } -/* }}} */ int fpm_conf_init_main(int test_conf, int force_daemon) /* {{{ */ { diff --git a/sapi/fpm/fpm/fpm_conf.h b/sapi/fpm/fpm/fpm_conf.h index cd71bb53fda66..fbef4ae9e8373 100644 --- a/sapi/fpm/fpm/fpm_conf.h +++ b/sapi/fpm/fpm/fpm_conf.h @@ -118,7 +118,7 @@ enum { int fpm_conf_init_main(int test_conf, int force_daemon); int fpm_worker_pool_config_free(struct fpm_worker_pool_config_s *wpc); -int fpm_conf_write_pid(); -int fpm_conf_unlink_pid(); +int fpm_conf_write_pid(void); +int fpm_conf_unlink_pid(void); #endif diff --git a/sapi/fpm/fpm/fpm_env.c b/sapi/fpm/fpm/fpm_env.c index 9931ab480cf60..c1f41f7bf9c26 100644 --- a/sapi/fpm/fpm/fpm_env.c +++ b/sapi/fpm/fpm/fpm_env.c @@ -60,7 +60,7 @@ int setenv(char *name, char *value, int overwrite) /* {{{ */ #endif #ifndef HAVE_CLEARENV -void clearenv() /* {{{ */ +void clearenv(void) { char **envp; char *s; @@ -79,7 +79,6 @@ void clearenv() /* {{{ */ } } -/* }}} */ #endif #ifndef HAVE_UNSETENV @@ -196,7 +195,7 @@ static int fpm_env_conf_wp(struct fpm_worker_pool_s *wp) /* {{{ */ } /* }}} */ -int fpm_env_init_main() /* {{{ */ +int fpm_env_init_main(void) { struct fpm_worker_pool_s *wp; char *title; @@ -274,4 +273,3 @@ int fpm_env_init_main() /* {{{ */ efree(title); return 0; } -/* }}} */ diff --git a/sapi/fpm/fpm/fpm_env.h b/sapi/fpm/fpm/fpm_env.h index d767608740e51..dacf6f8701544 100644 --- a/sapi/fpm/fpm/fpm_env.h +++ b/sapi/fpm/fpm/fpm_env.h @@ -8,7 +8,7 @@ #define SETPROCTITLE_PREFIX "php-fpm: " int fpm_env_init_child(struct fpm_worker_pool_s *wp); -int fpm_env_init_main(); +int fpm_env_init_main(void); void fpm_env_setproctitle(char *title); extern char **environ; @@ -18,7 +18,7 @@ int setenv(char *name, char *value, int overwrite); #endif #ifndef HAVE_CLEARENV -void clearenv(); +void clearenv(void); #endif #endif diff --git a/sapi/fpm/fpm/fpm_events.c b/sapi/fpm/fpm/fpm_events.c index 35b0ef8bb0eca..6d563fe809108 100644 --- a/sapi/fpm/fpm/fpm_events.c +++ b/sapi/fpm/fpm/fpm_events.c @@ -304,19 +304,17 @@ int fpm_event_pre_init(char *machanism) /* {{{ */ } /* }}} */ -const char *fpm_event_machanism_name() /* {{{ */ +const char *fpm_event_machanism_name(void) { return module ? module->name : NULL; } -/* }}} */ -int fpm_event_support_edge_trigger() /* {{{ */ +int fpm_event_support_edge_trigger(void) { return module ? module->support_edge_trigger : 0; } -/* }}} */ -int fpm_event_init_main() /* {{{ */ +int fpm_event_init_main(void) { struct fpm_worker_pool_s *wp; int max; @@ -352,7 +350,6 @@ int fpm_event_init_main() /* {{{ */ } return 0; } -/* }}} */ void fpm_event_loop(int err) /* {{{ */ { diff --git a/sapi/fpm/fpm/fpm_events.h b/sapi/fpm/fpm/fpm_events.h index e97ede082491f..dc3cc914affea 100644 --- a/sapi/fpm/fpm/fpm_events.h +++ b/sapi/fpm/fpm/fpm_events.h @@ -39,12 +39,12 @@ struct fpm_event_module_s { void fpm_event_loop(int err); void fpm_event_fire(struct fpm_event_s *ev); -int fpm_event_init_main(); +int fpm_event_init_main(void); int fpm_event_set(struct fpm_event_s *ev, int fd, int flags, void (*callback)(struct fpm_event_s *, short, void *), void *arg); int fpm_event_add(struct fpm_event_s *ev, unsigned long int timeout); int fpm_event_del(struct fpm_event_s *ev); int fpm_event_pre_init(char *machanism); -const char *fpm_event_machanism_name(); -int fpm_event_support_edge_trigger(); +const char *fpm_event_machanism_name(void); +int fpm_event_support_edge_trigger(void); #endif diff --git a/sapi/fpm/fpm/fpm_php.c b/sapi/fpm/fpm/fpm_php.c index 96648f44372db..92b189668206e 100644 --- a/sapi/fpm/fpm/fpm_php.c +++ b/sapi/fpm/fpm/fpm_php.c @@ -155,41 +155,35 @@ static int fpm_php_set_fcgi_mgmt_vars(struct fpm_worker_pool_s *wp) /* {{{ */ /* }}} */ #endif -char *fpm_php_script_filename(void) /* {{{ */ +char *fpm_php_script_filename(void) { return SG(request_info).path_translated; } -/* }}} */ -char *fpm_php_request_uri(void) /* {{{ */ +char *fpm_php_request_uri(void) { return (char *) SG(request_info).request_uri; } -/* }}} */ -char *fpm_php_request_method(void) /* {{{ */ +char *fpm_php_request_method(void) { return (char *) SG(request_info).request_method; } -/* }}} */ -char *fpm_php_query_string(void) /* {{{ */ +char *fpm_php_query_string(void) { return SG(request_info).query_string; } -/* }}} */ -char *fpm_php_auth_user(void) /* {{{ */ +char *fpm_php_auth_user(void) { return SG(request_info).auth_user; } -/* }}} */ -size_t fpm_php_content_length(void) /* {{{ */ +size_t fpm_php_content_length(void) { return SG(request_info).content_length; } -/* }}} */ static void fpm_php_cleanup(int which, void *arg) /* {{{ */ { @@ -201,20 +195,18 @@ static void fpm_php_cleanup(int which, void *arg) /* {{{ */ } /* }}} */ -void fpm_php_soft_quit() /* {{{ */ +void fpm_php_soft_quit(void) { fcgi_terminate(); } -/* }}} */ -int fpm_php_init_main() /* {{{ */ +int fpm_php_init_main(void) { if (0 > fpm_cleanup_add(FPM_CLEANUP_PARENT, fpm_php_cleanup, 0)) { return -1; } return 0; } -/* }}} */ int fpm_php_init_child(struct fpm_worker_pool_s *wp) /* {{{ */ { diff --git a/sapi/fpm/fpm/fpm_php.h b/sapi/fpm/fpm/fpm_php.h index 978f3209d53d6..c494bc89fd063 100644 --- a/sapi/fpm/fpm/fpm_php.h +++ b/sapi/fpm/fpm/fpm_php.h @@ -38,8 +38,8 @@ char *fpm_php_request_method(void); char *fpm_php_query_string(void); char *fpm_php_auth_user(void); size_t fpm_php_content_length(void); -void fpm_php_soft_quit(); -int fpm_php_init_main(); +void fpm_php_soft_quit(void); +int fpm_php_init_main(void); int fpm_php_apply_defines_ex(struct key_value_s *kv, int mode); int fpm_php_limit_extensions(char *path); char* fpm_php_get_string_from_table(zend_string *table, char *key); diff --git a/sapi/fpm/fpm/fpm_process_ctl.c b/sapi/fpm/fpm/fpm_process_ctl.c index 6f439651f5138..b4a06cc382b55 100644 --- a/sapi/fpm/fpm/fpm_process_ctl.c +++ b/sapi/fpm/fpm/fpm_process_ctl.c @@ -63,7 +63,7 @@ static int fpm_pctl_timeout_set(int sec) /* {{{ */ } /* }}} */ -static void fpm_pctl_exit() /* {{{ */ +static void fpm_pctl_exit(void) { zlog(ZLOG_NOTICE, "exiting, bye-bye!"); @@ -71,11 +71,10 @@ static void fpm_pctl_exit() /* {{{ */ fpm_cleanups_run(FPM_CLEANUP_PARENT_EXIT_MAIN); exit(FPM_EXIT_OK); } -/* }}} */ #define optional_arg(c) (saved_argc > c ? ", \"" : ""), (saved_argc > c ? saved_argv[c] : ""), (saved_argc > c ? "\"" : "") -static void fpm_pctl_exec() /* {{{ */ +static void fpm_pctl_exec(void) { zlog(ZLOG_DEBUG, "Blocking some signals before reexec"); if (0 > fpm_signals_block()) { @@ -104,9 +103,8 @@ static void fpm_pctl_exec() /* {{{ */ zlog(ZLOG_SYSERROR, "failed to reload: execvp() failed"); exit(FPM_EXIT_SOFTWARE); } -/* }}} */ -static void fpm_pctl_action_last() /* {{{ */ +static void fpm_pctl_action_last(void) { switch (fpm_state) { case FPM_PCTL_STATE_RELOADING: @@ -119,7 +117,6 @@ static void fpm_pctl_action_last() /* {{{ */ break; } } -/* }}} */ int fpm_pctl_kill(pid_t pid, int how) /* {{{ */ { @@ -175,7 +172,7 @@ void fpm_pctl_kill_all(int signo) /* {{{ */ } /* }}} */ -static void fpm_pctl_action_next() /* {{{ */ +static void fpm_pctl_action_next(void) { int sig, timeout; @@ -203,7 +200,6 @@ static void fpm_pctl_action_next() /* {{{ */ fpm_signal_sent = sig; fpm_pctl_timeout_set(timeout); } -/* }}} */ void fpm_pctl(int new_state, int action) /* {{{ */ { @@ -247,13 +243,12 @@ void fpm_pctl(int new_state, int action) /* {{{ */ } /* }}} */ -int fpm_pctl_can_spawn_children() /* {{{ */ +int fpm_pctl_can_spawn_children(void) { return fpm_state == FPM_PCTL_STATE_NORMAL; } -/* }}} */ -int fpm_pctl_child_exited() /* {{{ */ +int fpm_pctl_child_exited(void) { if (fpm_state == FPM_PCTL_STATE_NORMAL) { return 0; @@ -264,9 +259,8 @@ int fpm_pctl_child_exited() /* {{{ */ } return 0; } -/* }}} */ -int fpm_pctl_init_main() /* {{{ */ +int fpm_pctl_init_main(void) { int i; @@ -292,7 +286,6 @@ int fpm_pctl_init_main() /* {{{ */ } return 0; } -/* }}} */ static void fpm_pctl_check_request_timeout(struct timeval *now) /* {{{ */ { diff --git a/sapi/fpm/fpm/fpm_process_ctl.h b/sapi/fpm/fpm/fpm_process_ctl.h index bae1036e26f07..758a9a0d57661 100644 --- a/sapi/fpm/fpm/fpm_process_ctl.h +++ b/sapi/fpm/fpm/fpm_process_ctl.h @@ -16,14 +16,14 @@ struct fpm_child_s; void fpm_pctl(int new_state, int action); -int fpm_pctl_can_spawn_children(); +int fpm_pctl_can_spawn_children(void); int fpm_pctl_kill(pid_t pid, int how); void fpm_pctl_kill_all(int signo); void fpm_pctl_heartbeat(struct fpm_event_s *ev, short which, void *arg); void fpm_pctl_perform_idle_server_maintenance_heartbeat(struct fpm_event_s *ev, short which, void *arg); void fpm_pctl_on_socket_accept(struct fpm_event_s *ev, short which, void *arg); -int fpm_pctl_child_exited(); -int fpm_pctl_init_main(); +int fpm_pctl_child_exited(void); +int fpm_pctl_init_main(void); enum { diff --git a/sapi/fpm/fpm/fpm_request.c b/sapi/fpm/fpm/fpm_request.c index 4f51824138d4d..8d3e2b2dd9e77 100644 --- a/sapi/fpm/fpm/fpm_request.c +++ b/sapi/fpm/fpm/fpm_request.c @@ -34,7 +34,7 @@ const char *fpm_request_get_stage_name(int stage) { return requests_stages[stage]; } -void fpm_request_accepting() /* {{{ */ +void fpm_request_accepting(void) { struct fpm_scoreboard_proc_s *proc; struct timeval now; @@ -56,9 +56,8 @@ void fpm_request_accepting() /* {{{ */ /* idle++, active-- */ fpm_scoreboard_update_commit(1, -1, 0, 0, 0, 0, 0, FPM_SCOREBOARD_ACTION_INC, NULL); } -/* }}} */ -void fpm_request_reading_headers() /* {{{ */ +void fpm_request_reading_headers(void) { struct fpm_scoreboard_proc_s *proc; @@ -101,9 +100,8 @@ void fpm_request_reading_headers() /* {{{ */ /* idle--, active++, request++ */ fpm_scoreboard_update_commit(-1, 1, 0, 0, 1, 0, 0, FPM_SCOREBOARD_ACTION_INC, NULL); } -/* }}} */ -void fpm_request_info() /* {{{ */ +void fpm_request_info(void) { struct fpm_scoreboard_proc_s *proc; char *request_uri = fpm_php_request_uri(); @@ -151,9 +149,8 @@ void fpm_request_info() /* {{{ */ fpm_scoreboard_proc_release(proc); } -/* }}} */ -void fpm_request_executing() /* {{{ */ +void fpm_request_executing(void) { struct fpm_scoreboard_proc_s *proc; struct timeval now; @@ -170,9 +167,8 @@ void fpm_request_executing() /* {{{ */ proc->tv = now; fpm_scoreboard_proc_release(proc); } -/* }}} */ -void fpm_request_end(void) /* {{{ */ +void fpm_request_end(void) { struct fpm_scoreboard_proc_s *proc; struct timeval now; @@ -204,9 +200,8 @@ void fpm_request_end(void) /* {{{ */ proc->memory = memory; fpm_scoreboard_proc_release(proc); } -/* }}} */ -void fpm_request_finished() /* {{{ */ +void fpm_request_finished(void) { struct fpm_scoreboard_proc_s *proc; struct timeval now; @@ -223,7 +218,6 @@ void fpm_request_finished() /* {{{ */ proc->tv = now; fpm_scoreboard_proc_release(proc); } -/* }}} */ void fpm_request_check_timed_out(struct fpm_child_s *child, struct timeval *now, int terminate_timeout, int slowlog_timeout, int track_finished) /* {{{ */ { diff --git a/sapi/fpm/fpm/fpm_request.h b/sapi/fpm/fpm/fpm_request.h index 4d287427d68d4..c1cde0111be47 100644 --- a/sapi/fpm/fpm/fpm_request.h +++ b/sapi/fpm/fpm/fpm_request.h @@ -4,17 +4,17 @@ #define FPM_REQUEST_H 1 /* hanging in accept() */ -void fpm_request_accepting(); +void fpm_request_accepting(void); /* start reading fastcgi request from very first byte */ -void fpm_request_reading_headers(); +void fpm_request_reading_headers(void); /* not a stage really but a point in the php code, where all request params have become known to sapi */ -void fpm_request_info(); +void fpm_request_info(void); /* the script is executing */ -void fpm_request_executing(); +void fpm_request_executing(void); /* request ended: script response have been sent to web server */ void fpm_request_end(void); /* request processed: cleaning current request */ -void fpm_request_finished(); +void fpm_request_finished(void); struct fpm_child_s; struct timeval; diff --git a/sapi/fpm/fpm/fpm_scoreboard.c b/sapi/fpm/fpm/fpm_scoreboard.c index bf847d9dcac98..52d10a0416832 100644 --- a/sapi/fpm/fpm/fpm_scoreboard.c +++ b/sapi/fpm/fpm/fpm_scoreboard.c @@ -21,7 +21,7 @@ static float fpm_scoreboard_tick; #endif -int fpm_scoreboard_init_main() /* {{{ */ +int fpm_scoreboard_init_main(void) { struct fpm_worker_pool_s *wp; @@ -72,7 +72,6 @@ int fpm_scoreboard_init_main() /* {{{ */ } return 0; } -/* }}} */ static struct fpm_scoreboard_s *fpm_scoreboard_get_for_update(struct fpm_scoreboard_s *scoreboard) /* {{{ */ { @@ -186,11 +185,10 @@ void fpm_scoreboard_update( } /* }}} */ -struct fpm_scoreboard_s *fpm_scoreboard_get() /* {{{*/ +struct fpm_scoreboard_s *fpm_scoreboard_get(void) { return fpm_scoreboard; } -/* }}} */ static inline struct fpm_scoreboard_proc_s *fpm_scoreboard_proc_get_ex( struct fpm_scoreboard_s *scoreboard, int child_index, unsigned int nprocs) /* {{{*/ @@ -442,9 +440,8 @@ int fpm_scoreboard_proc_alloc(struct fpm_child_s *child) /* {{{ */ /* }}} */ #ifdef HAVE_TIMES -float fpm_scoreboard_get_tick() /* {{{ */ +float fpm_scoreboard_get_tick(void) { return fpm_scoreboard_tick; } -/* }}} */ #endif diff --git a/sapi/fpm/fpm/fpm_scoreboard.h b/sapi/fpm/fpm/fpm_scoreboard.h index 6925094936495..c488c64bfefc4 100644 --- a/sapi/fpm/fpm/fpm_scoreboard.h +++ b/sapi/fpm/fpm/fpm_scoreboard.h @@ -70,14 +70,14 @@ struct fpm_scoreboard_s { struct fpm_scoreboard_proc_s procs[]; }; -int fpm_scoreboard_init_main(); +int fpm_scoreboard_init_main(void); int fpm_scoreboard_init_child(struct fpm_worker_pool_s *wp); void fpm_scoreboard_update_begin(struct fpm_scoreboard_s *scoreboard); void fpm_scoreboard_update_commit(int idle, int active, int lq, int lq_len, int requests, int max_children_reached, int slow_rq, int action, struct fpm_scoreboard_s *scoreboard); void fpm_scoreboard_update(int idle, int active, int lq, int lq_len, int requests, int max_children_reached, int slow_rq, int action, struct fpm_scoreboard_s *scoreboard); -struct fpm_scoreboard_s *fpm_scoreboard_get(); +struct fpm_scoreboard_s *fpm_scoreboard_get(void); struct fpm_scoreboard_proc_s *fpm_scoreboard_proc_get(struct fpm_scoreboard_s *scoreboard, int child_index); struct fpm_scoreboard_proc_s *fpm_scoreboard_proc_get_from_child(struct fpm_child_s *child); @@ -97,7 +97,7 @@ struct fpm_scoreboard_s *fpm_scoreboard_copy(struct fpm_scoreboard_s *scoreboard void fpm_scoreboard_free_copy(struct fpm_scoreboard_s *scoreboard); #ifdef HAVE_TIMES -float fpm_scoreboard_get_tick(); +float fpm_scoreboard_get_tick(void); #endif #endif diff --git a/sapi/fpm/fpm/fpm_shm.c b/sapi/fpm/fpm/fpm_shm.c index 52ae60ed28bdb..d8bd701c138e8 100644 --- a/sapi/fpm/fpm/fpm_shm.c +++ b/sapi/fpm/fpm/fpm_shm.c @@ -60,8 +60,7 @@ int fpm_shm_free(void *mem, size_t size) /* {{{ */ } /* }}} */ -size_t fpm_shm_get_size_allocated() /* {{{*/ +size_t fpm_shm_get_size_allocated(void) { return fpm_shm_size; } -/* }}} */ diff --git a/sapi/fpm/fpm/fpm_shm.h b/sapi/fpm/fpm/fpm_shm.h index 4382aac29bf00..483e18b4988ba 100644 --- a/sapi/fpm/fpm/fpm_shm.h +++ b/sapi/fpm/fpm/fpm_shm.h @@ -5,6 +5,6 @@ void *fpm_shm_alloc(size_t size); int fpm_shm_free(void *mem, size_t size); -size_t fpm_shm_get_size_allocated(); +size_t fpm_shm_get_size_allocated(void); #endif diff --git a/sapi/fpm/fpm/fpm_signals.c b/sapi/fpm/fpm/fpm_signals.c index f5a5ae5ec1743..6aad4403768cf 100644 --- a/sapi/fpm/fpm/fpm_signals.c +++ b/sapi/fpm/fpm/fpm_signals.c @@ -182,7 +182,7 @@ static void sig_handler(int signo) /* {{{ */ } /* }}} */ -int fpm_signals_init_main() /* {{{ */ +int fpm_signals_init_main(void) { struct sigaction act; @@ -222,9 +222,8 @@ int fpm_signals_init_main() /* {{{ */ } return 0; } -/* }}} */ -int fpm_signals_init_child() /* {{{ */ +int fpm_signals_init_child(void) { struct sigaction act, act_dfl; @@ -257,15 +256,13 @@ int fpm_signals_init_child() /* {{{ */ } return 0; } -/* }}} */ -int fpm_signals_get_fd() /* {{{ */ +int fpm_signals_get_fd(void) { return sp[0]; } -/* }}} */ -int fpm_signals_init_mask() /* {{{ */ +int fpm_signals_init_mask(void) { /* Subset of signals from fpm_signals_init_main() and fpm_got_signal() blocked to avoid unexpected death during early init @@ -298,9 +295,8 @@ int fpm_signals_init_mask() /* {{{ */ } return 0; } -/* }}} */ -int fpm_signals_block() /* {{{ */ +int fpm_signals_block(void) { if (0 > sigprocmask(SIG_BLOCK, &block_sigset, NULL)) { zlog(ZLOG_SYSERROR, "failed to block signals"); @@ -308,9 +304,8 @@ int fpm_signals_block() /* {{{ */ } return 0; } -/* }}} */ -int fpm_signals_child_block() /* {{{ */ +int fpm_signals_child_block(void) { if (0 > sigprocmask(SIG_BLOCK, &child_block_sigset, NULL)) { zlog(ZLOG_SYSERROR, "failed to block child signals"); @@ -318,9 +313,8 @@ int fpm_signals_child_block() /* {{{ */ } return 0; } -/* }}} */ -int fpm_signals_unblock() /* {{{ */ +int fpm_signals_unblock(void) { /* Ensure that during reload after upgrade all signals are unblocked. block_sigset could have different value before execve() */ @@ -332,4 +326,3 @@ int fpm_signals_unblock() /* {{{ */ } return 0; } -/* }}} */ diff --git a/sapi/fpm/fpm/fpm_signals.h b/sapi/fpm/fpm/fpm_signals.h index f453fa4f7a327..67c12efdf4bac 100644 --- a/sapi/fpm/fpm/fpm_signals.h +++ b/sapi/fpm/fpm/fpm_signals.h @@ -5,13 +5,13 @@ #include -int fpm_signals_init_main(); -int fpm_signals_init_child(); -int fpm_signals_get_fd(); -int fpm_signals_init_mask(); -int fpm_signals_block(); -int fpm_signals_child_block(); -int fpm_signals_unblock(); +int fpm_signals_init_main(void); +int fpm_signals_init_child(void); +int fpm_signals_get_fd(void); +int fpm_signals_init_mask(void); +int fpm_signals_block(void); +int fpm_signals_child_block(void); +int fpm_signals_unblock(void); extern const char *fpm_signal_names[NSIG + 1]; diff --git a/sapi/fpm/fpm/fpm_sockets.c b/sapi/fpm/fpm/fpm_sockets.c index c2b4ea1c64a05..7bf0816c3d131 100644 --- a/sapi/fpm/fpm/fpm_sockets.c +++ b/sapi/fpm/fpm/fpm_sockets.c @@ -386,7 +386,7 @@ static int fpm_socket_af_unix_listening_socket(struct fpm_worker_pool_s *wp) /* } /* }}} */ -int fpm_sockets_init_main() /* {{{ */ +int fpm_sockets_init_main(void) { unsigned i, lq_len; struct fpm_worker_pool_s *wp; @@ -485,7 +485,6 @@ int fpm_sockets_init_main() /* {{{ */ } return 0; } -/* }}} */ #if HAVE_FPM_LQ diff --git a/sapi/fpm/fpm/fpm_sockets.h b/sapi/fpm/fpm/fpm_sockets.h index 8f1e3846b2919..1e31b84d6e802 100644 --- a/sapi/fpm/fpm/fpm_sockets.h +++ b/sapi/fpm/fpm/fpm_sockets.h @@ -24,7 +24,7 @@ #define FPM_ENV_SOCKET_SET_SIZE 128 enum fpm_address_domain fpm_sockets_domain_from_address(char *addr); -int fpm_sockets_init_main(); +int fpm_sockets_init_main(void); int fpm_socket_get_listening_queue(int sock, unsigned *cur_lq, unsigned *max_lq); int fpm_socket_unix_test_connect(struct sockaddr_un *sock, size_t socklen); diff --git a/sapi/fpm/fpm/fpm_stdio.c b/sapi/fpm/fpm/fpm_stdio.c index 9454710e536ea..2de4b589ef1dd 100644 --- a/sapi/fpm/fpm/fpm_stdio.c +++ b/sapi/fpm/fpm/fpm_stdio.c @@ -22,7 +22,7 @@ static int fd_stdout[2]; static int fd_stderr[2]; -int fpm_stdio_init_main() /* {{{ */ +int fpm_stdio_init_main(void) { int fd = open("/dev/null", O_RDWR); @@ -39,9 +39,8 @@ int fpm_stdio_init_main() /* {{{ */ close(fd); return 0; } -/* }}} */ -static inline int fpm_use_error_log() { /* {{{ */ +static inline int fpm_use_error_log(void) { /* * the error_log is NOT used when running in foreground * and from a tty (user looking at output). @@ -59,8 +58,7 @@ static inline int fpm_use_error_log() { /* {{{ */ return 0; } -/* }}} */ -int fpm_stdio_init_final() /* {{{ */ +int fpm_stdio_init_final(void) { if (fpm_use_error_log()) { /* prevent duping if logging to syslog */ @@ -82,7 +80,6 @@ int fpm_stdio_init_final() /* {{{ */ zlog_set_launched(); return 0; } -/* }}} */ int fpm_stdio_init_child(struct fpm_worker_pool_s *wp) /* {{{ */ { @@ -108,11 +105,10 @@ int fpm_stdio_init_child(struct fpm_worker_pool_s *wp) /* {{{ */ #define FPM_STDIO_CMD_FLUSH "\0fscf" -int fpm_stdio_flush_child() /* {{{ */ +int fpm_stdio_flush_child(void) { return write(STDERR_FILENO, FPM_STDIO_CMD_FLUSH, sizeof(FPM_STDIO_CMD_FLUSH)); } -/* }}} */ static void fpm_stdio_child_said(struct fpm_event_s *ev, short which, void *arg) /* {{{ */ { diff --git a/sapi/fpm/fpm/fpm_stdio.h b/sapi/fpm/fpm/fpm_stdio.h index ef96508459c9f..c0ff94d3cb609 100644 --- a/sapi/fpm/fpm/fpm_stdio.h +++ b/sapi/fpm/fpm/fpm_stdio.h @@ -7,10 +7,10 @@ #define STREAM_SET_MSG_PREFIX_FMT "[pool %s] child %d said into %s: " -int fpm_stdio_init_main(); -int fpm_stdio_init_final(); +int fpm_stdio_init_main(void); +int fpm_stdio_init_final(void); int fpm_stdio_init_child(struct fpm_worker_pool_s *wp); -int fpm_stdio_flush_child(); +int fpm_stdio_flush_child(void); int fpm_stdio_prepare_pipes(struct fpm_child_s *child); void fpm_stdio_child_use_pipes(struct fpm_child_s *child); int fpm_stdio_parent_use_pipes(struct fpm_child_s *child); diff --git a/sapi/fpm/fpm/fpm_systemd.c b/sapi/fpm/fpm/fpm_systemd.c index 31b6a3d27ae65..175312412330f 100644 --- a/sapi/fpm/fpm/fpm_systemd.c +++ b/sapi/fpm/fpm/fpm_systemd.c @@ -11,7 +11,7 @@ #include "fpm_systemd.h" -static void fpm_systemd() /* {{{ */ +static void fpm_systemd(void) { static unsigned long int last=0; struct fpm_worker_pool_s *wp; @@ -43,7 +43,6 @@ static void fpm_systemd() /* {{{ */ last = requests; } -/* }}} */ void fpm_systemd_heartbeat(struct fpm_event_s *ev, short which, void *arg) /* {{{ */ { @@ -79,7 +78,7 @@ void fpm_systemd_heartbeat(struct fpm_event_s *ev, short which, void *arg) /* {{ } /* }}} */ -int fpm_systemd_conf() /* {{{ */ +int fpm_systemd_conf(void) { char *watchdog; int interval = 0; @@ -109,4 +108,3 @@ int fpm_systemd_conf() /* {{{ */ } return 0; } -/* }}} */ diff --git a/sapi/fpm/fpm/fpm_systemd.h b/sapi/fpm/fpm/fpm_systemd.h index e978a7c7be48f..93a70fb5266e4 100644 --- a/sapi/fpm/fpm/fpm_systemd.h +++ b/sapi/fpm/fpm/fpm_systemd.h @@ -7,6 +7,6 @@ #define FPM_SYSTEMD_DEFAULT_HEARTBEAT (10000) void fpm_systemd_heartbeat(struct fpm_event_s *ev, short which, void *arg); -int fpm_systemd_conf(); +int fpm_systemd_conf(void); #endif diff --git a/sapi/fpm/fpm/fpm_trace_mach.c b/sapi/fpm/fpm/fpm_trace_mach.c index 1ecee23d261e9..092858e287d46 100644 --- a/sapi/fpm/fpm/fpm_trace_mach.c +++ b/sapi/fpm/fpm/fpm_trace_mach.c @@ -18,7 +18,7 @@ static vm_offset_t target_page_base; static vm_offset_t local_page; static mach_msg_type_number_t local_size; -static void fpm_mach_vm_deallocate() /* {{{ */ +static void fpm_mach_vm_deallocate(void) { if (local_page) { mach_vm_deallocate(mach_task_self(), local_page, local_size); @@ -27,7 +27,6 @@ static void fpm_mach_vm_deallocate() /* {{{ */ local_size = 0; } } -/* }}} */ static int fpm_mach_vm_read_page(vm_offset_t page) /* {{{ */ { diff --git a/sapi/fpm/fpm/fpm_unix.c b/sapi/fpm/fpm/fpm_unix.c index 654edd32d4271..649088f09fa42 100644 --- a/sapi/fpm/fpm/fpm_unix.c +++ b/sapi/fpm/fpm/fpm_unix.c @@ -452,7 +452,7 @@ int fpm_unix_init_child(struct fpm_worker_pool_s *wp) /* {{{ */ } /* }}} */ -int fpm_unix_init_main() /* {{{ */ +int fpm_unix_init_main(void) { struct fpm_worker_pool_s *wp; int is_root = !geteuid(); @@ -589,4 +589,3 @@ int fpm_unix_init_main() /* {{{ */ return 0; } -/* }}} */ diff --git a/sapi/fpm/fpm/fpm_unix.h b/sapi/fpm/fpm/fpm_unix.h index c65791f7ed492..2152daf1794b4 100644 --- a/sapi/fpm/fpm/fpm_unix.h +++ b/sapi/fpm/fpm/fpm_unix.h @@ -10,7 +10,7 @@ int fpm_unix_set_socket_premissions(struct fpm_worker_pool_s *wp, const char *pa int fpm_unix_free_socket_premissions(struct fpm_worker_pool_s *wp); int fpm_unix_init_child(struct fpm_worker_pool_s *wp); -int fpm_unix_init_main(); +int fpm_unix_init_main(void); extern size_t fpm_pagesize; diff --git a/sapi/fpm/fpm/fpm_worker_pool.c b/sapi/fpm/fpm/fpm_worker_pool.c index 65a9b226b1ae0..416313624a7ee 100644 --- a/sapi/fpm/fpm/fpm_worker_pool.c +++ b/sapi/fpm/fpm/fpm_worker_pool.c @@ -62,7 +62,7 @@ static void fpm_worker_pool_cleanup(int which, void *arg) /* {{{ */ } /* }}} */ -struct fpm_worker_pool_s *fpm_worker_pool_alloc() /* {{{ */ +struct fpm_worker_pool_s *fpm_worker_pool_alloc(void) { struct fpm_worker_pool_s *ret; @@ -77,13 +77,11 @@ struct fpm_worker_pool_s *fpm_worker_pool_alloc() /* {{{ */ ret->log_fd = -1; return ret; } -/* }}} */ -int fpm_worker_pool_init_main() /* {{{ */ +int fpm_worker_pool_init_main(void) { if (0 > fpm_cleanup_add(FPM_CLEANUP_ALL, fpm_worker_pool_cleanup, 0)) { return -1; } return 0; } -/* }}} */ diff --git a/sapi/fpm/fpm/fpm_worker_pool.h b/sapi/fpm/fpm/fpm_worker_pool.h index ac596cde60547..809f53a0545b5 100644 --- a/sapi/fpm/fpm/fpm_worker_pool.h +++ b/sapi/fpm/fpm/fpm_worker_pool.h @@ -47,9 +47,9 @@ struct fpm_worker_pool_s { #endif }; -struct fpm_worker_pool_s *fpm_worker_pool_alloc(); +struct fpm_worker_pool_s *fpm_worker_pool_alloc(void); void fpm_worker_pool_free(struct fpm_worker_pool_s *wp); -int fpm_worker_pool_init_main(); +int fpm_worker_pool_init_main(void); void fpm_worker_pool_free_limit_extensions(char **limit_extensions); From ce42dcf483ab6457269f86aa3c4ccc0a1b1f3108 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 29 Aug 2022 12:30:14 +0300 Subject: [PATCH 26/61] Fix ext/opcache/tests/jit/inc_obj_004.phpt failure introduced by fd74ee7e909c66f09d8d904a5438b275a13e8738 This should fix GH-9445 --- ext/opcache/jit/zend_jit_x86.dasc | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index dfe3b6aa78d7f..921f2cd2fcf9d 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -8782,6 +8782,9 @@ static int zend_jit_bool_jmpznz(dasm_State **Dst, const zend_op *opline, uint32_ } if ((op1_info & (MAY_BE_ANY-(MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG))) == MAY_BE_DOUBLE) { + if (op1_info & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG)) { + |.cold_code + } |2: if (CAN_USE_AVX()) { | vxorps xmm0, xmm0, xmm0 @@ -8830,6 +8833,10 @@ static int zend_jit_bool_jmpznz(dasm_State **Dst, const zend_op *opline, uint32_ |1: | SET_ZVAL_TYPE_INFO res_addr, eax } + if (op1_info & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG)) { + | jmp >9 + |.code + } } else { if (exit_addr) { if (branch_opcode == ZEND_JMPNZ || branch_opcode == ZEND_JMPNZ_EX) { @@ -8841,6 +8848,9 @@ static int zend_jit_bool_jmpznz(dasm_State **Dst, const zend_op *opline, uint32_ | je &exit_addr |1: } + if (op1_info & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG)) { + | jmp >9 + } } else { ZEND_ASSERT(true_label != (uint32_t)-1 || false_label != (uint32_t)-1); if (false_label != (uint32_t)-1 ) { @@ -8849,12 +8859,20 @@ static int zend_jit_bool_jmpznz(dasm_State **Dst, const zend_op *opline, uint32_ |1: if (true_label != (uint32_t)-1) { | jmp =>true_label + } else if (op1_info & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG)) { + | jmp >9 } } else { | jp => true_label | jne => true_label + if (op1_info & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG)) { + | jmp >9 + } } } + if (op1_info & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG)) { + |.code + } } } else if (op1_info & (MAY_BE_ANY - (MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG))) { if (op1_info & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG)) { From 725cb4e8ad8e96bdbd5126dfd80384003f2e5831 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Mon, 29 Aug 2022 12:41:36 +0200 Subject: [PATCH 27/61] Revert "Fix GH-9296: `ksort` behaves incorrectly on arrays with mixed keys" This reverts commit cd1aed8eddd2dccbb55fb1bc3d67b23a8455248c, as discussed on internals (). --- NEWS | 2 - ext/standard/array.c | 53 +++++++++++------- ext/standard/tests/array/002.phpt | 20 +++---- ext/standard/tests/array/gh9296.phpt | 17 ------ .../tests/array/krsort_variation8.phpt | Bin 3121 -> 3121 bytes .../tests/array/krsort_variation9.phpt | 8 +-- .../tests/array/ksort_variation8.phpt | Bin 3107 -> 3107 bytes .../tests/array/ksort_variation9.phpt | 8 +-- 8 files changed, 52 insertions(+), 56 deletions(-) delete mode 100644 ext/standard/tests/array/gh9296.phpt diff --git a/NEWS b/NEWS index 21d5d334a4e4c..5e0f75578366e 100644 --- a/NEWS +++ b/NEWS @@ -46,8 +46,6 @@ PHP NEWS - Standard: . Fixed bug GH-9017 (php_stream_sock_open_from_socket could return NULL). (Heiko Weber) - . Fixed bug GH-9296 (`ksort` behaves incorrectly on arrays with mixed keys). - (Denis Vaksman) - Streams: . Fixed bug GH-8472 (The resource returned by stream_socket_accept may have diff --git a/ext/standard/array.c b/ext/standard/array.c index d145661e3782e..32ad1b0eaa6ed 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -166,25 +166,40 @@ static zend_never_inline ZEND_COLD int stable_sort_fallback(Bucket *a, Bucket *b static zend_always_inline int php_array_key_compare_unstable_i(Bucket *f, Bucket *s) /* {{{ */ { - zval first; - zval second; - - if (f->key == NULL && s->key == NULL) { - return (zend_long)f->h > (zend_long)s->h ? 1 : -1; - } else if (f->key && s->key) { - return zendi_smart_strcmp(f->key, s->key); - } - if (f->key) { - ZVAL_STR(&first, f->key); - } else { - ZVAL_LONG(&first, f->h); - } - if (s->key) { - ZVAL_STR(&second, s->key); - } else { - ZVAL_LONG(&second, s->h); - } - return zend_compare(&first, &second); + zend_uchar t; + zend_long l1, l2; + double d; + + if (f->key == NULL) { + if (s->key == NULL) { + return (zend_long)f->h > (zend_long)s->h ? 1 : -1; + } else { + l1 = (zend_long)f->h; + t = is_numeric_string(s->key->val, s->key->len, &l2, &d, 1); + if (t == IS_LONG) { + /* pass */ + } else if (t == IS_DOUBLE) { + return ZEND_NORMALIZE_BOOL((double)l1 - d); + } else { + l2 = 0; + } + } + } else { + if (s->key) { + return zendi_smart_strcmp(f->key, s->key); + } else { + l2 = (zend_long)s->h; + t = is_numeric_string(f->key->val, f->key->len, &l1, &d, 1); + if (t == IS_LONG) { + /* pass */ + } else if (t == IS_DOUBLE) { + return ZEND_NORMALIZE_BOOL(d - (double)l2); + } else { + l1 = 0; + } + } + } + return ZEND_NORMALIZE_BOOL(l1 - l2); } /* }}} */ diff --git a/ext/standard/tests/array/002.phpt b/ext/standard/tests/array/002.phpt index 5cf377e2a3538..fdb838deb19dd 100644 --- a/ext/standard/tests/array/002.phpt +++ b/ext/standard/tests/array/002.phpt @@ -276,8 +276,6 @@ array(8) { -- Testing krsort() -- No second argument: array(8) { - ["test"]=> - int(27) [16777216]=> float(-0.3333333333333333) [1001]=> @@ -290,6 +288,8 @@ array(8) { string(4) "Test" [0]=> string(3) "PHP" + ["test"]=> + int(27) [-1000]=> array(2) { [0]=> @@ -300,8 +300,6 @@ array(8) { } Using SORT_REGULAR: array(8) { - ["test"]=> - int(27) [16777216]=> float(-0.3333333333333333) [1001]=> @@ -314,6 +312,8 @@ array(8) { string(4) "Test" [0]=> string(3) "PHP" + ["test"]=> + int(27) [-1000]=> array(2) { [0]=> @@ -334,10 +334,10 @@ array(8) { string(27) "PHP: Hypertext Preprocessor" [5]=> string(4) "Test" - ["test"]=> - int(27) [0]=> string(3) "PHP" + ["test"]=> + int(27) [-1000]=> array(2) { [0]=> @@ -383,6 +383,8 @@ array(8) { } [0]=> string(3) "PHP" + ["test"]=> + int(27) [5]=> string(4) "Test" [17]=> @@ -393,8 +395,6 @@ array(8) { string(6) "monkey" [16777216]=> float(-0.3333333333333333) - ["test"]=> - int(27) } Using SORT_REGULAR: array(8) { @@ -407,6 +407,8 @@ array(8) { } [0]=> string(3) "PHP" + ["test"]=> + int(27) [5]=> string(4) "Test" [17]=> @@ -417,8 +419,6 @@ array(8) { string(6) "monkey" [16777216]=> float(-0.3333333333333333) - ["test"]=> - int(27) } Using SORT_NUMERIC: array(8) { diff --git a/ext/standard/tests/array/gh9296.phpt b/ext/standard/tests/array/gh9296.phpt deleted file mode 100644 index cfbc5cbbb09ec..0000000000000 --- a/ext/standard/tests/array/gh9296.phpt +++ /dev/null @@ -1,17 +0,0 @@ ---TEST-- -GH-9296: incorrect ksort(..., SORT_REGULAR) behaviour on arrays with numeric and string keys ---FILE-- - 0, 600 => 1]; -ksort($array, SORT_REGULAR); -var_dump($array); -var_dump(array_key_first($array) <=> array_key_last($array)); -?> ---EXPECT-- -array(2) { - [600]=> - int(1) - ["aaa"]=> - int(0) -} -int(-1) diff --git a/ext/standard/tests/array/krsort_variation8.phpt b/ext/standard/tests/array/krsort_variation8.phpt index 39e72e2eb22211e4f3bb45963fc3ae7c3dab99d7..1483e6fd1bbc18abe1c129d73043254e66ee6dc7 100644 GIT binary patch delta 113 zcmdleu~A}!DBI)^4!zByZ1zl(k8+z%7UdC@QBa81HHx*h<5Eya%gIkH(a<&0v$Oz0 bO|II>t61G8>v3vf=u*O`i_0ZHFO>@bu$dh& delta 107 zcmdleu~A}!DBEUdHhZSYqHKDTk8+z%7UGeRR8WXkQi`>;<5Ey4E-A{)OV=>aR8Ugl Zs-3)w)orpKrxu15d7N6fT=Mf$xd8tI8>j#P diff --git a/ext/standard/tests/array/krsort_variation9.phpt b/ext/standard/tests/array/krsort_variation9.phpt index b0309f373d362..4364911b62127 100644 --- a/ext/standard/tests/array/krsort_variation9.phpt +++ b/ext/standard/tests/array/krsort_variation9.phpt @@ -82,22 +82,22 @@ array(5) { - With default sort flag - bool(true) array(3) { - ["c"]=> - string(5) "apple" ["a"]=> string(6) "orange" [0]=> string(6) "banana" + ["c"]=> + string(5) "apple" } - Sort flag = SORT_REGULAR - bool(true) array(3) { - ["c"]=> - string(5) "apple" ["a"]=> string(6) "orange" [0]=> string(6) "banana" + ["c"]=> + string(5) "apple" } -- Iteration 3 -- diff --git a/ext/standard/tests/array/ksort_variation8.phpt b/ext/standard/tests/array/ksort_variation8.phpt index 9a15c4dc3e75d7dd76ec29986cc84159096b381c..7b7e1c003e587897379970a72be8a1936fb5fce1 100644 GIT binary patch delta 161 zcmZ21u~=dQ2ixQ%P8ngPSX(4FgRDC8f!goJx})aK>#e=32=prl1gQ w08x{clb=|kVW4MVV5m9Sg3EI9CQfa}+R5`+T_-DWYEi>9_F68N{Jc~y069b~q5uE@ delta 91 zcmZ21u~=dQ2ixRSPKn80oHCQ^IAtd<*K`?!raf9G7y$XGjh9;@qQ R1x_u3O4)0 - string(6) "banana" ["a"]=> string(6) "orange" + [0]=> + string(6) "banana" ["c"]=> string(5) "apple" } - Sort flag = SORT_REGULAR - bool(true) array(3) { - [0]=> - string(6) "banana" ["a"]=> string(6) "orange" + [0]=> + string(6) "banana" ["c"]=> string(5) "apple" } From 4135e6011c2831cce29c257c6c46f32184d34d2b Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 29 Aug 2022 14:53:48 +0300 Subject: [PATCH 28/61] Fix memory leak Fixes oss-fuzz #50616 --- ext/opcache/Optimizer/dfa_pass.c | 4 +++- ext/opcache/tests/opt/assign_obj_001.phpt | 24 +++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 ext/opcache/tests/opt/assign_obj_001.phpt diff --git a/ext/opcache/Optimizer/dfa_pass.c b/ext/opcache/Optimizer/dfa_pass.c index 49f27b1151d9d..f223b922cf23b 100644 --- a/ext/opcache/Optimizer/dfa_pass.c +++ b/ext/opcache/Optimizer/dfa_pass.c @@ -357,7 +357,9 @@ static zend_bool opline_supports_assign_contraction( return opline->op1_type != IS_CV || opline->op1.var != cv_var; } - if (opline->opcode == ZEND_ASSIGN_OP + if ((opline->opcode == ZEND_ASSIGN_OP + || opline->opcode == ZEND_ASSIGN_OBJ + || opline->opcode == ZEND_ASSIGN_DIM) && opline->op1_type == IS_CV && opline->op1.var == cv_var && zend_may_throw(opline, &ssa->ops[ssa->vars[src_var].definition], op_array, ssa)) { diff --git a/ext/opcache/tests/opt/assign_obj_001.phpt b/ext/opcache/tests/opt/assign_obj_001.phpt new file mode 100644 index 0000000000000..efb473ddaa940 --- /dev/null +++ b/ext/opcache/tests/opt/assign_obj_001.phpt @@ -0,0 +1,24 @@ +--TEST-- +ASSIGN_OP 001: Incrrect optimization of ASSIGN_OBJ may lead to memory leak +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.optimization_level=-1 +--FILE-- +y = ''; +} +test(); +?> +--EXPECTF-- +Warning: Undefined variable $y in %sassign_obj_001.php on line 3 + +Warning: Undefined variable $a in %sassign_obj_001.php on line 3 + +Fatal error: Uncaught Error: Attempt to assign property "y" on string in %sassign_obj_001.php:4 +Stack trace: +#0 %sassign_obj_001.php(6): test() +#1 {main} + thrown in %sassign_obj_001.php on line 4 From f92505cf24e90a74d33bea8f20ca977b63aa9d4f Mon Sep 17 00:00:00 2001 From: Dmitry Menshikov Date: Sun, 3 Jul 2022 14:12:55 +0300 Subject: [PATCH 29/61] Fix GH-8885: access.log with stderr writes logs to error_log after reload This fix allows restoring the the original stderr so the logs are correctly written. --- NEWS | 4 + sapi/fpm/fpm/fpm_conf.c | 4 + sapi/fpm/fpm/fpm_events.c | 8 ++ sapi/fpm/fpm/fpm_process_ctl.c | 4 + sapi/fpm/fpm/fpm_stdio.c | 66 +++++++++++-- sapi/fpm/fpm/fpm_stdio.h | 4 + .../tests/bug8885-stderr-fd-reload-usr1.phpt | 92 +++++++++++++++++++ .../tests/bug8885-stderr-fd-reload-usr2.phpt | 92 +++++++++++++++++++ sapi/fpm/tests/tester.inc | 17 +++- 9 files changed, 282 insertions(+), 9 deletions(-) create mode 100644 sapi/fpm/tests/bug8885-stderr-fd-reload-usr1.phpt create mode 100644 sapi/fpm/tests/bug8885-stderr-fd-reload-usr2.phpt diff --git a/NEWS b/NEWS index 5e0f75578366e..2c5c1c5a841ba 100644 --- a/NEWS +++ b/NEWS @@ -12,6 +12,10 @@ PHP NEWS . Fixed bug #79451 (DOMDocument->replaceChild on doctype causes double free). (Nathan Freeman) +- FPM: + . Fixed bug GH-8885 (FPM access.log with stderr begins to write logs to + error_log after daemon reload). (Dmitry Menshikov) + - Streams: . Fixed bug GH-9316 ($http_response_header is wrong for long status line). (cmb, timwolla) diff --git a/sapi/fpm/fpm/fpm_conf.c b/sapi/fpm/fpm/fpm_conf.c index 7818cea47af76..8788ef3ecf3f9 100644 --- a/sapi/fpm/fpm/fpm_conf.c +++ b/sapi/fpm/fpm/fpm_conf.c @@ -1282,6 +1282,10 @@ static int fpm_conf_post_process(int force_daemon) /* {{{ */ fpm_evaluate_full_path(&fpm_global_config.error_log, NULL, PHP_LOCALSTATEDIR, 0); } + if (0 > fpm_stdio_save_original_stderr()) { + return -1; + } + if (0 > fpm_stdio_open_error_log(0)) { return -1; } diff --git a/sapi/fpm/fpm/fpm_events.c b/sapi/fpm/fpm/fpm_events.c index 6d563fe809108..48efd3a4e9e01 100644 --- a/sapi/fpm/fpm/fpm_events.c +++ b/sapi/fpm/fpm/fpm_events.c @@ -104,6 +104,11 @@ static void fpm_got_signal(struct fpm_event_s *ev, short which, void *arg) /* {{ break; case '1' : /* SIGUSR1 */ zlog(ZLOG_DEBUG, "received SIGUSR1"); + + /* fpm_stdio_init_final tied STDERR fd with error_log fd. This affects logging to the + * access.log if it was configured to write to the stderr. Check #8885. */ + fpm_stdio_restore_original_stderr(0); + if (0 == fpm_stdio_open_error_log(1)) { zlog(ZLOG_NOTICE, "error log file re-opened"); } else { @@ -118,6 +123,9 @@ static void fpm_got_signal(struct fpm_event_s *ev, short which, void *arg) /* {{ } /* else no access log are set */ + /* We need to tie stderr with error_log in the master process after log files reload. Check #8885. */ + fpm_stdio_redirect_stderr_to_error_log(); + break; case '2' : /* SIGUSR2 */ zlog(ZLOG_DEBUG, "received SIGUSR2"); diff --git a/sapi/fpm/fpm/fpm_process_ctl.c b/sapi/fpm/fpm/fpm_process_ctl.c index b4a06cc382b55..788b827d8a0f9 100644 --- a/sapi/fpm/fpm/fpm_process_ctl.c +++ b/sapi/fpm/fpm/fpm_process_ctl.c @@ -18,6 +18,7 @@ #include "fpm_worker_pool.h" #include "fpm_scoreboard.h" #include "fpm_sockets.h" +#include "fpm_stdio.h" #include "zlog.h" @@ -99,6 +100,9 @@ static void fpm_pctl_exec(void) ); fpm_cleanups_run(FPM_CLEANUP_PARENT_EXEC); + + fpm_stdio_restore_original_stderr(1); + execvp(saved_argv[0], saved_argv); zlog(ZLOG_SYSERROR, "failed to reload: execvp() failed"); exit(FPM_EXIT_SOFTWARE); diff --git a/sapi/fpm/fpm/fpm_stdio.c b/sapi/fpm/fpm/fpm_stdio.c index 2de4b589ef1dd..28246b01d2876 100644 --- a/sapi/fpm/fpm/fpm_stdio.c +++ b/sapi/fpm/fpm/fpm_stdio.c @@ -19,6 +19,7 @@ #include "fpm_stdio.h" #include "zlog.h" +static int fd_stderr_original = -1; static int fd_stdout[2]; static int fd_stderr[2]; @@ -59,6 +60,53 @@ static inline int fpm_use_error_log(void) { } int fpm_stdio_init_final(void) +{ + if (0 > fpm_stdio_redirect_stderr_to_error_log() || + 0 > fpm_stdio_redirect_stderr_to_dev_null_for_syslog()) { + + return -1; + } + + zlog_set_launched(); + return 0; +} +/* }}} */ + +int fpm_stdio_save_original_stderr(void) +{ + /* php-fpm loses STDERR fd after call of the fpm_stdio_init_final(). Check #8555. */ + zlog(ZLOG_DEBUG, "saving original STDERR fd: dup()"); + fd_stderr_original = dup(STDERR_FILENO); + if (0 > fd_stderr_original) { + zlog(ZLOG_SYSERROR, "failed to save original STDERR fd, access.log records may appear in error_log: dup()"); + return -1; + } + + return 0; +} + +int fpm_stdio_restore_original_stderr(int close_after_restore) +{ + /* php-fpm loses STDERR fd after call of the fpm_stdio_init_final(). Check #8555. */ + if (-1 != fd_stderr_original) { + zlog(ZLOG_DEBUG, "restoring original STDERR fd: dup2()"); + if (0 > dup2(fd_stderr_original, STDERR_FILENO)) { + zlog(ZLOG_SYSERROR, "failed to restore original STDERR fd, access.log records may appear in error_log: dup2()"); + return -1; + } else { + if (close_after_restore) { + close(fd_stderr_original); + } + } + } else { + zlog(ZLOG_DEBUG, "original STDERR fd is not restored, maybe function is called from a child: dup2()"); + return -1; + } + + return 0; +} + +int fpm_stdio_redirect_stderr_to_error_log(void) { if (fpm_use_error_log()) { /* prevent duping if logging to syslog */ @@ -66,18 +114,26 @@ int fpm_stdio_init_final(void) /* there might be messages to stderr from other parts of the code, we need to log them all */ if (0 > dup2(fpm_globals.error_log_fd, STDERR_FILENO)) { - zlog(ZLOG_SYSERROR, "failed to init stdio: dup2()"); + zlog(ZLOG_SYSERROR, "failed to tie stderr fd with error_log fd: dup2()"); return -1; } } + } + + return 0; +} + +int fpm_stdio_redirect_stderr_to_dev_null_for_syslog(void) +{ + if (fpm_use_error_log()) { #ifdef HAVE_SYSLOG_H - else if (fpm_globals.error_log_fd == ZLOG_SYSLOG) { + if (fpm_globals.error_log_fd == ZLOG_SYSLOG) { /* dup to /dev/null when using syslog */ dup2(STDOUT_FILENO, STDERR_FILENO); } #endif } - zlog_set_launched(); + return 0; } @@ -331,10 +387,6 @@ int fpm_stdio_open_error_log(int reopen) /* {{{ */ } if (reopen) { - if (fpm_use_error_log()) { - dup2(fd, STDERR_FILENO); - } - dup2(fd, fpm_globals.error_log_fd); close(fd); fd = fpm_globals.error_log_fd; /* for FD_CLOSEXEC to work */ diff --git a/sapi/fpm/fpm/fpm_stdio.h b/sapi/fpm/fpm/fpm_stdio.h index c0ff94d3cb609..49be50de562d9 100644 --- a/sapi/fpm/fpm/fpm_stdio.h +++ b/sapi/fpm/fpm/fpm_stdio.h @@ -16,5 +16,9 @@ void fpm_stdio_child_use_pipes(struct fpm_child_s *child); int fpm_stdio_parent_use_pipes(struct fpm_child_s *child); int fpm_stdio_discard_pipes(struct fpm_child_s *child); int fpm_stdio_open_error_log(int reopen); +int fpm_stdio_save_original_stderr(void); +int fpm_stdio_restore_original_stderr(int close_after_restore); +int fpm_stdio_redirect_stderr_to_dev_null_for_syslog(void); +int fpm_stdio_redirect_stderr_to_error_log(void); #endif diff --git a/sapi/fpm/tests/bug8885-stderr-fd-reload-usr1.phpt b/sapi/fpm/tests/bug8885-stderr-fd-reload-usr1.phpt new file mode 100644 index 0000000000000..37524a4bafec2 --- /dev/null +++ b/sapi/fpm/tests/bug8885-stderr-fd-reload-usr1.phpt @@ -0,0 +1,92 @@ +--TEST-- +FPM: bug8885 - access.log with stderr begins to write logs to error_log after daemon reload (GH-8885) +--SKIPIF-- + +--FILE-- + true]); +// getPrefixedFile('err.log') is the same path that returns processTemplate('{{FILE:LOG}}') +$errorLogFile = $tester->getPrefixedFile('err.log'); + +$tester->start(); +$tester->expectNoLogMessages(); + +$content = file_get_contents($errorLogFile); +assert($content !== false && strlen($content) > 0, 'File must not be empty'); + +$errorLogLines = explode("\n", $content); +array_pop($errorLogLines); + +assert(count($errorLogLines) === 2, 'Expected 2 records in the error_log file'); +assert(strpos($errorLogLines[0], 'NOTICE: fpm is running, pid')); +assert(strpos($errorLogLines[1], 'NOTICE: ready to handle connections')); + +$tester->ping('{{ADDR}}'); +$stderrLines = $tester->getLogLines(-1); +assert(count($stderrLines) === 1, 'Expected 1 record in the stderr output (access.log)'); +$stderrLine = $stderrLines[0]; +assert(preg_match('/127.0.0.1 .* "GET \/ping" 200$/', $stderrLine), 'Incorrect format of access.log record'); + +$tester->signal('USR1'); +$tester->expectNoLogMessages(); + +$content = file_get_contents($errorLogFile); +assert($content !== false && strlen($content) > 0, 'File must not be empty'); +$errorLogLines = explode("\n", $content); +array_pop($errorLogLines); + +assert(count($errorLogLines) >= 4, 'Expected at least 4 records in the error_log file'); +assert(strpos($errorLogLines[0], 'NOTICE: fpm is running, pid')); +assert(strpos($errorLogLines[1], 'NOTICE: ready to handle connections')); +assert(strpos($errorLogLines[2], 'NOTICE: error log file re-opened')); +assert(strpos($errorLogLines[3], 'NOTICE: access log file re-opened')); + + +$tester->ping('{{ADDR}}'); +$stderrLines = $tester->getLogLines(-1); +assert(count($stderrLines) === 1, 'Must be only 1 record in the access.log'); +assert(preg_match('/127.0.0.1 .* "GET \/ping" 200$/', $stderrLines[0]), 'Incorrect format of access.log record'); + +$tester->terminate(); +$stderrLines = $tester->expectNoLogMessages(); + +$content = file_get_contents($errorLogFile); +assert($content !== false && strlen($content) > 0, 'File must not be empty'); +$errorLogLines = explode("\n", $content); +array_pop($errorLogLines); +$errorLogLastLine = array_pop($errorLogLines); +assert(strpos($errorLogLastLine, 'NOTICE: exiting, bye-bye')); + +$tester->close(); +?> +Done +--EXPECT-- +Done +--CLEAN-- + diff --git a/sapi/fpm/tests/bug8885-stderr-fd-reload-usr2.phpt b/sapi/fpm/tests/bug8885-stderr-fd-reload-usr2.phpt new file mode 100644 index 0000000000000..16aea8afb828c --- /dev/null +++ b/sapi/fpm/tests/bug8885-stderr-fd-reload-usr2.phpt @@ -0,0 +1,92 @@ +--TEST-- +FPM: bug8885 - access.log with stderr begins to write logs to error_log after daemon reload (GH-8885) +--SKIPIF-- + +--FILE-- + true]); +// getPrefixedFile('err.log') is the same path that returns processTemplate('{{FILE:LOG}}') +$errorLogFile = $tester->getPrefixedFile('err.log'); + +$tester->start(); +$tester->expectNoLogMessages(); + +$content = file_get_contents($errorLogFile); +assert($content !== false && strlen($content) > 0, 'File must not be empty'); + +$errorLogLines = explode("\n", $content); +array_pop($errorLogLines); + +assert(count($errorLogLines) === 2, 'Expected 2 records in the error_log file'); +assert(strpos($errorLogLines[0], 'NOTICE: fpm is running, pid')); +assert(strpos($errorLogLines[1], 'NOTICE: ready to handle connections')); + +$tester->ping('{{ADDR}}'); +$stderrLines = $tester->getLogLines(-1); +assert(count($stderrLines) === 1, 'Expected 1 record in the stderr output (access.log)'); +$stderrLine = $stderrLines[0]; +assert(preg_match('/127.0.0.1 .* "GET \/ping" 200$/', $stderrLine), 'Incorrect format of access.log record'); + +$tester->signal('USR2'); +$tester->expectLogNotice('using inherited socket fd=\d+, "127.0.0.1:\d+"'); + +$content = file_get_contents($errorLogFile); +assert($content !== false && strlen($content) > 0, 'File must not be empty'); +$errorLogLines = explode("\n", $content); +array_pop($errorLogLines); + +assert(count($errorLogLines) >= 5, 'Expected at least 5 records in the error_log file'); +assert(strpos($errorLogLines[0], 'NOTICE: fpm is running, pid')); +assert(strpos($errorLogLines[1], 'NOTICE: ready to handle connections')); +assert(strpos($errorLogLines[2], 'NOTICE: Reloading in progress')); +assert(strpos($errorLogLines[3], 'NOTICE: reloading: execvp')); +assert(strpos($errorLogLines[4], 'NOTICE: using inherited socket')); + +$tester->ping('{{ADDR}}'); +$stderrLines = $tester->getLogLines(-1); +assert(count($stderrLines) === 1, 'Must be only 1 record in the access.log'); +assert(preg_match('/127.0.0.1 .* "GET \/ping" 200$/', $stderrLines[0]), 'Incorrect format of access.log record'); + +$tester->terminate(); +$stderrLines = $tester->expectNoLogMessages(); + +$content = file_get_contents($errorLogFile); +assert($content !== false && strlen($content) > 0, 'File must not be empty'); +$errorLogLines = explode("\n", $content); +array_pop($errorLogLines); +$errorLogLastLine = array_pop($errorLogLines); +assert(strpos($errorLogLastLine, 'NOTICE: exiting, bye-bye')); + +$tester->close(); +?> +Done +--EXPECT-- +Done +--CLEAN-- + diff --git a/sapi/fpm/tests/tester.inc b/sapi/fpm/tests/tester.inc index 5a190f0d39cbc..155bc234a8b74 100644 --- a/sapi/fpm/tests/tester.inc +++ b/sapi/fpm/tests/tester.inc @@ -35,6 +35,11 @@ class Tester */ const FILE_EXT_PID = 'pid'; + /** + * Name for the option to manage php-fpm --force-stderr flag + */ + const PHP_FPM_DISABLE_FORCE_STDERR = 'disable-force-stderr'; + /** * @var array */ @@ -365,7 +370,15 @@ class Tester { $configFile = $this->createConfig(); $desc = $this->outDesc ? [] : [1 => array('pipe', 'w'), 2 => array('redirect', 1)]; - $cmd = [self::findExecutable(), '-F', '-O', '-y', $configFile]; + + $cmd = [self::findExecutable(), '-F', '-y', $configFile]; + + if (!(isset($this->options[self::PHP_FPM_DISABLE_FORCE_STDERR]) && + $this->options[self::PHP_FPM_DISABLE_FORCE_STDERR] === true) + ) { + $cmd[] = '-O'; + } + if (getenv('TEST_FPM_RUN_AS_ROOT')) { $cmd[] = '--allow-to-run-as-root'; } @@ -1138,7 +1151,7 @@ class Tester * @param string $prefix * @return string */ - private function getPrefixedFile(string $extension, string $prefix = null) + public function getPrefixedFile(string $extension, string $prefix = null) { $fileName = rtrim($this->fileName, '.'); if (!is_null($prefix)) { From 263a07e5b0553e0b0c5b50a58682ad50f3455779 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 29 Aug 2022 17:12:57 +0300 Subject: [PATCH 30/61] typo --- ext/opcache/tests/opt/assign_obj_001.phpt | 2 +- ext/opcache/tests/opt/assign_op_001.phpt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/opcache/tests/opt/assign_obj_001.phpt b/ext/opcache/tests/opt/assign_obj_001.phpt index efb473ddaa940..205f111233e86 100644 --- a/ext/opcache/tests/opt/assign_obj_001.phpt +++ b/ext/opcache/tests/opt/assign_obj_001.phpt @@ -1,5 +1,5 @@ --TEST-- -ASSIGN_OP 001: Incrrect optimization of ASSIGN_OBJ may lead to memory leak +ASSIGN_OP 001: Incorrect optimization of ASSIGN_OBJ may lead to memory leak --INI-- opcache.enable=1 opcache.enable_cli=1 diff --git a/ext/opcache/tests/opt/assign_op_001.phpt b/ext/opcache/tests/opt/assign_op_001.phpt index b9db4202b46c0..7ac23d71c0d17 100644 --- a/ext/opcache/tests/opt/assign_op_001.phpt +++ b/ext/opcache/tests/opt/assign_op_001.phpt @@ -1,5 +1,5 @@ --TEST-- -ASSIGN_OP 001: Incrrect optimization of ASSIGN_OP may lead to memory leak +ASSIGN_OP 001: Incorrect optimization of ASSIGN_OP may lead to memory leak --INI-- opcache.enable=1 opcache.enable_cli=1 From bcdd9877e11eb056dad017700caa5e3b53a31060 Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Mon, 29 Aug 2022 16:40:31 +0100 Subject: [PATCH 31/61] Fix GH-8885 tests on MacOS --- .../tests/bug8885-stderr-fd-reload-usr1.phpt | 92 ------------------- .../tests/bug8885-stderr-fd-reload-usr2.phpt | 92 ------------------- 2 files changed, 184 deletions(-) delete mode 100644 sapi/fpm/tests/bug8885-stderr-fd-reload-usr1.phpt delete mode 100644 sapi/fpm/tests/bug8885-stderr-fd-reload-usr2.phpt diff --git a/sapi/fpm/tests/bug8885-stderr-fd-reload-usr1.phpt b/sapi/fpm/tests/bug8885-stderr-fd-reload-usr1.phpt deleted file mode 100644 index 37524a4bafec2..0000000000000 --- a/sapi/fpm/tests/bug8885-stderr-fd-reload-usr1.phpt +++ /dev/null @@ -1,92 +0,0 @@ ---TEST-- -FPM: bug8885 - access.log with stderr begins to write logs to error_log after daemon reload (GH-8885) ---SKIPIF-- - ---FILE-- - true]); -// getPrefixedFile('err.log') is the same path that returns processTemplate('{{FILE:LOG}}') -$errorLogFile = $tester->getPrefixedFile('err.log'); - -$tester->start(); -$tester->expectNoLogMessages(); - -$content = file_get_contents($errorLogFile); -assert($content !== false && strlen($content) > 0, 'File must not be empty'); - -$errorLogLines = explode("\n", $content); -array_pop($errorLogLines); - -assert(count($errorLogLines) === 2, 'Expected 2 records in the error_log file'); -assert(strpos($errorLogLines[0], 'NOTICE: fpm is running, pid')); -assert(strpos($errorLogLines[1], 'NOTICE: ready to handle connections')); - -$tester->ping('{{ADDR}}'); -$stderrLines = $tester->getLogLines(-1); -assert(count($stderrLines) === 1, 'Expected 1 record in the stderr output (access.log)'); -$stderrLine = $stderrLines[0]; -assert(preg_match('/127.0.0.1 .* "GET \/ping" 200$/', $stderrLine), 'Incorrect format of access.log record'); - -$tester->signal('USR1'); -$tester->expectNoLogMessages(); - -$content = file_get_contents($errorLogFile); -assert($content !== false && strlen($content) > 0, 'File must not be empty'); -$errorLogLines = explode("\n", $content); -array_pop($errorLogLines); - -assert(count($errorLogLines) >= 4, 'Expected at least 4 records in the error_log file'); -assert(strpos($errorLogLines[0], 'NOTICE: fpm is running, pid')); -assert(strpos($errorLogLines[1], 'NOTICE: ready to handle connections')); -assert(strpos($errorLogLines[2], 'NOTICE: error log file re-opened')); -assert(strpos($errorLogLines[3], 'NOTICE: access log file re-opened')); - - -$tester->ping('{{ADDR}}'); -$stderrLines = $tester->getLogLines(-1); -assert(count($stderrLines) === 1, 'Must be only 1 record in the access.log'); -assert(preg_match('/127.0.0.1 .* "GET \/ping" 200$/', $stderrLines[0]), 'Incorrect format of access.log record'); - -$tester->terminate(); -$stderrLines = $tester->expectNoLogMessages(); - -$content = file_get_contents($errorLogFile); -assert($content !== false && strlen($content) > 0, 'File must not be empty'); -$errorLogLines = explode("\n", $content); -array_pop($errorLogLines); -$errorLogLastLine = array_pop($errorLogLines); -assert(strpos($errorLogLastLine, 'NOTICE: exiting, bye-bye')); - -$tester->close(); -?> -Done ---EXPECT-- -Done ---CLEAN-- - diff --git a/sapi/fpm/tests/bug8885-stderr-fd-reload-usr2.phpt b/sapi/fpm/tests/bug8885-stderr-fd-reload-usr2.phpt deleted file mode 100644 index 16aea8afb828c..0000000000000 --- a/sapi/fpm/tests/bug8885-stderr-fd-reload-usr2.phpt +++ /dev/null @@ -1,92 +0,0 @@ ---TEST-- -FPM: bug8885 - access.log with stderr begins to write logs to error_log after daemon reload (GH-8885) ---SKIPIF-- - ---FILE-- - true]); -// getPrefixedFile('err.log') is the same path that returns processTemplate('{{FILE:LOG}}') -$errorLogFile = $tester->getPrefixedFile('err.log'); - -$tester->start(); -$tester->expectNoLogMessages(); - -$content = file_get_contents($errorLogFile); -assert($content !== false && strlen($content) > 0, 'File must not be empty'); - -$errorLogLines = explode("\n", $content); -array_pop($errorLogLines); - -assert(count($errorLogLines) === 2, 'Expected 2 records in the error_log file'); -assert(strpos($errorLogLines[0], 'NOTICE: fpm is running, pid')); -assert(strpos($errorLogLines[1], 'NOTICE: ready to handle connections')); - -$tester->ping('{{ADDR}}'); -$stderrLines = $tester->getLogLines(-1); -assert(count($stderrLines) === 1, 'Expected 1 record in the stderr output (access.log)'); -$stderrLine = $stderrLines[0]; -assert(preg_match('/127.0.0.1 .* "GET \/ping" 200$/', $stderrLine), 'Incorrect format of access.log record'); - -$tester->signal('USR2'); -$tester->expectLogNotice('using inherited socket fd=\d+, "127.0.0.1:\d+"'); - -$content = file_get_contents($errorLogFile); -assert($content !== false && strlen($content) > 0, 'File must not be empty'); -$errorLogLines = explode("\n", $content); -array_pop($errorLogLines); - -assert(count($errorLogLines) >= 5, 'Expected at least 5 records in the error_log file'); -assert(strpos($errorLogLines[0], 'NOTICE: fpm is running, pid')); -assert(strpos($errorLogLines[1], 'NOTICE: ready to handle connections')); -assert(strpos($errorLogLines[2], 'NOTICE: Reloading in progress')); -assert(strpos($errorLogLines[3], 'NOTICE: reloading: execvp')); -assert(strpos($errorLogLines[4], 'NOTICE: using inherited socket')); - -$tester->ping('{{ADDR}}'); -$stderrLines = $tester->getLogLines(-1); -assert(count($stderrLines) === 1, 'Must be only 1 record in the access.log'); -assert(preg_match('/127.0.0.1 .* "GET \/ping" 200$/', $stderrLines[0]), 'Incorrect format of access.log record'); - -$tester->terminate(); -$stderrLines = $tester->expectNoLogMessages(); - -$content = file_get_contents($errorLogFile); -assert($content !== false && strlen($content) > 0, 'File must not be empty'); -$errorLogLines = explode("\n", $content); -array_pop($errorLogLines); -$errorLogLastLine = array_pop($errorLogLines); -assert(strpos($errorLogLastLine, 'NOTICE: exiting, bye-bye')); - -$tester->close(); -?> -Done ---EXPECT-- -Done ---CLEAN-- - From 986e7319c54365e9758feaea9d590e215e3c306b Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Mon, 29 Aug 2022 16:42:01 +0100 Subject: [PATCH 32/61] Re-add fixed tests for GH-8885 --- .../tests/gh8885-stderr-fd-reload-usr1.phpt | 92 +++++++++++++++++++ .../tests/gh8885-stderr-fd-reload-usr2.phpt | 92 +++++++++++++++++++ 2 files changed, 184 insertions(+) create mode 100644 sapi/fpm/tests/gh8885-stderr-fd-reload-usr1.phpt create mode 100644 sapi/fpm/tests/gh8885-stderr-fd-reload-usr2.phpt diff --git a/sapi/fpm/tests/gh8885-stderr-fd-reload-usr1.phpt b/sapi/fpm/tests/gh8885-stderr-fd-reload-usr1.phpt new file mode 100644 index 0000000000000..4ff8d0660936e --- /dev/null +++ b/sapi/fpm/tests/gh8885-stderr-fd-reload-usr1.phpt @@ -0,0 +1,92 @@ +--TEST-- +FPM: GH-8885 - access.log with stderr begins to write logs to error_log after daemon reload +--SKIPIF-- + +--FILE-- + true]); +// getPrefixedFile('err.log') is the same path that returns processTemplate('{{FILE:LOG}}') +$errorLogFile = $tester->getPrefixedFile('err.log'); + +$tester->start(); +$tester->expectNoLogMessages(); + +$content = file_get_contents($errorLogFile); +assert($content !== false && strlen($content) > 0, 'File must not be empty'); + +$errorLogLines = explode("\n", $content); +array_pop($errorLogLines); + +assert(count($errorLogLines) === 2, 'Expected 2 records in the error_log file'); +assert(strpos($errorLogLines[0], 'NOTICE: fpm is running, pid')); +assert(strpos($errorLogLines[1], 'NOTICE: ready to handle connections')); + +$tester->ping('{{ADDR}}'); +$stderrLines = $tester->getLogLines(-1); +assert(count($stderrLines) === 1, 'Expected 1 record in the stderr output (access.log)'); +$stderrLine = $stderrLines[0]; +assert(preg_match('/127.0.0.1 .* "GET \/ping" 200$/', $stderrLine), 'Incorrect format of access.log record'); + +$tester->signal('USR1'); +$tester->expectNoLogMessages(); + +$content = file_get_contents($errorLogFile); +assert($content !== false && strlen($content) > 0, 'File must not be empty'); +$errorLogLines = explode("\n", $content); +array_pop($errorLogLines); + +assert(count($errorLogLines) >= 4, 'Expected at least 4 records in the error_log file'); +assert(strpos($errorLogLines[0], 'NOTICE: fpm is running, pid')); +assert(strpos($errorLogLines[1], 'NOTICE: ready to handle connections')); +assert(strpos($errorLogLines[2], 'NOTICE: error log file re-opened')); +assert(strpos($errorLogLines[3], 'NOTICE: access log file re-opened')); + + +$tester->ping('{{ADDR}}'); +$stderrLines = $tester->getLogLines(-1); +assert(count($stderrLines) === 1, 'Must be only 1 record in the access.log'); +assert(preg_match('/127.0.0.1 .* "GET \/ping" 200$/', $stderrLines[0]), 'Incorrect format of access.log record'); + +$tester->terminate(); +$stderrLines = $tester->expectNoLogMessages(); + +$content = file_get_contents($errorLogFile); +assert($content !== false && strlen($content) > 0, 'File must not be empty'); +$errorLogLines = explode("\n", $content); +array_pop($errorLogLines); +$errorLogLastLine = array_pop($errorLogLines); +assert(strpos($errorLogLastLine, 'NOTICE: exiting, bye-bye')); + +$tester->close(); +?> +Done +--EXPECT-- +Done +--CLEAN-- + diff --git a/sapi/fpm/tests/gh8885-stderr-fd-reload-usr2.phpt b/sapi/fpm/tests/gh8885-stderr-fd-reload-usr2.phpt new file mode 100644 index 0000000000000..68d9f6fa68b64 --- /dev/null +++ b/sapi/fpm/tests/gh8885-stderr-fd-reload-usr2.phpt @@ -0,0 +1,92 @@ +--TEST-- +FPM: GH-8885 - access.log with stderr begins to write logs to error_log after daemon reload +--SKIPIF-- + +--FILE-- + true]); +// getPrefixedFile('err.log') is the same path that returns processTemplate('{{FILE:LOG}}') +$errorLogFile = $tester->getPrefixedFile('err.log'); + +$tester->start(); +$tester->expectNoLogMessages(); + +$content = file_get_contents($errorLogFile); +assert($content !== false && strlen($content) > 0, 'File must not be empty'); + +$errorLogLines = explode("\n", $content); +array_pop($errorLogLines); + +assert(count($errorLogLines) === 2, 'Expected 2 records in the error_log file'); +assert(strpos($errorLogLines[0], 'NOTICE: fpm is running, pid')); +assert(strpos($errorLogLines[1], 'NOTICE: ready to handle connections')); + +$tester->ping('{{ADDR}}'); +$stderrLines = $tester->getLogLines(-1); +assert(count($stderrLines) === 1, 'Expected 1 record in the stderr output (access.log)'); +$stderrLine = $stderrLines[0]; +assert(preg_match('/127.0.0.1 .* "GET \/ping" 200$/', $stderrLine), 'Incorrect format of access.log record'); + +$tester->signal('USR2'); +$tester->expectLogNotice('using inherited socket fd=\d+, "127.0.0.1:\d+"'); + +$content = file_get_contents($errorLogFile); +assert($content !== false && strlen($content) > 0, 'File must not be empty'); +$errorLogLines = explode("\n", $content); +array_pop($errorLogLines); + +assert(count($errorLogLines) >= 5, 'Expected at least 5 records in the error_log file'); +assert(strpos($errorLogLines[0], 'NOTICE: fpm is running, pid')); +assert(strpos($errorLogLines[1], 'NOTICE: ready to handle connections')); +assert(strpos($errorLogLines[2], 'NOTICE: Reloading in progress')); +assert(strpos($errorLogLines[3], 'NOTICE: reloading: execvp')); +assert(strpos($errorLogLines[4], 'NOTICE: using inherited socket')); + +$tester->ping('{{ADDR}}'); +$stderrLines = $tester->getLogLines(-1); +assert(count($stderrLines) === 1, 'Must be only 1 record in the access.log'); +assert(preg_match('/127.0.0.1 .* "GET \/ping" 200$/', $stderrLines[0]), 'Incorrect format of access.log record'); + +$tester->terminate(); +$stderrLines = $tester->expectNoLogMessages(); + +$content = file_get_contents($errorLogFile); +assert($content !== false && strlen($content) > 0, 'File must not be empty'); +$errorLogLines = explode("\n", $content); +array_pop($errorLogLines); +$errorLogLastLine = array_pop($errorLogLines); +assert(strpos($errorLogLastLine, 'NOTICE: exiting, bye-bye')); + +$tester->close(); +?> +Done +--EXPECT-- +Done +--CLEAN-- + From 3503b1daa265777588b3219b82219a0056675ca0 Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Sun, 26 Jun 2022 15:34:33 +0100 Subject: [PATCH 33/61] Fix bug #77780: "Headers already sent" when previous connection was aborted This change primarily splits SAPI deactivation to module and destroy parts. The reason is that currently some SAPIs might bail out on deactivation. One of those SAPI is PHP-FPM that can bail out on request end if for example the connection is closed by the client (web sever). The problem is that in such case the resources are not freed and some values reset. The most visible impact can have not resetting the PG(headers_sent) which can cause erorrs in the next request. One such issue is described in #77780 bug which this fixes and is also cover by a test in this commit. It seems reasonable to separate deactivation and destroying of the resource which means that the bail out will not impact it. --- NEWS | 2 + main/SAPI.c | 12 ++++- main/SAPI.h | 2 + main/main.c | 6 ++- .../fpm/tests/bug77780-header-sent-error.phpt | 54 +++++++++++++++++++ sapi/fpm/tests/fcgi.inc | 25 ++++++--- sapi/fpm/tests/response.inc | 18 +++++-- sapi/fpm/tests/tester.inc | 18 +++++-- 8 files changed, 119 insertions(+), 18 deletions(-) create mode 100644 sapi/fpm/tests/bug77780-header-sent-error.phpt diff --git a/NEWS b/NEWS index 2c5c1c5a841ba..81762e523fe64 100644 --- a/NEWS +++ b/NEWS @@ -15,6 +15,8 @@ PHP NEWS - FPM: . Fixed bug GH-8885 (FPM access.log with stderr begins to write logs to error_log after daemon reload). (Dmitry Menshikov) + . Fixed bug #77780 ("Headers already sent..." when previous connection was + aborted). (Jakub Zelenka) - Streams: . Fixed bug GH-9316 ($http_response_header is wrong for long status line). diff --git a/main/SAPI.c b/main/SAPI.c index 0a7f219e847e5..eea417cedcc38 100644 --- a/main/SAPI.c +++ b/main/SAPI.c @@ -485,7 +485,7 @@ static void sapi_send_headers_free(void) } } -SAPI_API void sapi_deactivate(void) +SAPI_API void sapi_deactivate_module(void) { zend_llist_destroy(&SG(sapi_headers).headers); if (SG(request_info).request_body) { @@ -519,6 +519,10 @@ SAPI_API void sapi_deactivate(void) if (sapi_module.deactivate) { sapi_module.deactivate(); } +} + +SAPI_API void sapi_deactivate_destroy(void) +{ if (SG(rfc1867_uploaded_files)) { destroy_uploaded_files_hash(); } @@ -533,6 +537,12 @@ SAPI_API void sapi_deactivate(void) SG(global_request_time) = 0; } +SAPI_API void sapi_deactivate(void) +{ + sapi_deactivate_module(); + sapi_deactivate_destroy(); +} + SAPI_API void sapi_initialize_empty_request(void) { diff --git a/main/SAPI.h b/main/SAPI.h index b0d2928369fc0..0f9e896683a85 100644 --- a/main/SAPI.h +++ b/main/SAPI.h @@ -143,6 +143,8 @@ extern SAPI_API sapi_globals_struct sapi_globals; SAPI_API void sapi_startup(sapi_module_struct *sf); SAPI_API void sapi_shutdown(void); SAPI_API void sapi_activate(void); +SAPI_API void sapi_deactivate_module(void); +SAPI_API void sapi_deactivate_destroy(void); SAPI_API void sapi_deactivate(void); SAPI_API void sapi_initialize_empty_request(void); SAPI_API void sapi_add_request_header(const char *var, unsigned int var_len, char *val, unsigned int val_len, void *arg); diff --git a/main/main.c b/main/main.c index 9772d8fd760a6..40684f32dc146 100644 --- a/main/main.c +++ b/main/main.c @@ -1860,10 +1860,12 @@ void php_request_shutdown(void *dummy) zend_post_deactivate_modules(); } zend_end_try(); - /* 12. SAPI related shutdown (free stuff) */ + /* 12. SAPI related shutdown*/ zend_try { - sapi_deactivate(); + sapi_deactivate_module(); } zend_end_try(); + /* free SAPI stuff */ + sapi_deactivate_destroy(); /* 13. free virtual CWD memory */ virtual_cwd_deactivate(); diff --git a/sapi/fpm/tests/bug77780-header-sent-error.phpt b/sapi/fpm/tests/bug77780-header-sent-error.phpt new file mode 100644 index 0000000000000..b5e76918547f1 --- /dev/null +++ b/sapi/fpm/tests/bug77780-header-sent-error.phpt @@ -0,0 +1,54 @@ +--TEST-- +FPM: bug77780 - Headers already sent error incorrectly emitted +--SKIPIF-- + +--EXTENSIONS-- +session +--FILE-- +start(); +$tester->expectLogStartNotices(); +$tester + ->request( + headers: [ + 'PHP_VALUE' => "session.cookie_secure=1", + ], + readLimit: 10, + expectError: true + ); +$tester->request( + headers: [ + 'PHP_VALUE' => "session.cookie_secure=1", + ] + ) + ->expectNoError(); +$tester->terminate(); +$tester->close(); + +?> +Done +--EXPECT-- +Done +--CLEAN-- + diff --git a/sapi/fpm/tests/fcgi.inc b/sapi/fpm/tests/fcgi.inc index d17a659dd9c02..7d236c1b03a5e 100644 --- a/sapi/fpm/tests/fcgi.inc +++ b/sapi/fpm/tests/fcgi.inc @@ -26,6 +26,7 @@ namespace Adoy\FastCGI; class TimedOutException extends \Exception {} class ForbiddenException extends \Exception {} +class ReadLimitExceeded extends \Exception {} /** * Handles communication with a FastCGI application @@ -404,16 +405,24 @@ class Client /** * Read a FastCGI Packet * + * @param int $readLimit max content size * @return array + * @throws ReadLimitExceeded */ - private function readPacket() + private function readPacket($readLimit = -1) { if ($packet = fread($this->_sock, self::HEADER_LEN)) { $resp = $this->decodePacketHeader($packet); $resp['content'] = ''; if ($resp['contentLength']) { - $len = $resp['contentLength']; - while ($len && $buf=fread($this->_sock, $len)) { + $len = $resp['contentLength']; + if ($readLimit >= 0 && $len > $readLimit) { + // close connection so it can be re-set reset and throw an error + fclose($this->_sock); + $this->_sock = null; + throw new ReadLimitExceeded("Content has $len bytes but the limit is $readLimit bytes"); + } + while ($len && $buf = fread($this->_sock, $len)) { $len -= strlen($buf); $resp['content'] .= $buf; } @@ -473,15 +482,16 @@ class Client * * @param array $params Array of parameters * @param string $stdin Content + * @param int $readLimit [optional] the number of bytes to accept in a single packet or -1 if unlimited * @return array * @throws ForbiddenException * @throws TimedOutException * @throws \Exception */ - public function request_data(array $params, $stdin) + public function request_data(array $params, $stdin, $readLimit = -1) { $id = $this->async_request($params, $stdin); - return $this->wait_for_response_data($id); + return $this->wait_for_response_data($id, 0, $readLimit); } /** @@ -579,12 +589,13 @@ class Client * * @param int $requestId * @param int $timeoutMs [optional] the number of milliseconds to wait. + * @param int $readLimit [optional] the number of bytes to accept in a single packet or -1 if unlimited * @return array response data * @throws ForbiddenException * @throws TimedOutException * @throws \Exception */ - public function wait_for_response_data($requestId, $timeoutMs = 0) + public function wait_for_response_data($requestId, $timeoutMs = 0, $readLimit = -1) { if (!isset($this->_requests[$requestId])) { throw new \Exception('Invalid request id given'); @@ -608,7 +619,7 @@ class Client // but still not get the response requested $startTime = microtime(true); - while ($resp = $this->readPacket()) { + while ($resp = $this->readPacket($readLimit)) { if ($resp['type'] == self::STDOUT || $resp['type'] == self::STDERR) { if ($resp['type'] == self::STDERR) { $this->_requests[$resp['requestId']]['state'] = self::REQ_STATE_ERR; diff --git a/sapi/fpm/tests/response.inc b/sapi/fpm/tests/response.inc index b531feacdca7e..1d0783b66ec35 100644 --- a/sapi/fpm/tests/response.inc +++ b/sapi/fpm/tests/response.inc @@ -111,21 +111,31 @@ class Response } /** - * @param string $errorMessage + * @param string|null $errorMessage * @return Response */ public function expectError($errorMessage) { $errorData = $this->getErrorData(); if ($errorData !== $errorMessage) { - $this->error( - "The expected error message '$errorMessage' is not equal to returned error '$errorData'" - ); + $expectedErrorMessage = $errorMessage !== null + ? "The expected error message '$errorMessage' is not equal to returned error '$errorData'" + : "No error message expected but received '$errorData'"; + $this->error($expectedErrorMessage); } return $this; } + /** + * @param string $errorMessage + * @return Response + */ + public function expectNoError() + { + return $this->expectError(null); + } + /** * @param string $contentType * @return string|null diff --git a/sapi/fpm/tests/tester.inc b/sapi/fpm/tests/tester.inc index 155bc234a8b74..dce81bfeb76f9 100644 --- a/sapi/fpm/tests/tester.inc +++ b/sapi/fpm/tests/tester.inc @@ -593,6 +593,8 @@ class Tester * @param string|null $successMessage * @param string|null $errorMessage * @param bool $connKeepAlive + * @param bool $expectError + * @param int $readLimit * @return Response */ public function request( @@ -602,7 +604,9 @@ class Tester string $address = null, string $successMessage = null, string $errorMessage = null, - bool $connKeepAlive = false + bool $connKeepAlive = false, + bool $expectError = false, + int $readLimit = -1, ) { if ($this->hasError()) { return new Response(null, true); @@ -612,11 +616,17 @@ class Tester try { $this->response = new Response( - $this->getClient($address, $connKeepAlive)->request_data($params, false) + $this->getClient($address, $connKeepAlive)->request_data($params, false, $readLimit) ); - $this->message($successMessage); + if ($expectError) { + $this->error('Expected request error but the request was successful'); + } else { + $this->message($successMessage); + } } catch (\Exception $exception) { - if ($errorMessage === null) { + if ($expectError) { + $this->message($successMessage); + } elseif ($errorMessage === null) { $this->error("Request failed", $exception); } else { $this->message($errorMessage); From 3d6ed8c852a6b03887896e2fd471f662397f045c Mon Sep 17 00:00:00 2001 From: Sara Golemon Date: Tue, 30 Aug 2022 12:15:27 +0000 Subject: [PATCH 34/61] Catch up dev version numbers --- Zend/zend.h | 2 +- configure.ac | 2 +- main/php_version.h | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Zend/zend.h b/Zend/zend.h index 68ddf46872d48..a43edf9b01b60 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -20,7 +20,7 @@ #ifndef ZEND_H #define ZEND_H -#define ZEND_VERSION "4.0.21-dev" +#define ZEND_VERSION "4.0.24-dev" #define ZEND_ENGINE_3 diff --git a/configure.ac b/configure.ac index 87fdd415e247d..ee0ae055e346a 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.0.21-dev],[https://bugs.php.net],[php],[https://www.php.net]) +AC_INIT([PHP],[8.0.24-dev],[https://bugs.php.net],[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 3259dab14a6fa..5594e041079d2 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 0 -#define PHP_RELEASE_VERSION 21 +#define PHP_RELEASE_VERSION 24 #define PHP_EXTRA_VERSION "-dev" -#define PHP_VERSION "8.0.21-dev" -#define PHP_VERSION_ID 80021 +#define PHP_VERSION "8.0.24-dev" +#define PHP_VERSION_ID 80024 From 1862152145759ecfad3e9c939922e8c4719d918f Mon Sep 17 00:00:00 2001 From: Ben Ramsey Date: Tue, 30 Aug 2022 09:13:46 -0500 Subject: [PATCH 35/61] Revert "Fix GH-9296: `ksort` behaves incorrectly on arrays with mixed keys" This reverts commit cd1aed8eddd2dccbb55fb1bc3d67b23a8455248c, as discussed on internals (). --- NEWS | 4 -- ext/standard/array.c | 53 ++++++++++++------- ext/standard/tests/array/002.phpt | 20 +++---- ext/standard/tests/array/gh9296.phpt | 17 ------ .../tests/array/krsort_variation9.phpt | 8 +-- .../tests/array/ksort_variation9.phpt | 8 +-- 6 files changed, 52 insertions(+), 58 deletions(-) delete mode 100644 ext/standard/tests/array/gh9296.phpt diff --git a/NEWS b/NEWS index 765a321ece9e6..ac630004c5de0 100644 --- a/NEWS +++ b/NEWS @@ -71,10 +71,6 @@ PHP NEWS - SQLite3: . Fixed bug GH-9032 (SQLite3 authorizer crashes on NULL values). (cmb) -- Standard: - . Fixed bug GH-9296 (`ksort` behaves incorrectly on arrays with mixed keys). - (Denis Vaksman) - - Streams: . Fixed bug GH-8472 (The resource returned by stream_socket_accept may have incorrect metadata). (Jakub Zelenka) diff --git a/ext/standard/array.c b/ext/standard/array.c index aa57b261c1fdb..e4261b428e9b0 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -166,25 +166,40 @@ static zend_never_inline ZEND_COLD int stable_sort_fallback(Bucket *a, Bucket *b static zend_always_inline int php_array_key_compare_unstable_i(Bucket *f, Bucket *s) /* {{{ */ { - zval first; - zval second; - - if (f->key == NULL && s->key == NULL) { - return (zend_long)f->h > (zend_long)s->h ? 1 : -1; - } else if (f->key && s->key) { - return zendi_smart_strcmp(f->key, s->key); - } - if (f->key) { - ZVAL_STR(&first, f->key); - } else { - ZVAL_LONG(&first, f->h); - } - if (s->key) { - ZVAL_STR(&second, s->key); - } else { - ZVAL_LONG(&second, s->h); - } - return zend_compare(&first, &second); + zend_uchar t; + zend_long l1, l2; + double d; + + if (f->key == NULL) { + if (s->key == NULL) { + return (zend_long)f->h > (zend_long)s->h ? 1 : -1; + } else { + l1 = (zend_long)f->h; + t = is_numeric_string(s->key->val, s->key->len, &l2, &d, 1); + if (t == IS_LONG) { + /* pass */ + } else if (t == IS_DOUBLE) { + return ZEND_NORMALIZE_BOOL((double)l1 - d); + } else { + l2 = 0; + } + } + } else { + if (s->key) { + return zendi_smart_strcmp(f->key, s->key); + } else { + l2 = (zend_long)s->h; + t = is_numeric_string(f->key->val, f->key->len, &l1, &d, 1); + if (t == IS_LONG) { + /* pass */ + } else if (t == IS_DOUBLE) { + return ZEND_NORMALIZE_BOOL(d - (double)l2); + } else { + l1 = 0; + } + } + } + return ZEND_NORMALIZE_BOOL(l1 - l2); } /* }}} */ diff --git a/ext/standard/tests/array/002.phpt b/ext/standard/tests/array/002.phpt index 5cf377e2a3538..fdb838deb19dd 100644 --- a/ext/standard/tests/array/002.phpt +++ b/ext/standard/tests/array/002.phpt @@ -276,8 +276,6 @@ array(8) { -- Testing krsort() -- No second argument: array(8) { - ["test"]=> - int(27) [16777216]=> float(-0.3333333333333333) [1001]=> @@ -290,6 +288,8 @@ array(8) { string(4) "Test" [0]=> string(3) "PHP" + ["test"]=> + int(27) [-1000]=> array(2) { [0]=> @@ -300,8 +300,6 @@ array(8) { } Using SORT_REGULAR: array(8) { - ["test"]=> - int(27) [16777216]=> float(-0.3333333333333333) [1001]=> @@ -314,6 +312,8 @@ array(8) { string(4) "Test" [0]=> string(3) "PHP" + ["test"]=> + int(27) [-1000]=> array(2) { [0]=> @@ -334,10 +334,10 @@ array(8) { string(27) "PHP: Hypertext Preprocessor" [5]=> string(4) "Test" - ["test"]=> - int(27) [0]=> string(3) "PHP" + ["test"]=> + int(27) [-1000]=> array(2) { [0]=> @@ -383,6 +383,8 @@ array(8) { } [0]=> string(3) "PHP" + ["test"]=> + int(27) [5]=> string(4) "Test" [17]=> @@ -393,8 +395,6 @@ array(8) { string(6) "monkey" [16777216]=> float(-0.3333333333333333) - ["test"]=> - int(27) } Using SORT_REGULAR: array(8) { @@ -407,6 +407,8 @@ array(8) { } [0]=> string(3) "PHP" + ["test"]=> + int(27) [5]=> string(4) "Test" [17]=> @@ -417,8 +419,6 @@ array(8) { string(6) "monkey" [16777216]=> float(-0.3333333333333333) - ["test"]=> - int(27) } Using SORT_NUMERIC: array(8) { diff --git a/ext/standard/tests/array/gh9296.phpt b/ext/standard/tests/array/gh9296.phpt deleted file mode 100644 index cfbc5cbbb09ec..0000000000000 --- a/ext/standard/tests/array/gh9296.phpt +++ /dev/null @@ -1,17 +0,0 @@ ---TEST-- -GH-9296: incorrect ksort(..., SORT_REGULAR) behaviour on arrays with numeric and string keys ---FILE-- - 0, 600 => 1]; -ksort($array, SORT_REGULAR); -var_dump($array); -var_dump(array_key_first($array) <=> array_key_last($array)); -?> ---EXPECT-- -array(2) { - [600]=> - int(1) - ["aaa"]=> - int(0) -} -int(-1) diff --git a/ext/standard/tests/array/krsort_variation9.phpt b/ext/standard/tests/array/krsort_variation9.phpt index b0309f373d362..4364911b62127 100644 --- a/ext/standard/tests/array/krsort_variation9.phpt +++ b/ext/standard/tests/array/krsort_variation9.phpt @@ -82,22 +82,22 @@ array(5) { - With default sort flag - bool(true) array(3) { - ["c"]=> - string(5) "apple" ["a"]=> string(6) "orange" [0]=> string(6) "banana" + ["c"]=> + string(5) "apple" } - Sort flag = SORT_REGULAR - bool(true) array(3) { - ["c"]=> - string(5) "apple" ["a"]=> string(6) "orange" [0]=> string(6) "banana" + ["c"]=> + string(5) "apple" } -- Iteration 3 -- diff --git a/ext/standard/tests/array/ksort_variation9.phpt b/ext/standard/tests/array/ksort_variation9.phpt index 0023a9e0602ae..9322af70f57fa 100644 --- a/ext/standard/tests/array/ksort_variation9.phpt +++ b/ext/standard/tests/array/ksort_variation9.phpt @@ -81,20 +81,20 @@ array(5) { - With default sort flag - bool(true) array(3) { - [0]=> - string(6) "banana" ["a"]=> string(6) "orange" + [0]=> + string(6) "banana" ["c"]=> string(5) "apple" } - Sort flag = SORT_REGULAR - bool(true) array(3) { - [0]=> - string(6) "banana" ["a"]=> string(6) "orange" + [0]=> + string(6) "banana" ["c"]=> string(5) "apple" } From 65619e868c2b63a79b858ab05cbc97ae14bbe622 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Tue, 30 Aug 2022 16:51:25 +0200 Subject: [PATCH 36/61] Fix tests These changes have been overlooked, when 7908aae30cd4241bed505addc3b5f7da27feef8b had been reverted. --- .../tests/array/krsort_variation8.phpt | 24 +++++------ .../tests/array/ksort_variation8.phpt | 40 +++++++++---------- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/ext/standard/tests/array/krsort_variation8.phpt b/ext/standard/tests/array/krsort_variation8.phpt index 4c1c6f2173d26..caa0f21936027 100644 --- a/ext/standard/tests/array/krsort_variation8.phpt +++ b/ext/standard/tests/array/krsort_variation8.phpt @@ -41,6 +41,10 @@ echo "Done\n"; -- Testing krsort() by supplying mixed value array, 'flag' value is default -- bool(true) array(13) { + [5]=> + string(1) "5" + [4]=> + float(4.01) ["b"]=> string(1) "b" ["array2"]=> @@ -81,23 +85,23 @@ array(13) { string(2) "ab" ["True"]=> string(4) "True" - [5]=> - string(1) "5" - [4]=> - float(4.01) [0]=> float(0.001) ["-.9"]=> string(3) "-.9" - [-2]=> - float(-2.98989) [""]=> string(0) "" + [-2]=> + float(-2.98989) } -- Testing krsort() by supplying mixed value array, 'flag' value is SORT_REGULAR -- bool(true) array(13) { + [5]=> + string(1) "5" + [4]=> + float(4.01) ["b"]=> string(1) "b" ["array2"]=> @@ -138,17 +142,13 @@ array(13) { string(2) "ab" ["True"]=> string(4) "True" - [5]=> - string(1) "5" - [4]=> - float(4.01) [0]=> float(0.001) ["-.9"]=> string(3) "-.9" - [-2]=> - float(-2.98989) [""]=> string(0) "" + [-2]=> + float(-2.98989) } Done diff --git a/ext/standard/tests/array/ksort_variation8.phpt b/ext/standard/tests/array/ksort_variation8.phpt index 236c405c64b95..10ed218211f07 100644 --- a/ext/standard/tests/array/ksort_variation8.phpt +++ b/ext/standard/tests/array/ksort_variation8.phpt @@ -40,26 +40,18 @@ echo "Done\n"; -- Testing ksort() by supplying mixed value array, 'flag' value is default -- bool(true) array(13) { - [""]=> - string(0) "" [-2]=> float(-2.98989) + [""]=> + string(0) "" ["-.9"]=> string(3) "-.9" - [0]=> - float(0.001) - [4]=> - float(4.01) - [5]=> - string(1) "5" ["True"]=> string(4) "True" ["ab"]=> string(2) "ab" ["abcd"]=> string(4) "abcd" - ["abcd%0abcd%0abcd"]=> - string(14) "abcd%0abcd%0abcd" ["array1"]=> array(0) { } @@ -92,31 +84,31 @@ array(13) { } ["b"]=> string(1) "b" + [0]=> + float(0.001) + ["abcd%0abcd%0abcd"]=> + string(14) "abcd%0abcd%0abcd" + [4]=> + float(4.01) + [5]=> + string(1) "5" } -- Testing ksort() by supplying mixed value array, 'flag' value is SORT_REGULAR -- bool(true) array(13) { - [""]=> - string(0) "" [-2]=> float(-2.98989) + [""]=> + string(0) "" ["-.9"]=> string(3) "-.9" - [0]=> - float(0.001) - [4]=> - float(4.01) - [5]=> - string(1) "5" ["True"]=> string(4) "True" ["ab"]=> string(2) "ab" ["abcd"]=> string(4) "abcd" - ["abcd%0abcd%0abcd"]=> - string(14) "abcd%0abcd%0abcd" ["array1"]=> array(0) { } @@ -149,5 +141,13 @@ array(13) { } ["b"]=> string(1) "b" + [0]=> + float(0.001) + ["abcd%0abcd%0abcd"]=> + string(14) "abcd%0abcd%0abcd" + [4]=> + float(4.01) + [5]=> + string(1) "5" } Done From f8b217a3452e76113b833eec8a49bc2b6e8d1fdd Mon Sep 17 00:00:00 2001 From: Niklas Keller Date: Mon, 8 Aug 2022 23:54:24 +0200 Subject: [PATCH 37/61] Fix pcre.jit on Apple Silicon This backports https://github.com/zherczeg/sljit/pull/105. Relates to bug #80435, however, it doesn't solve the bus error on PHP 8.0, but PHP 8.1 builds fine now. Closes GH-9279. --- NEWS | 3 +++ ext/pcre/pcre2lib/sljit/sljitExecAllocator.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/NEWS b/NEWS index ac630004c5de0..a5dcc78b668dd 100644 --- a/NEWS +++ b/NEWS @@ -18,6 +18,9 @@ PHP NEWS . Fixed bug #77780 ("Headers already sent..." when previous connection was aborted). (Jakub Zelenka) +- PCRE: + . Fixed pcre.jit on Apple Silicon. (Niklas Keller) + - Streams: . Fixed bug GH-9316 ($http_response_header is wrong for long status line). (cmb, timwolla) diff --git a/ext/pcre/pcre2lib/sljit/sljitExecAllocator.c b/ext/pcre/pcre2lib/sljit/sljitExecAllocator.c index 6e5bf78e45fe9..b268624822219 100644 --- a/ext/pcre/pcre2lib/sljit/sljitExecAllocator.c +++ b/ext/pcre/pcre2lib/sljit/sljitExecAllocator.c @@ -187,10 +187,13 @@ static SLJIT_INLINE void* alloc_chunk(sljit_uw size) if (retval == MAP_FAILED) return NULL; +#ifdef __FreeBSD__ + /* HardenedBSD's mmap lies, so check permissions again */ if (mprotect(retval, size, PROT_READ | PROT_WRITE | PROT_EXEC) < 0) { munmap(retval, size); return NULL; } +#endif /* FreeBSD */ SLJIT_UPDATE_WX_FLAGS(retval, (uint8_t *)retval + size, 0); From 2cfb028e22f807d859823d040a77c912e8afb996 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 1 Sep 2022 23:17:20 +0200 Subject: [PATCH 38/61] Fix class name FQN when AST dumping new and class const Fixes GH-9447 Closes GH-9462 --- NEWS | 2 ++ Zend/zend_ast.c | 2 +- Zend/zend_compile.c | 4 ++-- Zend/zend_compile.h | 3 +++ ext/reflection/tests/gh9447.phpt | 39 ++++++++++++++++++++++++++++++++ 5 files changed, 47 insertions(+), 3 deletions(-) create mode 100644 ext/reflection/tests/gh9447.phpt diff --git a/NEWS b/NEWS index a5dcc78b668dd..f263798514391 100644 --- a/NEWS +++ b/NEWS @@ -7,6 +7,8 @@ PHP NEWS (Tim Starling) . Fixed bug GH-9361 (Segmentation fault on script exit #9379). (cmb, Christian Schneider) + . Fixed bug GH-9447 (Invalid class FQN emitted by AST dump for new and class + constants in constant expressions). (ilutov) - DOM: . Fixed bug #79451 (DOMDocument->replaceChild on doctype causes double free). diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c index d0a180ee6a9c1..07cb9c5fbb7c0 100644 --- a/Zend/zend_ast.c +++ b/Zend/zend_ast.c @@ -482,7 +482,7 @@ static zend_result zend_ast_add_unpacked_element(zval *result, zval *expr) { zend_class_entry *zend_ast_fetch_class(zend_ast *ast, zend_class_entry *scope) { - return zend_fetch_class_with_scope(zend_ast_get_str(ast), ast->attr | ZEND_FETCH_CLASS_EXCEPTION, scope); + return zend_fetch_class_with_scope(zend_ast_get_str(ast), (ast->attr >> ZEND_CONST_EXPR_NEW_FETCH_TYPE_SHIFT) | ZEND_FETCH_CLASS_EXCEPTION, scope); } ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *scope) diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 4a49687415c1a..8157ea169c820 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -9738,8 +9738,8 @@ static void zend_compile_const_expr_class_const(zend_ast **ast_ptr) /* {{{ */ zend_string_release_ex(class_name, 0); if (tmp != class_name) { zval *zv = zend_ast_get_zval(class_ast); - ZVAL_STR(zv, tmp); + class_ast->attr = ZEND_NAME_FQ; } } @@ -9834,7 +9834,7 @@ static void zend_compile_const_expr_new(zend_ast **ast_ptr) zval *class_ast_zv = zend_ast_get_zval(class_ast); zval_ptr_dtor_nogc(class_ast_zv); ZVAL_STR(class_ast_zv, class_name); - class_ast->attr = fetch_type; + class_ast->attr = fetch_type << ZEND_CONST_EXPR_NEW_FETCH_TYPE_SHIFT; } static void zend_compile_const_expr_args(zend_ast **ast_ptr) diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index d396f3530a522..ac304ac7f6ae9 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -917,6 +917,9 @@ ZEND_API zend_string *zend_type_to_string(zend_type type); #define ZEND_NAME_NOT_FQ 1 #define ZEND_NAME_RELATIVE 2 +/* ZEND_FETCH_ flags in class name AST of new const expression must not clash with ZEND_NAME_ flags */ +#define ZEND_CONST_EXPR_NEW_FETCH_TYPE_SHIFT 2 + #define ZEND_TYPE_NULLABLE (1<<8) #define ZEND_ARRAY_SYNTAX_LIST 1 /* list() */ diff --git a/ext/reflection/tests/gh9447.phpt b/ext/reflection/tests/gh9447.phpt new file mode 100644 index 0000000000000..9ee908329733a --- /dev/null +++ b/ext/reflection/tests/gh9447.phpt @@ -0,0 +1,39 @@ +--TEST-- +GH-9447: Invalid class FQN emitted by AST dump for new and class constants in constant expressions +--FILE-- +getParameters() as $p) { + echo $p, "\n"; +} + +?> +--EXPECT-- +Parameter #0 [ $a = \App\Bar::BAZ ] +Parameter #1 [ $b = new \App\Bar() ] +Parameter #2 [ $c = new parent() ] +Parameter #3 [ $d = new self() ] +Parameter #4 [ $e = new \App\Bar() ] +Parameter #5 [ $f = new \SomewhereElse\Qux() ] +Parameter #6 [ $g = new \App\Qux() ] +Parameter #7 [ $i = new \Qux() ] From 93f11d84294d7eaadb9d9fc3c0996ff30279011d Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 2 Sep 2022 13:32:50 +0200 Subject: [PATCH 39/61] Fix GH-8932: Provide a way to get the called-scope of closures (#9299) Co-authored-by: Christoph M. Becker --- ext/reflection/php_reflection.c | 22 ++++++ ext/reflection/php_reflection.stub.php | 3 + ext/reflection/php_reflection_arginfo.h | 6 +- ...lectionFunction_getClosureCalledClass.phpt | 70 +++++++++++++++++++ 4 files changed, 100 insertions(+), 1 deletion(-) create mode 100644 ext/reflection/tests/ReflectionFunction_getClosureCalledClass.phpt diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index e6c63b852e096..ae5b0f1ac246e 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -1633,6 +1633,28 @@ ZEND_METHOD(ReflectionFunctionAbstract, getClosureScopeClass) } /* }}} */ +/* {{{ Returns the called scope associated to the closure */ +ZEND_METHOD(ReflectionFunctionAbstract, getClosureCalledClass) +{ + reflection_object *intern; + + if (zend_parse_parameters_none() == FAILURE) { + RETURN_THROWS(); + } + GET_REFLECTION_OBJECT(); + if (!Z_ISUNDEF(intern->obj)) { + zend_class_entry *called_scope; + zend_function *closure_func; + zend_object *object; + if (Z_OBJ_HANDLER(intern->obj, get_closure) + && Z_OBJ_HANDLER(intern->obj, get_closure)(Z_OBJ(intern->obj), &called_scope, &closure_func, &object, 1) == SUCCESS + && closure_func && (called_scope || closure_func->common.scope)) { + zend_reflection_class_factory(called_scope ? (zend_class_entry *) called_scope : closure_func->common.scope, return_value); + } + } +} +/* }}} */ + /* {{{ Returns a dynamically created closure for the function */ ZEND_METHOD(ReflectionFunction, getClosure) { diff --git a/ext/reflection/php_reflection.stub.php b/ext/reflection/php_reflection.stub.php index b0bfade520f10..31d8d0530c95c 100644 --- a/ext/reflection/php_reflection.stub.php +++ b/ext/reflection/php_reflection.stub.php @@ -48,6 +48,9 @@ public function getClosureThis() {} /** @return ReflectionClass|null */ public function getClosureScopeClass() {} + /** @return ReflectionClass|null */ + public function getClosureCalledClass() {} + /** @return string|false */ public function getDocComment() {} diff --git a/ext/reflection/php_reflection_arginfo.h b/ext/reflection/php_reflection_arginfo.h index 6fdc0c44d22ee..788485b2dd701 100644 --- a/ext/reflection/php_reflection_arginfo.h +++ b/ext/reflection/php_reflection_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 6e98777552147f4a413db16ecd87c9a6931f9c00 */ + * Stub hash: 9309c0d567aae3041255b5f9b9782add9b6ac783 */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Reflection_getModifierNames, 0, 0, 1) ZEND_ARG_TYPE_INFO(0, modifiers, IS_LONG, 0) @@ -27,6 +27,8 @@ ZEND_END_ARG_INFO() #define arginfo_class_ReflectionFunctionAbstract_getClosureScopeClass arginfo_class_ReflectionFunctionAbstract_inNamespace +#define arginfo_class_ReflectionFunctionAbstract_getClosureCalledClass arginfo_class_ReflectionFunctionAbstract_inNamespace + #define arginfo_class_ReflectionFunctionAbstract_getDocComment arginfo_class_ReflectionFunctionAbstract_inNamespace #define arginfo_class_ReflectionFunctionAbstract_getEndLine arginfo_class_ReflectionFunctionAbstract_inNamespace @@ -501,6 +503,7 @@ ZEND_METHOD(ReflectionFunctionAbstract, isGenerator); ZEND_METHOD(ReflectionFunctionAbstract, isVariadic); ZEND_METHOD(ReflectionFunctionAbstract, getClosureThis); ZEND_METHOD(ReflectionFunctionAbstract, getClosureScopeClass); +ZEND_METHOD(ReflectionFunctionAbstract, getClosureCalledClass); ZEND_METHOD(ReflectionFunctionAbstract, getDocComment); ZEND_METHOD(ReflectionFunctionAbstract, getEndLine); ZEND_METHOD(ReflectionFunctionAbstract, getExtension); @@ -719,6 +722,7 @@ static const zend_function_entry class_ReflectionFunctionAbstract_methods[] = { ZEND_ME(ReflectionFunctionAbstract, isVariadic, arginfo_class_ReflectionFunctionAbstract_isVariadic, ZEND_ACC_PUBLIC) ZEND_ME(ReflectionFunctionAbstract, getClosureThis, arginfo_class_ReflectionFunctionAbstract_getClosureThis, ZEND_ACC_PUBLIC) ZEND_ME(ReflectionFunctionAbstract, getClosureScopeClass, arginfo_class_ReflectionFunctionAbstract_getClosureScopeClass, ZEND_ACC_PUBLIC) + ZEND_ME(ReflectionFunctionAbstract, getClosureCalledClass, arginfo_class_ReflectionFunctionAbstract_getClosureCalledClass, ZEND_ACC_PUBLIC) ZEND_ME(ReflectionFunctionAbstract, getDocComment, arginfo_class_ReflectionFunctionAbstract_getDocComment, ZEND_ACC_PUBLIC) ZEND_ME(ReflectionFunctionAbstract, getEndLine, arginfo_class_ReflectionFunctionAbstract_getEndLine, ZEND_ACC_PUBLIC) ZEND_ME(ReflectionFunctionAbstract, getExtension, arginfo_class_ReflectionFunctionAbstract_getExtension, ZEND_ACC_PUBLIC) diff --git a/ext/reflection/tests/ReflectionFunction_getClosureCalledClass.phpt b/ext/reflection/tests/ReflectionFunction_getClosureCalledClass.phpt new file mode 100644 index 0000000000000..3c556c2e37cd4 --- /dev/null +++ b/ext/reflection/tests/ReflectionFunction_getClosureCalledClass.phpt @@ -0,0 +1,70 @@ +--TEST-- +GH-8932 (Provide a way to get the called-scope of closures) +--FILE-- +'.$name, "\n"; + } + + public static function b() { + echo static::class.'::b', "\n"; + } + + + public function c() { + echo static::class.'->c', "\n"; + } +} + +class B extends A {} + +$c = ['B', 'b']; +$d = \Closure::fromCallable($c); +$r = new \ReflectionFunction($d); +var_dump($r->getClosureCalledClass()); +$d(); + +$c = [new B(), 'c']; +$d = \Closure::fromCallable($c); +$r = new \ReflectionFunction($d); +var_dump($r->getClosureCalledClass()); +$d(); + +$c = ['B', 'd']; +$d = \Closure::fromCallable($c); +$r = new \ReflectionFunction($d); +var_dump($r->getClosureCalledClass()); +$d(); + +$c = [new B(), 'e']; +$d = \Closure::fromCallable($c); +$r = new \ReflectionFunction($d); +var_dump($r->getClosureCalledClass()); +$d(); +?> +--EXPECTF-- +object(ReflectionClass)#%d (1) { + ["name"]=> + string(1) "B" +} +B::b +object(ReflectionClass)#%d (1) { + ["name"]=> + string(1) "B" +} +B->c +object(ReflectionClass)#%d (1) { + ["name"]=> + string(1) "B" +} +B::d +object(ReflectionClass)#%d (1) { + ["name"]=> + string(1) "B" +} +B->e From db1ef9720925424c549bfd06cc5f434eea1f1173 Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Fri, 2 Sep 2022 13:14:55 +0200 Subject: [PATCH 40/61] Add tests --- ...lectionFunction_getClosureCalledClass.phpt | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/ext/reflection/tests/ReflectionFunction_getClosureCalledClass.phpt b/ext/reflection/tests/ReflectionFunction_getClosureCalledClass.phpt index 3c556c2e37cd4..ab06a6472e0c1 100644 --- a/ext/reflection/tests/ReflectionFunction_getClosureCalledClass.phpt +++ b/ext/reflection/tests/ReflectionFunction_getClosureCalledClass.phpt @@ -19,6 +19,12 @@ class A { public function c() { echo static::class.'->c', "\n"; } + + public function makeClosure() { + return function () { + echo static::class.'::{closure}'."\n"; + }; + } } class B extends A {} @@ -46,6 +52,26 @@ $d = \Closure::fromCallable($c); $r = new \ReflectionFunction($d); var_dump($r->getClosureCalledClass()); $d(); + +$c = ['A', 'b']; +$d = \Closure::fromCallable($c); +$r = new \ReflectionFunction($d); +var_dump($r->getClosureCalledClass()); +$d(); + +$b = new B(); +$d = $b->makeClosure(); +$r = new \ReflectionFunction($d); +var_dump($r->getClosureCalledClass()); +$d(); + +$d = function () { + echo "{closure}\n"; +}; +$r = new \ReflectionFunction($d); +var_dump($r->getClosureCalledClass()); +$d(); + ?> --EXPECTF-- object(ReflectionClass)#%d (1) { @@ -68,3 +94,15 @@ object(ReflectionClass)#%d (1) { string(1) "B" } B->e +object(ReflectionClass)#%d (1) { + ["name"]=> + string(1) "A" +} +A::b +object(ReflectionClass)#%d (1) { + ["name"]=> + string(1) "B" +} +B::{closure} +NULL +{closure} From 6aedc5eaf003967bbf0ce8b95ebe8fa7766c0a4a Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Fri, 2 Sep 2022 13:40:31 +0200 Subject: [PATCH 41/61] [ci skip] NEWS --- NEWS | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS b/NEWS index 81762e523fe64..805dec249ad86 100644 --- a/NEWS +++ b/NEWS @@ -18,6 +18,10 @@ PHP NEWS . Fixed bug #77780 ("Headers already sent..." when previous connection was aborted). (Jakub Zelenka) +- Reflection: + . Fixed bug GH-8932 (ReflectionFunction provides no way to get the called + class of a Closure). (cmb, Nicolas Grekas) + - Streams: . Fixed bug GH-9316 ($http_response_header is wrong for long status line). (cmb, timwolla) From 6deddd39500916870e4a0fda32783b6489c79d4e Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Fri, 2 Sep 2022 13:53:20 +0200 Subject: [PATCH 42/61] [ci skip] NEWS --- NEWS | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS b/NEWS index f263798514391..b05aaaa635d60 100644 --- a/NEWS +++ b/NEWS @@ -23,6 +23,10 @@ PHP NEWS - PCRE: . Fixed pcre.jit on Apple Silicon. (Niklas Keller) +- Reflection: + . Fixed bug GH-8932 (ReflectionFunction provides no way to get the called + class of a Closure). (cmb, Nicolas Grekas) + - Streams: . Fixed bug GH-9316 ($http_response_header is wrong for long status line). (cmb, timwolla) From 81cb005ef7787954b4adab3543e3c443f9dd293e Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 5 Sep 2022 12:55:50 +0300 Subject: [PATCH 43/61] Fix type inference Fixes oss-fuzz #50792 --- ext/opcache/Optimizer/zend_inference.c | 3 +++ .../tests/jit/fetch_dim_func_arg_002.phpt | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 ext/opcache/tests/jit/fetch_dim_func_arg_002.phpt diff --git a/ext/opcache/Optimizer/zend_inference.c b/ext/opcache/Optimizer/zend_inference.c index 1eed2b9c1217c..559997a3ea293 100644 --- a/ext/opcache/Optimizer/zend_inference.c +++ b/ext/opcache/Optimizer/zend_inference.c @@ -3319,6 +3319,9 @@ static zend_always_inline int _zend_update_type_info( opline->op1_type, opline->result_type == IS_VAR, opline->op2_type == IS_UNUSED); + if (opline->opcode == ZEND_FETCH_DIM_FUNC_ARG && (t1 & (MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE|MAY_BE_RESOURCE))) { + tmp |= MAY_BE_NULL; + } if (opline->opcode == ZEND_FETCH_DIM_IS && (t1 & MAY_BE_STRING)) { tmp |= MAY_BE_NULL; } diff --git a/ext/opcache/tests/jit/fetch_dim_func_arg_002.phpt b/ext/opcache/tests/jit/fetch_dim_func_arg_002.phpt new file mode 100644 index 0000000000000..a80fb0b2bc5c4 --- /dev/null +++ b/ext/opcache/tests/jit/fetch_dim_func_arg_002.phpt @@ -0,0 +1,18 @@ +--TEST-- +JIT FETCH_DIM_FUNC_ARG: 002 +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit_buffer_size=1M +--SKIPIF-- + +--FILE-- + +DONE +--EXPECTF-- +Warning: Trying to access array offset on value of type bool in %sfetch_dim_func_arg_002.php on line 2 +DONE From 59180b50b39c1222b63572f8dd7a5942126dbacf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Kocsis?= Date: Mon, 5 Sep 2022 12:37:53 +0200 Subject: [PATCH 44/61] Fix inexistent skipif.inc --- ext/opcache/tests/jit/fetch_dim_func_arg_002.phpt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/opcache/tests/jit/fetch_dim_func_arg_002.phpt b/ext/opcache/tests/jit/fetch_dim_func_arg_002.phpt index a80fb0b2bc5c4..3699eba2045f0 100644 --- a/ext/opcache/tests/jit/fetch_dim_func_arg_002.phpt +++ b/ext/opcache/tests/jit/fetch_dim_func_arg_002.phpt @@ -5,8 +5,8 @@ opcache.enable=1 opcache.enable_cli=1 opcache.file_update_protection=0 opcache.jit_buffer_size=1M ---SKIPIF-- - +--EXTENSIONS-- +opcache --FILE-- Date: Mon, 5 Sep 2022 14:53:33 +0200 Subject: [PATCH 45/61] Fix GH-9411: PgSQL large object resource is incorrectly closed Co-authored-by: Christoph M. Becker Closes GH-9411. --- NEWS | 4 +++ ext/pdo_pgsql/pgsql_driver.c | 47 +++++++++++++++++++++++++++---- ext/pdo_pgsql/pgsql_statement.c | 6 ++++ ext/pdo_pgsql/php_pdo_pgsql_int.h | 2 ++ ext/pdo_pgsql/tests/gh9411.phpt | 41 +++++++++++++++++++++++++++ 5 files changed, 95 insertions(+), 5 deletions(-) create mode 100644 ext/pdo_pgsql/tests/gh9411.phpt diff --git a/NEWS b/NEWS index 805dec249ad86..3e85f1483ec93 100644 --- a/NEWS +++ b/NEWS @@ -18,6 +18,10 @@ PHP NEWS . Fixed bug #77780 ("Headers already sent..." when previous connection was aborted). (Jakub Zelenka) +- PDO_PGSQL: + . Fixed bug GH-9411 (PgSQL large object resource is incorrectly closed). + (Yurunsoft) + - Reflection: . Fixed bug GH-8932 (ReflectionFunction provides no way to get the called class of a Closure). (cmb, Nicolas Grekas) diff --git a/ext/pdo_pgsql/pgsql_driver.c b/ext/pdo_pgsql/pgsql_driver.c index b6449095ca0cb..c90ef468907eb 100644 --- a/ext/pdo_pgsql/pgsql_driver.c +++ b/ext/pdo_pgsql/pgsql_driver.c @@ -35,6 +35,8 @@ #include "zend_exceptions.h" #include "pgsql_driver_arginfo.h" +static int pgsql_handle_in_transaction(pdo_dbh_t *dbh); + static char * _pdo_pgsql_trim_message(const char *message, int persistent) { register int i = strlen(message)-1; @@ -141,10 +143,12 @@ static ssize_t pgsql_lob_read(php_stream *stream, char *buf, size_t count) static int pgsql_lob_close(php_stream *stream, int close_handle) { struct pdo_pgsql_lob_self *self = (struct pdo_pgsql_lob_self*)stream->abstract; + pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)(Z_PDO_DBH_P(&self->dbh))->driver_data; if (close_handle) { lo_close(self->conn, self->lfd); } + zend_hash_index_del(H->lob_streams, php_stream_get_resource_id(stream)); zval_ptr_dtor(&self->dbh); efree(self); return 0; @@ -195,6 +199,7 @@ php_stream *pdo_pgsql_create_lob_stream(zval *dbh, int lfd, Oid oid) if (stm) { Z_ADDREF_P(dbh); + zend_hash_index_add_ptr(H->lob_streams, php_stream_get_resource_id(stm), stm->res); return stm; } @@ -203,10 +208,29 @@ php_stream *pdo_pgsql_create_lob_stream(zval *dbh, int lfd, Oid oid) } /* }}} */ +void pdo_pgsql_close_lob_streams(pdo_dbh_t *dbh) +{ + zend_resource *res; + pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data; + if (H->lob_streams) { + ZEND_HASH_REVERSE_FOREACH_PTR(H->lob_streams, res) { + if (res->type >= 0) { + zend_list_close(res); + } + } ZEND_HASH_FOREACH_END(); + } +} + static int pgsql_handle_closer(pdo_dbh_t *dbh) /* {{{ */ { pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data; if (H) { + if (H->lob_streams) { + pdo_pgsql_close_lob_streams(dbh); + zend_hash_destroy(H->lob_streams); + pefree(H->lob_streams, dbh->is_persistent); + H->lob_streams = NULL; + } if (H->server) { PQfinish(H->server); H->server = NULL; @@ -298,6 +322,8 @@ static zend_long pgsql_handle_doer(pdo_dbh_t *dbh, const char *sql, size_t sql_l zend_long ret = 1; ExecStatusType qs; + bool in_trans = pgsql_handle_in_transaction(dbh); + if (!(res = PQexec(H->server, sql))) { /* fatal error */ pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, NULL); @@ -316,6 +342,9 @@ static zend_long pgsql_handle_doer(pdo_dbh_t *dbh, const char *sql, size_t sql_l ret = Z_L(0); } PQclear(res); + if (in_trans && !pgsql_handle_in_transaction(dbh)) { + pdo_pgsql_close_lob_streams(dbh); + } return ret; } @@ -501,9 +530,7 @@ static int pdo_pgsql_check_liveness(pdo_dbh_t *dbh) static int pgsql_handle_in_transaction(pdo_dbh_t *dbh) { - pdo_pgsql_db_handle *H; - - H = (pdo_pgsql_db_handle *)dbh->driver_data; + pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data; return PQtransactionStatus(H->server) > PQTRANS_IDLE; } @@ -536,7 +563,9 @@ static int pgsql_handle_commit(pdo_dbh_t *dbh) /* When deferred constraints are used the commit could fail, and a ROLLBACK implicitly ran. See bug #67462 */ - if (!ret) { + if (ret) { + pdo_pgsql_close_lob_streams(dbh); + } else { dbh->in_txn = pgsql_handle_in_transaction(dbh); } @@ -545,7 +574,13 @@ static int pgsql_handle_commit(pdo_dbh_t *dbh) static int pgsql_handle_rollback(pdo_dbh_t *dbh) { - return pdo_pgsql_transaction_cmd("ROLLBACK", dbh); + int ret = pdo_pgsql_transaction_cmd("ROLLBACK", dbh); + + if (ret) { + pdo_pgsql_close_lob_streams(dbh); + } + + return ret; } /* {{{ Returns true if the copy worked fine or false if error */ @@ -1233,6 +1268,8 @@ static int pdo_pgsql_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* {{{ } H->server = PQconnectdb(conn_str); + H->lob_streams = (HashTable *) pemalloc(sizeof(HashTable), dbh->is_persistent); + zend_hash_init(H->lob_streams, 0, NULL, NULL, 1); if (tmp_user) { zend_string_release_ex(tmp_user, 0); diff --git a/ext/pdo_pgsql/pgsql_statement.c b/ext/pdo_pgsql/pgsql_statement.c index 21f4c83807ea0..4c32ac80e8d07 100644 --- a/ext/pdo_pgsql/pgsql_statement.c +++ b/ext/pdo_pgsql/pgsql_statement.c @@ -134,6 +134,8 @@ static int pgsql_stmt_execute(pdo_stmt_t *stmt) pdo_pgsql_db_handle *H = S->H; ExecStatusType status; + bool in_trans = stmt->dbh->methods->in_transaction(stmt->dbh); + /* ensure that we free any previous unfetched results */ if(S->result) { PQclear(S->result); @@ -252,6 +254,10 @@ static int pgsql_stmt_execute(pdo_stmt_t *stmt) stmt->row_count = (zend_long)PQntuples(S->result); } + if (in_trans && !stmt->dbh->methods->in_transaction(stmt->dbh)) { + pdo_pgsql_close_lob_streams(stmt->dbh); + } + return 1; } diff --git a/ext/pdo_pgsql/php_pdo_pgsql_int.h b/ext/pdo_pgsql/php_pdo_pgsql_int.h index bc31c9cdeee0f..eea1ad647eed1 100644 --- a/ext/pdo_pgsql/php_pdo_pgsql_int.h +++ b/ext/pdo_pgsql/php_pdo_pgsql_int.h @@ -45,6 +45,7 @@ typedef struct { zend_bool emulate_prepares; zend_bool disable_native_prepares; /* deprecated since 5.6 */ zend_bool disable_prepares; + HashTable *lob_streams; } pdo_pgsql_db_handle; typedef struct { @@ -109,5 +110,6 @@ php_stream *pdo_pgsql_create_lob_stream(zval *pdh, int lfd, Oid oid); extern const php_stream_ops pdo_pgsql_lob_stream_ops; void pdo_libpq_version(char *buf, size_t len); +void pdo_pgsql_close_lob_streams(pdo_dbh_t *dbh); #endif /* PHP_PDO_PGSQL_INT_H */ diff --git a/ext/pdo_pgsql/tests/gh9411.phpt b/ext/pdo_pgsql/tests/gh9411.phpt new file mode 100644 index 0000000000000..c8a11e89df627 --- /dev/null +++ b/ext/pdo_pgsql/tests/gh9411.phpt @@ -0,0 +1,41 @@ +--TEST-- +Bug GH-9411 (PgSQL large object resource is incorrectly closed) +--SKIPIF-- + +--FILE-- +setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); +$db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false); + +$db->beginTransaction(); +$oid = $db->pgsqlLOBCreate(); +var_dump($lob = $db->pgsqlLOBOpen($oid, 'wb')); +fwrite($lob, 'test'); +$db->rollback(); +var_dump($lob); + +$db->beginTransaction(); +$oid = $db->pgsqlLOBCreate(); +var_dump($lob = $db->pgsqlLOBOpen($oid, 'wb')); +fwrite($lob, 'test'); +$db->commit(); +var_dump($lob); + +$db->beginTransaction(); +var_dump($lob = $db->pgsqlLOBOpen($oid, 'wb')); +var_dump(fgets($lob)); +?> +--EXPECTF-- +resource(%d) of type (stream) +resource(%d) of type (Unknown) +resource(%d) of type (stream) +resource(%d) of type (Unknown) +resource(%d) of type (stream) +string(4) "test" From 1435fc6262749d3f9861ef41a3d63825bac8ca2c Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Fri, 2 Sep 2022 16:12:38 +0200 Subject: [PATCH 46/61] Private method incorrectly marked as "overwrites" in reflection Fix GH-9409 Closes GH-9469 --- NEWS | 2 ++ ext/reflection/php_reflection.c | 2 +- .../tests/ReflectionClass_toString_003.phpt | 4 ++-- ext/reflection/tests/gh9409.phpt | 24 +++++++++++++++++++ 4 files changed, 29 insertions(+), 3 deletions(-) create mode 100644 ext/reflection/tests/gh9409.phpt diff --git a/NEWS b/NEWS index 3e85f1483ec93..cbf0dd418bd16 100644 --- a/NEWS +++ b/NEWS @@ -25,6 +25,8 @@ PHP NEWS - Reflection: . Fixed bug GH-8932 (ReflectionFunction provides no way to get the called class of a Closure). (cmb, Nicolas Grekas) + . Fixed bug GH-9409 (Private method is incorrectly dumped as "overwrites"). + (ilutov) - Streams: . Fixed bug GH-9316 ($http_response_header is wrong for long status line). diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index ae5b0f1ac246e..de3c9602fd37f 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -784,7 +784,7 @@ static void _function_string(smart_str *str, zend_function *fptr, zend_class_ent } else if (fptr->common.scope->parent) { lc_name = zend_string_tolower(fptr->common.function_name); if ((overwrites = zend_hash_find_ptr(&fptr->common.scope->parent->function_table, lc_name)) != NULL) { - if (fptr->common.scope != overwrites->common.scope) { + if (fptr->common.scope != overwrites->common.scope && !(overwrites->common.fn_flags & ZEND_ACC_PRIVATE)) { smart_str_append_printf(str, ", overwrites %s", ZSTR_VAL(overwrites->common.scope->name)); } } diff --git a/ext/reflection/tests/ReflectionClass_toString_003.phpt b/ext/reflection/tests/ReflectionClass_toString_003.phpt index a67d0bfac5fe3..4d488325eebbf 100644 --- a/ext/reflection/tests/ReflectionClass_toString_003.phpt +++ b/ext/reflection/tests/ReflectionClass_toString_003.phpt @@ -66,7 +66,7 @@ Class [ class B extends A ] { } - Methods [1] { - Method [ private method f ] { + Method [ private method f ] { @@ %s 6 - 6 } } @@ -111,7 +111,7 @@ Class [ class D extends C ] { } - Methods [1] { - Method [ private method f ] { + Method [ private method f ] { @@ %s 12 - 12 } } diff --git a/ext/reflection/tests/gh9409.phpt b/ext/reflection/tests/gh9409.phpt new file mode 100644 index 0000000000000..a10e7b5303a77 --- /dev/null +++ b/ext/reflection/tests/gh9409.phpt @@ -0,0 +1,24 @@ +--TEST-- +GH-9409: Private method is incorrectly dumped as "overwrites" +--FILE-- +getMethod('privateMethod'); +echo (new ReflectionClass('C'))->getMethod('privateMethod'); + +?> +--EXPECTF-- +Method [ private method privateMethod ] { + @@ %s %d - %d +} +Method [ private method privateMethod ] { + @@ %s %d - %d +} From d5373eac460517d0a7a090a34ee259936cb40fa7 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Fri, 2 Sep 2022 17:10:09 +0200 Subject: [PATCH 47/61] Fix lsp error in eval'd code referring to incorrect class for static type Fixes GH-9407 Closes GH-9471 --- NEWS | 2 ++ Zend/tests/gh9407.phpt | 24 ++++++++++++++++++++++++ Zend/zend_compile.c | 3 ++- 3 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 Zend/tests/gh9407.phpt diff --git a/NEWS b/NEWS index cbf0dd418bd16..86b61f62a70d8 100644 --- a/NEWS +++ b/NEWS @@ -7,6 +7,8 @@ PHP NEWS (Tim Starling) . Fixed bug GH-9361 (Segmentation fault on script exit #9379). (cmb, Christian Schneider) + . Fixed bug GH-9407 (LSP error in eval'd code refers to wrong class for static + type). (ilutov) - DOM: . Fixed bug #79451 (DOMDocument->replaceChild on doctype causes double free). diff --git a/Zend/tests/gh9407.phpt b/Zend/tests/gh9407.phpt new file mode 100644 index 0000000000000..6712c9ccc9c3f --- /dev/null +++ b/Zend/tests/gh9407.phpt @@ -0,0 +1,24 @@ +--TEST-- +GH-9407: LSP error in eval'd code refers to wrong class for static type +--FILE-- + +--EXPECTF-- +Fatal error: Declaration of B::duplicate(): A must be compatible with A::duplicate(): static in %s : eval()'d code on line %d diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index cde1758ffc4e2..2a04c49b55f1d 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -1207,7 +1207,8 @@ zend_string *zend_type_to_string_resolved(zend_type type, zend_class_entry *scop } if (type_mask & MAY_BE_STATIC) { zend_string *name = ZSTR_KNOWN(ZEND_STR_STATIC); - if (scope) { + // During compilation of eval'd code the called scope refers to the scope calling the eval + if (scope && !zend_is_compiling()) { zend_class_entry *called_scope = zend_get_called_scope(EG(current_execute_data)); if (called_scope) { name = called_scope->name; From aa7f4497bfd78b0bf3981ce94789a3093b55f92a Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Wed, 7 Sep 2022 22:55:28 +0200 Subject: [PATCH 48/61] Fix undefined left shift in oci The bit is shifted into the signed bit which is undefined. Make the integer explicitly unsigned before shifting. --- ext/oci8/php_oci8_int.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/oci8/php_oci8_int.h b/ext/oci8/php_oci8_int.h index 825437bc5704d..55eb8de6b4b6c 100644 --- a/ext/oci8/php_oci8_int.h +++ b/ext/oci8/php_oci8_int.h @@ -103,7 +103,7 @@ extern zend_class_entry *oci_coll_class_entry_ptr; * PHP_OCI_CRED_EXT must be distinct from the OCI_xxx privilege * values. */ -#define PHP_OCI_CRED_EXT (1<<31) +#define PHP_OCI_CRED_EXT (1u<<31) #if ((PHP_OCI_CRED_EXT == OCI_DEFAULT) || (PHP_OCI_CRED_EXT & (OCI_SYSOPER | OCI_SYSDBA))) #error Invalid value for PHP_OCI_CRED_EXT #endif From 4a8cca241f5eb01452398e8b32eb42218b0838bc Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 8 Sep 2022 00:45:28 +0200 Subject: [PATCH 49/61] Skip oci tests that leak under asan --- ext/oci8/tests/privileged_connect1.phpt | 5 ++++- ext/pdo_oci/tests/pecl_bug_6364.phpt | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ext/oci8/tests/privileged_connect1.phpt b/ext/oci8/tests/privileged_connect1.phpt index 762ce5ece530b..816f3fe7594bd 100644 --- a/ext/oci8/tests/privileged_connect1.phpt +++ b/ext/oci8/tests/privileged_connect1.phpt @@ -1,7 +1,10 @@ --TEST-- privileged connect tests --SKIPIF-- - + --INI-- oci8.privileged_connect=1 --FILE-- diff --git a/ext/pdo_oci/tests/pecl_bug_6364.phpt b/ext/pdo_oci/tests/pecl_bug_6364.phpt index affdc77649e43..f8da1356659e2 100644 --- a/ext/pdo_oci/tests/pecl_bug_6364.phpt +++ b/ext/pdo_oci/tests/pecl_bug_6364.phpt @@ -3,6 +3,7 @@ PECL PDO_OCI Bug #6364 (segmentation fault on stored procedure call with OUT bin --SKIPIF-- From 466e4dc2a2946aa903bdbb98941b435ac1935a7e Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Fri, 9 Sep 2022 10:50:03 +0200 Subject: [PATCH 50/61] Check return value of zend_jit_trace_get_exit_addr() (#9097) --- ext/opcache/jit/zend_jit_arm64.dasc | 30 ++++++++++++++++++++++++++++ ext/opcache/jit/zend_jit_x86.dasc | 31 +++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/ext/opcache/jit/zend_jit_arm64.dasc b/ext/opcache/jit/zend_jit_arm64.dasc index f623e07c83f4d..d2a8fead2672e 100644 --- a/ext/opcache/jit/zend_jit_arm64.dasc +++ b/ext/opcache/jit/zend_jit_arm64.dasc @@ -2997,6 +2997,9 @@ static int zend_jit_trace_end(dasm_State **Dst, zend_jit_trace_info *t) |.cold_code for (i = 0; i < t->exit_count; i++) { exit_addr = zend_jit_trace_get_exit_addr(i); + if (!exit_addr) { + return 0; + } | b &exit_addr } |=>1: // end of the code @@ -3809,6 +3812,9 @@ static int zend_jit_inc_dec(dasm_State **Dst, const zend_op *opline, uint32_t op exit_point = zend_jit_trace_get_exit_point(opline + 1, 0); exit_addr = zend_jit_trace_get_exit_addr(exit_point); + if (!exit_addr) { + return 0; + } | bvs &exit_addr if ((opline->opcode == ZEND_PRE_INC || opline->opcode == ZEND_PRE_DEC) && @@ -4111,6 +4117,9 @@ static int zend_jit_math_long_long(dasm_State **Dst, if (res_info & MAY_BE_GUARD) { int32_t exit_point = zend_jit_trace_get_exit_point(opline, 0); const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point); + if (!exit_addr) { + return 0; + } if ((res_info & MAY_BE_ANY) == MAY_BE_LONG) { if (use_ovf_flag) { | bvs &exit_addr @@ -6319,6 +6328,9 @@ static int zend_jit_assign_dim_op(dasm_State **Dst, const zend_op *opline, uint3 && !(op2_info & ((MAY_BE_ANY|MAY_BE_UNDEF) - (MAY_BE_LONG|MAY_BE_STRING)))) { int32_t exit_point = zend_jit_trace_get_exit_point(opline, 0); not_found_exit_addr = zend_jit_trace_get_exit_addr(exit_point); + if (!not_found_exit_addr) { + return 0; + } } if (!zend_jit_fetch_dimension_address_inner(Dst, opline, BP_VAR_RW, op1_info, op2_info, dim_type, NULL, not_found_exit_addr, NULL)) { @@ -12498,6 +12510,9 @@ static int zend_jit_fetch_obj(dasm_State **Dst, && (op1_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_OBJECT) { exit_point = zend_jit_trace_get_exit_point(opline, 0); exit_addr = zend_jit_trace_get_exit_addr(exit_point); + if (!exit_addr) { + return 0; + } } else { val_addr = ZEND_ADDR_MEM_ZVAL(ZREG_REG0, 0); | LOAD_ZVAL_ADDR REG0, prop_addr @@ -12888,6 +12903,9 @@ static int zend_jit_incdec_obj(dasm_State **Dst, if (use_prop_guard) { int32_t exit_point = zend_jit_trace_get_exit_point(opline, 0); const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point); + if (!exit_addr) { + return 0; + } | IF_NOT_ZVAL_TYPE var_addr, prop_type, &exit_addr, ZREG_TMP1 var_info = (1 << prop_type) | (var_info & ~(MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)); @@ -13027,6 +13045,9 @@ static int zend_jit_incdec_obj(dasm_State **Dst, SET_STACK_TYPE(stack, EX_VAR_TO_NUM(opline->result.var), IS_DOUBLE, 0); exit_point = zend_jit_trace_get_exit_point(opline + 1, 0); exit_addr = zend_jit_trace_get_exit_addr(exit_point); + if (!exit_addr) { + return 0; + } SET_STACK_INFO(stack, EX_VAR_TO_NUM(opline->result.var), old_res_info); ssa->var_info[ssa_op->result_def].type = res_info & ~MAY_BE_GUARD; | b &exit_addr @@ -13320,6 +13341,9 @@ static int zend_jit_assign_obj_op(dasm_State **Dst, if (use_prop_guard) { int32_t exit_point = zend_jit_trace_get_exit_point(opline, 0); const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point); + if (!exit_addr) { + return 0; + } | IF_NOT_ZVAL_TYPE var_addr, prop_type, &exit_addr, ZREG_TMP1 var_info = (1 << prop_type) | (var_info & ~(MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)); @@ -14095,10 +14119,16 @@ static int zend_jit_switch(dasm_State **Dst, const zend_op *opline, const zend_o if (next_opline != opline + 1) { exit_point = zend_jit_trace_get_exit_point(opline + 1, 0); fallback_label = zend_jit_trace_get_exit_addr(exit_point); + if (!fallback_label) { + return 0; + } } if (next_opline != default_opline) { exit_point = zend_jit_trace_get_exit_point(default_opline, 0); default_label = zend_jit_trace_get_exit_addr(exit_point); + if (!default_label) { + return 0; + } } } diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index 24936e94d3737..ba6e52abbccb0 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -4166,6 +4166,9 @@ static int zend_jit_inc_dec(dasm_State **Dst, const zend_op *opline, uint32_t op exit_point = zend_jit_trace_get_exit_point(opline + 1, 0); exit_addr = zend_jit_trace_get_exit_addr(exit_point); + if (!exit_addr) { + return 0; + } | jo &exit_addr if ((opline->opcode == ZEND_PRE_INC || opline->opcode == ZEND_PRE_DEC) && @@ -4465,6 +4468,9 @@ static int zend_jit_math_long_long(dasm_State **Dst, if (res_info & MAY_BE_GUARD) { int32_t exit_point = zend_jit_trace_get_exit_point(opline, 0); const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point); + if (!exit_addr) { + return 0; + } if ((res_info & MAY_BE_ANY) == MAY_BE_LONG) { | jo &exit_addr if (Z_MODE(res_addr) == IS_REG && result_reg != Z_REG(res_addr)) { @@ -6852,6 +6858,9 @@ static int zend_jit_assign_dim_op(dasm_State **Dst, const zend_op *opline, uint3 && !(op2_info & ((MAY_BE_ANY|MAY_BE_UNDEF) - (MAY_BE_LONG|MAY_BE_STRING)))) { int32_t exit_point = zend_jit_trace_get_exit_point(opline, 0); not_found_exit_addr = zend_jit_trace_get_exit_addr(exit_point); + if (!not_found_exit_addr) { + return 0; + } } if (!zend_jit_fetch_dimension_address_inner(Dst, opline, BP_VAR_RW, op1_info, op2_info, dim_type, NULL, not_found_exit_addr, NULL)) { @@ -13235,6 +13244,9 @@ static int zend_jit_fetch_obj(dasm_State **Dst, && (op1_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_OBJECT) { exit_point = zend_jit_trace_get_exit_point(opline, 0); exit_addr = zend_jit_trace_get_exit_addr(exit_point); + if (!exit_addr) { + return 0; + } } else { val_addr = ZEND_ADDR_MEM_ZVAL(ZREG_R0, 0); | LOAD_ZVAL_ADDR r0, prop_addr @@ -13626,6 +13638,9 @@ static int zend_jit_incdec_obj(dasm_State **Dst, if (use_prop_guard) { int32_t exit_point = zend_jit_trace_get_exit_point(opline, 0); const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point); + if (!exit_addr) { + return 0; + } | IF_NOT_ZVAL_TYPE var_addr, prop_type, &exit_addr var_info = (1 << prop_type) | (var_info & ~(MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)); @@ -13784,6 +13799,9 @@ static int zend_jit_incdec_obj(dasm_State **Dst, SET_STACK_TYPE(stack, EX_VAR_TO_NUM(opline->result.var), IS_DOUBLE, 0); exit_point = zend_jit_trace_get_exit_point(opline + 1, 0); exit_addr = zend_jit_trace_get_exit_addr(exit_point); + if (!exit_addr) { + return 0; + } SET_STACK_INFO(stack, EX_VAR_TO_NUM(opline->result.var), old_res_info); ssa->var_info[ssa_op->result_def].type = res_info & ~MAY_BE_GUARD; | jmp &exit_addr @@ -14107,6 +14125,9 @@ static int zend_jit_assign_obj_op(dasm_State **Dst, if (use_prop_guard) { int32_t exit_point = zend_jit_trace_get_exit_point(opline, 0); const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point); + if (!exit_addr) { + return 0; + } | IF_NOT_ZVAL_TYPE var_addr, prop_type, &exit_addr var_info = (1 << prop_type) | (var_info & ~(MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)); @@ -14807,6 +14828,10 @@ static int zend_jit_fetch_this(dasm_State **Dst, const zend_op *opline, const ze int32_t exit_point = zend_jit_trace_get_exit_point(opline, ZEND_JIT_EXIT_TO_VM); const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point); + if (!exit_addr) { + return 0; + } + | cmp byte EX->This.u1.v.type, IS_OBJECT | jne &exit_addr @@ -14980,10 +15005,16 @@ static int zend_jit_switch(dasm_State **Dst, const zend_op *opline, const zend_o if (next_opline != opline + 1) { exit_point = zend_jit_trace_get_exit_point(opline + 1, 0); fallback_label = zend_jit_trace_get_exit_addr(exit_point); + if (!fallback_label) { + return 0; + } } if (next_opline != default_opline) { exit_point = zend_jit_trace_get_exit_point(default_opline, 0); default_label = zend_jit_trace_get_exit_addr(exit_point); + if (!default_label) { + return 0; + } } } From d0b3096ff0f6f6f491833858f126a80f18b81151 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 12 Sep 2022 11:38:31 +0300 Subject: [PATCH 51/61] Reset FG(user_stream_current_filename) at the end of request Attempt to fix oss-fuzz #51047 --- main/streams/streams.c | 1 + 1 file changed, 1 insertion(+) diff --git a/main/streams/streams.c b/main/streams/streams.c index 7e023e4593f19..62a4359f32d5f 100644 --- a/main/streams/streams.c +++ b/main/streams/streams.c @@ -1665,6 +1665,7 @@ static void stream_resource_persistent_dtor(zend_resource *rsrc) void php_shutdown_stream_hashes(void) { + FG(user_stream_current_filename) = NULL; if (FG(stream_wrappers)) { zend_hash_destroy(FG(stream_wrappers)); efree(FG(stream_wrappers)); From 9af98cd4657bfcfe21f42ab36d9be7de7b2709b2 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Sun, 11 Sep 2022 19:40:20 +0200 Subject: [PATCH 52/61] Fix ZEND_RC_MOD_CHECK() for thread local ini parser strings --- Zend/zend_ini_parser.y | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Zend/zend_ini_parser.y b/Zend/zend_ini_parser.y index 7eb3753520775..58ad4b360bbf6 100644 --- a/Zend/zend_ini_parser.y +++ b/Zend/zend_ini_parser.y @@ -269,6 +269,9 @@ ZEND_API zend_result zend_parse_ini_string(char *str, bool unbuffered_errors, in static void zval_ini_dtor(zval *zv) { if (Z_TYPE_P(zv) == IS_STRING) { + if (ZEND_SYSTEM_INI) { + GC_MAKE_PERSISTENT_LOCAL(Z_STR_P(zv)); + } zend_string_release(Z_STR_P(zv)); } } @@ -324,6 +327,9 @@ statement: printf("NORMAL: '%s' = '%s'\n", Z_STRVAL($1), Z_STRVAL($3)); #endif ZEND_INI_PARSER_CB(&$1, &$3, NULL, ZEND_INI_PARSER_ENTRY, ZEND_INI_PARSER_ARG); + if (ZEND_SYSTEM_INI) { + GC_MAKE_PERSISTENT_LOCAL(Z_STR($1)); + } zend_string_release(Z_STR($1)); zval_ini_dtor(&$3); } From 293e69179d8611bd1e4ae12f28ff3ad9b5fa8377 Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Tue, 6 Sep 2022 11:37:04 +0100 Subject: [PATCH 53/61] Fix GH-9308 GMP throws the wrong error when a GMP object is passed to gmp_init() Closes GH-9490 --- NEWS | 4 +++ ext/gmp/gmp.c | 76 ++++++++++++++++++++++----------------- ext/gmp/tests/gh9308.phpt | 19 ++++++++++ 3 files changed, 66 insertions(+), 33 deletions(-) create mode 100644 ext/gmp/tests/gh9308.phpt diff --git a/NEWS b/NEWS index 86b61f62a70d8..5f584f10ea11c 100644 --- a/NEWS +++ b/NEWS @@ -20,6 +20,10 @@ PHP NEWS . Fixed bug #77780 ("Headers already sent..." when previous connection was aborted). (Jakub Zelenka) +- GMP + . Fixed bug GH-9308 (GMP throws the wrong error when a GMP object is passed + to gmp_init()). (Girgias) + - PDO_PGSQL: . Fixed bug GH-9411 (PgSQL large object resource is incorrectly closed). (Yurunsoft) diff --git a/ext/gmp/gmp.c b/ext/gmp/gmp.c index 4894b09afe442..b6329daeeea0e 100644 --- a/ext/gmp/gmp.c +++ b/ext/gmp/gmp.c @@ -586,6 +586,33 @@ ZEND_MODULE_INFO_D(gmp) } /* }}} */ +static zend_result convert_zstr_to_gmp(mpz_t gmp_number, const zend_string *val, zend_long base, uint32_t arg_pos) +{ + const char *num_str = ZSTR_VAL(val); + bool skip_lead = false; + + if (ZSTR_LEN(val) >= 2 && num_str[0] == '0') { + if ((base == 0 || base == 16) && (num_str[1] == 'x' || num_str[1] == 'X')) { + base = 16; + skip_lead = true; + } else if ((base == 0 || base == 2) && (num_str[1] == 'b' || num_str[1] == 'B')) { + base = 2; + skip_lead = true; + } + } + + int gmp_ret = mpz_set_str(gmp_number, (skip_lead ? &num_str[2] : num_str), (int) base); + if (-1 == gmp_ret) { + if (arg_pos == 0) { + zend_value_error("Number is not an integer string"); + } else { + zend_argument_value_error(arg_pos, "is not an integer string"); + } + return FAILURE; + } + + return SUCCESS; +} /* {{{ convert_to_gmp * Convert zval to be gmp number */ @@ -596,31 +623,7 @@ static zend_result convert_to_gmp(mpz_t gmpnumber, zval *val, zend_long base, ui mpz_set_si(gmpnumber, Z_LVAL_P(val)); return SUCCESS; case IS_STRING: { - char *numstr = Z_STRVAL_P(val); - zend_bool skip_lead = 0; - int ret; - - if (Z_STRLEN_P(val) >= 2 && numstr[0] == '0') { - if ((base == 0 || base == 16) && (numstr[1] == 'x' || numstr[1] == 'X')) { - base = 16; - skip_lead = 1; - } else if ((base == 0 || base == 2) && (numstr[1] == 'b' || numstr[1] == 'B')) { - base = 2; - skip_lead = 1; - } - } - - ret = mpz_set_str(gmpnumber, (skip_lead ? &numstr[2] : numstr), (int) base); - if (-1 == ret) { - if (arg_pos == 0) { - zend_value_error("Number is not an integer string"); - } else { - zend_argument_value_error(arg_pos, "is not an integer string"); - } - return FAILURE; - } - - return SUCCESS; + return convert_zstr_to_gmp(gmpnumber, Z_STR_P(val), base, arg_pos); } default: { zend_long lval; @@ -868,22 +871,29 @@ static inline void _gmp_unary_opl(INTERNAL_FUNCTION_PARAMETERS, gmp_unary_opl_t /* {{{ Initializes GMP number */ ZEND_FUNCTION(gmp_init) { - zval *number_arg; - mpz_ptr gmpnumber; + mpz_ptr gmp_number; + zend_string *arg_str = NULL; + zend_long arg_l = 0; zend_long base = 0; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|l", &number_arg, &base) == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_START(1, 2) + Z_PARAM_STR_OR_LONG(arg_str, arg_l) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(base) + ZEND_PARSE_PARAMETERS_END(); if (base && (base < 2 || base > GMP_MAX_BASE)) { zend_argument_value_error(2, "must be between 2 and %d", GMP_MAX_BASE); RETURN_THROWS(); } - INIT_GMP_RETVAL(gmpnumber); - if (convert_to_gmp(gmpnumber, number_arg, base, 1) == FAILURE) { - RETURN_THROWS(); + INIT_GMP_RETVAL(gmp_number); + if (arg_str) { + if (convert_zstr_to_gmp(gmp_number, arg_str, base, 1) == FAILURE) { + RETURN_THROWS(); + } + } else { + mpz_set_si(gmp_number, arg_l); } } /* }}} */ diff --git a/ext/gmp/tests/gh9308.phpt b/ext/gmp/tests/gh9308.phpt new file mode 100644 index 0000000000000..d12dc598956b0 --- /dev/null +++ b/ext/gmp/tests/gh9308.phpt @@ -0,0 +1,19 @@ +--TEST-- +Bug GH-9308: GMP throws the wrong error when a GMP object is passed to gmp_init() +--SKIPIF-- + +--FILE-- +getMessage(), \PHP_EOL; +} + +?> +--EXPECT-- +gmp_init(): Argument #1 ($num) must be of type string|int, GMP given From 47500f3300d4dab8508cd3f897f5a0b8a4cfa159 Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Tue, 30 Aug 2022 17:16:27 +0100 Subject: [PATCH 54/61] Fix GH-9421 Incorrect argument number for ValueError in NumberFormatter Closes GH-9489 --- NEWS | 4 ++ ext/intl/formatter/formatter_format.c | 13 +++- ext/intl/formatter/formatter_parse.c | 12 +++- .../formatter_format_and_parse_errors.phpt | 65 +++++++++++++++++++ 4 files changed, 91 insertions(+), 3 deletions(-) create mode 100644 ext/intl/tests/formatter_format_and_parse_errors.phpt diff --git a/NEWS b/NEWS index 5f584f10ea11c..e514fbf717b47 100644 --- a/NEWS +++ b/NEWS @@ -24,6 +24,10 @@ PHP NEWS . Fixed bug GH-9308 (GMP throws the wrong error when a GMP object is passed to gmp_init()). (Girgias) +- Intl + . Fixed bug GH-9421 (Incorrect argument number for ValueError in NumberFormatter). + (Girgias) + - PDO_PGSQL: . Fixed bug GH-9411 (PgSQL large object resource is incorrectly closed). (Yurunsoft) diff --git a/ext/intl/formatter/formatter_format.c b/ext/intl/formatter/formatter_format.c index aa9c5915adeb8..7c10e2b668f97 100644 --- a/ext/intl/formatter/formatter_format.c +++ b/ext/intl/formatter/formatter_format.c @@ -103,9 +103,18 @@ PHP_FUNCTION( numfmt_format ) } INTL_METHOD_CHECK_STATUS( nfo, "Number formatting failed" ); break; - + case FORMAT_TYPE_CURRENCY: + if (getThis()) { + const char *space; + const char *class_name = get_active_class_name(&space); + zend_argument_value_error(2, "cannot be NumberFormatter::TYPE_CURRENCY constant, " + "use %s%sformatCurrency() method instead", class_name, space); + } else { + zend_argument_value_error(3, "cannot be NumberFormatter::TYPE_CURRENCY constant, use numfmt_format_currency() function instead"); + } + RETURN_THROWS(); default: - zend_argument_value_error(3, "must be a NumberFormatter::TYPE_* constant"); + zend_argument_value_error(getThis() ? 2 : 3, "must be a NumberFormatter::TYPE_* constant"); RETURN_THROWS(); } diff --git a/ext/intl/formatter/formatter_parse.c b/ext/intl/formatter/formatter_parse.c index 9940cc5fe7bd0..1a0db887328b8 100644 --- a/ext/intl/formatter/formatter_parse.c +++ b/ext/intl/formatter/formatter_parse.c @@ -85,8 +85,18 @@ PHP_FUNCTION( numfmt_parse ) val_double = unum_parseDouble(FORMATTER_OBJECT(nfo), sstr, sstr_len, position_p, &INTL_DATA_ERROR_CODE(nfo)); RETVAL_DOUBLE(val_double); break; + case FORMAT_TYPE_CURRENCY: + if (getThis()) { + const char *space; + const char *class_name = get_active_class_name(&space); + zend_argument_value_error(2, "cannot be NumberFormatter::TYPE_CURRENCY constant, " + "use %s%sparseCurrency() method instead", class_name, space); + } else { + zend_argument_value_error(3, "cannot be NumberFormatter::TYPE_CURRENCY constant, use numfmt_parse_currency() function instead"); + } + goto cleanup; default: - zend_argument_value_error(3, "must be a NumberFormatter::TYPE_* constant"); + zend_argument_value_error(getThis() ? 2 : 3, "must be a NumberFormatter::TYPE_* constant"); goto cleanup; } diff --git a/ext/intl/tests/formatter_format_and_parse_errors.phpt b/ext/intl/tests/formatter_format_and_parse_errors.phpt new file mode 100644 index 0000000000000..061b0eac250af --- /dev/null +++ b/ext/intl/tests/formatter_format_and_parse_errors.phpt @@ -0,0 +1,65 @@ +--TEST-- +ValueErrors for format/parse methods and procedural functions +--SKIPIF-- + +--FILE-- +getMessage(), \PHP_EOL; +} +try { + $o->format($num, -20); +} catch (\ValueError $e) { + echo $e->getMessage(), \PHP_EOL; +} +try { + numfmt_parse($o, $str, -20); +} catch (\ValueError $e) { + echo $e->getMessage(), \PHP_EOL; +} +try { + $o->parse($str, -20); +} catch (\ValueError $e) { + echo $e->getMessage(), \PHP_EOL; +} + +/* With NumberFormatter::TYPE_CURRENCY */ +try { + numfmt_format($o, $num, NumberFormatter::TYPE_CURRENCY); +} catch (\ValueError $e) { + echo $e->getMessage(), \PHP_EOL; +} +try { + $o->format($num, NumberFormatter::TYPE_CURRENCY); +} catch (\ValueError $e) { + echo $e->getMessage(), \PHP_EOL; +} +try { + numfmt_parse($o, $str, NumberFormatter::TYPE_CURRENCY); +} catch (\ValueError $e) { + echo $e->getMessage(), \PHP_EOL; +} +try { + $o->parse($str, NumberFormatter::TYPE_CURRENCY); +} catch (\ValueError $e) { + echo $e->getMessage(), \PHP_EOL; +} + +?> +--EXPECT-- +numfmt_format(): Argument #3 ($type) must be a NumberFormatter::TYPE_* constant +NumberFormatter::format(): Argument #2 ($type) must be a NumberFormatter::TYPE_* constant +numfmt_parse(): Argument #3 ($type) must be a NumberFormatter::TYPE_* constant +NumberFormatter::parse(): Argument #2 ($type) must be a NumberFormatter::TYPE_* constant +numfmt_format(): Argument #3 ($type) cannot be NumberFormatter::TYPE_CURRENCY constant, use numfmt_format_currency() function instead +NumberFormatter::format(): Argument #2 ($type) cannot be NumberFormatter::TYPE_CURRENCY constant, use NumberFormatter::formatCurrency() method instead +numfmt_parse(): Argument #3 ($type) cannot be NumberFormatter::TYPE_CURRENCY constant, use numfmt_parse_currency() function instead +NumberFormatter::parse(): Argument #2 ($type) cannot be NumberFormatter::TYPE_CURRENCY constant, use NumberFormatter::parseCurrency() method instead From 9a73ec03677b7c8a988fdef539ac9b0e69f8ea25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Vo=C5=99=C3=AD=C5=A1ek?= Date: Mon, 12 Sep 2022 22:53:15 +0200 Subject: [PATCH 55/61] Always skip randomly failing OCI8 extauth tests This might be caused by an issue with the Oracle Instant Client libraries[1]; we skip the tests for the time being. [1] Closes GH-9524. --- ext/oci8/tests/extauth_01.phpt | 5 +---- ext/oci8/tests/extauth_02.phpt | 4 +--- ext/oci8/tests/extauth_03.phpt | 4 +--- ext/oci8/tests/extauth_04.phpt | 4 ++-- 4 files changed, 5 insertions(+), 12 deletions(-) diff --git a/ext/oci8/tests/extauth_01.phpt b/ext/oci8/tests/extauth_01.phpt index db23097d82d5b..00c94b67c0d06 100644 --- a/ext/oci8/tests/extauth_01.phpt +++ b/ext/oci8/tests/extauth_01.phpt @@ -4,16 +4,13 @@ Test External Authentication errors with oci_connect --INI-- oci8.privileged_connect=1 --FILE-- --INI-- oci8.privileged_connect=1 --FILE-- --INI-- oci8.privileged_connect=1 --FILE-- +--INI-- +oci8.privileged_connect=1 --FILE-- Date: Mon, 12 Sep 2022 11:36:24 +0200 Subject: [PATCH 56/61] Fix oci_success_with_info.phpt test random failures Closes GH-9525. --- ext/pdo_oci/tests/oci_success_with_info.phpt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ext/pdo_oci/tests/oci_success_with_info.phpt b/ext/pdo_oci/tests/oci_success_with_info.phpt index 144bb816d425c..8c43c46e19681 100644 --- a/ext/pdo_oci/tests/oci_success_with_info.phpt +++ b/ext/pdo_oci/tests/oci_success_with_info.phpt @@ -3,6 +3,10 @@ Handling OCI_SUCCESS_WITH_INFO --EXTENSIONS-- pdo pdo_oci +--SKIPIF-- + --FILE-- exec('CREATE USER BUG77120_USER IDENTIFIED BY "' . $password . '" PROFILE $conn->exec('GRANT CREATE SESSION TO BUG77120_USER'); // let the password expire -sleep(2); +sleep(3); // 2 seconds is causing random test failures $conn = connectAsUser('BUG77120_USER', $password); var_dump($conn->errorInfo()); From 4ef300ff5ee309394e78bd92d6cb9cd47cf4195a Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Mon, 25 Jul 2022 15:58:59 +0200 Subject: [PATCH 57/61] Fix #81726: phar wrapper: DOS when using quine gzip file The phar wrapper needs to uncompress the file; the uncompressed file might be compressed, so the wrapper implementation loops. This raises potential DOS issues regarding too deep or even infinite recursion (the latter are called compressed file quines[1]). We avoid that by introducing a recursion limit; we choose the somewhat arbitrary limit `3`. This issue has been reported by real_as3617 and gPayl0ad. [1] --- NEWS | 2 ++ ext/phar/phar.c | 16 +++++++++++----- ext/phar/tests/bug81726.gz | Bin 0 -> 204 bytes ext/phar/tests/bug81726.phpt | 14 ++++++++++++++ 4 files changed, 27 insertions(+), 5 deletions(-) create mode 100644 ext/phar/tests/bug81726.gz create mode 100644 ext/phar/tests/bug81726.phpt diff --git a/NEWS b/NEWS index 94c8fea4ef75d..415628f2dcb0b 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,8 @@ PHP NEWS ?? ??? ????, PHP 8.1.11 - Core: + . Fixed bug #81726: phar wrapper: DOS when using quine gzip file. + (CVE-2022-31628). (cmb) . Fixed bug GH-9323 (Crash in ZEND_RETURN/GC/zend_call_function) (Tim Starling) . Fixed bug GH-9361 (Segmentation fault on script exit #9379). (cmb, diff --git a/ext/phar/phar.c b/ext/phar/phar.c index bc08e4edde05d..1d5815c6d5509 100644 --- a/ext/phar/phar.c +++ b/ext/phar/phar.c @@ -1626,7 +1626,8 @@ static int phar_open_from_fp(php_stream* fp, char *fname, size_t fname_len, char const char zip_magic[] = "PK\x03\x04"; const char gz_magic[] = "\x1f\x8b\x08"; const char bz_magic[] = "BZh"; - char *pos, test = '\0'; + char *pos; + int recursion_count = 3; // arbitrary limit to avoid too deep or even infinite recursion const int window_size = 1024; char buffer[1024 + sizeof(token)]; /* a 1024 byte window + the size of the halt_compiler token (moving window) */ const zend_long readsize = sizeof(buffer) - sizeof(token); @@ -1654,8 +1655,7 @@ static int phar_open_from_fp(php_stream* fp, char *fname, size_t fname_len, char MAPPHAR_ALLOC_FAIL("internal corruption of phar \"%s\" (truncated entry)") } - if (!test) { - test = '\1'; + if (recursion_count) { pos = buffer+tokenlen; if (!memcmp(pos, gz_magic, 3)) { char err = 0; @@ -1715,7 +1715,10 @@ static int phar_open_from_fp(php_stream* fp, char *fname, size_t fname_len, char compression = PHAR_FILE_COMPRESSED_GZ; /* now, start over */ - test = '\0'; + if (!--recursion_count) { + MAPPHAR_ALLOC_FAIL("unable to decompress gzipped phar archive \"%s\""); + break; + } continue; } else if (!memcmp(pos, bz_magic, 3)) { php_stream_filter *filter; @@ -1753,7 +1756,10 @@ static int phar_open_from_fp(php_stream* fp, char *fname, size_t fname_len, char compression = PHAR_FILE_COMPRESSED_BZ2; /* now, start over */ - test = '\0'; + if (!--recursion_count) { + MAPPHAR_ALLOC_FAIL("unable to decompress bzipped phar archive \"%s\""); + break; + } continue; } diff --git a/ext/phar/tests/bug81726.gz b/ext/phar/tests/bug81726.gz new file mode 100644 index 0000000000000000000000000000000000000000..67b41ba3b6567fb242296fbb5db1504dd562c285 GIT binary patch literal 204 zcmb2|=HOref&Yc2nR%&t=~WC25)9A(%i|Dt5_1=0XJBRc^&i0ka~VV!USk*QP&~o_ nktKo!bjW{@YyLCvGJN{)1lEBn)?BbahT(tZ|CMKe>QFcU?_ozX literal 0 HcmV?d00001 diff --git a/ext/phar/tests/bug81726.phpt b/ext/phar/tests/bug81726.phpt new file mode 100644 index 0000000000000..11a148c28ea93 --- /dev/null +++ b/ext/phar/tests/bug81726.phpt @@ -0,0 +1,14 @@ +--TEST-- +Bug #81726 (phar wrapper: DOS when using quine gzip file) +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +Warning: fopen(phar://%s): failed to open stream: unable to decompress gzipped phar archive "%s" in %s on line %d +bool(false) From 168750bf3e28e368e277466f3dc949324a67c226 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Tue, 27 Sep 2022 17:43:40 +0200 Subject: [PATCH 58/61] Fix regression introduced by fixing bug 81726 When a tar phar is created, `phar_open_from_fp()` is also called, but since the file has just been created, none of the format checks can succeed, so we continue to loop, but must not check again for the format. Therefore, we bring back the old `test` variable. Closes GH-9620. --- ext/phar/phar.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ext/phar/phar.c b/ext/phar/phar.c index 1d5815c6d5509..b45586d1e8fad 100644 --- a/ext/phar/phar.c +++ b/ext/phar/phar.c @@ -1626,7 +1626,7 @@ static int phar_open_from_fp(php_stream* fp, char *fname, size_t fname_len, char const char zip_magic[] = "PK\x03\x04"; const char gz_magic[] = "\x1f\x8b\x08"; const char bz_magic[] = "BZh"; - char *pos; + char *pos, test = '\0'; int recursion_count = 3; // arbitrary limit to avoid too deep or even infinite recursion const int window_size = 1024; char buffer[1024 + sizeof(token)]; /* a 1024 byte window + the size of the halt_compiler token (moving window) */ @@ -1655,7 +1655,8 @@ static int phar_open_from_fp(php_stream* fp, char *fname, size_t fname_len, char MAPPHAR_ALLOC_FAIL("internal corruption of phar \"%s\" (truncated entry)") } - if (recursion_count) { + if (!test && recursion_count) { + test = '\1'; pos = buffer+tokenlen; if (!memcmp(pos, gz_magic, 3)) { char err = 0; @@ -1715,6 +1716,7 @@ static int phar_open_from_fp(php_stream* fp, char *fname, size_t fname_len, char compression = PHAR_FILE_COMPRESSED_GZ; /* now, start over */ + test = '\0'; if (!--recursion_count) { MAPPHAR_ALLOC_FAIL("unable to decompress gzipped phar archive \"%s\""); break; @@ -1756,6 +1758,7 @@ static int phar_open_from_fp(php_stream* fp, char *fname, size_t fname_len, char compression = PHAR_FILE_COMPRESSED_BZ2; /* now, start over */ + test = '\0'; if (!--recursion_count) { MAPPHAR_ALLOC_FAIL("unable to decompress bzipped phar archive \"%s\""); break; From 91abc41f21babf1c8a6acce90c032703bd9bf0c7 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Tue, 27 Sep 2022 17:52:01 +0200 Subject: [PATCH 59/61] Fix new bug81726.phpt for PHP 8.0 The error message has slightly changed, so we adapt our expectations. --- ext/phar/tests/bug81726.phpt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/phar/tests/bug81726.phpt b/ext/phar/tests/bug81726.phpt index 11a148c28ea93..b698f0803706a 100644 --- a/ext/phar/tests/bug81726.phpt +++ b/ext/phar/tests/bug81726.phpt @@ -10,5 +10,5 @@ if (!extension_loaded("zlib")) die("skip zlib extension not available"); var_dump(fopen("phar://" . __DIR__ . "/bug81726.gz", "r")); ?> --EXPECTF-- -Warning: fopen(phar://%s): failed to open stream: unable to decompress gzipped phar archive "%s" in %s on line %d +Warning: fopen(phar://%s): Failed to open stream: unable to decompress gzipped phar archive "%s" in %s on line %d bool(false) From 6d9a4f3125b580f2e9f44890efcf8f5b458c94ad Mon Sep 17 00:00:00 2001 From: Derick Rethans Date: Fri, 9 Sep 2022 16:54:03 +0100 Subject: [PATCH 60/61] Fix #81727: Don't mangle HTTP variable names that clash with ones that have a specific semantic meaning. --- NEWS | 2 ++ ext/standard/tests/bug81727.phpt | 15 +++++++++++++++ main/php_variables.c | 14 ++++++++++++++ 3 files changed, 31 insertions(+) create mode 100644 ext/standard/tests/bug81727.phpt diff --git a/NEWS b/NEWS index 415628f2dcb0b..c33953e6e6920 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,8 @@ PHP NEWS - Core: . Fixed bug #81726: phar wrapper: DOS when using quine gzip file. (CVE-2022-31628). (cmb) + . Fixed bug #81727: Don't mangle HTTP variable names that clash with ones + that have a specific semantic meaning. (CVE-2022-31629). (Derick) . Fixed bug GH-9323 (Crash in ZEND_RETURN/GC/zend_call_function) (Tim Starling) . Fixed bug GH-9361 (Segmentation fault on script exit #9379). (cmb, diff --git a/ext/standard/tests/bug81727.phpt b/ext/standard/tests/bug81727.phpt new file mode 100644 index 0000000000000..71a9cb46c83be --- /dev/null +++ b/ext/standard/tests/bug81727.phpt @@ -0,0 +1,15 @@ +--TEST-- +Bug #81727: $_COOKIE name starting with ..Host/..Secure should be discarded +--COOKIE-- +..Host-test=ignore; __Host-test=correct; . Secure-test=ignore; . Elephpant=Awesome; +--FILE-- + +--EXPECT-- +array(2) { + ["__Host-test"]=> + string(7) "correct" + ["__Elephpant"]=> + string(7) "Awesome" +} diff --git a/main/php_variables.c b/main/php_variables.c index 0261cf0098ee4..17e4a1e5d2cf1 100644 --- a/main/php_variables.c +++ b/main/php_variables.c @@ -104,6 +104,20 @@ PHPAPI void php_register_variable_ex(const char *var_name, zval *val, zval *trac } var_len = p - var; + /* Discard variable if mangling made it start with __Host-, where pre-mangling it did not start with __Host- */ + if (strncmp(var, "__Host-", sizeof("__Host-")-1) == 0 && strncmp(var_name, "__Host-", sizeof("__Host-")-1) != 0) { + zval_ptr_dtor_nogc(val); + free_alloca(var_orig, use_heap); + return; + } + + /* Discard variable if mangling made it start with __Secure-, where pre-mangling it did not start with __Secure- */ + if (strncmp(var, "__Secure-", sizeof("__Secure-")-1) == 0 && strncmp(var_name, "__Secure-", sizeof("__Secure-")-1) != 0) { + zval_ptr_dtor_nogc(val); + free_alloca(var_orig, use_heap); + return; + } + if (var_len==0) { /* empty variable name, or variable name with a space in it */ zval_ptr_dtor_nogc(val); free_alloca(var_orig, use_heap); From b357a4fe713d5a8f096f89d30019e5d322711c64 Mon Sep 17 00:00:00 2001 From: Patrick Allaert Date: Wed, 28 Sep 2022 11:05:55 +0200 Subject: [PATCH 61/61] Update versions and NEWS for PHP 8.1.11 --- NEWS | 2 +- Zend/zend.h | 2 +- configure.ac | 2 +- main/php_version.h | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/NEWS b/NEWS index c33953e6e6920..bf5ac0bc21b24 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,6 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? ????, PHP 8.1.11 +29 Sep 2022, PHP 8.1.11 - Core: . Fixed bug #81726: phar wrapper: DOS when using quine gzip file. diff --git a/Zend/zend.h b/Zend/zend.h index 632869a9b37d3..ba80a804ed785 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -20,7 +20,7 @@ #ifndef ZEND_H #define ZEND_H -#define ZEND_VERSION "4.1.11-dev" +#define ZEND_VERSION "4.1.11" #define ZEND_ENGINE_3 diff --git a/configure.ac b/configure.ac index 75021f30b983e..ee2d248105f6a 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.11-dev],[https://bugs.php.net],[php],[https://www.php.net]) +AC_INIT([PHP],[8.1.11],[https://bugs.php.net],[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 baf7b8c6b1893..ceeb6aeff3abe 100644 --- a/main/php_version.h +++ b/main/php_version.h @@ -3,6 +3,6 @@ #define PHP_MAJOR_VERSION 8 #define PHP_MINOR_VERSION 1 #define PHP_RELEASE_VERSION 11 -#define PHP_EXTRA_VERSION "-dev" -#define PHP_VERSION "8.1.11-dev" +#define PHP_EXTRA_VERSION "" +#define PHP_VERSION "8.1.11" #define PHP_VERSION_ID 80111