From d276ea54f42958bbc2cb22d4644227f883d3876c Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Wed, 6 Nov 2024 11:59:07 +0100 Subject: [PATCH 01/40] Skip tests if ldap_set_rebind_proc() is not available This is already done by ldap_set_rebind_proc_error.phpt, but not by the other two affected tests. Closes GH-16708. --- ext/ldap/tests/ldap_set_rebind_proc_basic.phpt | 5 ++++- ext/ldap/tests/ldap_unbind_variation.phpt | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/ext/ldap/tests/ldap_set_rebind_proc_basic.phpt b/ext/ldap/tests/ldap_set_rebind_proc_basic.phpt index 09c0d06d81fd7..40bff93a154e7 100644 --- a/ext/ldap/tests/ldap_set_rebind_proc_basic.phpt +++ b/ext/ldap/tests/ldap_set_rebind_proc_basic.phpt @@ -6,7 +6,10 @@ Patrick Allaert --EXTENSIONS-- ldap --SKIPIF-- - + --FILE-- --EXTENSIONS-- ldap --SKIPIF-- - + --FILE-- Date: Mon, 4 Nov 2024 23:41:09 +0100 Subject: [PATCH 02/40] Fix GH-10992: Improper long path support for relative paths Relative paths are passed to the ioutils APIs, these are not properly converted to long paths. If the path length already exceeds a given threshold (usually 259 characters, but only 247 for `mkdir()`), the long path prefix is prepended, resulting in an invalid path, since long paths have to be absolute. If the path length does not exceed that threshold, no conversion to a long path is done, although that may be necessary. Thus we take the path length of the current working directory into account when checking the threshold, and prepend it to the filename if necessary. Since this is only relevant for NTS builds, and using the current working directory of the process would be erroneous for ZTS builds, we skip the new code for ZTS builds. Closes GH-16687. --- NEWS | 4 +++ ext/standard/tests/directory/gh10992.phpt | 16 +++++++++++ win32/ioutil.c | 29 ++++++++++++++++--- win32/ioutil.h | 34 +++++++++++++++++++---- 4 files changed, 73 insertions(+), 10 deletions(-) create mode 100644 ext/standard/tests/directory/gh10992.phpt diff --git a/NEWS b/NEWS index a833bf4355ede..24947599456a7 100644 --- a/NEWS +++ b/NEWS @@ -40,6 +40,10 @@ PHP NEWS . Fixed bug #49169 (SoapServer calls wrong function, although "SOAP action" header is correct). (nielsdos) +- Windows: + . Fixed bug GH-10992 (Improper long path support for relative paths). (cmb, + nielsdos) + - XMLWriter: . Improved performance and reduce memory consumption. (nielsdos) diff --git a/ext/standard/tests/directory/gh10992.phpt b/ext/standard/tests/directory/gh10992.phpt new file mode 100644 index 0000000000000..99ac8a5ecd290 --- /dev/null +++ b/ext/standard/tests/directory/gh10992.phpt @@ -0,0 +1,16 @@ +--TEST-- +GH-10992 (Improper long path support for relative paths) +--FILE-- + +--EXPECT-- +bool(true) +bool(true) +bool(true) +bool(true) diff --git a/win32/ioutil.c b/win32/ioutil.c index acd4103c613b1..9c313d6001be1 100644 --- a/win32/ioutil.c +++ b/win32/ioutil.c @@ -281,7 +281,7 @@ PW32IO int php_win32_ioutil_close(int fd) PW32IO int php_win32_ioutil_mkdir_w(const wchar_t *path, mode_t mode) {/*{{{*/ - size_t path_len; + size_t path_len, dir_len = 0; const wchar_t *my_path; if (!path) { @@ -292,7 +292,16 @@ PW32IO int php_win32_ioutil_mkdir_w(const wchar_t *path, mode_t mode) PHP_WIN32_IOUTIL_CHECK_PATH_W(path, -1, 0) path_len = wcslen(path); - if (path_len < _MAX_PATH && path_len >= _MAX_PATH - 12) { +#ifndef ZTS + if (!PHP_WIN32_IOUTIL_IS_ABSOLUTEW(path, path_len) && !PHP_WIN32_IOUTIL_IS_JUNCTION_PATHW(path, path_len) && !PHP_WIN32_IOUTIL_IS_UNC_PATHW(path, path_len)) { + dir_len = GetCurrentDirectoryW(0, NULL); + if (dir_len == 0) { + return -1; + } + } +#endif + + if (dir_len + path_len < _MAX_PATH && dir_len + path_len >= _MAX_PATH - 12) { /* Special case here. From the doc: "When using an API to create a directory, the specified path cannot be @@ -315,7 +324,7 @@ PW32IO int php_win32_ioutil_mkdir_w(const wchar_t *path, mode_t mode) } if (!PHP_WIN32_IOUTIL_IS_LONG_PATHW(tmp, path_len)) { - wchar_t *_tmp = (wchar_t *) malloc((path_len + PHP_WIN32_IOUTIL_LONG_PATH_PREFIX_LENW + 1) * sizeof(wchar_t)); + wchar_t *_tmp = (wchar_t *) malloc((dir_len + path_len + PHP_WIN32_IOUTIL_LONG_PATH_PREFIX_LENW + 1) * sizeof(wchar_t)); wchar_t *src, *dst; if (!_tmp) { SET_ERRNO_FROM_WIN32_CODE(ERROR_NOT_ENOUGH_MEMORY); @@ -325,6 +334,18 @@ PW32IO int php_win32_ioutil_mkdir_w(const wchar_t *path, mode_t mode) memmove(_tmp, PHP_WIN32_IOUTIL_LONG_PATH_PREFIXW, PHP_WIN32_IOUTIL_LONG_PATH_PREFIX_LENW * sizeof(wchar_t)); src = tmp; dst = _tmp + PHP_WIN32_IOUTIL_LONG_PATH_PREFIX_LENW; +#ifndef ZTS + if (dir_len > 0) { + size_t len = GetCurrentDirectoryW(dir_len, dst); + if (len == 0 || len + 1 != dir_len) { + free(tmp); + free(_tmp); + return -1; + } + dst += len; + *dst++ = PHP_WIN32_IOUTIL_DEFAULT_SLASHW; + } +#endif while (src < tmp + path_len) { if (*src == PHP_WIN32_IOUTIL_FW_SLASHW) { *dst++ = PHP_WIN32_IOUTIL_DEFAULT_SLASHW; @@ -333,7 +354,7 @@ PW32IO int php_win32_ioutil_mkdir_w(const wchar_t *path, mode_t mode) *dst++ = *src++; } } - path_len += PHP_WIN32_IOUTIL_LONG_PATH_PREFIX_LENW; + path_len += PHP_WIN32_IOUTIL_LONG_PATH_PREFIX_LENW + dir_len; _tmp[path_len] = L'\0'; free(tmp); tmp = _tmp; diff --git a/win32/ioutil.h b/win32/ioutil.h index 6a7055fc71a77..454efdc353648 100644 --- a/win32/ioutil.h +++ b/win32/ioutil.h @@ -175,18 +175,28 @@ PW32IO php_win32_ioutil_normalization_result php_win32_ioutil_normalize_path_w(w __forceinline static wchar_t *php_win32_ioutil_conv_any_to_w(const char* in, size_t in_len, size_t *out_len) {/*{{{*/ wchar_t *mb, *ret; - size_t mb_len; + size_t mb_len, dir_len = 0; mb = php_win32_cp_conv_any_to_w(in, in_len, &mb_len); if (!mb) { return NULL; } +#ifndef ZTS + if (!PHP_WIN32_IOUTIL_IS_ABSOLUTEW(mb, mb_len) && !PHP_WIN32_IOUTIL_IS_JUNCTION_PATHW(mb, mb_len) && !PHP_WIN32_IOUTIL_IS_UNC_PATHW(mb, mb_len)) { + dir_len = GetCurrentDirectoryW(0, NULL); + if (dir_len == 0) { + free(mb); + return NULL; + } + } +#endif + /* Only prefix with long if it's needed. */ - if (mb_len >= _MAX_PATH) { + if (dir_len + mb_len >= _MAX_PATH) { size_t new_mb_len; - ret = (wchar_t *) malloc((mb_len + PHP_WIN32_IOUTIL_LONG_PATH_PREFIX_LENW + 1) * sizeof(wchar_t)); + ret = (wchar_t *) malloc((dir_len + mb_len + PHP_WIN32_IOUTIL_LONG_PATH_PREFIX_LENW + 1) * sizeof(wchar_t)); if (!ret) { free(mb); return NULL; @@ -199,7 +209,7 @@ __forceinline static wchar_t *php_win32_ioutil_conv_any_to_w(const char* in, siz } if (new_mb_len > mb_len) { - wchar_t *tmp = (wchar_t *) realloc(ret, (new_mb_len + 1) * sizeof(wchar_t)); + wchar_t *tmp = (wchar_t *) realloc(ret, (dir_len + new_mb_len + 1) * sizeof(wchar_t)); if (!tmp) { free(ret); free(mb); @@ -215,6 +225,18 @@ __forceinline static wchar_t *php_win32_ioutil_conv_any_to_w(const char* in, siz } else { wchar_t *src = mb, *dst = ret + PHP_WIN32_IOUTIL_LONG_PATH_PREFIX_LENW; memmove(ret, PHP_WIN32_IOUTIL_LONG_PATH_PREFIXW, PHP_WIN32_IOUTIL_LONG_PATH_PREFIX_LENW * sizeof(wchar_t)); +#ifndef ZTS + if (dir_len > 0) { + size_t len = GetCurrentDirectoryW(dir_len, dst); + if (len == 0 || len + 1 != dir_len) { + free(ret); + free(mb); + return NULL; + } + dst += len; + *dst++ = PHP_WIN32_IOUTIL_DEFAULT_SLASHW; + } +#endif while (src < mb + mb_len) { if (*src == PHP_WIN32_IOUTIL_FW_SLASHW) { *dst++ = PHP_WIN32_IOUTIL_DEFAULT_SLASHW; @@ -223,9 +245,9 @@ __forceinline static wchar_t *php_win32_ioutil_conv_any_to_w(const char* in, siz *dst++ = *src++; } } - ret[mb_len + PHP_WIN32_IOUTIL_LONG_PATH_PREFIX_LENW] = L'\0'; + ret[mb_len + PHP_WIN32_IOUTIL_LONG_PATH_PREFIX_LENW + dir_len] = L'\0'; - mb_len += PHP_WIN32_IOUTIL_LONG_PATH_PREFIX_LENW; + mb_len += PHP_WIN32_IOUTIL_LONG_PATH_PREFIX_LENW + dir_len; } free(mb); From 452c5ac989beec4696f257d07c588bc1a61a8d44 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 7 Nov 2024 14:53:12 +0100 Subject: [PATCH 03/40] Fix incorrect filename of dl()'d internal consts (#16721) We should only attempt to fetch the current filename for user constants. dl() may attempt to register internal constants after execution has already started, thus incorrectly linking the user file invoking dl(). See GH-16663 --- Zend/zend_constants.c | 11 ++++++----- ext/dl_test/dl_test.c | 2 ++ ext/dl_test/dl_test.stub.php | 3 +++ ext/dl_test/dl_test_arginfo.h | 7 ++++++- 4 files changed, 17 insertions(+), 6 deletions(-) diff --git a/Zend/zend_constants.c b/Zend/zend_constants.c index 9206eb8e1638d..4d9a769f1de3a 100644 --- a/Zend/zend_constants.c +++ b/Zend/zend_constants.c @@ -504,11 +504,12 @@ ZEND_API zend_result zend_register_constant(zend_constant *c) name = c->name; } - zend_string *filename = zend_get_executed_filename_ex(); - if (filename == NULL) { - c->filename = NULL; - } else { - c->filename = zend_string_copy(filename); + c->filename = NULL; + if (ZEND_CONSTANT_MODULE_NUMBER(c) == PHP_USER_CONSTANT) { + zend_string *filename = zend_get_executed_filename_ex(); + if (filename) { + c->filename = zend_string_copy(filename); + } } /* Check if the user is trying to define any special constant */ diff --git a/ext/dl_test/dl_test.c b/ext/dl_test/dl_test.c index 33008a2b57205..04f013f64709f 100644 --- a/ext/dl_test/dl_test.c +++ b/ext/dl_test/dl_test.c @@ -94,6 +94,8 @@ PHP_MINIT_FUNCTION(dl_test) fprintf(stderr, "DL TEST MINIT\n"); } + register_dl_test_symbols(module_number); + return SUCCESS; } /* }}} */ diff --git a/ext/dl_test/dl_test.stub.php b/ext/dl_test/dl_test.stub.php index 524c8206365b8..2b1545175046c 100644 --- a/ext/dl_test/dl_test.stub.php +++ b/ext/dl_test/dl_test.stub.php @@ -8,3 +8,6 @@ function dl_test_test1(): void {} function dl_test_test2(string $str = ""): string {} + +/** @var int */ +const DL_TEST_CONST = 42; diff --git a/ext/dl_test/dl_test_arginfo.h b/ext/dl_test/dl_test_arginfo.h index 0b6627b19b009..276eae4ac7dce 100644 --- a/ext/dl_test/dl_test_arginfo.h +++ b/ext/dl_test/dl_test_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 547ddbc21e9aa853b491cb17e902bbbb9cc2df00 */ + * Stub hash: e1154d736a190512ecf51e30719d53e685ca5513 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_dl_test_test1, 0, 0, IS_VOID, 0) ZEND_END_ARG_INFO() @@ -16,3 +16,8 @@ static const zend_function_entry ext_functions[] = { ZEND_FE(dl_test_test2, arginfo_dl_test_test2) ZEND_FE_END }; + +static void register_dl_test_symbols(int module_number) +{ + REGISTER_LONG_CONSTANT("DL_TEST_CONST", 42, CONST_PERSISTENT); +} From 8a712003aaf2395d89f53652f88f2147e89983a1 Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Mon, 4 Nov 2024 17:34:49 -0500 Subject: [PATCH 04/40] ext/standard/tests/strings/crypt_sha256.phpt: fix on musl Among other things, this test tries to run too few and too many rounds of SHA256. In both cases, it is expecting an error, but that behavior depends on the implementation: * PHP's own implementation raises an error in either case * libxcrypt raises an error in either case * Older versions of glibc would clamp the number of rounds to a valid amount (newer versions don't have libcrypt) * Musl libc clamps values that are too low, but raises an error for values that are too high If PHP is built with --with-external-libcrypt, the musl implementation above can be used. Even if libxcrypt is installed, PHP will notice that no additional -lfoo flags are needed to use the crypt implementation in musl. To pass on such a system, we must not test for the "too few rounds" behavior. --- ext/standard/tests/strings/crypt_sha256.phpt | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/ext/standard/tests/strings/crypt_sha256.phpt b/ext/standard/tests/strings/crypt_sha256.phpt index 095e8f1691336..324248294be72 100644 --- a/ext/standard/tests/strings/crypt_sha256.phpt +++ b/ext/standard/tests/strings/crypt_sha256.phpt @@ -39,12 +39,10 @@ $tests = array( 'a short string', '$5$rounds=123456$asaltof16chars..$gP3VQ/6X7UUEW3HkBn2w1/Ptq2jxPyzV/cZKmF/wJvD' ), + + // The "too many rounds" behavior depends on the crypt() + // implementation, but for now everyone agrees on what to do. 8 => array( - '$5$rounds=10$roundstoolow', - 'the number of rounds is too low', - '*0' - ), - 9 => array( '$5$rounds=1000000000$roundstoohigh', 'the number of rounds is too high', '*0' From f5d2e7b779b417449109e672627e68cb69c14385 Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Mon, 4 Nov 2024 18:47:46 -0500 Subject: [PATCH 05/40] ext/standard/tests/crypt/des_fallback_invalid_salt.phpt: less valid salt Musl's crypt() implementation of DES tries to handle invalid salts and can make this test fail because it returns an answer and not an error. Even musl however will reject a salt with a ':' in it, so we can make this test cross-platform by supplying an even less valid salt. --- ext/standard/tests/crypt/des_fallback_invalid_salt.phpt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ext/standard/tests/crypt/des_fallback_invalid_salt.phpt b/ext/standard/tests/crypt/des_fallback_invalid_salt.phpt index b0797657d80a2..8b00c81bbd1ce 100644 --- a/ext/standard/tests/crypt/des_fallback_invalid_salt.phpt +++ b/ext/standard/tests/crypt/des_fallback_invalid_salt.phpt @@ -3,8 +3,11 @@ Test DES with invalid fallback --FILE-- --EXPECT-- From 4dc0b40f42945d7de991be44ed6006ec6d0639a4 Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Mon, 4 Nov 2024 18:50:07 -0500 Subject: [PATCH 06/40] ext/standard/crypt.c: handle musl failure tokens Musl's crypt() returns "*" to indicate failure in contrast with the "*0" returned by PHP/libxcrypt. This causes test failures, but more importantly, is a pretty silly thing to expect the user to know. This commit catches the musl value and turns it into "*0". --- ext/standard/crypt.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/ext/standard/crypt.c b/ext/standard/crypt.c index 14eb6cda9735a..54687f6cdf307 100644 --- a/ext/standard/crypt.c +++ b/ext/standard/crypt.c @@ -177,7 +177,19 @@ PHPAPI zend_string *php_crypt(const char *password, const int pass_len, const ch if (!crypt_res || (salt[0] == '*' && salt[1] == '0')) { return NULL; - } else { + } + else if (!strcmp(crypt_res, "*")) { + /* Musl crypt() uses "*" as a failure token rather + * than the "*0" that libxcrypt/PHP use. Our test + * suite in particular looks for "*0" in a few places, + * and it would be annoying to handle both values + * explicitly. It seems wise to abstract this detail + * from the end user: if it's annoying for us, imagine + * how annoying it would be in end-user code; not that + * anyone would think of it. */ + return NULL; + } + else { result = zend_string_init(crypt_res, strlen(crypt_res), 0); return result; } From 40997c2c62d7b83ae870b90210e0376ac1ae0a1c Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Thu, 7 Nov 2024 15:56:38 +0100 Subject: [PATCH 07/40] [ci skip] NEWS for GH-16702 --- NEWS | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS b/NEWS index 24947599456a7..8653ae145cda7 100644 --- a/NEWS +++ b/NEWS @@ -40,6 +40,10 @@ PHP NEWS . Fixed bug #49169 (SoapServer calls wrong function, although "SOAP action" header is correct). (nielsdos) +- Standard: + . Fixed crypt() tests on musl when using --with-external-libcrypt + (Michael Orlitzky). + - Windows: . Fixed bug GH-10992 (Improper long path support for relative paths). (cmb, nielsdos) From fb257ee83c405fecf449571bfcd1cc0fb4910336 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 7 Nov 2024 16:32:45 +0100 Subject: [PATCH 08/40] Upgrade master to Ubuntu 24.04 (GH-16704) --- .github/actions/apt-x32/action.yml | 2 -- .github/actions/configure-x32/action.yml | 3 +-- .github/workflows/push.yml | 6 +++--- .github/workflows/root.yml | 5 ++++- Zend/zend_portability.h | 7 +++++++ ext/curl/tests/bug77535.phpt | 2 +- ext/curl/tests/curl_pushfunction_trampoline.phpt | 2 +- ext/pcntl/tests/pcntl_setns_basic.phpt | 8 ++++++++ ext/pcntl/tests/pcntl_setns_newpid.phpt | 9 ++++++++- ext/pdo_odbc/tests/long_columns.phpt | 6 ++---- ext/standard/basic_functions.c | 1 + 11 files changed, 36 insertions(+), 15 deletions(-) diff --git a/.github/actions/apt-x32/action.yml b/.github/actions/apt-x32/action.yml index 0638881d1e4c2..af1d7918bb28d 100644 --- a/.github/actions/apt-x32/action.yml +++ b/.github/actions/apt-x32/action.yml @@ -33,13 +33,11 @@ runs: libsodium-dev:i386 \ libsqlite3-dev:i386 \ libssl-dev:i386 \ - libtidy-dev:i386 \ libwebp-dev:i386 \ libxml2-dev:i386 \ libxml2-dev:i386 \ libxpm-dev:i386 \ libxslt1-dev:i386 \ - libzip-dev:i386 \ locales \ make \ pkg-config:i386 \ diff --git a/.github/actions/configure-x32/action.yml b/.github/actions/configure-x32/action.yml index c07c49bb2c4f1..de500e02d4991 100644 --- a/.github/actions/configure-x32/action.yml +++ b/.github/actions/configure-x32/action.yml @@ -10,6 +10,7 @@ runs: run: | set -x + export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:/usr/lib/i386-linux-gnu/pkgconfig" ./buildconf --force export CFLAGS="-m32 -msse2" export CXXFLAGS="-m32 -msse2" @@ -33,12 +34,10 @@ runs: --with-freetype \ --with-xpm \ --enable-exif \ - --with-zip \ --with-zlib \ --enable-soap \ --enable-xmlreader \ --with-xsl \ - --with-tidy \ --enable-sysvsem \ --enable-sysvshm \ --enable-shmop \ diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 684934c7073ee..6baf80d5f84b0 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -78,7 +78,7 @@ jobs: zts: true asan: true name: "LINUX_X64_${{ matrix.debug && 'DEBUG' || 'RELEASE' }}_${{ matrix.zts && 'ZTS' || 'NTS' }}${{ matrix.asan && '_ASAN' || '' }}" - runs-on: ubuntu-${{ !matrix.asan && '22' || '24' }}.04 + runs-on: ubuntu-24.04 timeout-minutes: 50 steps: - name: git checkout @@ -142,7 +142,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 50 container: - image: ubuntu:20.04 + image: ubuntu:24.04 env: MYSQL_TEST_HOST: mysql PDO_MYSQL_TEST_DSN: mysql:host=mysql;dbname=test @@ -255,7 +255,7 @@ jobs: BENCHMARKING: name: BENCHMARKING if: github.repository == 'php/php-src' || github.event_name == 'pull_request' - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 timeout-minutes: 50 steps: - name: git checkout diff --git a/.github/workflows/root.yml b/.github/workflows/root.yml index f526e9bea30d5..9a2e3db7c6be8 100644 --- a/.github/workflows/root.yml +++ b/.github/workflows/root.yml @@ -52,6 +52,9 @@ jobs: libmysqlclient_with_mysqli: ${{ (matrix.branch.version[0] == 8 && matrix.branch.version[1] == 1) }} run_alpine: ${{ (matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 4) || matrix.branch.version[0] >= 9 }} run_macos_arm64: ${{ (matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 4) || matrix.branch.version[0] >= 9 }} - ubuntu_version: ${{ ((matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 3) || matrix.branch.version[0] >= 9) && '22.04' || '20.04' }} + ubuntu_version: ${{ + (((matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 4) || matrix.branch.version[0] >= 9) && '24.04') + || ((matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 3) && '22.04') + || '20.04' }} windows_version: ${{ ((matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 4) || matrix.branch.version[0] >= 9) && '2022' || '2019' }} secrets: inherit diff --git a/Zend/zend_portability.h b/Zend/zend_portability.h index e292d993219ca..9ab46f9b32cfe 100644 --- a/Zend/zend_portability.h +++ b/Zend/zend_portability.h @@ -515,6 +515,13 @@ extern "C++" { # undef HAVE_FUNC_ATTRIBUTE_IFUNC #endif +#if __has_feature(memory_sanitizer) +# include +# define MSAN_UNPOISON(value) __msan_unpoison(&(value), sizeof(value)) +#else +# define MSAN_UNPOISON(value) +#endif + /* Only use ifunc resolvers if we have __builtin_cpu_supports() and __builtin_cpu_init(), * otherwise the use of zend_cpu_supports() may not be safe inside ifunc resolvers. */ #if defined(HAVE_FUNC_ATTRIBUTE_IFUNC) && defined(HAVE_FUNC_ATTRIBUTE_TARGET) && \ diff --git a/ext/curl/tests/bug77535.phpt b/ext/curl/tests/bug77535.phpt index 522818516ae69..600bfef62b9aa 100644 --- a/ext/curl/tests/bug77535.phpt +++ b/ext/curl/tests/bug77535.phpt @@ -2,7 +2,7 @@ Bug #77535 (Invalid callback, h2 server push) --EXTENSIONS-- curl ---XLEAK-- +--XFAIL-- --SKIPIF-- --FILE-- --FILE-- --FILE-- Date: Thu, 7 Nov 2024 16:35:56 +0100 Subject: [PATCH 09/40] [skip ci] Update to ubuntu 24.04 for asan in nightly --- .github/workflows/root.yml | 4 +++- ext/ldap/tests/ldap_sasl_bind_error.phpt | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/root.yml b/.github/workflows/root.yml index 9a2e3db7c6be8..a4e806cde03d3 100644 --- a/.github/workflows/root.yml +++ b/.github/workflows/root.yml @@ -46,7 +46,9 @@ jobs: matrix: branch: ${{ fromJson(needs.GENERATE_MATRIX.outputs.branches) }} with: - asan_ubuntu_version: '20.04' + asan_ubuntu_version: ${{ + (((matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 4) || matrix.branch.version[0] >= 9) && '24.04') + || '20.04' }} branch: ${{ matrix.branch.ref }} community_verify_type_inference: ${{ (matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 4) || matrix.branch.version[0] >= 9 }} libmysqlclient_with_mysqli: ${{ (matrix.branch.version[0] == 8 && matrix.branch.version[1] == 1) }} diff --git a/ext/ldap/tests/ldap_sasl_bind_error.phpt b/ext/ldap/tests/ldap_sasl_bind_error.phpt index 3c43f77096bc8..f5497c33fecaa 100644 --- a/ext/ldap/tests/ldap_sasl_bind_error.phpt +++ b/ext/ldap/tests/ldap_sasl_bind_error.phpt @@ -5,6 +5,7 @@ Patrick Allaert # Belgian PHP Testfest 2009 --EXTENSIONS-- ldap +--XLEAK-- --SKIPIF-- From e74e66e3f7b2774fde34d526e9ce372939d210a1 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Mon, 16 Sep 2024 12:26:48 +0100 Subject: [PATCH 10/40] Fix oss-fuzz report triggered by GH-15712 commit. It triggered allocation overflow which, even fixed, in turn gives memory leak on 32 bits but the allocator relies on signed integers. close GH-15915 --- NEWS | 2 ++ Zend/zend_strtod.c | 15 +++++++++++---- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/NEWS b/NEWS index 8d967754ee49a..b9ed3187b78c1 100644 --- a/NEWS +++ b/NEWS @@ -28,6 +28,8 @@ PHP NEWS . Fixed bug GH-16508 (Incorrect line number in inheritance errors of delayed early bound classes). (ilutov) . Fixed bug GH-16648 (Use-after-free during array sorting). (ilutov) + . Fixed bug GH-15915 (overflow with a high value for precision INI). + (David Carlier / cmb) - Curl: . Fixed bug GH-16302 (CurlMultiHandle holds a reference to CurlHandle if diff --git a/Zend/zend_strtod.c b/Zend/zend_strtod.c index eb3a94332ae35..38caef0b10fd0 100644 --- a/Zend/zend_strtod.c +++ b/Zend/zend_strtod.c @@ -3613,13 +3613,20 @@ rv_alloc(i) int i; rv_alloc(int i) #endif { - int k, *r; - size_t j = sizeof(ULong); + int j, k, *r; + size_t rem; + + rem = sizeof(Bigint) - sizeof(ULong) - sizeof(int); + + + j = sizeof(ULong); + if (i > ((INT_MAX >> 2) + rem)) + zend_error_noreturn(E_ERROR, "rv_alloc() allocation overflow %d", i); for(k = 0; - sizeof(Bigint) - sizeof(ULong) - sizeof(int) + j <= (size_t)i; - j <<= 1) + rem + j <= (size_t)i; j <<= 1) k++; + r = (int*)Balloc(k); *r = k; return From 03eeec16f0fcfd64bc95102b96de99a4a309049f Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Wed, 21 Aug 2024 13:25:16 +0200 Subject: [PATCH 11/40] Fix rename_variation12*.phpt parallel test conflicts For rename_variation12.phpt this is actually not necessary, since there is no rename_variation11.phpt, but we still fix it to be in sync with rename_variation12-win32.phpt which actually is prone to parallel conflicts. (cherry picked from commit d4263ddc40358f5267d5e621c66f4ed74c70b5b9) --- ext/standard/tests/file/rename_variation12-win32.phpt | 8 ++++---- ext/standard/tests/file/rename_variation12.phpt | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ext/standard/tests/file/rename_variation12-win32.phpt b/ext/standard/tests/file/rename_variation12-win32.phpt index 7ecaed35d7dc7..527a8865c331e 100644 --- a/ext/standard/tests/file/rename_variation12-win32.phpt +++ b/ext/standard/tests/file/rename_variation12-win32.phpt @@ -11,8 +11,8 @@ if (substr(PHP_OS, 0, 3) != 'WIN') die('skip.. for Windows'); /* Creating unique files in various dirs by passing relative paths to $dir arg */ echo "*** Testing rename() with absolute and relative paths ***\n"; -$mainDir = "renameVar11"; -$subDir = "renameVar11Sub"; +$mainDir = "renameVar12"; +$subDir = "renameVar12Sub"; $absMainDir = __DIR__."/".$mainDir; mkdir($absMainDir); $absSubDir = $absMainDir."/".$subDir; @@ -83,12 +83,12 @@ bool(true) -- Iteration 5 -- -Warning: rename(%s/renameVar11/renameVar11Sub/..///renameVar11Sub//..//../renameVar11Sub/renameMe.tmp,%s/renameVar11/renameVar11Sub/..///renameVar11Sub//..//../renameVar11Sub/IwasRenamed.tmp): The system cannot find the path specified (code: 3) in %s on line %d +Warning: rename(%s/renameVar12/renameVar12Sub/..///renameVar12Sub//..//../renameVar12Sub/renameMe.tmp,%s/renameVar12/renameVar12Sub/..///renameVar12Sub//..//../renameVar12Sub/IwasRenamed.tmp): The system cannot find the path specified (code: 3) in %s on line %d bool(false) -- Iteration 6 -- -Warning: rename(%s/renameVar11/renameVar11Sub/BADDIR/renameMe.tmp,%s/renameVar11/renameVar11Sub/BADDIR/IwasRenamed.tmp): The system cannot find the path specified (code: 3) in %s on line %d +Warning: rename(%s/renameVar12/renameVar12Sub/BADDIR/renameMe.tmp,%s/renameVar12/renameVar12Sub/BADDIR/IwasRenamed.tmp): The system cannot find the path specified (code: 3) in %s on line %d bool(false) -- Iteration 7 -- diff --git a/ext/standard/tests/file/rename_variation12.phpt b/ext/standard/tests/file/rename_variation12.phpt index b38aab7ed1d0b..8675b17aab5c0 100644 --- a/ext/standard/tests/file/rename_variation12.phpt +++ b/ext/standard/tests/file/rename_variation12.phpt @@ -11,8 +11,8 @@ if (substr(PHP_OS, 0, 3) == 'WIN') die('skip.. not for Windows'); /* Creating unique files in various dirs by passing relative paths to $dir arg */ echo "*** Testing rename() with absolute and relative paths ***\n"; -$mainDir = "renameVar11"; -$subDir = "renameVar11Sub"; +$mainDir = "renameVar12"; +$subDir = "renameVar12Sub"; $absMainDir = __DIR__."/".$mainDir; mkdir($absMainDir); $absSubDir = $absMainDir."/".$subDir; @@ -83,12 +83,12 @@ bool(true) -- Iteration 5 -- -Warning: rename(%s/renameVar11/renameVar11Sub/..///renameVar11Sub//..//../renameVar11Sub/renameMe.tmp,%s/renameVar11/renameVar11Sub/..///renameVar11Sub//..//../renameVar11Sub/IwasRenamed.tmp): %s in %s on line %d +Warning: rename(%s/renameVar12/renameVar12Sub/..///renameVar12Sub//..//../renameVar12Sub/renameMe.tmp,%s/renameVar12/renameVar12Sub/..///renameVar12Sub//..//../renameVar12Sub/IwasRenamed.tmp): %s in %s on line %d bool(false) -- Iteration 6 -- -Warning: rename(%s/renameVar11/renameVar11Sub/BADDIR/renameMe.tmp,%s/renameVar11/renameVar11Sub/BADDIR/IwasRenamed.tmp): %s in %s on line %d +Warning: rename(%s/renameVar12/renameVar12Sub/BADDIR/renameMe.tmp,%s/renameVar12/renameVar12Sub/BADDIR/IwasRenamed.tmp): %s in %s on line %d bool(false) -- Iteration 7 -- From d8a63a38c62c039688461ce5642431d655331e98 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Wed, 6 Nov 2024 14:34:22 +0000 Subject: [PATCH 12/40] ext/standard: Move sort() related tests into subfolder --- ext/standard/tests/array/001.phpt | 2 +- ext/standard/tests/array/{ => sort}/array_multisort_basic1.phpt | 0 ext/standard/tests/array/{ => sort}/array_multisort_basic2.phpt | 0 ext/standard/tests/array/{ => sort}/array_multisort_case.phpt | 0 ext/standard/tests/array/{ => sort}/array_multisort_error.phpt | 0 ext/standard/tests/array/{ => sort}/array_multisort_incase.phpt | 0 .../tests/array/{ => sort}/array_multisort_natural.phpt | 0 .../tests/array/{ => sort}/array_multisort_natural_case.phpt | 0 .../tests/array/{ => sort}/array_multisort_natural_incase.phpt | 0 .../tests/array/{ => sort}/array_multisort_stability.phpt | 0 .../tests/array/{ => sort}/array_multisort_variation1.phpt | 0 .../tests/array/{ => sort}/array_multisort_variation10.phpt | 0 .../tests/array/{ => sort}/array_multisort_variation11.phpt | 0 .../tests/array/{ => sort}/array_multisort_variation2.phpt | 0 .../tests/array/{ => sort}/array_multisort_variation3.phpt | 0 .../tests/array/{ => sort}/array_multisort_variation4.phpt | 0 .../tests/array/{ => sort}/array_multisort_variation5.phpt | 0 .../tests/array/{ => sort}/array_multisort_variation6.phpt | 0 .../tests/array/{ => sort}/array_multisort_variation7.phpt | 0 .../tests/array/{ => sort}/array_multisort_variation8.phpt | 0 .../tests/array/{ => sort}/array_multisort_variation9.phpt | 0 ext/standard/tests/array/{ => sort}/array_shuffle_basic.phpt | 0 ext/standard/tests/array/{ => sort}/arsort_basic.phpt | 0 ext/standard/tests/array/{ => sort}/arsort_object1.phpt | 0 ext/standard/tests/array/{ => sort}/arsort_object2.phpt | 0 ext/standard/tests/array/{ => sort}/arsort_variation10.phpt | 0 ext/standard/tests/array/{ => sort}/arsort_variation11.phpt | 0 ext/standard/tests/array/{ => sort}/arsort_variation3.phpt | 0 ext/standard/tests/array/{ => sort}/arsort_variation4.phpt | 0 ext/standard/tests/array/{ => sort}/arsort_variation5.phpt | 0 ext/standard/tests/array/{ => sort}/arsort_variation6.phpt | 0 ext/standard/tests/array/{ => sort}/arsort_variation7.phpt | 0 ext/standard/tests/array/{ => sort}/arsort_variation8.phpt | 0 ext/standard/tests/array/{ => sort}/arsort_variation9.phpt | 0 ext/standard/tests/array/{ => sort}/asort_basic.phpt | 0 ext/standard/tests/array/{ => sort}/asort_object1.phpt | 0 ext/standard/tests/array/{ => sort}/asort_object2.phpt | 0 ext/standard/tests/array/{ => sort}/asort_stability.phpt | 0 ext/standard/tests/array/{ => sort}/asort_variation10.phpt | 0 ext/standard/tests/array/{ => sort}/asort_variation11.phpt | 0 ext/standard/tests/array/{ => sort}/asort_variation3.phpt | 0 ext/standard/tests/array/{ => sort}/asort_variation4.phpt | 0 ext/standard/tests/array/{ => sort}/asort_variation5.phpt | 0 ext/standard/tests/array/{ => sort}/asort_variation6.phpt | 0 ext/standard/tests/array/{ => sort}/asort_variation7.phpt | 0 ext/standard/tests/array/{ => sort}/asort_variation8.phpt | 0 ext/standard/tests/array/{ => sort}/asort_variation9.phpt | 0 ext/standard/tests/array/{ => sort}/bug24897.phpt | 0 ext/standard/tests/array/{ => sort}/bug25359.phpt | 0 ext/standard/tests/array/{ => sort}/bug33382.phpt | 0 ext/standard/tests/array/{ => sort}/bug36975.phpt | 0 ext/standard/tests/array/{ => sort}/bug44929.phpt | 0 ext/standard/tests/array/{ => sort}/bug50006.phpt | 0 ext/standard/tests/array/{ => sort}/bug50006_1.phpt | 0 ext/standard/tests/array/{ => sort}/bug50006_2.phpt | 0 ext/standard/tests/array/{ => sort}/bug71334.phpt | 0 ext/standard/tests/array/{ => sort}/bug77395.phpt | 0 ext/standard/tests/array/{ => sort}/data.inc | 0 ext/standard/tests/array/{ => sort}/gh9296.phpt | 0 .../tests/array/{002.phpt => sort/internal_sorts_basic.phpt} | 0 ext/standard/tests/array/{ => sort}/krsort_basic.phpt | 0 ext/standard/tests/array/{ => sort}/krsort_object.phpt | 0 ext/standard/tests/array/{ => sort}/krsort_variation10.phpt | 0 ext/standard/tests/array/{ => sort}/krsort_variation11.phpt | 0 ext/standard/tests/array/{ => sort}/krsort_variation3.phpt | 0 ext/standard/tests/array/{ => sort}/krsort_variation4.phpt | 0 ext/standard/tests/array/{ => sort}/krsort_variation5.phpt | 0 ext/standard/tests/array/{ => sort}/krsort_variation6.phpt | 0 ext/standard/tests/array/{ => sort}/krsort_variation7.phpt | 0 ext/standard/tests/array/{ => sort}/krsort_variation8.phpt | 0 ext/standard/tests/array/{ => sort}/krsort_variation9.phpt | 0 ext/standard/tests/array/{ => sort}/ksort_basic.phpt | 0 ext/standard/tests/array/{ => sort}/ksort_object.phpt | 0 ext/standard/tests/array/{ => sort}/ksort_variation10.phpt | 0 ext/standard/tests/array/{ => sort}/ksort_variation11.phpt | 0 ext/standard/tests/array/{ => sort}/ksort_variation3.phpt | 0 ext/standard/tests/array/{ => sort}/ksort_variation4.phpt | 0 ext/standard/tests/array/{ => sort}/ksort_variation5.phpt | 0 ext/standard/tests/array/{ => sort}/ksort_variation6.phpt | 0 ext/standard/tests/array/{ => sort}/ksort_variation7.phpt | 0 ext/standard/tests/array/{ => sort}/ksort_variation8.phpt | 0 ext/standard/tests/array/{ => sort}/ksort_variation9.phpt | 0 ext/standard/tests/array/{ => sort}/locale_sort.phpt | 0 ext/standard/tests/array/{ => sort}/natcasesort_basic.phpt | 0 ext/standard/tests/array/{ => sort}/natcasesort_object1.phpt | 0 ext/standard/tests/array/{ => sort}/natcasesort_object2.phpt | 0 .../tests/array/{ => sort}/natcasesort_variation10.phpt | 0 .../tests/array/{ => sort}/natcasesort_variation11.phpt | 0 ext/standard/tests/array/{ => sort}/natcasesort_variation2.phpt | 0 ext/standard/tests/array/{ => sort}/natcasesort_variation3.phpt | 0 ext/standard/tests/array/{ => sort}/natcasesort_variation4.phpt | 0 ext/standard/tests/array/{ => sort}/natcasesort_variation5.phpt | 0 ext/standard/tests/array/{ => sort}/natcasesort_variation6.phpt | 0 ext/standard/tests/array/{ => sort}/natcasesort_variation7.phpt | 0 ext/standard/tests/array/{ => sort}/natcasesort_variation8.phpt | 0 ext/standard/tests/array/{ => sort}/natcasesort_variation9.phpt | 0 ext/standard/tests/array/{ => sort}/natsort_basic.phpt | 0 .../array/{004.phpt => sort/natsort_natcasesort_basics.phpt} | 0 ext/standard/tests/array/{ => sort}/rsort_basic.phpt | 0 ext/standard/tests/array/{ => sort}/rsort_object1.phpt | 0 ext/standard/tests/array/{ => sort}/rsort_object2.phpt | 0 ext/standard/tests/array/{ => sort}/rsort_variation10.phpt | 0 ext/standard/tests/array/{ => sort}/rsort_variation11.phpt | 0 ext/standard/tests/array/{ => sort}/rsort_variation3.phpt | 0 ext/standard/tests/array/{ => sort}/rsort_variation4.phpt | 0 ext/standard/tests/array/{ => sort}/rsort_variation5.phpt | 0 ext/standard/tests/array/{ => sort}/rsort_variation6.phpt | 0 ext/standard/tests/array/{ => sort}/rsort_variation7.phpt | 0 ext/standard/tests/array/{ => sort}/rsort_variation8.phpt | 0 ext/standard/tests/array/{ => sort}/rsort_variation9.phpt | 0 ext/standard/tests/array/{ => sort}/shuffle_basic1.phpt | 0 ext/standard/tests/array/{ => sort}/shuffle_basic2.phpt | 0 ext/standard/tests/array/{ => sort}/shuffle_variation2.phpt | 0 ext/standard/tests/array/{ => sort}/shuffle_variation3.phpt | 0 ext/standard/tests/array/{ => sort}/shuffle_variation4.phpt | 0 ext/standard/tests/array/{ => sort}/shuffle_variation5.phpt | 0 ext/standard/tests/array/{ => sort}/sort_basic.phpt | 0 ext/standard/tests/array/{ => sort}/sort_object1.phpt | 0 ext/standard/tests/array/{ => sort}/sort_object2.phpt | 0 ext/standard/tests/array/{ => sort}/sort_variation10.phpt | 0 ext/standard/tests/array/{ => sort}/sort_variation11.phpt | 0 ext/standard/tests/array/{ => sort}/sort_variation3.phpt | 0 ext/standard/tests/array/{ => sort}/sort_variation4.phpt | 0 ext/standard/tests/array/{ => sort}/sort_variation5.phpt | 0 ext/standard/tests/array/{ => sort}/sort_variation6.phpt | 0 ext/standard/tests/array/{ => sort}/sort_variation7.phpt | 0 ext/standard/tests/array/{ => sort}/sort_variation8.phpt | 0 ext/standard/tests/array/{ => sort}/sort_variation9.phpt | 0 ext/standard/tests/array/{ => sort}/uasort_basic1.phpt | 0 ext/standard/tests/array/{ => sort}/uasort_basic2.phpt | 0 ext/standard/tests/array/{ => sort}/uasort_object1.phpt | 0 ext/standard/tests/array/{ => sort}/uasort_object2.phpt | 0 ext/standard/tests/array/{ => sort}/uasort_variation10.phpt | 0 ext/standard/tests/array/{ => sort}/uasort_variation11.phpt | 0 ext/standard/tests/array/{ => sort}/uasort_variation3.phpt | 0 ext/standard/tests/array/{ => sort}/uasort_variation4.phpt | 0 ext/standard/tests/array/{ => sort}/uasort_variation5.phpt | 0 ext/standard/tests/array/{ => sort}/uasort_variation6.phpt | 0 ext/standard/tests/array/{ => sort}/uasort_variation7.phpt | 0 ext/standard/tests/array/{ => sort}/uasort_variation8.phpt | 0 ext/standard/tests/array/{ => sort}/uksort_basic.phpt | 0 .../tests/array/{003.phpt => sort/user_sort_basics.phpt} | 0 ext/standard/tests/array/{ => sort}/usort_basic.phpt | 0 ext/standard/tests/array/{ => sort}/usort_object1.phpt | 0 ext/standard/tests/array/{ => sort}/usort_object2.phpt | 0 ext/standard/tests/array/{ => sort}/usort_stability.phpt | 0 ext/standard/tests/array/{ => sort}/usort_variation10.phpt | 0 ext/standard/tests/array/{ => sort}/usort_variation11.phpt | 0 ext/standard/tests/array/{ => sort}/usort_variation3.phpt | 0 ext/standard/tests/array/{ => sort}/usort_variation4.phpt | 0 ext/standard/tests/array/{ => sort}/usort_variation5.phpt | 0 ext/standard/tests/array/{ => sort}/usort_variation6.phpt | 0 ext/standard/tests/array/{ => sort}/usort_variation7.phpt | 0 ext/standard/tests/array/{ => sort}/usort_variation8.phpt | 0 ext/standard/tests/array/{ => sort}/usort_variation9.phpt | 0 155 files changed, 1 insertion(+), 1 deletion(-) rename ext/standard/tests/array/{ => sort}/array_multisort_basic1.phpt (100%) rename ext/standard/tests/array/{ => sort}/array_multisort_basic2.phpt (100%) rename ext/standard/tests/array/{ => sort}/array_multisort_case.phpt (100%) rename ext/standard/tests/array/{ => sort}/array_multisort_error.phpt (100%) rename ext/standard/tests/array/{ => sort}/array_multisort_incase.phpt (100%) rename ext/standard/tests/array/{ => sort}/array_multisort_natural.phpt (100%) rename ext/standard/tests/array/{ => sort}/array_multisort_natural_case.phpt (100%) rename ext/standard/tests/array/{ => sort}/array_multisort_natural_incase.phpt (100%) rename ext/standard/tests/array/{ => sort}/array_multisort_stability.phpt (100%) rename ext/standard/tests/array/{ => sort}/array_multisort_variation1.phpt (100%) rename ext/standard/tests/array/{ => sort}/array_multisort_variation10.phpt (100%) rename ext/standard/tests/array/{ => sort}/array_multisort_variation11.phpt (100%) rename ext/standard/tests/array/{ => sort}/array_multisort_variation2.phpt (100%) rename ext/standard/tests/array/{ => sort}/array_multisort_variation3.phpt (100%) rename ext/standard/tests/array/{ => sort}/array_multisort_variation4.phpt (100%) rename ext/standard/tests/array/{ => sort}/array_multisort_variation5.phpt (100%) rename ext/standard/tests/array/{ => sort}/array_multisort_variation6.phpt (100%) rename ext/standard/tests/array/{ => sort}/array_multisort_variation7.phpt (100%) rename ext/standard/tests/array/{ => sort}/array_multisort_variation8.phpt (100%) rename ext/standard/tests/array/{ => sort}/array_multisort_variation9.phpt (100%) rename ext/standard/tests/array/{ => sort}/array_shuffle_basic.phpt (100%) rename ext/standard/tests/array/{ => sort}/arsort_basic.phpt (100%) rename ext/standard/tests/array/{ => sort}/arsort_object1.phpt (100%) rename ext/standard/tests/array/{ => sort}/arsort_object2.phpt (100%) rename ext/standard/tests/array/{ => sort}/arsort_variation10.phpt (100%) rename ext/standard/tests/array/{ => sort}/arsort_variation11.phpt (100%) rename ext/standard/tests/array/{ => sort}/arsort_variation3.phpt (100%) rename ext/standard/tests/array/{ => sort}/arsort_variation4.phpt (100%) rename ext/standard/tests/array/{ => sort}/arsort_variation5.phpt (100%) rename ext/standard/tests/array/{ => sort}/arsort_variation6.phpt (100%) rename ext/standard/tests/array/{ => sort}/arsort_variation7.phpt (100%) rename ext/standard/tests/array/{ => sort}/arsort_variation8.phpt (100%) rename ext/standard/tests/array/{ => sort}/arsort_variation9.phpt (100%) rename ext/standard/tests/array/{ => sort}/asort_basic.phpt (100%) rename ext/standard/tests/array/{ => sort}/asort_object1.phpt (100%) rename ext/standard/tests/array/{ => sort}/asort_object2.phpt (100%) rename ext/standard/tests/array/{ => sort}/asort_stability.phpt (100%) rename ext/standard/tests/array/{ => sort}/asort_variation10.phpt (100%) rename ext/standard/tests/array/{ => sort}/asort_variation11.phpt (100%) rename ext/standard/tests/array/{ => sort}/asort_variation3.phpt (100%) rename ext/standard/tests/array/{ => sort}/asort_variation4.phpt (100%) rename ext/standard/tests/array/{ => sort}/asort_variation5.phpt (100%) rename ext/standard/tests/array/{ => sort}/asort_variation6.phpt (100%) rename ext/standard/tests/array/{ => sort}/asort_variation7.phpt (100%) rename ext/standard/tests/array/{ => sort}/asort_variation8.phpt (100%) rename ext/standard/tests/array/{ => sort}/asort_variation9.phpt (100%) rename ext/standard/tests/array/{ => sort}/bug24897.phpt (100%) rename ext/standard/tests/array/{ => sort}/bug25359.phpt (100%) rename ext/standard/tests/array/{ => sort}/bug33382.phpt (100%) rename ext/standard/tests/array/{ => sort}/bug36975.phpt (100%) rename ext/standard/tests/array/{ => sort}/bug44929.phpt (100%) rename ext/standard/tests/array/{ => sort}/bug50006.phpt (100%) rename ext/standard/tests/array/{ => sort}/bug50006_1.phpt (100%) rename ext/standard/tests/array/{ => sort}/bug50006_2.phpt (100%) rename ext/standard/tests/array/{ => sort}/bug71334.phpt (100%) rename ext/standard/tests/array/{ => sort}/bug77395.phpt (100%) rename ext/standard/tests/array/{ => sort}/data.inc (100%) rename ext/standard/tests/array/{ => sort}/gh9296.phpt (100%) rename ext/standard/tests/array/{002.phpt => sort/internal_sorts_basic.phpt} (100%) rename ext/standard/tests/array/{ => sort}/krsort_basic.phpt (100%) rename ext/standard/tests/array/{ => sort}/krsort_object.phpt (100%) rename ext/standard/tests/array/{ => sort}/krsort_variation10.phpt (100%) rename ext/standard/tests/array/{ => sort}/krsort_variation11.phpt (100%) rename ext/standard/tests/array/{ => sort}/krsort_variation3.phpt (100%) rename ext/standard/tests/array/{ => sort}/krsort_variation4.phpt (100%) rename ext/standard/tests/array/{ => sort}/krsort_variation5.phpt (100%) rename ext/standard/tests/array/{ => sort}/krsort_variation6.phpt (100%) rename ext/standard/tests/array/{ => sort}/krsort_variation7.phpt (100%) rename ext/standard/tests/array/{ => sort}/krsort_variation8.phpt (100%) rename ext/standard/tests/array/{ => sort}/krsort_variation9.phpt (100%) rename ext/standard/tests/array/{ => sort}/ksort_basic.phpt (100%) rename ext/standard/tests/array/{ => sort}/ksort_object.phpt (100%) rename ext/standard/tests/array/{ => sort}/ksort_variation10.phpt (100%) rename ext/standard/tests/array/{ => sort}/ksort_variation11.phpt (100%) rename ext/standard/tests/array/{ => sort}/ksort_variation3.phpt (100%) rename ext/standard/tests/array/{ => sort}/ksort_variation4.phpt (100%) rename ext/standard/tests/array/{ => sort}/ksort_variation5.phpt (100%) rename ext/standard/tests/array/{ => sort}/ksort_variation6.phpt (100%) rename ext/standard/tests/array/{ => sort}/ksort_variation7.phpt (100%) rename ext/standard/tests/array/{ => sort}/ksort_variation8.phpt (100%) rename ext/standard/tests/array/{ => sort}/ksort_variation9.phpt (100%) rename ext/standard/tests/array/{ => sort}/locale_sort.phpt (100%) rename ext/standard/tests/array/{ => sort}/natcasesort_basic.phpt (100%) rename ext/standard/tests/array/{ => sort}/natcasesort_object1.phpt (100%) rename ext/standard/tests/array/{ => sort}/natcasesort_object2.phpt (100%) rename ext/standard/tests/array/{ => sort}/natcasesort_variation10.phpt (100%) rename ext/standard/tests/array/{ => sort}/natcasesort_variation11.phpt (100%) rename ext/standard/tests/array/{ => sort}/natcasesort_variation2.phpt (100%) rename ext/standard/tests/array/{ => sort}/natcasesort_variation3.phpt (100%) rename ext/standard/tests/array/{ => sort}/natcasesort_variation4.phpt (100%) rename ext/standard/tests/array/{ => sort}/natcasesort_variation5.phpt (100%) rename ext/standard/tests/array/{ => sort}/natcasesort_variation6.phpt (100%) rename ext/standard/tests/array/{ => sort}/natcasesort_variation7.phpt (100%) rename ext/standard/tests/array/{ => sort}/natcasesort_variation8.phpt (100%) rename ext/standard/tests/array/{ => sort}/natcasesort_variation9.phpt (100%) rename ext/standard/tests/array/{ => sort}/natsort_basic.phpt (100%) rename ext/standard/tests/array/{004.phpt => sort/natsort_natcasesort_basics.phpt} (100%) rename ext/standard/tests/array/{ => sort}/rsort_basic.phpt (100%) rename ext/standard/tests/array/{ => sort}/rsort_object1.phpt (100%) rename ext/standard/tests/array/{ => sort}/rsort_object2.phpt (100%) rename ext/standard/tests/array/{ => sort}/rsort_variation10.phpt (100%) rename ext/standard/tests/array/{ => sort}/rsort_variation11.phpt (100%) rename ext/standard/tests/array/{ => sort}/rsort_variation3.phpt (100%) rename ext/standard/tests/array/{ => sort}/rsort_variation4.phpt (100%) rename ext/standard/tests/array/{ => sort}/rsort_variation5.phpt (100%) rename ext/standard/tests/array/{ => sort}/rsort_variation6.phpt (100%) rename ext/standard/tests/array/{ => sort}/rsort_variation7.phpt (100%) rename ext/standard/tests/array/{ => sort}/rsort_variation8.phpt (100%) rename ext/standard/tests/array/{ => sort}/rsort_variation9.phpt (100%) rename ext/standard/tests/array/{ => sort}/shuffle_basic1.phpt (100%) rename ext/standard/tests/array/{ => sort}/shuffle_basic2.phpt (100%) rename ext/standard/tests/array/{ => sort}/shuffle_variation2.phpt (100%) rename ext/standard/tests/array/{ => sort}/shuffle_variation3.phpt (100%) rename ext/standard/tests/array/{ => sort}/shuffle_variation4.phpt (100%) rename ext/standard/tests/array/{ => sort}/shuffle_variation5.phpt (100%) rename ext/standard/tests/array/{ => sort}/sort_basic.phpt (100%) rename ext/standard/tests/array/{ => sort}/sort_object1.phpt (100%) rename ext/standard/tests/array/{ => sort}/sort_object2.phpt (100%) rename ext/standard/tests/array/{ => sort}/sort_variation10.phpt (100%) rename ext/standard/tests/array/{ => sort}/sort_variation11.phpt (100%) rename ext/standard/tests/array/{ => sort}/sort_variation3.phpt (100%) rename ext/standard/tests/array/{ => sort}/sort_variation4.phpt (100%) rename ext/standard/tests/array/{ => sort}/sort_variation5.phpt (100%) rename ext/standard/tests/array/{ => sort}/sort_variation6.phpt (100%) rename ext/standard/tests/array/{ => sort}/sort_variation7.phpt (100%) rename ext/standard/tests/array/{ => sort}/sort_variation8.phpt (100%) rename ext/standard/tests/array/{ => sort}/sort_variation9.phpt (100%) rename ext/standard/tests/array/{ => sort}/uasort_basic1.phpt (100%) rename ext/standard/tests/array/{ => sort}/uasort_basic2.phpt (100%) rename ext/standard/tests/array/{ => sort}/uasort_object1.phpt (100%) rename ext/standard/tests/array/{ => sort}/uasort_object2.phpt (100%) rename ext/standard/tests/array/{ => sort}/uasort_variation10.phpt (100%) rename ext/standard/tests/array/{ => sort}/uasort_variation11.phpt (100%) rename ext/standard/tests/array/{ => sort}/uasort_variation3.phpt (100%) rename ext/standard/tests/array/{ => sort}/uasort_variation4.phpt (100%) rename ext/standard/tests/array/{ => sort}/uasort_variation5.phpt (100%) rename ext/standard/tests/array/{ => sort}/uasort_variation6.phpt (100%) rename ext/standard/tests/array/{ => sort}/uasort_variation7.phpt (100%) rename ext/standard/tests/array/{ => sort}/uasort_variation8.phpt (100%) rename ext/standard/tests/array/{ => sort}/uksort_basic.phpt (100%) rename ext/standard/tests/array/{003.phpt => sort/user_sort_basics.phpt} (100%) rename ext/standard/tests/array/{ => sort}/usort_basic.phpt (100%) rename ext/standard/tests/array/{ => sort}/usort_object1.phpt (100%) rename ext/standard/tests/array/{ => sort}/usort_object2.phpt (100%) rename ext/standard/tests/array/{ => sort}/usort_stability.phpt (100%) rename ext/standard/tests/array/{ => sort}/usort_variation10.phpt (100%) rename ext/standard/tests/array/{ => sort}/usort_variation11.phpt (100%) rename ext/standard/tests/array/{ => sort}/usort_variation3.phpt (100%) rename ext/standard/tests/array/{ => sort}/usort_variation4.phpt (100%) rename ext/standard/tests/array/{ => sort}/usort_variation5.phpt (100%) rename ext/standard/tests/array/{ => sort}/usort_variation6.phpt (100%) rename ext/standard/tests/array/{ => sort}/usort_variation7.phpt (100%) rename ext/standard/tests/array/{ => sort}/usort_variation8.phpt (100%) rename ext/standard/tests/array/{ => sort}/usort_variation9.phpt (100%) diff --git a/ext/standard/tests/array/001.phpt b/ext/standard/tests/array/001.phpt index c88aee367fad7..908f707e4b16d 100644 --- a/ext/standard/tests/array/001.phpt +++ b/ext/standard/tests/array/001.phpt @@ -4,7 +4,7 @@ Test array_merge and array_walk precision=14 --FILE-- Date: Wed, 6 Nov 2024 16:01:58 +0000 Subject: [PATCH 13/40] ext/standard: Split sort tests that contain escape sequences --- .../tests/array/sort/arsort_variation5.phpt | 233 ++++---------- .../arsort_variation_escape_sequences.phpt | 59 ++++ .../tests/array/sort/asort_variation5.phpt | 235 ++++---------- .../asort_variation_escape_sequences.phpt | 59 ++++ .../tests/array/sort/krsort_variation5.phpt | 294 ++++++------------ .../krsort_variation_escape_sequences.phpt | 59 ++++ .../tests/array/sort/ksort_variation5.phpt | 268 +++++----------- .../ksort_variation_escape_sequences.phpt | 59 ++++ .../tests/array/sort/rsort_variation5.phpt | 224 ++++--------- .../rsort_variation_escape_sequences.phpt | 59 ++++ .../tests/array/sort/sort_variation5.phpt | 164 ++-------- .../sort/sort_variation_escape_sequences.phpt | 59 ++++ 12 files changed, 744 insertions(+), 1028 deletions(-) create mode 100644 ext/standard/tests/array/sort/arsort_variation_escape_sequences.phpt create mode 100644 ext/standard/tests/array/sort/asort_variation_escape_sequences.phpt create mode 100644 ext/standard/tests/array/sort/krsort_variation_escape_sequences.phpt create mode 100644 ext/standard/tests/array/sort/ksort_variation_escape_sequences.phpt create mode 100644 ext/standard/tests/array/sort/rsort_variation_escape_sequences.phpt create mode 100644 ext/standard/tests/array/sort/sort_variation_escape_sequences.phpt diff --git a/ext/standard/tests/array/sort/arsort_variation5.phpt b/ext/standard/tests/array/sort/arsort_variation5.phpt index eb3f2f95674df..08c70d8e07ddb 100644 --- a/ext/standard/tests/array/sort/arsort_variation5.phpt +++ b/ext/standard/tests/array/sort/arsort_variation5.phpt @@ -2,235 +2,120 @@ Test arsort() function : usage variations - sort strings --FILE-- "lemoN", + "Orange" => "Orange", + "banana" => "banana", + "apple" => "apple", + "Test" => "Test", + "TTTT" => "TTTT", + "ttt" => "ttt", + "ww" => "ww", + "x" => "x", + "X" => "X", + "oraNGe" => "oraNGe", + "BANANA" => "BANANA", +]; -$various_arrays = array ( - // group of escape sequences - array ("null"=> null, "NULL" => NULL, "\a" => "\a", "\cx" => "\cx", "\e" => "\e", - "\f" => "\f", "\n" =>"\n", "\r" => "\r", "\t" => "\t", "\xhh" => "\xhh", - "\ddd" => "\ddd", "\v" => "\v" - ), +echo "Default flag\n"; +$temp_array = $array; +var_dump(arsort($temp_array)); // expecting : bool(true) +var_dump($temp_array); - // array contains combination of capital/small letters - array ('l' => "lemoN", 'O' => "Orange", 'b' => "banana", 'a' => "apple", 'Te' => "Test", - 'T' => "TTTT", 't' => "ttt", 'w' => "ww", 'x' => "x", 'X' => "X", 'o' => "oraNGe", - 'B' => "BANANA" - ) -); +echo "SORT_REGULAR\n"; +$temp_array = $array; +var_dump(arsort($temp_array, SORT_REGULAR)); // expecting : bool(true) +var_dump($temp_array); -$flags = array("SORT_REGULAR" => SORT_REGULAR, "SORT_STRING" => SORT_STRING); +echo "SORT_STRING\n"; +$temp_array = $array; +var_dump(arsort($temp_array, SORT_STRING)); // expecting : bool(true) +var_dump($temp_array); -$count = 1; -echo "\n-- Testing arsort() by supplying various string arrays --\n"; - -// loop through to test arsort() with different arrays -foreach ($various_arrays as $array) { - echo "\n-- Iteration $count --\n"; - - echo "- With default sort_flag -\n"; - $temp_array = $array; - var_dump(arsort($temp_array) ); // expecting : bool(true) - var_dump($temp_array); - - // loop through $flags array and setting all possible flag values - foreach($flags as $key => $flag){ - echo "- Sort_flag = $key -\n"; - $temp_array = $array; - var_dump(arsort($temp_array, $flag) ); // expecting : bool(true) - var_dump($temp_array); - } - $count++; -} - -echo "Done\n"; ?> --EXPECT-- -*** Testing arsort() : usage variations *** - --- Testing arsort() by supplying various string arrays -- - --- Iteration 1 -- -- With default sort_flag - -bool(true) -array(12) { - ["\xhh"]=> - string(4) "\xhh" - ["\ddd"]=> - string(4) "\ddd" - ["\cx"]=> - string(3) "\cx" - ["\a"]=> - string(2) "\a" - [""]=> - string(1) "" - [" "]=> - string(1) " " - [" "]=> - string(1) " " - [" "]=> - string(1) " " - [" -"]=> - string(1) " -" - [" "]=> - string(1) " " - ["null"]=> - NULL - ["NULL"]=> - NULL -} -- Sort_flag = SORT_REGULAR - -bool(true) -array(12) { - ["\xhh"]=> - string(4) "\xhh" - ["\ddd"]=> - string(4) "\ddd" - ["\cx"]=> - string(3) "\cx" - ["\a"]=> - string(2) "\a" - [""]=> - string(1) "" - [" "]=> - string(1) " " - [" "]=> - string(1) " " - [" "]=> - string(1) " " - [" -"]=> - string(1) " -" - [" "]=> - string(1) " " - ["null"]=> - NULL - ["NULL"]=> - NULL -} -- Sort_flag = SORT_STRING - -bool(true) -array(12) { - ["\xhh"]=> - string(4) "\xhh" - ["\ddd"]=> - string(4) "\ddd" - ["\cx"]=> - string(3) "\cx" - ["\a"]=> - string(2) "\a" - [""]=> - string(1) "" - [" "]=> - string(1) " " - [" "]=> - string(1) " " - [" "]=> - string(1) " " - [" -"]=> - string(1) " -" - [" "]=> - string(1) " " - ["null"]=> - NULL - ["NULL"]=> - NULL -} - --- Iteration 2 -- -- With default sort_flag - +Default flag bool(true) array(12) { ["x"]=> string(1) "x" - ["w"]=> + ["ww"]=> string(2) "ww" - ["t"]=> + ["ttt"]=> string(3) "ttt" - ["o"]=> + ["oraNGe"]=> string(6) "oraNGe" - ["l"]=> + ["lemoN"]=> string(5) "lemoN" - ["b"]=> + ["banana"]=> string(6) "banana" - ["a"]=> + ["apple"]=> string(5) "apple" ["X"]=> string(1) "X" - ["Te"]=> + ["Test"]=> string(4) "Test" - ["T"]=> + ["TTTT"]=> string(4) "TTTT" - ["O"]=> + ["Orange"]=> string(6) "Orange" - ["B"]=> + ["BANANA"]=> string(6) "BANANA" } -- Sort_flag = SORT_REGULAR - +SORT_REGULAR bool(true) array(12) { ["x"]=> string(1) "x" - ["w"]=> + ["ww"]=> string(2) "ww" - ["t"]=> + ["ttt"]=> string(3) "ttt" - ["o"]=> + ["oraNGe"]=> string(6) "oraNGe" - ["l"]=> + ["lemoN"]=> string(5) "lemoN" - ["b"]=> + ["banana"]=> string(6) "banana" - ["a"]=> + ["apple"]=> string(5) "apple" ["X"]=> string(1) "X" - ["Te"]=> + ["Test"]=> string(4) "Test" - ["T"]=> + ["TTTT"]=> string(4) "TTTT" - ["O"]=> + ["Orange"]=> string(6) "Orange" - ["B"]=> + ["BANANA"]=> string(6) "BANANA" } -- Sort_flag = SORT_STRING - +SORT_STRING bool(true) array(12) { ["x"]=> string(1) "x" - ["w"]=> + ["ww"]=> string(2) "ww" - ["t"]=> + ["ttt"]=> string(3) "ttt" - ["o"]=> + ["oraNGe"]=> string(6) "oraNGe" - ["l"]=> + ["lemoN"]=> string(5) "lemoN" - ["b"]=> + ["banana"]=> string(6) "banana" - ["a"]=> + ["apple"]=> string(5) "apple" ["X"]=> string(1) "X" - ["Te"]=> + ["Test"]=> string(4) "Test" - ["T"]=> + ["TTTT"]=> string(4) "TTTT" - ["O"]=> + ["Orange"]=> string(6) "Orange" - ["B"]=> + ["BANANA"]=> string(6) "BANANA" } -Done diff --git a/ext/standard/tests/array/sort/arsort_variation_escape_sequences.phpt b/ext/standard/tests/array/sort/arsort_variation_escape_sequences.phpt new file mode 100644 index 0000000000000..b4a533c42114c --- /dev/null +++ b/ext/standard/tests/array/sort/arsort_variation_escape_sequences.phpt @@ -0,0 +1,59 @@ +--TEST-- +Test arsort() function: sorting escape sequences +--FILE-- + "\xhh", + "\ddd" => "\ddd", + "\cx" => "\cx", + "\a" => "\a", + "\e" => "\e", + "\r" => "\r", + "\f" => "\f", + "\v" => "\v", + "\n" => "\n", + "\t" => "\t", + null => null, +]; + +$array = [ + null => null, + "\a" => "\a", + "\cx" => "\cx", + "\e" => "\e", + "\f" => "\f", + "\n" => "\n", + "\r" => "\r", + "\t" => "\t", + "\xhh" => "\xhh", + "\ddd" => "\ddd", + "\v" => "\v", +]; + +echo "Default flag\n"; +$temp_array = $array; +var_dump(arsort($temp_array)); // expecting : bool(true) +var_dump($temp_array === EXPECTED_RESULT); + +echo "SORT_REGULAR\n"; +$temp_array = $array; +var_dump(arsort($temp_array, SORT_REGULAR)); // expecting : bool(true) +var_dump($temp_array === EXPECTED_RESULT); + +echo "SORT_STRING\n"; +$temp_array = $array; +var_dump(arsort($temp_array, SORT_STRING)); // expecting : bool(true) +var_dump($temp_array === EXPECTED_RESULT); + +?> +--EXPECT-- +Default flag +bool(true) +bool(true) +SORT_REGULAR +bool(true) +bool(true) +SORT_STRING +bool(true) +bool(true) diff --git a/ext/standard/tests/array/sort/asort_variation5.phpt b/ext/standard/tests/array/sort/asort_variation5.phpt index f39c4829b1758..d5a8930f090c3 100644 --- a/ext/standard/tests/array/sort/asort_variation5.phpt +++ b/ext/standard/tests/array/sort/asort_variation5.phpt @@ -2,235 +2,120 @@ Test asort() function : usage variations - sort strings --FILE-- "lemoN", + "Orange" => "Orange", + "banana" => "banana", + "apple" => "apple", + "Test" => "Test", + "TTTT" => "TTTT", + "ttt" => "ttt", + "ww" => "ww", + "x" => "x", + "X" => "X", + "oraNGe" => "oraNGe", + "BANANA" => "BANANA", +]; -$various_arrays = array ( - // group of escape sequences - array ("null"=> null, "NULL" => NULL, "\a" => "\a", "\cx" => "\cx", "\e" => "\e", - "\f" => "\f", "\n" =>"\n", "\r" => "\r", "\t" => "\t", "\xhh" => "\xhh", - "\ddd" => "\ddd", "\v" => "\v" - ), +echo "Default flag\n"; +$temp_array = $array; +var_dump(asort($temp_array)); // expecting : bool(true) +var_dump($temp_array); - // array contains combination of capital/small letters - array ('l' => "lemoN", 'O' => "Orange", 'b' => "banana", 'a' => "apple", 'Te' => "Test", - 'T' => "TTTT", 't' => "ttt", 'w' => "ww", 'x' => "x", 'X' => "X", 'o' => "oraNGe", - 'B' => "BANANA" - ) -); +echo "SORT_REGULAR\n"; +$temp_array = $array; +var_dump(asort($temp_array, SORT_REGULAR)); // expecting : bool(true) +var_dump($temp_array); -$flags = array("SORT_REGULAR" => SORT_REGULAR, "SORT_STRING" => SORT_STRING); +echo "SORT_STRING\n"; +$temp_array = $array; +var_dump(asort($temp_array, SORT_STRING)); // expecting : bool(true) +var_dump($temp_array); -$count = 1; -echo "\n-- Testing asort() by supplying various string arrays --\n"; - -// loop through to test asort() with different arrays -foreach ($various_arrays as $array) { - echo "\n-- Iteration $count --\n"; - - echo "- With default sort_flag -\n"; - $temp_array = $array; - var_dump(asort($temp_array) ); // expecting : bool(true) - var_dump($temp_array); - - // loop through $flags array and setting all possible flag values - foreach($flags as $key => $flag){ - echo "- Sort_flag = $key -\n"; - $temp_array = $array; - var_dump(asort($temp_array, $flag) ); // expecting : bool(true) - var_dump($temp_array); - } - $count++; -} - -echo "Done\n"; ?> --EXPECT-- -*** Testing asort() : usage variations *** - --- Testing asort() by supplying various string arrays -- - --- Iteration 1 -- -- With default sort_flag - -bool(true) -array(12) { - ["null"]=> - NULL - ["NULL"]=> - NULL - [" "]=> - string(1) " " - [" -"]=> - string(1) " -" - [" "]=> - string(1) " " - [" "]=> - string(1) " " - [" "]=> - string(1) " " - [""]=> - string(1) "" - ["\a"]=> - string(2) "\a" - ["\cx"]=> - string(3) "\cx" - ["\ddd"]=> - string(4) "\ddd" - ["\xhh"]=> - string(4) "\xhh" -} -- Sort_flag = SORT_REGULAR - +Default flag bool(true) array(12) { - ["null"]=> - NULL - ["NULL"]=> - NULL - [" "]=> - string(1) " " - [" -"]=> - string(1) " -" - [" "]=> - string(1) " " - [" "]=> - string(1) " " - [" "]=> - string(1) " " - [""]=> - string(1) "" - ["\a"]=> - string(2) "\a" - ["\cx"]=> - string(3) "\cx" - ["\ddd"]=> - string(4) "\ddd" - ["\xhh"]=> - string(4) "\xhh" -} -- Sort_flag = SORT_STRING - -bool(true) -array(12) { - ["null"]=> - NULL - ["NULL"]=> - NULL - [" "]=> - string(1) " " - [" -"]=> - string(1) " -" - [" "]=> - string(1) " " - [" "]=> - string(1) " " - [" "]=> - string(1) " " - [""]=> - string(1) "" - ["\a"]=> - string(2) "\a" - ["\cx"]=> - string(3) "\cx" - ["\ddd"]=> - string(4) "\ddd" - ["\xhh"]=> - string(4) "\xhh" -} - --- Iteration 2 -- -- With default sort_flag - -bool(true) -array(12) { - ["B"]=> + ["BANANA"]=> string(6) "BANANA" - ["O"]=> + ["Orange"]=> string(6) "Orange" - ["T"]=> + ["TTTT"]=> string(4) "TTTT" - ["Te"]=> + ["Test"]=> string(4) "Test" ["X"]=> string(1) "X" - ["a"]=> + ["apple"]=> string(5) "apple" - ["b"]=> + ["banana"]=> string(6) "banana" - ["l"]=> + ["lemoN"]=> string(5) "lemoN" - ["o"]=> + ["oraNGe"]=> string(6) "oraNGe" - ["t"]=> + ["ttt"]=> string(3) "ttt" - ["w"]=> + ["ww"]=> string(2) "ww" ["x"]=> string(1) "x" } -- Sort_flag = SORT_REGULAR - +SORT_REGULAR bool(true) array(12) { - ["B"]=> + ["BANANA"]=> string(6) "BANANA" - ["O"]=> + ["Orange"]=> string(6) "Orange" - ["T"]=> + ["TTTT"]=> string(4) "TTTT" - ["Te"]=> + ["Test"]=> string(4) "Test" ["X"]=> string(1) "X" - ["a"]=> + ["apple"]=> string(5) "apple" - ["b"]=> + ["banana"]=> string(6) "banana" - ["l"]=> + ["lemoN"]=> string(5) "lemoN" - ["o"]=> + ["oraNGe"]=> string(6) "oraNGe" - ["t"]=> + ["ttt"]=> string(3) "ttt" - ["w"]=> + ["ww"]=> string(2) "ww" ["x"]=> string(1) "x" } -- Sort_flag = SORT_STRING - +SORT_STRING bool(true) array(12) { - ["B"]=> + ["BANANA"]=> string(6) "BANANA" - ["O"]=> + ["Orange"]=> string(6) "Orange" - ["T"]=> + ["TTTT"]=> string(4) "TTTT" - ["Te"]=> + ["Test"]=> string(4) "Test" ["X"]=> string(1) "X" - ["a"]=> + ["apple"]=> string(5) "apple" - ["b"]=> + ["banana"]=> string(6) "banana" - ["l"]=> + ["lemoN"]=> string(5) "lemoN" - ["o"]=> + ["oraNGe"]=> string(6) "oraNGe" - ["t"]=> + ["ttt"]=> string(3) "ttt" - ["w"]=> + ["ww"]=> string(2) "ww" ["x"]=> string(1) "x" -} -Done +} \ No newline at end of file diff --git a/ext/standard/tests/array/sort/asort_variation_escape_sequences.phpt b/ext/standard/tests/array/sort/asort_variation_escape_sequences.phpt new file mode 100644 index 0000000000000..6de02b66ae0a6 --- /dev/null +++ b/ext/standard/tests/array/sort/asort_variation_escape_sequences.phpt @@ -0,0 +1,59 @@ +--TEST-- +Test asort() function: sorting escape sequences +--FILE-- + null, + "\t" => "\t", + "\n" => "\n", + "\v" => "\v", + "\f" => "\f", + "\r" => "\r", + "\e" => "\e", + "\a" => "\a", + "\cx" => "\cx", + "\ddd" => "\ddd", + "\xhh" => "\xhh", +]; + +$array = [ + null => null, + "\a" => "\a", + "\cx" => "\cx", + "\e" => "\e", + "\f" => "\f", + "\n" => "\n", + "\r" => "\r", + "\t" => "\t", + "\xhh" => "\xhh", + "\ddd" => "\ddd", + "\v" => "\v", +]; + +echo "Default flag\n"; +$temp_array = $array; +var_dump(asort($temp_array)); // expecting : bool(true) +var_dump($temp_array === EXPECTED_RESULT); + +echo "SORT_REGULAR\n"; +$temp_array = $array; +var_dump(asort($temp_array, SORT_REGULAR)); // expecting : bool(true) +var_dump($temp_array === EXPECTED_RESULT); + +echo "SORT_STRING\n"; +$temp_array = $array; +var_dump(asort($temp_array, SORT_STRING)); // expecting : bool(true) +var_dump($temp_array === EXPECTED_RESULT); + +?> +--EXPECT-- +Default flag +bool(true) +bool(true) +SORT_REGULAR +bool(true) +bool(true) +SORT_STRING +bool(true) +bool(true) diff --git a/ext/standard/tests/array/sort/krsort_variation5.phpt b/ext/standard/tests/array/sort/krsort_variation5.phpt index 7475805f8d4d5..b1fe5897f16c9 100644 --- a/ext/standard/tests/array/sort/krsort_variation5.phpt +++ b/ext/standard/tests/array/sort/krsort_variation5.phpt @@ -2,224 +2,120 @@ Test krsort() function : usage variations - sort strings --FILE-- "lemoN", + "Orange" => "Orange", + "banana" => "banana", + "apple" => "apple", + "Test" => "Test", + "TTTT" => "TTTT", + "ttt" => "ttt", + "ww" => "ww", + "x" => "x", + "X" => "X", + "oraNGe" => "oraNGe", + "BANANA" => "BANANA", +]; -$various_arrays = array ( - // diff. escape sequence chars with key values - array ( null => null, NULL => NULL, "\a" => "\a", "\cx" => "\cx", "\e" => "\e", - "\f" => "\f", "\n" =>"\n", "\r" => "\r", "\t" => "\t", "\xhh" => "\xhh", - "\ddd" => "\ddd", "\v" => "\v" - ), +echo "Default flag\n"; +$temp_array = $array; +var_dump(ksort($temp_array)); // expecting : bool(true) +var_dump($temp_array); - // array containing different strings with key values - array ( 'Lemon' => "lemoN", 'o' => "Orange", 'B' => "banana", 'Apple' => "apple", 'te' => "Test", - 't' => "TTTT", 'T' => "ttt", 'W' => "ww", 'X' => "x", 'x' => "X", 'O' => "oraNGe", - 'B' => "BANANA" - ) -); +echo "SORT_REGULAR\n"; +$temp_array = $array; +var_dump(ksort($temp_array, SORT_REGULAR)); // expecting : bool(true) +var_dump($temp_array); -$flags = array("SORT_REGULAR" => SORT_REGULAR, "SORT_STRING" => SORT_STRING); +echo "SORT_STRING\n"; +$temp_array = $array; +var_dump(ksort($temp_array, SORT_STRING)); // expecting : bool(true) +var_dump($temp_array); -$count = 1; -echo "\n-- Testing krsort() by supplying various string arrays --\n"; - -// loop through to test krsort() with different arrays -foreach ($various_arrays as $array) { - echo "\n-- Iteration $count --\n"; - - echo "- With default sort flag -\n"; - $temp_array = $array; - var_dump(krsort($temp_array) ); // expecting : bool(true) - var_dump($temp_array); - - // loop through $flags array and call krsort() with all possible sort flag values - foreach($flags as $key => $flag){ - echo "- Sort flag = $key -\n"; - $temp_array = $array; - var_dump(krsort($temp_array, $flag) ); // expecting : bool(true) - var_dump($temp_array); - } - $count++; -} - -echo "Done\n"; ?> --EXPECT-- -*** Testing krsort() : usage variations *** - --- Testing krsort() by supplying various string arrays -- - --- Iteration 1 -- -- With default sort flag - +Default flag bool(true) -array(11) { - ["\xhh"]=> - string(4) "\xhh" - ["\ddd"]=> - string(4) "\ddd" - ["\cx"]=> - string(3) "\cx" - ["\a"]=> - string(2) "\a" - [""]=> - string(1) "" - [" "]=> - string(1) " " - [" "]=> - string(1) " " - [" "]=> - string(1) " " - [" -"]=> - string(1) " -" - [" "]=> - string(1) " " - [""]=> - NULL -} -- Sort flag = SORT_REGULAR - -bool(true) -array(11) { - ["\xhh"]=> - string(4) "\xhh" - ["\ddd"]=> - string(4) "\ddd" - ["\cx"]=> - string(3) "\cx" - ["\a"]=> - string(2) "\a" - [""]=> - string(1) "" - [" "]=> - string(1) " " - [" "]=> - string(1) " " - [" "]=> - string(1) " " - [" -"]=> - string(1) " -" - [" "]=> - string(1) " " - [""]=> - NULL -} -- Sort flag = SORT_STRING - -bool(true) -array(11) { - ["\xhh"]=> - string(4) "\xhh" - ["\ddd"]=> - string(4) "\ddd" - ["\cx"]=> - string(3) "\cx" - ["\a"]=> - string(2) "\a" - [""]=> - string(1) "" - [" "]=> - string(1) " " - [" "]=> - string(1) " " - [" "]=> - string(1) " " - [" -"]=> - string(1) " -" - [" "]=> - string(1) " " - [""]=> - NULL -} - --- Iteration 2 -- -- With default sort flag - -bool(true) -array(11) { - ["x"]=> - string(1) "X" - ["te"]=> - string(4) "Test" - ["t"]=> - string(4) "TTTT" - ["o"]=> +array(12) { + ["BANANA"]=> + string(6) "BANANA" + ["Orange"]=> string(6) "Orange" + ["TTTT"]=> + string(4) "TTTT" + ["Test"]=> + string(4) "Test" ["X"]=> - string(1) "x" - ["W"]=> - string(2) "ww" - ["T"]=> - string(3) "ttt" - ["O"]=> - string(6) "oraNGe" - ["Lemon"]=> - string(5) "lemoN" - ["B"]=> - string(6) "BANANA" - ["Apple"]=> + string(1) "X" + ["apple"]=> string(5) "apple" + ["banana"]=> + string(6) "banana" + ["lemoN"]=> + string(5) "lemoN" + ["oraNGe"]=> + string(6) "oraNGe" + ["ttt"]=> + string(3) "ttt" + ["ww"]=> + string(2) "ww" + ["x"]=> + string(1) "x" } -- Sort flag = SORT_REGULAR - +SORT_REGULAR bool(true) -array(11) { - ["x"]=> - string(1) "X" - ["te"]=> - string(4) "Test" - ["t"]=> - string(4) "TTTT" - ["o"]=> +array(12) { + ["BANANA"]=> + string(6) "BANANA" + ["Orange"]=> string(6) "Orange" + ["TTTT"]=> + string(4) "TTTT" + ["Test"]=> + string(4) "Test" ["X"]=> - string(1) "x" - ["W"]=> - string(2) "ww" - ["T"]=> - string(3) "ttt" - ["O"]=> - string(6) "oraNGe" - ["Lemon"]=> - string(5) "lemoN" - ["B"]=> - string(6) "BANANA" - ["Apple"]=> + string(1) "X" + ["apple"]=> string(5) "apple" + ["banana"]=> + string(6) "banana" + ["lemoN"]=> + string(5) "lemoN" + ["oraNGe"]=> + string(6) "oraNGe" + ["ttt"]=> + string(3) "ttt" + ["ww"]=> + string(2) "ww" + ["x"]=> + string(1) "x" } -- Sort flag = SORT_STRING - +SORT_STRING bool(true) -array(11) { - ["x"]=> - string(1) "X" - ["te"]=> - string(4) "Test" - ["t"]=> - string(4) "TTTT" - ["o"]=> +array(12) { + ["BANANA"]=> + string(6) "BANANA" + ["Orange"]=> string(6) "Orange" + ["TTTT"]=> + string(4) "TTTT" + ["Test"]=> + string(4) "Test" ["X"]=> - string(1) "x" - ["W"]=> - string(2) "ww" - ["T"]=> - string(3) "ttt" - ["O"]=> - string(6) "oraNGe" - ["Lemon"]=> - string(5) "lemoN" - ["B"]=> - string(6) "BANANA" - ["Apple"]=> + string(1) "X" + ["apple"]=> string(5) "apple" + ["banana"]=> + string(6) "banana" + ["lemoN"]=> + string(5) "lemoN" + ["oraNGe"]=> + string(6) "oraNGe" + ["ttt"]=> + string(3) "ttt" + ["ww"]=> + string(2) "ww" + ["x"]=> + string(1) "x" } -Done diff --git a/ext/standard/tests/array/sort/krsort_variation_escape_sequences.phpt b/ext/standard/tests/array/sort/krsort_variation_escape_sequences.phpt new file mode 100644 index 0000000000000..ac56df76ed7ca --- /dev/null +++ b/ext/standard/tests/array/sort/krsort_variation_escape_sequences.phpt @@ -0,0 +1,59 @@ +--TEST-- +Test krsort() function: sorting escape sequences +--FILE-- + "\xhh", + "\ddd" => "\ddd", + "\cx" => "\cx", + "\a" => "\a", + "\e" => "\e", + "\r" => "\r", + "\f" => "\f", + "\v" => "\v", + "\n" => "\n", + "\t" => "\t", + null => null, +]; + +$array = [ + null => null, + "\a" => "\a", + "\cx" => "\cx", + "\e" => "\e", + "\f" => "\f", + "\n" => "\n", + "\r" => "\r", + "\t" => "\t", + "\xhh" => "\xhh", + "\ddd" => "\ddd", + "\v" => "\v", +]; + +echo "Default flag\n"; +$temp_array = $array; +var_dump(krsort($temp_array)); // expecting : bool(true) +var_dump($temp_array === EXPECTED_RESULT); + +echo "SORT_REGULAR\n"; +$temp_array = $array; +var_dump(krsort($temp_array, SORT_REGULAR)); // expecting : bool(true) +var_dump($temp_array === EXPECTED_RESULT); + +echo "SORT_STRING\n"; +$temp_array = $array; +var_dump(krsort($temp_array, SORT_STRING)); // expecting : bool(true) +var_dump($temp_array === EXPECTED_RESULT); + +?> +--EXPECT-- +Default flag +bool(true) +bool(true) +SORT_REGULAR +bool(true) +bool(true) +SORT_STRING +bool(true) +bool(true) diff --git a/ext/standard/tests/array/sort/ksort_variation5.phpt b/ext/standard/tests/array/sort/ksort_variation5.phpt index 0538043744228..f69b0b14d5d05 100644 --- a/ext/standard/tests/array/sort/ksort_variation5.phpt +++ b/ext/standard/tests/array/sort/ksort_variation5.phpt @@ -2,224 +2,120 @@ Test ksort() function : usage variations - sort strings --FILE-- "lemoN", + "Orange" => "Orange", + "banana" => "banana", + "apple" => "apple", + "Test" => "Test", + "TTTT" => "TTTT", + "ttt" => "ttt", + "ww" => "ww", + "x" => "x", + "X" => "X", + "oraNGe" => "oraNGe", + "BANANA" => "BANANA", +]; -$various_arrays = array ( - // diff. escape sequence chars with key values - array ( null => null, NULL => NULL, "\a" => "\a", "\cx" => "\cx", "\e" => "\e", - "\f" => "\f", "\n" =>"\n", "\r" => "\r", "\t" => "\t", "\xhh" => "\xhh", - "\ddd" => "\ddd", "\v" => "\v" - ), +echo "Default flag\n"; +$temp_array = $array; +var_dump(ksort($temp_array)); // expecting : bool(true) +var_dump($temp_array); - // array containing different strings with key values - array ( 'Lemon' => "lemoN", 'o' => "Orange", 'B' => "banana", 'Apple' => "apple", 'te' => "Test", - 't' => "TTTT", 'T' => "ttt", 'W' => "ww", 'X' => "x", 'x' => "X", 'O' => "oraNGe", - 'B' => "BANANA" - ) -); +echo "SORT_REGULAR\n"; +$temp_array = $array; +var_dump(ksort($temp_array, SORT_REGULAR)); // expecting : bool(true) +var_dump($temp_array); -$flags = array("SORT_REGULAR" => SORT_REGULAR, "SORT_STRING" => SORT_STRING); +echo "SORT_STRING\n"; +$temp_array = $array; +var_dump(ksort($temp_array, SORT_STRING)); // expecting : bool(true) +var_dump($temp_array); -$count = 1; -echo "\n-- Testing ksort() by supplying various string arrays --\n"; - -// loop through to test ksort() with different arrays -foreach ($various_arrays as $array) { - echo "\n-- Iteration $count --\n"; - - echo "- With default sort flag -\n"; - $temp_array = $array; - var_dump(ksort($temp_array) ); // expecting : bool(true) - var_dump($temp_array); - - // loop through $flags array and call ksort() with all possible sort flag values - foreach($flags as $key => $flag){ - echo "- Sort flag = $key -\n"; - $temp_array = $array; - var_dump(ksort($temp_array, $flag) ); // expecting : bool(true) - var_dump($temp_array); - } - $count++; -} - -echo "Done\n"; ?> --EXPECT-- -*** Testing ksort() : usage variations *** - --- Testing ksort() by supplying various string arrays -- - --- Iteration 1 -- -- With default sort flag - -bool(true) -array(11) { - [""]=> - NULL - [" "]=> - string(1) " " - [" -"]=> - string(1) " -" - [" "]=> - string(1) " " - [" "]=> - string(1) " " - [" "]=> - string(1) " " - [""]=> - string(1) "" - ["\a"]=> - string(2) "\a" - ["\cx"]=> - string(3) "\cx" - ["\ddd"]=> - string(4) "\ddd" - ["\xhh"]=> - string(4) "\xhh" -} -- Sort flag = SORT_REGULAR - -bool(true) -array(11) { - [""]=> - NULL - [" "]=> - string(1) " " - [" -"]=> - string(1) " -" - [" "]=> - string(1) " " - [" "]=> - string(1) " " - [" "]=> - string(1) " " - [""]=> - string(1) "" - ["\a"]=> - string(2) "\a" - ["\cx"]=> - string(3) "\cx" - ["\ddd"]=> - string(4) "\ddd" - ["\xhh"]=> - string(4) "\xhh" -} -- Sort flag = SORT_STRING - -bool(true) -array(11) { - [""]=> - NULL - [" "]=> - string(1) " " - [" -"]=> - string(1) " -" - [" "]=> - string(1) " " - [" "]=> - string(1) " " - [" "]=> - string(1) " " - [""]=> - string(1) "" - ["\a"]=> - string(2) "\a" - ["\cx"]=> - string(3) "\cx" - ["\ddd"]=> - string(4) "\ddd" - ["\xhh"]=> - string(4) "\xhh" -} - --- Iteration 2 -- -- With default sort flag - +Default flag bool(true) -array(11) { - ["Apple"]=> - string(5) "apple" - ["B"]=> +array(12) { + ["BANANA"]=> string(6) "BANANA" - ["Lemon"]=> + ["Orange"]=> + string(6) "Orange" + ["TTTT"]=> + string(4) "TTTT" + ["Test"]=> + string(4) "Test" + ["X"]=> + string(1) "X" + ["apple"]=> + string(5) "apple" + ["banana"]=> + string(6) "banana" + ["lemoN"]=> string(5) "lemoN" - ["O"]=> + ["oraNGe"]=> string(6) "oraNGe" - ["T"]=> + ["ttt"]=> string(3) "ttt" - ["W"]=> + ["ww"]=> string(2) "ww" - ["X"]=> + ["x"]=> string(1) "x" - ["o"]=> +} +SORT_REGULAR +bool(true) +array(12) { + ["BANANA"]=> + string(6) "BANANA" + ["Orange"]=> string(6) "Orange" - ["t"]=> + ["TTTT"]=> string(4) "TTTT" - ["te"]=> + ["Test"]=> string(4) "Test" - ["x"]=> + ["X"]=> string(1) "X" -} -- Sort flag = SORT_REGULAR - -bool(true) -array(11) { - ["Apple"]=> + ["apple"]=> string(5) "apple" - ["B"]=> - string(6) "BANANA" - ["Lemon"]=> + ["banana"]=> + string(6) "banana" + ["lemoN"]=> string(5) "lemoN" - ["O"]=> + ["oraNGe"]=> string(6) "oraNGe" - ["T"]=> + ["ttt"]=> string(3) "ttt" - ["W"]=> + ["ww"]=> string(2) "ww" - ["X"]=> + ["x"]=> string(1) "x" - ["o"]=> +} +SORT_STRING +bool(true) +array(12) { + ["BANANA"]=> + string(6) "BANANA" + ["Orange"]=> string(6) "Orange" - ["t"]=> + ["TTTT"]=> string(4) "TTTT" - ["te"]=> + ["Test"]=> string(4) "Test" - ["x"]=> + ["X"]=> string(1) "X" -} -- Sort flag = SORT_STRING - -bool(true) -array(11) { - ["Apple"]=> + ["apple"]=> string(5) "apple" - ["B"]=> - string(6) "BANANA" - ["Lemon"]=> + ["banana"]=> + string(6) "banana" + ["lemoN"]=> string(5) "lemoN" - ["O"]=> + ["oraNGe"]=> string(6) "oraNGe" - ["T"]=> + ["ttt"]=> string(3) "ttt" - ["W"]=> + ["ww"]=> string(2) "ww" - ["X"]=> - string(1) "x" - ["o"]=> - string(6) "Orange" - ["t"]=> - string(4) "TTTT" - ["te"]=> - string(4) "Test" ["x"]=> - string(1) "X" + string(1) "x" } -Done diff --git a/ext/standard/tests/array/sort/ksort_variation_escape_sequences.phpt b/ext/standard/tests/array/sort/ksort_variation_escape_sequences.phpt new file mode 100644 index 0000000000000..e880227b1c9e0 --- /dev/null +++ b/ext/standard/tests/array/sort/ksort_variation_escape_sequences.phpt @@ -0,0 +1,59 @@ +--TEST-- +Test ksort() function: sorting escape sequences +--FILE-- + null, + "\t" => "\t", + "\n" => "\n", + "\v" => "\v", + "\f" => "\f", + "\r" => "\r", + "\e" => "\e", + "\a" => "\a", + "\cx" => "\cx", + "\ddd" => "\ddd", + "\xhh" => "\xhh", +]; + +$array = [ + null => null, + "\a" => "\a", + "\cx" => "\cx", + "\e" => "\e", + "\f" => "\f", + "\n" => "\n", + "\r" => "\r", + "\t" => "\t", + "\xhh" => "\xhh", + "\ddd" => "\ddd", + "\v" => "\v", +]; + +echo "Default flag\n"; +$temp_array = $array; +var_dump(ksort($temp_array)); // expecting : bool(true) +var_dump($temp_array === EXPECTED_RESULT); + +echo "SORT_REGULAR\n"; +$temp_array = $array; +var_dump(ksort($temp_array, SORT_REGULAR)); // expecting : bool(true) +var_dump($temp_array === EXPECTED_RESULT); + +echo "SORT_STRING\n"; +$temp_array = $array; +var_dump(ksort($temp_array, SORT_STRING)); // expecting : bool(true) +var_dump($temp_array === EXPECTED_RESULT); + +?> +--EXPECT-- +Default flag +bool(true) +bool(true) +SORT_REGULAR +bool(true) +bool(true) +SORT_STRING +bool(true) +bool(true) diff --git a/ext/standard/tests/array/sort/rsort_variation5.phpt b/ext/standard/tests/array/sort/rsort_variation5.phpt index 6b05443b520bd..c4dd3f6a9ce70 100644 --- a/ext/standard/tests/array/sort/rsort_variation5.phpt +++ b/ext/standard/tests/array/sort/rsort_variation5.phpt @@ -2,214 +2,120 @@ Test rsort() function : usage variations - String values --FILE-- SORT_REGULAR, "SORT_STRING" => SORT_STRING); +echo "SORT_STRING\n"; +$temp_array = $array; +var_dump(sort($temp_array, SORT_STRING)); // expecting : bool(true) +var_dump($temp_array); -$count = 1; -// loop through to test rsort() with different arrays -foreach ($various_arrays as $array) { - echo "\n-- Iteration $count --\n"; - - echo "- With Default sort flag -\n"; - $temp_array = $array; - var_dump(rsort($temp_array) ); - var_dump($temp_array); - - // loop through $flags array and setting all possible flag values - foreach($flags as $key => $flag){ - echo "- Sort flag = $key -\n"; - - $temp_array = $array; - var_dump(rsort($temp_array, $flag) ); - var_dump($temp_array); - } - $count++; -} - -echo "Done"; ?> --EXPECT-- -*** Testing rsort() : variation *** - --- Iteration 1 -- -- With Default sort flag - -bool(true) -array(11) { - [0]=> - string(4) "\xhh" - [1]=> - string(4) "\ddd" - [2]=> - string(3) "\cx" - [3]=> - string(2) "\a" - [4]=> - string(1) "" - [5]=> - string(1) " " - [6]=> - string(1) " " - [7]=> - string(1) " -" - [8]=> - string(1) " " - [9]=> - NULL - [10]=> - NULL -} -- Sort flag = SORT_REGULAR - -bool(true) -array(11) { - [0]=> - string(4) "\xhh" - [1]=> - string(4) "\ddd" - [2]=> - string(3) "\cx" - [3]=> - string(2) "\a" - [4]=> - string(1) "" - [5]=> - string(1) " " - [6]=> - string(1) " " - [7]=> - string(1) " -" - [8]=> - string(1) " " - [9]=> - NULL - [10]=> - NULL -} -- Sort flag = SORT_STRING - -bool(true) -array(11) { - [0]=> - string(4) "\xhh" - [1]=> - string(4) "\ddd" - [2]=> - string(3) "\cx" - [3]=> - string(2) "\a" - [4]=> - string(1) "" - [5]=> - string(1) " " - [6]=> - string(1) " " - [7]=> - string(1) " -" - [8]=> - string(1) " " - [9]=> - NULL - [10]=> - NULL -} - --- Iteration 2 -- -- With Default sort flag - +Default flag bool(true) array(12) { [0]=> - string(1) "x" + string(6) "BANANA" [1]=> - string(2) "ww" + string(6) "Orange" [2]=> - string(3) "ttt" + string(4) "TTTT" [3]=> - string(6) "oraNGe" + string(4) "Test" [4]=> - string(5) "lemoN" + string(1) "X" [5]=> - string(6) "banana" - [6]=> string(5) "apple" + [6]=> + string(6) "banana" [7]=> - string(1) "X" + string(5) "lemoN" [8]=> - string(4) "Test" + string(6) "oraNGe" [9]=> - string(4) "TTTT" + string(3) "ttt" [10]=> - string(6) "Orange" + string(2) "ww" [11]=> - string(6) "BANANA" + string(1) "x" } -- Sort flag = SORT_REGULAR - +SORT_REGULAR bool(true) array(12) { [0]=> - string(1) "x" + string(6) "BANANA" [1]=> - string(2) "ww" + string(6) "Orange" [2]=> - string(3) "ttt" + string(4) "TTTT" [3]=> - string(6) "oraNGe" + string(4) "Test" [4]=> - string(5) "lemoN" + string(1) "X" [5]=> - string(6) "banana" - [6]=> string(5) "apple" + [6]=> + string(6) "banana" [7]=> - string(1) "X" + string(5) "lemoN" [8]=> - string(4) "Test" + string(6) "oraNGe" [9]=> - string(4) "TTTT" + string(3) "ttt" [10]=> - string(6) "Orange" + string(2) "ww" [11]=> - string(6) "BANANA" + string(1) "x" } -- Sort flag = SORT_STRING - +SORT_STRING bool(true) array(12) { [0]=> - string(1) "x" + string(6) "BANANA" [1]=> - string(2) "ww" + string(6) "Orange" [2]=> - string(3) "ttt" + string(4) "TTTT" [3]=> - string(6) "oraNGe" + string(4) "Test" [4]=> - string(5) "lemoN" + string(1) "X" [5]=> - string(6) "banana" - [6]=> string(5) "apple" + [6]=> + string(6) "banana" [7]=> - string(1) "X" + string(5) "lemoN" [8]=> - string(4) "Test" + string(6) "oraNGe" [9]=> - string(4) "TTTT" + string(3) "ttt" [10]=> - string(6) "Orange" + string(2) "ww" [11]=> - string(6) "BANANA" + string(1) "x" } -Done diff --git a/ext/standard/tests/array/sort/rsort_variation_escape_sequences.phpt b/ext/standard/tests/array/sort/rsort_variation_escape_sequences.phpt new file mode 100644 index 0000000000000..57edbe66e1514 --- /dev/null +++ b/ext/standard/tests/array/sort/rsort_variation_escape_sequences.phpt @@ -0,0 +1,59 @@ +--TEST-- +Test rsort() function: sorting escape sequences +--FILE-- + +--EXPECT-- +Default flag +bool(true) +bool(true) +SORT_REGULAR +bool(true) +bool(true) +SORT_STRING +bool(true) +bool(true) diff --git a/ext/standard/tests/array/sort/sort_variation5.phpt b/ext/standard/tests/array/sort/sort_variation5.phpt index 6c49342df25d8..c9e369f4a2807 100644 --- a/ext/standard/tests/array/sort/sort_variation5.phpt +++ b/ext/standard/tests/array/sort/sort_variation5.phpt @@ -2,145 +2,40 @@ Test sort() function : usage variations - sort strings --FILE-- SORT_REGULAR, "SORT_STRING" => SORT_STRING); +echo "SORT_STRING\n"; +$temp_array = $array; +var_dump(sort($temp_array, SORT_STRING)); // expecting : bool(true) +var_dump($temp_array); -$count = 1; -echo "\n-- Testing sort() by supplying various string arrays --\n"; - -// loop through to test sort() with different arrays -foreach ($various_arrays as $array) { - echo "\n-- Iteration $count --\n"; - - echo "- With Default sort flag -\n"; - $temp_array = $array; - var_dump(sort($temp_array) ); // expecting : bool(true) - var_dump($temp_array); - - // loop through $flags array and setting all possible flag values - foreach($flags as $key => $flag){ - echo "- Sort flag = $key -\n"; - $temp_array = $array; - var_dump(sort($temp_array, $flag) ); // expecting : bool(true) - var_dump($temp_array); - } - $count++; -} - -echo "Done\n"; ?> --EXPECT-- -*** Testing sort() : usage variations *** - --- Testing sort() by supplying various string arrays -- - --- Iteration 1 -- -- With Default sort flag - -bool(true) -array(12) { - [0]=> - NULL - [1]=> - NULL - [2]=> - string(1) " " - [3]=> - string(1) " -" - [4]=> - string(1) " " - [5]=> - string(1) " " - [6]=> - string(1) " " - [7]=> - string(1) "" - [8]=> - string(2) "\a" - [9]=> - string(3) "\cx" - [10]=> - string(4) "\ddd" - [11]=> - string(4) "\xhh" -} -- Sort flag = SORT_REGULAR - -bool(true) -array(12) { - [0]=> - NULL - [1]=> - NULL - [2]=> - string(1) " " - [3]=> - string(1) " -" - [4]=> - string(1) " " - [5]=> - string(1) " " - [6]=> - string(1) " " - [7]=> - string(1) "" - [8]=> - string(2) "\a" - [9]=> - string(3) "\cx" - [10]=> - string(4) "\ddd" - [11]=> - string(4) "\xhh" -} -- Sort flag = SORT_STRING - -bool(true) -array(12) { - [0]=> - NULL - [1]=> - NULL - [2]=> - string(1) " " - [3]=> - string(1) " -" - [4]=> - string(1) " " - [5]=> - string(1) " " - [6]=> - string(1) " " - [7]=> - string(1) "" - [8]=> - string(2) "\a" - [9]=> - string(3) "\cx" - [10]=> - string(4) "\ddd" - [11]=> - string(4) "\xhh" -} - --- Iteration 2 -- -- With Default sort flag - +Default flag bool(true) array(12) { [0]=> @@ -168,7 +63,7 @@ array(12) { [11]=> string(1) "x" } -- Sort flag = SORT_REGULAR - +SORT_REGULAR bool(true) array(12) { [0]=> @@ -196,7 +91,7 @@ array(12) { [11]=> string(1) "x" } -- Sort flag = SORT_STRING - +SORT_STRING bool(true) array(12) { [0]=> @@ -224,4 +119,3 @@ array(12) { [11]=> string(1) "x" } -Done diff --git a/ext/standard/tests/array/sort/sort_variation_escape_sequences.phpt b/ext/standard/tests/array/sort/sort_variation_escape_sequences.phpt new file mode 100644 index 0000000000000..e824a6f7e9c9f --- /dev/null +++ b/ext/standard/tests/array/sort/sort_variation_escape_sequences.phpt @@ -0,0 +1,59 @@ +--TEST-- +Test sort() function: sorting escape sequences +--FILE-- + +--EXPECT-- +Default flag +bool(true) +bool(true) +SORT_REGULAR +bool(true) +bool(true) +SORT_STRING +bool(true) +bool(true) From f3b150a6a615b07b77ec576465de8022b5c60525 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Wed, 6 Nov 2024 16:55:05 +0000 Subject: [PATCH 14/40] ext/standard: Move array_walk(_recursive)() tests into subfolder --- ext/standard/tests/array/{ => array_walk}/array_walk.phpt | 0 ext/standard/tests/array/{ => array_walk}/array_walk_basic1.phpt | 0 ext/standard/tests/array/{ => array_walk}/array_walk_basic2.phpt | 0 ext/standard/tests/array/{ => array_walk}/array_walk_closure.phpt | 0 ext/standard/tests/array/{ => array_walk}/array_walk_error2.phpt | 0 ext/standard/tests/array/{ => array_walk}/array_walk_object1.phpt | 0 ext/standard/tests/array/{ => array_walk}/array_walk_object2.phpt | 0 ext/standard/tests/array/{ => array_walk}/array_walk_objects.phpt | 0 .../tests/array/{ => array_walk}/array_walk_rec_objects.phpt | 0 .../tests/array/{ => array_walk}/array_walk_recursive.phpt | 0 .../tests/array/{ => array_walk}/array_walk_recursive1.phpt | 0 .../tests/array/{ => array_walk}/array_walk_recursive_basic1.phpt | 0 .../tests/array/{ => array_walk}/array_walk_recursive_basic2.phpt | 0 .../tests/array/{ => array_walk}/array_walk_recursive_error2.phpt | 0 .../array/{ => array_walk}/array_walk_recursive_object1.phpt | 0 .../array/{ => array_walk}/array_walk_recursive_object2.phpt | 0 .../array/{ => array_walk}/array_walk_recursive_variation3.phpt | 0 .../array/{ => array_walk}/array_walk_recursive_variation4.phpt | 0 .../array/{ => array_walk}/array_walk_recursive_variation5.phpt | 0 .../array/{ => array_walk}/array_walk_recursive_variation6.phpt | 0 .../array/{ => array_walk}/array_walk_recursive_variation7.phpt | 0 .../array/{ => array_walk}/array_walk_recursive_variation8.phpt | 0 .../array/{ => array_walk}/array_walk_recursive_variation9.phpt | 0 .../tests/array/{ => array_walk}/array_walk_variation3.phpt | 0 .../tests/array/{ => array_walk}/array_walk_variation4.phpt | 0 .../tests/array/{ => array_walk}/array_walk_variation5.phpt | 0 .../tests/array/{ => array_walk}/array_walk_variation6.phpt | 0 .../tests/array/{ => array_walk}/array_walk_variation7.phpt | 0 .../tests/array/{ => array_walk}/array_walk_variation8.phpt | 0 .../tests/array/{ => array_walk}/array_walk_variation9.phpt | 0 ext/standard/tests/array/{ => array_walk}/bug12776.phpt | 0 ext/standard/tests/array/{ => array_walk}/bug30266.phpt | 0 ext/standard/tests/array/{ => array_walk}/bug34066.phpt | 0 ext/standard/tests/array/{ => array_walk}/bug34066_1.phpt | 0 ext/standard/tests/array/{ => array_walk}/bug34982.phpt | 0 ext/standard/tests/array/{ => array_walk}/bug39576.phpt | 0 ext/standard/tests/array/{ => array_walk}/bug42850.phpt | 0 ext/standard/tests/array/{ => array_walk}/bug52719.phpt | 0 ext/standard/tests/array/{ => array_walk}/bug61730.phpt | 0 ext/standard/tests/array/{ => array_walk}/bug61967.phpt | 0 ext/standard/tests/array/{ => array_walk}/bug62607.phpt | 0 ext/standard/tests/array/{ => array_walk}/bug69068.phpt | 0 ext/standard/tests/array/{ => array_walk}/bug69068_2.phpt | 0 ext/standard/tests/array/{ => array_walk}/bug70713.phpt | 0 ext/standard/tests/array/{ => array_walk}/bug79839.phpt | 0 45 files changed, 0 insertions(+), 0 deletions(-) rename ext/standard/tests/array/{ => array_walk}/array_walk.phpt (100%) rename ext/standard/tests/array/{ => array_walk}/array_walk_basic1.phpt (100%) rename ext/standard/tests/array/{ => array_walk}/array_walk_basic2.phpt (100%) rename ext/standard/tests/array/{ => array_walk}/array_walk_closure.phpt (100%) rename ext/standard/tests/array/{ => array_walk}/array_walk_error2.phpt (100%) rename ext/standard/tests/array/{ => array_walk}/array_walk_object1.phpt (100%) rename ext/standard/tests/array/{ => array_walk}/array_walk_object2.phpt (100%) rename ext/standard/tests/array/{ => array_walk}/array_walk_objects.phpt (100%) rename ext/standard/tests/array/{ => array_walk}/array_walk_rec_objects.phpt (100%) rename ext/standard/tests/array/{ => array_walk}/array_walk_recursive.phpt (100%) rename ext/standard/tests/array/{ => array_walk}/array_walk_recursive1.phpt (100%) rename ext/standard/tests/array/{ => array_walk}/array_walk_recursive_basic1.phpt (100%) rename ext/standard/tests/array/{ => array_walk}/array_walk_recursive_basic2.phpt (100%) rename ext/standard/tests/array/{ => array_walk}/array_walk_recursive_error2.phpt (100%) rename ext/standard/tests/array/{ => array_walk}/array_walk_recursive_object1.phpt (100%) rename ext/standard/tests/array/{ => array_walk}/array_walk_recursive_object2.phpt (100%) rename ext/standard/tests/array/{ => array_walk}/array_walk_recursive_variation3.phpt (100%) rename ext/standard/tests/array/{ => array_walk}/array_walk_recursive_variation4.phpt (100%) rename ext/standard/tests/array/{ => array_walk}/array_walk_recursive_variation5.phpt (100%) rename ext/standard/tests/array/{ => array_walk}/array_walk_recursive_variation6.phpt (100%) rename ext/standard/tests/array/{ => array_walk}/array_walk_recursive_variation7.phpt (100%) rename ext/standard/tests/array/{ => array_walk}/array_walk_recursive_variation8.phpt (100%) rename ext/standard/tests/array/{ => array_walk}/array_walk_recursive_variation9.phpt (100%) rename ext/standard/tests/array/{ => array_walk}/array_walk_variation3.phpt (100%) rename ext/standard/tests/array/{ => array_walk}/array_walk_variation4.phpt (100%) rename ext/standard/tests/array/{ => array_walk}/array_walk_variation5.phpt (100%) rename ext/standard/tests/array/{ => array_walk}/array_walk_variation6.phpt (100%) rename ext/standard/tests/array/{ => array_walk}/array_walk_variation7.phpt (100%) rename ext/standard/tests/array/{ => array_walk}/array_walk_variation8.phpt (100%) rename ext/standard/tests/array/{ => array_walk}/array_walk_variation9.phpt (100%) rename ext/standard/tests/array/{ => array_walk}/bug12776.phpt (100%) rename ext/standard/tests/array/{ => array_walk}/bug30266.phpt (100%) rename ext/standard/tests/array/{ => array_walk}/bug34066.phpt (100%) rename ext/standard/tests/array/{ => array_walk}/bug34066_1.phpt (100%) rename ext/standard/tests/array/{ => array_walk}/bug34982.phpt (100%) rename ext/standard/tests/array/{ => array_walk}/bug39576.phpt (100%) rename ext/standard/tests/array/{ => array_walk}/bug42850.phpt (100%) rename ext/standard/tests/array/{ => array_walk}/bug52719.phpt (100%) rename ext/standard/tests/array/{ => array_walk}/bug61730.phpt (100%) rename ext/standard/tests/array/{ => array_walk}/bug61967.phpt (100%) rename ext/standard/tests/array/{ => array_walk}/bug62607.phpt (100%) rename ext/standard/tests/array/{ => array_walk}/bug69068.phpt (100%) rename ext/standard/tests/array/{ => array_walk}/bug69068_2.phpt (100%) rename ext/standard/tests/array/{ => array_walk}/bug70713.phpt (100%) rename ext/standard/tests/array/{ => array_walk}/bug79839.phpt (100%) diff --git a/ext/standard/tests/array/array_walk.phpt b/ext/standard/tests/array/array_walk/array_walk.phpt similarity index 100% rename from ext/standard/tests/array/array_walk.phpt rename to ext/standard/tests/array/array_walk/array_walk.phpt diff --git a/ext/standard/tests/array/array_walk_basic1.phpt b/ext/standard/tests/array/array_walk/array_walk_basic1.phpt similarity index 100% rename from ext/standard/tests/array/array_walk_basic1.phpt rename to ext/standard/tests/array/array_walk/array_walk_basic1.phpt diff --git a/ext/standard/tests/array/array_walk_basic2.phpt b/ext/standard/tests/array/array_walk/array_walk_basic2.phpt similarity index 100% rename from ext/standard/tests/array/array_walk_basic2.phpt rename to ext/standard/tests/array/array_walk/array_walk_basic2.phpt diff --git a/ext/standard/tests/array/array_walk_closure.phpt b/ext/standard/tests/array/array_walk/array_walk_closure.phpt similarity index 100% rename from ext/standard/tests/array/array_walk_closure.phpt rename to ext/standard/tests/array/array_walk/array_walk_closure.phpt diff --git a/ext/standard/tests/array/array_walk_error2.phpt b/ext/standard/tests/array/array_walk/array_walk_error2.phpt similarity index 100% rename from ext/standard/tests/array/array_walk_error2.phpt rename to ext/standard/tests/array/array_walk/array_walk_error2.phpt diff --git a/ext/standard/tests/array/array_walk_object1.phpt b/ext/standard/tests/array/array_walk/array_walk_object1.phpt similarity index 100% rename from ext/standard/tests/array/array_walk_object1.phpt rename to ext/standard/tests/array/array_walk/array_walk_object1.phpt diff --git a/ext/standard/tests/array/array_walk_object2.phpt b/ext/standard/tests/array/array_walk/array_walk_object2.phpt similarity index 100% rename from ext/standard/tests/array/array_walk_object2.phpt rename to ext/standard/tests/array/array_walk/array_walk_object2.phpt diff --git a/ext/standard/tests/array/array_walk_objects.phpt b/ext/standard/tests/array/array_walk/array_walk_objects.phpt similarity index 100% rename from ext/standard/tests/array/array_walk_objects.phpt rename to ext/standard/tests/array/array_walk/array_walk_objects.phpt diff --git a/ext/standard/tests/array/array_walk_rec_objects.phpt b/ext/standard/tests/array/array_walk/array_walk_rec_objects.phpt similarity index 100% rename from ext/standard/tests/array/array_walk_rec_objects.phpt rename to ext/standard/tests/array/array_walk/array_walk_rec_objects.phpt diff --git a/ext/standard/tests/array/array_walk_recursive.phpt b/ext/standard/tests/array/array_walk/array_walk_recursive.phpt similarity index 100% rename from ext/standard/tests/array/array_walk_recursive.phpt rename to ext/standard/tests/array/array_walk/array_walk_recursive.phpt diff --git a/ext/standard/tests/array/array_walk_recursive1.phpt b/ext/standard/tests/array/array_walk/array_walk_recursive1.phpt similarity index 100% rename from ext/standard/tests/array/array_walk_recursive1.phpt rename to ext/standard/tests/array/array_walk/array_walk_recursive1.phpt diff --git a/ext/standard/tests/array/array_walk_recursive_basic1.phpt b/ext/standard/tests/array/array_walk/array_walk_recursive_basic1.phpt similarity index 100% rename from ext/standard/tests/array/array_walk_recursive_basic1.phpt rename to ext/standard/tests/array/array_walk/array_walk_recursive_basic1.phpt diff --git a/ext/standard/tests/array/array_walk_recursive_basic2.phpt b/ext/standard/tests/array/array_walk/array_walk_recursive_basic2.phpt similarity index 100% rename from ext/standard/tests/array/array_walk_recursive_basic2.phpt rename to ext/standard/tests/array/array_walk/array_walk_recursive_basic2.phpt diff --git a/ext/standard/tests/array/array_walk_recursive_error2.phpt b/ext/standard/tests/array/array_walk/array_walk_recursive_error2.phpt similarity index 100% rename from ext/standard/tests/array/array_walk_recursive_error2.phpt rename to ext/standard/tests/array/array_walk/array_walk_recursive_error2.phpt diff --git a/ext/standard/tests/array/array_walk_recursive_object1.phpt b/ext/standard/tests/array/array_walk/array_walk_recursive_object1.phpt similarity index 100% rename from ext/standard/tests/array/array_walk_recursive_object1.phpt rename to ext/standard/tests/array/array_walk/array_walk_recursive_object1.phpt diff --git a/ext/standard/tests/array/array_walk_recursive_object2.phpt b/ext/standard/tests/array/array_walk/array_walk_recursive_object2.phpt similarity index 100% rename from ext/standard/tests/array/array_walk_recursive_object2.phpt rename to ext/standard/tests/array/array_walk/array_walk_recursive_object2.phpt diff --git a/ext/standard/tests/array/array_walk_recursive_variation3.phpt b/ext/standard/tests/array/array_walk/array_walk_recursive_variation3.phpt similarity index 100% rename from ext/standard/tests/array/array_walk_recursive_variation3.phpt rename to ext/standard/tests/array/array_walk/array_walk_recursive_variation3.phpt diff --git a/ext/standard/tests/array/array_walk_recursive_variation4.phpt b/ext/standard/tests/array/array_walk/array_walk_recursive_variation4.phpt similarity index 100% rename from ext/standard/tests/array/array_walk_recursive_variation4.phpt rename to ext/standard/tests/array/array_walk/array_walk_recursive_variation4.phpt diff --git a/ext/standard/tests/array/array_walk_recursive_variation5.phpt b/ext/standard/tests/array/array_walk/array_walk_recursive_variation5.phpt similarity index 100% rename from ext/standard/tests/array/array_walk_recursive_variation5.phpt rename to ext/standard/tests/array/array_walk/array_walk_recursive_variation5.phpt diff --git a/ext/standard/tests/array/array_walk_recursive_variation6.phpt b/ext/standard/tests/array/array_walk/array_walk_recursive_variation6.phpt similarity index 100% rename from ext/standard/tests/array/array_walk_recursive_variation6.phpt rename to ext/standard/tests/array/array_walk/array_walk_recursive_variation6.phpt diff --git a/ext/standard/tests/array/array_walk_recursive_variation7.phpt b/ext/standard/tests/array/array_walk/array_walk_recursive_variation7.phpt similarity index 100% rename from ext/standard/tests/array/array_walk_recursive_variation7.phpt rename to ext/standard/tests/array/array_walk/array_walk_recursive_variation7.phpt diff --git a/ext/standard/tests/array/array_walk_recursive_variation8.phpt b/ext/standard/tests/array/array_walk/array_walk_recursive_variation8.phpt similarity index 100% rename from ext/standard/tests/array/array_walk_recursive_variation8.phpt rename to ext/standard/tests/array/array_walk/array_walk_recursive_variation8.phpt diff --git a/ext/standard/tests/array/array_walk_recursive_variation9.phpt b/ext/standard/tests/array/array_walk/array_walk_recursive_variation9.phpt similarity index 100% rename from ext/standard/tests/array/array_walk_recursive_variation9.phpt rename to ext/standard/tests/array/array_walk/array_walk_recursive_variation9.phpt diff --git a/ext/standard/tests/array/array_walk_variation3.phpt b/ext/standard/tests/array/array_walk/array_walk_variation3.phpt similarity index 100% rename from ext/standard/tests/array/array_walk_variation3.phpt rename to ext/standard/tests/array/array_walk/array_walk_variation3.phpt diff --git a/ext/standard/tests/array/array_walk_variation4.phpt b/ext/standard/tests/array/array_walk/array_walk_variation4.phpt similarity index 100% rename from ext/standard/tests/array/array_walk_variation4.phpt rename to ext/standard/tests/array/array_walk/array_walk_variation4.phpt diff --git a/ext/standard/tests/array/array_walk_variation5.phpt b/ext/standard/tests/array/array_walk/array_walk_variation5.phpt similarity index 100% rename from ext/standard/tests/array/array_walk_variation5.phpt rename to ext/standard/tests/array/array_walk/array_walk_variation5.phpt diff --git a/ext/standard/tests/array/array_walk_variation6.phpt b/ext/standard/tests/array/array_walk/array_walk_variation6.phpt similarity index 100% rename from ext/standard/tests/array/array_walk_variation6.phpt rename to ext/standard/tests/array/array_walk/array_walk_variation6.phpt diff --git a/ext/standard/tests/array/array_walk_variation7.phpt b/ext/standard/tests/array/array_walk/array_walk_variation7.phpt similarity index 100% rename from ext/standard/tests/array/array_walk_variation7.phpt rename to ext/standard/tests/array/array_walk/array_walk_variation7.phpt diff --git a/ext/standard/tests/array/array_walk_variation8.phpt b/ext/standard/tests/array/array_walk/array_walk_variation8.phpt similarity index 100% rename from ext/standard/tests/array/array_walk_variation8.phpt rename to ext/standard/tests/array/array_walk/array_walk_variation8.phpt diff --git a/ext/standard/tests/array/array_walk_variation9.phpt b/ext/standard/tests/array/array_walk/array_walk_variation9.phpt similarity index 100% rename from ext/standard/tests/array/array_walk_variation9.phpt rename to ext/standard/tests/array/array_walk/array_walk_variation9.phpt diff --git a/ext/standard/tests/array/bug12776.phpt b/ext/standard/tests/array/array_walk/bug12776.phpt similarity index 100% rename from ext/standard/tests/array/bug12776.phpt rename to ext/standard/tests/array/array_walk/bug12776.phpt diff --git a/ext/standard/tests/array/bug30266.phpt b/ext/standard/tests/array/array_walk/bug30266.phpt similarity index 100% rename from ext/standard/tests/array/bug30266.phpt rename to ext/standard/tests/array/array_walk/bug30266.phpt diff --git a/ext/standard/tests/array/bug34066.phpt b/ext/standard/tests/array/array_walk/bug34066.phpt similarity index 100% rename from ext/standard/tests/array/bug34066.phpt rename to ext/standard/tests/array/array_walk/bug34066.phpt diff --git a/ext/standard/tests/array/bug34066_1.phpt b/ext/standard/tests/array/array_walk/bug34066_1.phpt similarity index 100% rename from ext/standard/tests/array/bug34066_1.phpt rename to ext/standard/tests/array/array_walk/bug34066_1.phpt diff --git a/ext/standard/tests/array/bug34982.phpt b/ext/standard/tests/array/array_walk/bug34982.phpt similarity index 100% rename from ext/standard/tests/array/bug34982.phpt rename to ext/standard/tests/array/array_walk/bug34982.phpt diff --git a/ext/standard/tests/array/bug39576.phpt b/ext/standard/tests/array/array_walk/bug39576.phpt similarity index 100% rename from ext/standard/tests/array/bug39576.phpt rename to ext/standard/tests/array/array_walk/bug39576.phpt diff --git a/ext/standard/tests/array/bug42850.phpt b/ext/standard/tests/array/array_walk/bug42850.phpt similarity index 100% rename from ext/standard/tests/array/bug42850.phpt rename to ext/standard/tests/array/array_walk/bug42850.phpt diff --git a/ext/standard/tests/array/bug52719.phpt b/ext/standard/tests/array/array_walk/bug52719.phpt similarity index 100% rename from ext/standard/tests/array/bug52719.phpt rename to ext/standard/tests/array/array_walk/bug52719.phpt diff --git a/ext/standard/tests/array/bug61730.phpt b/ext/standard/tests/array/array_walk/bug61730.phpt similarity index 100% rename from ext/standard/tests/array/bug61730.phpt rename to ext/standard/tests/array/array_walk/bug61730.phpt diff --git a/ext/standard/tests/array/bug61967.phpt b/ext/standard/tests/array/array_walk/bug61967.phpt similarity index 100% rename from ext/standard/tests/array/bug61967.phpt rename to ext/standard/tests/array/array_walk/bug61967.phpt diff --git a/ext/standard/tests/array/bug62607.phpt b/ext/standard/tests/array/array_walk/bug62607.phpt similarity index 100% rename from ext/standard/tests/array/bug62607.phpt rename to ext/standard/tests/array/array_walk/bug62607.phpt diff --git a/ext/standard/tests/array/bug69068.phpt b/ext/standard/tests/array/array_walk/bug69068.phpt similarity index 100% rename from ext/standard/tests/array/bug69068.phpt rename to ext/standard/tests/array/array_walk/bug69068.phpt diff --git a/ext/standard/tests/array/bug69068_2.phpt b/ext/standard/tests/array/array_walk/bug69068_2.phpt similarity index 100% rename from ext/standard/tests/array/bug69068_2.phpt rename to ext/standard/tests/array/array_walk/bug69068_2.phpt diff --git a/ext/standard/tests/array/bug70713.phpt b/ext/standard/tests/array/array_walk/bug70713.phpt similarity index 100% rename from ext/standard/tests/array/bug70713.phpt rename to ext/standard/tests/array/array_walk/bug70713.phpt diff --git a/ext/standard/tests/array/bug79839.phpt b/ext/standard/tests/array/array_walk/bug79839.phpt similarity index 100% rename from ext/standard/tests/array/bug79839.phpt rename to ext/standard/tests/array/array_walk/bug79839.phpt From 875a9dc4c4a61131420f17c32636800b574776c1 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Fri, 8 Nov 2024 04:09:13 +0000 Subject: [PATCH 15/40] Fix introduced leaks from GH-15715. Choosing here to shrink the requested allocation to its max value. --- Zend/zend_strtod.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Zend/zend_strtod.c b/Zend/zend_strtod.c index 38caef0b10fd0..634db19e792af 100644 --- a/Zend/zend_strtod.c +++ b/Zend/zend_strtod.c @@ -3622,7 +3622,7 @@ rv_alloc(int i) j = sizeof(ULong); if (i > ((INT_MAX >> 2) + rem)) - zend_error_noreturn(E_ERROR, "rv_alloc() allocation overflow %d", i); + i = (INT_MAX >> 2) + rem; for(k = 0; rem + j <= (size_t)i; j <<= 1) k++; From 3b609ab0e473da57c1ca875b69ebf30ede799360 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Fri, 8 Nov 2024 13:54:12 +0100 Subject: [PATCH 16/40] [skip ci] Fix asan ubuntu image condition in nightly This was meant only for master. 8.4 should still use 22.04. --- .github/workflows/root.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/root.yml b/.github/workflows/root.yml index a4e806cde03d3..cefabd0394a46 100644 --- a/.github/workflows/root.yml +++ b/.github/workflows/root.yml @@ -47,7 +47,7 @@ jobs: branch: ${{ fromJson(needs.GENERATE_MATRIX.outputs.branches) }} with: asan_ubuntu_version: ${{ - (((matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 4) || matrix.branch.version[0] >= 9) && '24.04') + (((matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 5) || matrix.branch.version[0] >= 9) && '24.04') || '20.04' }} branch: ${{ matrix.branch.ref }} community_verify_type_inference: ${{ (matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 4) || matrix.branch.version[0] >= 9 }} @@ -55,7 +55,7 @@ jobs: run_alpine: ${{ (matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 4) || matrix.branch.version[0] >= 9 }} run_macos_arm64: ${{ (matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 4) || matrix.branch.version[0] >= 9 }} ubuntu_version: ${{ - (((matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 4) || matrix.branch.version[0] >= 9) && '24.04') + (((matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 5) || matrix.branch.version[0] >= 9) && '24.04') || ((matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 3) && '22.04') || '20.04' }} windows_version: ${{ ((matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 4) || matrix.branch.version[0] >= 9) && '2022' || '2019' }} From 065bde1e1325f948ce570811ef1cc109a71d6aaa Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Wed, 23 Oct 2024 21:57:31 +0200 Subject: [PATCH 17/40] Fix GH-16432: PHP-FPM 8.2 SIGSEGV in fpm_get_status --- NEWS | 3 ++ sapi/fpm/fpm/fpm_status.c | 5 +- .../fpm/tests/gh16432-status-high-nprocs.phpt | 46 +++++++++++++++++++ 3 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 sapi/fpm/tests/gh16432-status-high-nprocs.phpt diff --git a/NEWS b/NEWS index b9ed3187b78c1..6f370c9f096e4 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,9 @@ PHP NEWS - Calendar: . Fixed jdtogregorian overflow. (David Carlier) +- FPM: + . Fixed GH-16432 (PHP-FPM 8.2 SIGSEGV in fpm_get_status). (Jakub Zelenka) + - PDO: . Fixed memory leak of `setFetchMode()`. (SakiTakamachi) diff --git a/sapi/fpm/fpm/fpm_status.c b/sapi/fpm/fpm/fpm_status.c index f698753cf4c65..cebaa18c964bd 100644 --- a/sapi/fpm/fpm/fpm_status.c +++ b/sapi/fpm/fpm/fpm_status.c @@ -62,7 +62,8 @@ int fpm_status_export_to_zval(zval *status) /* copy the scoreboard not to bother other processes */ scoreboard = *scoreboard_p; - struct fpm_scoreboard_proc_s procs[scoreboard.nprocs]; + struct fpm_scoreboard_proc_s *procs = safe_emalloc( + sizeof(struct fpm_scoreboard_proc_s), scoreboard.nprocs, 0); struct fpm_scoreboard_proc_s *proc_p; for(i=0; i +--FILE-- +createSourceFileAndScriptName(); +$tester->start(); +$tester->expectLogStartNotices(); +$tester->request()->expectBody('bool(false)'); +$tester->terminate(); +$tester->expectLogTerminatingNotices(); +$tester->close(); + +?> +Done +--EXPECT-- +Done +--CLEAN-- + From 27b4df424771d47553c6b1e9594b2986bfbd9ba7 Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Fri, 8 Nov 2024 17:00:58 +0100 Subject: [PATCH 18/40] Fix 8.4 NEWS file --- NEWS | 1149 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 1117 insertions(+), 32 deletions(-) diff --git a/NEWS b/NEWS index 8653ae145cda7..86672aea04a32 100644 --- a/NEWS +++ b/NEWS @@ -1,62 +1,1147 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? ????, PHP 8.5.0alpha1 +?? ??? ????, PHP 8.4.0 + +- Calendar: + . Fixed jdtogregorian overflow. (David Carlier) + +- PDO: + . Fixed memory leak of `setFetchMode()`. (SakiTakamachi) + +07 Nov 2024, PHP 8.4.0RC4 + +- BcMath: + . Fixed bug GH-16265 (Added early return case when result is 0) + (Saki Takamachi). + . Fixed bug GH-16262 (Fixed a bug where size_t underflows) (Saki Takamachi). + +- Core: + . Fixed bug GH-16574 (Incorrect error "undefined method" messages). + (nielsdos) + . Fixed bug GH-16577 (EG(strtod_state).freelist leaks with opcache.preload). + (nielsdos) + . Fixed bug GH-16615 (Assertion failure in zend_std_read_property). (Arnaud) + . Fixed bug GH-16342 (Added ReflectionProperty::isLazy()). (Arnaud) + . Fixed bug GH-16648 (Use-after-free during array sorting). (ilutov) + +- Date: + . Fixed bug GH-14732 (date_sun_info() fails for non-finite values). (cmb) + +- DOM: + . Fixed bug GH-16594 (Assertion failure in DOM -> before). (nielsdos) + . Fixed bug GH-16593 (Assertion failure in DOM->replaceChild). (nielsdos) + . Fixed bug GH-16595 (Another UAF in DOM -> cloneNode). (nielsdos) + +- FPM: + . Fixed bug GH-16628 (FPM logs are getting corrupted with this log + statement). (nielsdos) + +- GD: + . Fixed bug GH-16559 (UBSan abort in ext/gd/libgd/gd_interpolation.c:1007). + (nielsdos) + +- GMP: + . Fixed segfaults and other issues related to operator overloading with + GMP objects. (Girgias) + +- Opcache: + . Fixed bug GH-16572 (Incorrect result with reflection in low-trigger JIT). + (nielsdos) + +- OpenSSL: + . Fix various memory leaks on error conditions in openssl_x509_parse(). + (nielsdos) + +- PDO: + . Fixed bug GH-16167 (Prevent mixing PDO sub-classes with different DSN). + (kocsismate) + . Fixed bug GH-16314 ("Pdo\Mysql object is uninitialized" when opening a + persistent connection). (kocsismate) + +- PDO_ODBC: + . Fixed bug GH-16450 (PDO_ODBC can inject garbage into field values). (cmb) + +- Reflection: + . Fixed bug GH-16601 (Memory leak in Reflection constructors). (nielsdos) + +- Session: + . Fixed bug GH-16590 (UAF in session_encode()). (nielsdos) + +- SPL: + . Fixed bug GH-16588 (UAF in Observer->serialize). (nielsdos) + . Fix GH-16477 (Segmentation fault when calling __debugInfo() after failed + SplFileObject::__constructor). (Girgias) + . Fixed bug GH-16589 (UAF in SplDoublyLinked->serialize()). (nielsdos) + . Fixed bug GH-16604 (Memory leaks in SPL constructors). (nielsdos) + . Fixed bug GH-16646 (UAF in ArrayObject::unset() and + ArrayObject::exchangeArray()). (ilutov) + +- SysVShm: + . Fixed bug GH-16591 (Assertion error in shm_put_var). (nielsdos, cmb) + +24 Oct 2024, PHP 8.4.0RC3 + +- Cli: + . Fixed bug GH-16373 (Shebang is not skipped for router script in cli-server + started through shebang). (ilutov) - COM: - . Fix property access of PHP objects wrapped in variant. (cmb) + . Fixed out of bound writes to SafeArray data. (cmb) + +- Core: + . Fixed bug OSS-Fuzz #371445205 (Heap-use-after-free in attr_free). + (nielsdos) + . Fixed bug GH-16168 (php 8.1 and earlier crash immediately when compiled + with Xcode 16 clang on macOS 15). (nielsdos) + . Fixed bug GH-16371 (Assertion failure in Zend/zend_weakrefs.c:646). (Arnaud) + . Fixed missing error when adding asymmetric visibility to static properties. + (ilutov) + . Fixed bug OSS-Fuzz #71407 (Null-dereference WRITE in + zend_lazy_object_clone). (Arnaud) + . Fixed bug GH-16515 (Incorrect propagation of ZEND_ACC_RETURN_REFERENCE for + call trampoline). (ilutov) + . Fixed bug GH-16509 (Incorrect line number in function redeclaration error). + (ilutov) + . Fixed bug GH-16508 (Incorrect line number in inheritance errors of delayed + early bound classes). (ilutov) + +- Curl: + . Fixed bug GH-16302 (CurlMultiHandle holds a reference to CurlHandle if + curl_multi_add_handle fails). (timwolla) + . Fixed bug GH-16359 (crash with curl_setopt* CURLOPT_WRITEFUNCTION + without null callback). (David Carlier) + +- Date: + . Fixed bug GH-16454 (Unhandled INF in date_sunset() with tiny $utcOffset). + (cmb) + +- DBA: + . Fixed bug GH-16390 (dba_open() can segfault for "pathless" streams). (cmb) + +- DOM: + . Fixed bug GH-16316 (DOMXPath breaks when not initialized properly). + (nielsdos) + . Add missing hierarchy checks to replaceChild. (nielsdos) + . Fixed bug GH-16465 (Heap buffer overflow in DOMNode->getElementByTagName). + (nielsdos) + . Fixed bug GH-16336 (Attribute intern document mismanagement). (nielsdos) + . Fixed bug GH-16338 (Null-dereference in ext/dom/node.c). (nielsdos) + . Fixed bug GH-16473 (dom_import_simplexml stub is wrong). (nielsdos) + . Fixed bug GH-16533 (Segfault when adding attribute to parent that is not + an element). (nielsdos) + . Fixed bug GH-16535 (UAF when using document as a child). (nielsdos) + +- EXIF: + . Fixed bug GH-16409 (Segfault in exif_thumbnail when not dealing with a + real file). (nielsdos, cmb) + +- FFI: + . Fixed bug GH-16397 (Segmentation fault when comparing FFI object). + (nielsdos) + +- Filter: + . Fixed bug GH-16523 (FILTER_FLAG_HOSTNAME accepts ending hyphen). (cmb) + +- GD: + . Fixed bug GH-16334 (imageaffine overflow on matrix elements). + (David Carlier) + . Fixed bug GH-16427 (Unchecked libavif return values). (cmb) + +- GMP: + . Fixed floating point exception bug with gmp_pow when using + large exposant values. (David Carlier). + . Fixed bug GH-16411 (gmp_export() can cause overflow). (cmb) + . Fixed bug GH-16501 (gmp_random_bits() can cause overflow). + (David Carlier) + . Fixed gmp_pow() overflow bug with large base/exponents. + (David Carlier) + +- MBstring: + . Fixed bug GH-16361 (mb_substr overflow on start/length arguments). + (David Carlier) + +- Opcache: + . Fixed bug GH-16408 (Array to string conversion warning emitted in + optimizer). (ilutov) + +- OpenSSL: + . Fixed bug GH-16357 (openssl may modify member types of certificate arrays). + (cmb) + . Fixed bug GH-16433 (Large values for openssl_csr_sign() $days overflow). + (cmb) + +- Phar: + . Fixed bug GH-16406 (Assertion failure in ext/phar/phar.c:2808). (nielsdos) + +- PHPDBG: + . Fixed bug GH-16174 (Empty string is an invalid expression for ev). (cmb) + +- Session: + . Fixed bug GH-16385 (Unexpected null returned by session_set_cookie_params). + (nielsdos) + . Fixed bug GH-16290 (overflow on cookie_lifetime ini value). + (David Carlier) + +- SOAP: + . Fixed bug GH-16318 (Recursive array segfaults soap encoding). (nielsdos) + . Fixed bug GH-16429 (Segmentation fault access null pointer in SoapClient). + (nielsdos) + +- Sockets: + . Fixed bug with overflow socket_recvfrom $length argument. (David Carlier) + +- SPL: + . Fixed bug GH-16337 (Use-after-free in SplHeap). (nielsdos) + . Fixed bug GH-16464 (Use-after-free in SplDoublyLinkedList::offsetSet()). + (ilutov) + . Fixed bug GH-16479 (Use-after-free in SplObjectStorage::setInfo()). (ilutov) + . Fixed bug GH-16478 (Use-after-free in SplFixedArray::unset()). (ilutov) + +- Standard: + . Fixed bug GH-16293 (Failed assertion when throwing in assert() callback with + bail enabled). (ilutov) + +- XMLReader: + . Fixed bug GH-16292 (Segmentation fault in ext/xmlreader/php_xmlreader.c). + (nielsdos) + +- Zlib: + . Fixed bug GH-16326 (Memory management is broken for bad dictionaries.) + (cmb) + +10 Oct 2024, PHP 8.4.0RC2 + +- CGI: + . Fixed bug GHSA-p99j-rfp4-xqvq (Bypass of CVE-2024-4577, Parameter Injection + Vulnerability). (CVE-2024-8926) (nielsdos) + . Fixed bug GHSA-94p6-54jq-9mwp (cgi.force_redirect configuration is + bypassable due to the environment variable collision). (CVE-2024-8927) + (nielsdos) + +- Calendar: + . Fixed GH-16240: jdtounix overflow on argument value. (David Carlier) + . Fixed GH-16241: easter_days/easter_date overflow on year argument. + (David Carlier) + . Fixed GH-16263: jddayofweek overflow. (cmb) + . Fixed GH-16234: jewishtojd overflow. (nielsdos) + +- CLI: + . Fixed bug GH-16137: duplicate http headers when set several times by + the client. (David Carlier) + +- Core: + . Fixed bug GH-16040 (Use-after-free of object released in hook). (ilutov) + . Fixed bug GH-16054 (Segmentation fault when resizing hash table iterator + list while adding). (nielsdos) + . Fixed bug GH-15905 (Assertion failure for TRACK_VARS_SERVER). (cmb) + . Fixed bug GH-15907 (Failed assertion when promoting Serialize deprecation to + exception). (ilutov) + . Fixed bug GH-15851 (Segfault when printing backtrace during cleanup of + nested generator frame). (ilutov) + . Fixed bug GH-16026 (Reuse of dtor fiber during shutdown). (Arnaud) + . Fixed bug GH-15999 (zend_std_write_property() assertion failure with lazy + objects). (Arnaud) + . Fixed bug GH-15866 (Core dumped in Zend/zend_generators.c). (Arnaud) + . Fixed bug GH-15960 (Foreach edge cases with lazy objects). (Arnaud) + . Fixed bug GH-16188 (Assertion failure in Zend/zend_exceptions.c). (Arnaud) + . Fixed bug GH-16233 (Observer segfault when calling user function in + internal function via trampoline). (nielsdos) + . Fixed bug GH-16185 (Various hooked object iterator issues). (ilutov) + +- DOM: + . Fixed bug GH-16039 (Segmentation fault (access null pointer) in + ext/dom/parentnode/tree.c). (nielsdos) + . Fixed bug GH-16149 (Null pointer dereference in + DOMElement->getAttributeNames()). (nielsdos) + . Fixed bug GH-16151 (Assertion failure in ext/dom/parentnode/tree.c). + (nielsdos) + . Fixed bug GH-16190 (Using reflection to call Dom\Node::__construct + causes assertion failure). (nielsdos) + . Fixed bug GH-16150 (Use after free in php_dom.c). (nielsdos) + . Fixed bug GH-16152 (Memory leak in DOMProcessingInstruction/DOMDocument). + (nielsdos) + . Fix edge-case in DOM parsing decoding. (nielsdos) + +- FPM: + . Fixed bug GHSA-865w-9rf3-2wh5 (Logs from childrens may be altered). + (CVE-2024-9026) (Jakub Zelenka) + +- JSON: + . Fixed bug GH-15168 (stack overflow in json_encode()). (nielsdos) + +- GD: + . Fixed bug GH-16232 (bitshift overflow on wbmp file content reading / + fix backport from upstream). (David Carlier) + . Fixed bug GH-12264 (overflow/underflow on imagerotate degrees value) + (David Carlier) + . Fixed bug GH-16274 (imagescale underflow on RBG channels / + fix backport from upstream). (David Carlier) + +- LDAP: + . Fixed bug GH-16032 (Various NULL pointer dereferencements in + ldap_modify_batch()). (Girgias) + . Fixed bug GH-16101 (Segfault in ldap_list(), ldap_read(), and ldap_search() + when LDAPs array is not a list). (Girgias) + . Fix GH-16132 (php_ldap_do_modify() attempts to free pointer not allocated + by ZMM.). (Girgias) + . Fix GH-16136 (Memory leak in php_ldap_do_modify() when entry is not a + proper dictionary). (Girgias) + +- MBString: + . Fixed bug GH-16261 (Reference invariant broken in mb_convert_variables()). + (nielsdos) + +- Opcache: + . Fixed bug GH-16009 (Segmentation fault with frameless functions and + undefined CVs). (nielsdos) + . Fixed bug GH-16186 (Assertion failure in Zend/zend_operators.c). (Arnaud) + +- PCRE: + . Fixed bug GH-16184 (UBSan address overflowed in ext/pcre/php_pcre.c). + (nielsdos) + +- PHPDBG: + . Fixed bug GH-16181 (phpdbg: exit in exception handler reports fatal error). + (cmb) + . Fixed bug GH-16041 (Support stack limit in phpdbg). (Arnaud) + +- Reflection: + . Fixed bug GH-16122 (The return value of ReflectionFunction::getNamespaceName() + and ReflectionFunction::inNamespace() for closures is incorrect). (timwolla) + . Fixed bug GH-16187 (Assertion failure in ext/reflection/php_reflection.c). + (DanielEScherzer) + . Fixed bug GH-16162 (No ReflectionProperty::IS_VIRTUAL) (DanielEScherzer) + +- SAPI: + . Fixed bug GHSA-9pqp-7h25-4f32 (Erroneous parsing of multipart form data). + (CVE-2024-8925) (Arnaud) + +- SOAP: + . Fixed bug GH-16237 (Segmentation fault when cloning SoapServer). (nielsdos) + . Fix Soap leaking http_msg on error. (nielsdos) + . Fixed bug GH-16256 (Assertion failure in ext/soap/php_encoding.c:460). + (nielsdos) + . Fixed bug GH-16259 (Soap segfault when classmap instantiation fails). + (nielsdos) + +- Standard: + . Fixed bug GH-16053 (Assertion failure in Zend/zend_hash.c). (Arnaud) + . Fixed bug GH-15169 (stack overflow when var serialization in + ext/standard/var). (nielsdos) + +- Windows: + . Fixed bug GH-16199 (GREP_HEADER() is broken). (Peter Kokot) + +26 Sep 2024, PHP 8.4.0RC1 + +- BcMath: + . bcpow() performance improvement. (Jorg Sowa) + . ext/bcmath: Check for scale overflow. (SakiTakamachi) + . [RFC] ext/bcmath: Added bcdivmod. (SakiTakamachi) + . Fix GH-15968 (Avoid converting objects to strings in operator calculations). + (SakiTakamachi) + +- Curl: + . Added CURLOPT_DEBUGFUNCTION as a Curl option. (Ayesh Karunaratne) + +- Debugging: + . Fixed bug GH-15923 (GDB: Python Exception : + exceptions must derive from BaseException). (nielsdos) + +- DOM: + . Fix XML serializer errata: xmlns="" serialization should be allowed. + (nielsdos) + . Fixed bug GH-15910 (Assertion failure in ext/dom/element.c). (nielsdos) + . Fix unsetting DOM properties. (nielsdos) + +- MBString: + . Fixed bug GH-15824 (mb_detect_encoding(): Argument $encodings contains + invalid encoding "UTF8"). (Yuya Hamada) + . Updated Unicode data tables to Unicode 16.0. (Ayesh Karunaratne) + +- Opcache: + . Fixed bug GH-15657 (Segmentation fault in dasm_x86.h). (nielsdos) + . Added opcache_jit_blacklist() function. (Bob) + +- PCRE: + . Fixed GH-16189 (underflow on offset argument). (David Carlier) + +- PHPDBG: + . Fixed bug GH-15901 (phpdbg: Assertion failure on i funcs). (cmb) + +- PCRE: + . Fix UAF issues with PCRE after request shutdown. (nielsdos) + +- PDO_MYSQL: + . Fixed GH-15949 (PDO_MySQL not properly quoting PDO_PARAM_LOB binary + data). (mbeccati, lcobucci) + +- PDO_PGSQL: + . Fixed GH-15986 (Double-free due to Pdo\Pgsql::setNoticeCallback()). (cmb, + nielsdos) + . Fixed GH-12940 (Using PQclosePrepared when available instead of + the DEALLOCATE command to free statements resources). (David Carlier) + +- Reflection: + . Add missing ReflectionProperty::hasHook[s]() methods. (ilutov) + . Add missing ReflectionProperty::isFinal() method. (ilutov) + +- SimpleXML: + . Fixed bug GH-15837 (Segmentation fault in ext/simplexml/simplexml.c). + (nielsdos) + +- Sockets: + . Fixed bug GH-16267 (socket_strerror overflow on errno argument). + (David Carlier) + +- SOAP: + . Fixed bug #73182 (PHP SOAPClient does not support stream context HTTP + headers in array form). (nielsdos) + . Fixed bug #62900 (Wrong namespace on xsd import error message). (nielsdos) + . Fixed bug GH-15711 (SoapClient can't convert BackedEnum to scalar value). + (nielsdos) + +- SPL: + . Fixed bug GH-15918 (Assertion failure in ext/spl/spl_fixedarray.c). + (nielsdos) + +- Standard: + . Add support for backed enums in http_build_query(). (ilutov) + . Fixed bug GH-15982 (Assertion failure with array_find when references are + involved). (nielsdos) + +- Streams: + . Fixed bugs GH-15908 and GH-15026 (leak / assertion failure in streams.c). + (nielsdos) + . Fixed bug GH-15980 (Signed integer overflow in main/streams/streams.c). + (cmb) + +- TSRM: + . Prevent closing of unrelated handles. (cmb) + +- Windows: + . Fixed minimal Windows version. (cmb) + +- Zip: + . Added ZipArchive::ER_TRUNCATED_ZIP added in libzip 1.11. (Remi) + +12 Sep 2024, PHP 8.4.0beta5 + +- BCMath: + . Fixed LONG_MAX in BCMath ext. (Saki Takamachi) + . Fixed bcdiv() div by one. (Saki Takamachi) + . [RFC] Support object types in BCMath. (Saki Takamachi) - Core: - . Fixed bug GH-16665 (\array and \callable should not be usable in - class_alias). (nielsdos) + . Fixed bug GH-15330 (Do not scan generator frames more than once). (Arnaud) + . Fixed bug GH-15644 (Asymmetric visibility doesn't work with hooks). (ilutov) + . Implemented lazy objects RFC. (Arnaud) + . Fixed bug GH-15686 (Building shared iconv with external iconv library). + (Peter Kokot, zeriyoshi) + . Fixed missing error when adding asymmetric visibility to unilateral virtual + property. (ilutov) + . Fixed bug GH-15693 (Unnecessary include in main.c bloats binary). + (nielsdos) + . Fixed bug GH-15731 (AllowDynamicProperties validation should error on + enums). (DanielEScherzer) + . Fixed uninitialized lineno in constant AST of internal enums. (ilutov) - Curl: - . Added curl_multi_get_handles(). (timwolla) + . The CURLOPT_DNS_USE_GLOBAL_CACHE option is now silently ignored. (Ayesh Karunaratne) - DOM: - . Added Dom\Element::$outerHTML. (nielsdos) + . Fixed bug GH-13988 (Storing DOMElement consume 4 times more memory in + PHP 8.1 than in PHP 8.0). (nielsdos) + . Fixed bug GH-15654 (Signed integer overflow in ext/dom/nodelist.c). + (nielsdos) + +- GD: + . Added gdImageClone to bundled libgd. (David Carlier) + +- Hash: + . Fixed bug GH-15742 (php_hash_sha.h incompatible with C++). (cmb) + +- OpenSSL: + . Implement GH-13514 PASSWORD_ARGON2 from OpenSSL 3.2. (Remi) + +- PDO: + . The internal header php_pdo_int.h is no longer installed; it is not + supposed to be used by PDO drivers. (cmb) + +- PDO_Firebird: + . Fixed GH-15604 (Always make input parameters nullable). (sim1984) + +- Reflection: + . Fixed bug GH-15718 (Segfault on ReflectionProperty::get{Hook,Hooks}() on + dynamic properties). (DanielEScherzer) + . Fixed bug GH-15694 (ReflectionProperty::isInitialized() is incorrect for + hooked properties). (ilutov) + +- SOAP: + . Fixed bug #61525 (SOAP functions require at least one space after HTTP + header colon). (nielsdos) + . Implement request #47317 (SoapServer::__getLastResponse()). (nielsdos) + +- Standard: + . Fixed bug GH-15552 (Signed integer overflow in ext/standard/scanf.c). (cmb) + . Implemented GH-15685 (improve proc_open error reporting on Windows). (cmb) + +- Streams: + . Fixed bug GH-15628 (php_stream_memory_get_buffer() not zero-terminated). + (cmb) + +29 Aug 2024, PHP 8.4.0beta4 + +- Core: + . Fixed bug GH-15408 (MSan false-positve on zend_max_execution_timer). + (zeriyoshi) + . Fixed bug GH-15438 (Hooks on constructor promoted properties without + visibility are ignored). (ilutov) + . Fixed bug GH-15419 (Missing readonly+hook incompatibility check for readonly + classes). (ilutov) + . Fixed bug GH-15187 (Various hooked object iterator issues). (ilutov) + . Fixed bug GH-15456 (Crash in get_class_vars() on virtual properties). + (ilutov) + . Fixed bug GH-15501 (Windows HAVE_
_H macros defined to 1 or + undefined). (Peter Kokot) + . Fixed bug GH-15565 (--disable-ipv6 during compilation produces error + EAI_SYSTEM not found). (nielsdos) + . Implemented asymmetric visibility for properties. (ilutov) + +- Curl: + . Added CURLOPT_PREREQFUNCTION Curl option to set a custom callback + after the connection is established, but before the request is + performed. (Ayesh Karunaratne) + . Added CURLOPT_SERVER_RESPONSE_TIMEOUT, which was formerly known as + CURLOPT_FTP_RESPONSE_TIMEOUT. (Ayesh Karunaratne) + +- Date: + . Fixed bug GH-13773 (DatePeriod not taking into account microseconds for end + date). (Mark Bennewitz, Derick) + +- DOM: + . Fixed bug GH-15551 (Segmentation fault (access null pointer) in + ext/dom/xml_common.h). (nielsdos) + . Fixed bug GH-15570 (Segmentation fault (access null pointer) in + ext/dom/html5_serializer.c). (nielsdos) + +- FPM: + . Added memory peak to the scoreboard / status page. (Flávio Heleno) + +- MySQLnd: + . Fixed bug GH-15432 (Heap corruption when querying a vector). (cmb, + Kamil Tekiela) + +- Opcache: + . Fixed bug GH-15490 (Building of callgraph modifies preloaded symbols). + (ilutov) + . Fixed bug GH-15178 (Assertion in tracing JIT on hooks). (ilutov) + +- PDO_MYSQL: + . mysqlnd: support ER_CLIENT_INTERACTION_TIMEOUT. (Appla) + +- Session: + . Emit warnings for non-positive values of session.gc_divisor and negative values + of session.gc_probability. (Jorg Sowa) + +- Standard: + . The "allowed_classes" option for unserialize() now throws TypeErrors and + ValueErrors if it is not an array of class names. (Girgias) + +- Streams: + . Fixed bug GH-14930 (Custom stream wrapper dir_readdir output truncated to + 255 characters in PHP 8.3). (Joe Cai) + + +15 Aug 2024, PHP 8.4.0beta3 + +- Core: + . Exiting a namespace now clears seen symbols. (ilutov) + . The exit (and die) language constructs now behave more like a function. + They can be passed liked callables, are affected by the strict_types + declare statement, and now perform the usual type coercions instead of + casting any non-integer value to a string. + As such, passing invalid types to exit/die may now result in a TypeError + being thrown. (Girgias) + +- CURL: + . Added CURLOPT_TCP_KEEPCNT to set the number of probes to send before + dropping the connection. (David Carlier) + +- Hash: + . Fix GH-15384 (Build fails on Alpine / Musl for amd64). (timwolla) + +- Sockets: + . Added SO_BINDTOIFINDEX to bind a socket to an interface index. + (David Carlier) + +- Standard: + . php_uname() now throws ValueErrors on invalid inputs. (Girgias) + +15 Aug 2024, PHP 8.4.0beta1 + +- Core: + . Updated build system scripts config.guess to 2024-07-27 and config.sub to + 2024-05-27. (Peter Kokot) + . Fixed bug GH-15240 (Infinite recursion in trait hook). (ilutov) + . Fixed bug GH-15140 (Missing variance check for abstract set with asymmetric + type). (ilutov) + . Fixed bug GH-15181 (Disabled output handler is flushed again). (cmb) + . Passing E_USER_ERROR to trigger_error() is now deprecated. (Girgias) + . Fixed bug GH-15292 (Dynamic AVX detection is broken for MSVC). (nielsdos) + . Using "_" as a class name is now deprecated. (Girgias) + +- Curl: + . Added constants CURL_HTTP_VERSION_3 (libcurl 7.66) and CURL_HTTP_VERSION_3ONLY + (libcurl 7.88) as options for CURLOPT_HTTP_VERSION (Ayesh Karunaratne) + +- Date: + . Constants SUNFUNCS_RET_TIMESTAMP, SUNFUNCS_RET_STRING, and SUNFUNCS_RET_DOUBLE + are now deprecated. (Jorg Sowa) + +- DBA: + . Passing null or false to dba_key_split() is deprecated. (Grigias) + +- DOM: + . Fixed bug GH-15192 (Segmentation fault in dom extension + (html5_serializer)). (nielsdos) + . Deprecated DOM_PHP_ERR constant. (nielsdos) + . Removed DOMImplementation::getFeature(). (nielsdos) + . Fixed bug GH-15331 (Element::$substitutedNodeValue test failed). (nielsdos) + +- Hash: + . Deprecated passing incorrect data types for options to ext/hash functions. + (nielsdos) + . Added SSE2 and SHA-NI implementation of SHA-256. (timwolla, Colin Percival, + Graham Percival) + +- Mysqli: + . The mysqli_ping() function and mysqli::ping() method are now deprecated, + as the reconnect feature was removed in PHP 8.2. (Kamil Tekiela) + . The mysqli_kill() function and mysqli::kill() method are now deprecated. + If this functionality is needed a SQL "KILL" command can be used instead. + (Kamil Tekiela) + . The mysqli_refresh() function and mysqli::refresh() method are now deprecated. + If this functionality is needed a SQL "FLUSH" command can be used instead. + (Kamil Tekiela) + . Passing explicitly the $mode parameter to mysqli_store_result() has been + deprecated. As the MYSQLI_STORE_RESULT_COPY_DATA constant was only used in + conjunction with this function it has also been deprecated. (Girgias) + +- PDO_Firebird: + . Support proper formatting of time zone types. (sim1984) + +- PHPDBG: + . array out of bounds, stack overflow handled for segfault handler on windows. + (David Carlier) + +- Random: + . lcg_value() is now deprecated. (timwolla) + +- Readline: + . Fixed bug #51558 (Shared readline build fails). (Peter Kokot) + +- Session: + . INI settings session.sid_length and session.sid_bits_per_character are now + deprecated. (timwolla) + +- SOAP: + . Passing an int to SoapServer::addFunction() is now deprecated. + If all PHP functions need to be provided flatten the array returned by + get_defined_functions(). (Girgias) + . The SOAP_FUNCTIONS_ALL constant is now deprecated. (Girgias) + +- Sockets: + . Added IP_PORTRANGE* constants for BSD systems to control ephemeral port + ranges. (David Carlier) + . Added SOCK_NONBLOCK/SOCK_CLOEXEC constants for socket_create and + socket_create_pair to apply O_NONBLOCK/O_CLOEXEC flags to the + newly created sockets. (David Carlier) + +- SPL: + . The SplFixedArray::__wakeup() method has been deprecated as it implements + __serialize() and __unserialize() which need to be overwritten instead. + (TysonAndre) + . Passing a non-empty string for the $escape parameter of: + - SplFileObject::setCsvControl() + - SplFileObject::fputcsv() + - SplFileObject::fgetcsv() + is now deprecated. (Girgias) + +- Standard: + . Unserializing the uppercase 'S' tag is now deprecated. (timwolla) + . Enables crc32 auxiliary detection on OpenBSD. (David Carlier) + . Passing a non-empty string for the $escape parameter of: + - fputcsv() + - fgetcsv() + - str_getcsv() + is now deprecated. (Girgias) + . The str_getcsv() function now throws ValueErrors when the $separator and + $enclosure arguments are not one byte long, or if the $escape is not one + byte long or the empty string. This aligns the behaviour to be identical + to that of fputcsv() and fgetcsv(). (Girgias) + +- Streams: + . Implemented GH-15155 (Stream context is lost when custom stream wrapper is + being filtered). (Quentin Dreyer) + +- XML: + . The xml_set_object() function has been deprecated. (Girgias) + . Passing non-callable strings to the xml_set_*_handler() functions is now + deprecated. (Girgias) + +01 Aug 2024, PHP 8.4.0alpha4 + +- GMP: + . RFC: Change GMP bool cast behavior. (Saki Takamachi) + +01 Aug 2024, PHP 8.4.0alpha3 + +- Core: + . Fix GH-14978 (The xmlreader extension phpize build). (Peter Kokot) + . Throw Error exception when encountering recursion during comparison, rather + than fatal error. (ilutov) + . Added missing cstddef include for C++ builds. (cmb) + . Fixed bug GH-15108 (Segfault when destroying generator during shutdown). + (Arnaud) + . Fixed bug GH-15275 (Crash during GC of suspended generator delegate). + (Arnaud) + +- BCMath: + . Adjust bcround()'s $mode parameter to only accept the RoundingMode + enum. (timwolla, saki) + +- DOM: + . Fix trampoline leak in xpath callables. (nielsdos) + . Throw instead of silently failing when creating a too long text node in + (DOM)ParentNode and (DOM)ChildNode. (nielsdos) + +- FPM: + . /dev/poll events.mechanism for Solaris/Illumos setting had been retired. + (David Carlier) + +- GMP: + . The GMP class is now final and cannot be extended anymore. (Girgias) + +- Intl: + . Added SpoofChecker::setAllowedChars to set unicode chars ranges. + (David Carlier) + . Fixed bug GH-15087 (IntlChar::foldCase()'s $option is not optional). (cmb) + +- Opcache: + . Fixed bug GH-13775 (Memory leak possibly related to opcache SHM placement). + (Arnaud, nielsdos) + +- OpenSSL: + . Bumped minimum required OpenSSL version to 1.1.0. (cmb) + +- PDO_FIREBIRD: + . Added Pdo\Firebird::ATTR_API_VERSION. (SakiTakamachi) + . Added getApiVersion() and removed from getAttribute(). + (SakiTakamachi) + . Supported Firebird 4.0 datatypes. (sim1984) + +- PGSQL: + . pg_convert/pg_insert/pg_update/pg_delete ; regexes are now cached. + (David Carlier) + +- Random: + . Fixed bug GH-15094 (php_random_default_engine() is not C++ conforming). + (cmb) + +- Readline: + . Fixed readline_info, rl_line_buffer_length/rl_len globals on update. + (David Carlier) + +- Standard: + . Fix references in request_parse_body() options array. (nielsdos) + . Add RoundingMode enum. (timwolla, saki) + +- Tidy: + . Failures in the constructor now throw exceptions rather than emitting + warnings and having a broken object. (nielsdos) + . Add tidyNode::getNextSibling() and tidyNode::getPreviousSibling(). + (nielsdos) + +- XMLReader: + . Fixed bug GH-15123 (var_dump doesn't actually work on XMLReader). + (nielsdos) + +- XSL: + . Fix trampoline leak in xpath callables. (nielsdos) + +18 Jul 2024, PHP 8.4.0alpha2 + +- Core: + . Fixed bug GH-14801 (Fix build for armv7). (andypost) + . Implemented property hooks RFC. (ilutov) + +- DOM: + . Improve support for template elements. (nielsdos) + +- GD: + . Check overflow/underflow for imagescale/imagefilter. (David Carlier) + +- LibXML: + . Added LIBXML_NO_XXE constant. (nielsdos) + +- Opcache: + . Fixed bug GH-14873 (PHP 8.4 min function fails on typed integer). + (nielsdos) + +- PDO: + . Fixed bug GH-14792 (Compilation failure on pdo_* extensions). + (Peter Kokot) + +- Standard: + . Change highlight_string() and print_r() return type to string|true. (Ayesh) + +- Windows: + . Update the icon of the Windows executables, e.g. php.exe. (Ayesh, + Nurudin Imširović) + +- XML: + . Fixed bug #81481 (xml_get_current_byte_index limited to 32-bit numbers on + 64-bit builds). (nielsdos) + +04 Jul 2024, PHP 8.4.0alpha1 + +- BCMath: + . [RFC] Add bcfloor, bcceil and bcround to BCMath. (Saki Takamachi) + . Improve performance. (Saki Takamachi, nielsdos) + +- Core: + . Added zend_call_stack_get implementation for NetBSD, DragonFlyBSD, + Solaris and Haiku. (David Carlier) + . Enabled ifunc checks on FreeBSD from the 12.x releases. (Freaky) + . Changed the type of PHP_DEBUG and PHP_ZTS constants to bool. (haszi) + . Fixed bug GH-13142 (Undefined variable name is shortened when contains \0). + (nielsdos) + . Fixed bug GH-13178 (Iterator positions incorrect when converting packed + array to hashed). (ilutov) + . Fixed zend fiber build for solaris default mode (32 bits). (David Carlier) + . Fixed zend call stack size for macOs/arm64. (David Carlier) + . Added support for Zend Max Execution Timers on FreeBSD. (Kévin Dunglas) + . Ensure fiber stack is not backed by THP. (crrodriguez) + . Implement GH-13609 (Dump wrapped object in WeakReference class). (nielsdos) + . Added sparc64 arch assembly support for zend fiber. (Claudio Jeker) + . Fixed GH-13581 no space available for TLS on NetBSD. (Paul Ripke) + . Added fiber Sys-V loongarch64 support. (qiangxuhui) + . Adjusted closure names to include the parent function's name. (timwolla) + . Improve randomness of uploaded file names and files created by tempnam(). + (Arnaud) + . Added gc and shutdown callbacks to zend_mm custom handlers. + (Florian Engelhardt) + . Fixed bug GH-14650 (Compute the size of pages before allocating memory). + (Julien Voisin) + . Fixed bug GH-11928 (The --enable-re2c-cgoto doesn't add the -g flag). + (Peter Kokot) + . Added the #[\Deprecated] attribute. (beberlei, timwolla) + . Fixed GH-11389 (Allow suspending fibers in destructors). (Arnaud, trowski) + +- Curl: + . Deprecated the CURLOPT_BINARYTRANSFER constant. (divinity76) + . Bumped required libcurl version to 7.61.0. (Ayesh) + . Added feature_list key to the curl_version() return value. (Ayesh) + +- Date: + . Added DateTime[Immutable]::createFromTimestamp. (Marc Bennewitz) + . Added DateTime[Immutable]::[get|set]Microsecond. (Marc Bennewitz) + +- DOM: + . Added DOMNode::compareDocumentPosition(). (nielsdos) + . Implement #53655 (Improve speed of DOMNode::C14N() on large XML documents). + (nielsdos) + . Fix cloning attribute with namespace disappearing namespace. (nielsdos) + . Implement DOM HTML5 parsing and serialization RFC. (nielsdos) + . Fix DOMElement->prefix with empty string creates bogus prefix. (nielsdos) + . Handle OOM more consistently. (nielsdos) + . Implemented "Improve callbacks in ext/dom and ext/xsl" RFC. (nielsdos) + . Added DOMXPath::quote() static method. (divinity76) + . Implemented opt-in ext/dom spec compliance RFC. (nielsdos) + . Fixed bug #79701 (getElementById does not correctly work with duplicate + definitions). (nielsdos) + . Implemented "New ext-dom features in PHP 8.4" RFC. (nielsdos) + . Fixed GH-14698 (segfault on DOM node dereference). (David Carlier) + +- Fileinfo: + . Update to libmagic 5.45. (nielsdos) + . Fixed bug #65106 (PHP fails to compile ext/fileinfo). (Guillaume Outters) + +- FPM: + . Implement GH-12385 (flush headers without body when calling flush()). + (nielsdos) + . Added DragonFlyBSD system to the list which set FPM_BACKLOG_DEFAULT + to SOMAXCONN. (David Carlier) + +- FTP: + . Removed the deprecated inet_ntoa call support. (David Carlier) + . Fixed bug #63937 (Upload speed 10 times slower with PHP). (nielsdos) + +- GD: + . Fix parameter numbers and missing alpha check for imagecolorset(). + (Giovanni Giacobbi) + . imagepng/imagejpeg/imagewep/imageavif now throw an exception on + invalid quality parameter. (David Carlier) + +- Gettext: + . bind_textdomain_codeset, textdomain and d(*)gettext functions + now throw an exception on empty domain. (David Carlier) + +- Hash: + . Changed return type of hash_update() to true. (nielsdos) + . Added HashContext::__debugInfo(). (timwolla) + +- IMAP: + . Moved to PECL. (Derick Rethans) + +- Intl: + . Added IntlDateFormatter::PATTERN constant. (David Carlier) + . Fixed Numberformatter::__construct when the locale is invalid, now + throws an exception. (David Carlier) + . Added NumberFormatter::ROUND_TOWARD_ZERO and ::ROUND_AWAY_FROM_ZERO as + aliases for ::ROUND_DOWN and ::ROUND_UP. (Jorg Sowa) + . Added NumberFormatter::ROUND_HALFODD. (Ayesh Karunaratne) + . Added PROPERTY_IDS_UNARY_OPERATOR, PROPERTY_ID_COMPAT_MATH_START and + PROPERTY_ID_COMPAT_MATH_CONTINUE constants. (David Carlier) + . Added IntlDateFormatter::getIanaID/intltz_get_iana_id method/function. + (David Carlier) + . Set to C++17 standard for icu 74 and onwards. (David Carlier) + . resourcebundle_get(), ResourceBundle::get(), and accessing offsets on a + ResourceBundle object now throw: + - TypeError for invalid offset types + - ValueError for an empty string + - ValueError if the integer index does not fit in a signed 32 bit integer + . ResourceBundle::get() now has a tentative return type of: + ResourceBundle|array|string|int|null + . Added the new Grapheme function grapheme_str_split. (youkidearitai) + . Added IntlDateFormatter::parseToCalendar. (David Carlier) + +- LDAP: + . Added LDAP_OPT_X_TLS_PROTOCOL_MAX/LDAP_OPT_X_TLS_PROTOCOL_TLS1_3 + constants. (StephenWall) + +- LibXML: + . Added LIBXML_RECOVER constant. (nielsdos) + . libxml_set_streams_context() now throws immediately on an invalid context + instead of at the use-site. (nielsdos) + +- MBString: + . Added mb_trim, mb_ltrim and mb_rtrim. (Yuya Hamada) + . Added mb_ucfirst and mb_lcfirst. (Yuya Hamada) + . Updated Unicode data tables to Unicode 15.1. (Ayesh Karunaratne) + +- MySQLnd: + . Fixed bug GH-13440 (PDO quote bottleneck). (nielsdos) + . Fixed bug GH-10599 (Apache crash on Windows when using a self-referencing + anonymous function inside a class with an active mysqli connection). + (nielsdos) + +- Opcache: + . Added large shared segments support for FreeBSD. (David Carlier) + . If JIT is enabled, PHP will now exit with a fatal error on startup in case + of JIT startup initialization issues. (danog) + . Increased the maximum value of opcache.interned_strings_buffer to 32767 on + 64bit archs. (Arnaud) + . Fixed bug GH-13834 (Applying non-zero offset 36 to null pointer in + zend_jit.c). (nielsdos) + . Fixed bug GH-14361 (Deep recursion in zend_cfg.c causes segfault). + (nielsdos) + +- OpenSSL: + . Fixed bug #80269 (OpenSSL sets Subject wrong with extraattribs parameter). + (Jakub Zelenka) + . Implement request #48520 (openssl_csr_new - allow multiple values in DN). + (Jakub Zelenka) + . Introduced new serial_hex parameter to openssl_csr_sign. (Jakub Zelenka, + Florian Sowade) + . Added X509_PURPOSE_OCSP_HELPER and X509_PURPOSE_TIMESTAMP_SIGN constants. + (Vincent Jardin) + . Bumped minimum required OpenSSL version to 1.1.1. (Ayesh Karunaratne) + . Added compile-time option --with-openssl-legacy-provider to enable legacy + provider. (Adam Saponara) + . Added support for Curve25519 + Curve448 based keys. (Manuel Mausz) + . Fixed bug GH-13343 (openssl_x509_parse should not allow omitted seconds in + UTCTimes). (Jakub Zelenka) - Output: - . Fixed calculation of aligned buffer size. (cmb) + . Clear output handler status flags during handler initialization. (haszi) + . Fixed bug with url_rewriter.hosts not used by output_add_rewrite_var(). + (haszi) + +- PCNTL: + . Added pcntl_setns for Linux. (David Carlier) + . Added pcntl_getcpuaffinity/pcntl_setcpuaffinity. (David Carlier) + . Updated pcntl_get_signal_handler signal id upper limit to be + more in line with platforms limits. (David Carlier) + . Added pcntl_getcpu for Linux/FreeBSD/Solaris/Illumos. (David Carlier) + . Added pcntl_getqos_class/pcntl_setqos_class for macOs. (David Carlier) + . Added SIGCKPT/SIGCKPTEXIT constants for DragonFlyBSD. (David Carlier) + . Added FreeBSD's SIGTRAP handling to pcntl_siginfo_to_zval. (David Carlier) + . Added POSIX pcntl_waitid. (Vladimir Vrzić) + +- PCRE: + . Upgrade bundled pcre2lib to version 10.43. (nielsdos) + . Add "/r" modifier. (Ayesh) + . Upgrade bundled pcre2lib to version 10.44. (Ayesh) + +- PDO: + . Fixed setAttribute and getAttribute. (SakiTakamachi) + . Implemented PDO driver-specific subclasses RFC. (danack, kocsismate) + . Added support for PDO driver-specific SQL parsers. (Matteo Beccati) + +- PDO_DBLIB: + . Fixed setAttribute and getAttribute. (SakiTakamachi) + . Added class Pdo\DbLib. (danack, kocsismate) + +- PDO_FIREBIRD: + . Fixed setAttribute and getAttribute. (SakiTakamachi) + . Feature: Add transaction isolation level and mode settings to pdo_firebird. + (SakiTakamachi) + . Added class Pdo\Firebird. (danack, kocsismate) + +- PDO_MYSQL: + . Fixed setAttribute and getAttribute. (SakiTakamachi) + . Added class Pdo\Mysql. (danack, kocsismate) + . Added custom SQL parser. (Matteo Beccati) + +- PDO_ODBC: + . Added class Pdo\Odbc. (danack, kocsismate) - PDO_PGSQL: - . Added Iterable support for PDO::pgsqlCopyFromArray. (KentarouTakeda) - . Implement GH-15387 Pdo\Pgsql::setAttribute(PDO::ATTR_PREFETCH, 0) or - Pdo\Pgsql::prepare(…, [ PDO::ATTR_PREFETCH => 0 ]) make fetch() lazy - instead of storing the whole result set in memory (Guillaume Outters) + . Fixed GH-12423, DSN credentials being prioritized over the user/password + PDO constructor arguments. (SakiTakamachi) + . Fixed native float support with pdo_pgsql query results. (Yurunsoft) + . Added class Pdo\Pgsql. (danack, kocsismate) + . Retrieve the memory usage of the query result resource. (KentarouTakeda) + . Added Pdo\Pgsql::setNoticeCallBack method to receive DB notices. + (outtersg) + . Added custom SQL parser. (Matteo Beccati) + +- PDO_SQLITE: + . Added class Pdo\Sqlite. (danack, kocsismate) + . Fixed bug #81227 (PDO::inTransaction reports false when in transaction). + (nielsdos) + . Added custom SQL parser. (Matteo Beccati) - PGSQL: - . Added pg_close_stmt to close a prepared statement while allowing - its name to be reused. (David Carlier) - . Added Iterable support for pgsql_copy_from. (David Carlier) + . Added the possibility to have no conditions for pg_select. (OmarEmaraDev) + . Persistent connections support the PGSQL_CONNECT_FORCE_RENEW flag. + (David Carlier) + . Added pg_result_memory_size to get the query result memory usage. + (KentarouTakeda) + . Added pg_change_password to alter an user's password. (David Carlier) + . Added pg_put_copy_data/pg_put_copy_end to send COPY commands and signal + the end of the COPY. (David Carlier) + . Added pg_socket_poll to poll on the connection. (David Carlier) + . Added pg_jit to get infos on server JIT support. (David Carlier) + . Added pg_set_chunked_rows_size to fetch results per chunk. (David Carlier) + +- Phar: + . Fixed bug GH-12532 (PharData created from zip has incorrect timestamp). + (nielsdos) - POSIX: - . Added POSIX_SC_OPEN_MAX constant to get the number of file descriptors - a process can handle. (David Carlier) + . Added POSIX_SC_CHILD_MAX and POSIX_SC_CLK_TCK constants. (Jakub Zelenka) + . Updated posix_isatty to set the error number on file descriptors. + (David Carlier) -- Random: - . Moves from /dev/urandom usage to arc4random_buf on Haiku. (David Carlier) +- PSpell: + . Moved to PECL. (Derick Rethans) + +- Reflection: + . Implement GH-12908 (Show attribute name/class in ReflectionAttribute dump). + (nielsdos) + . Make ReflectionGenerator::getFunction() legal after generator termination. + (timwolla) + . Added ReflectionGenerator::isClosed(). (timwolla) + +- SimpleXML: + . Fixed bug GH-12192 (SimpleXML infinite loop when getName() is called + within foreach). (nielsdos) + . Fixed bug GH-12208 (SimpleXML infinite loop when a cast is used inside a + foreach). (nielsdos) + . Fixed bug #55098 (SimpleXML iteration produces infinite loop). (nielsdos) + . Fix signature of simplexml_import_dom(). (nielsdos) + +- Sockets: + . Added multicast group support for ipv4 on FreeBSD. (jonathan@tangential.ca) + . Added the TCP_SYNCNT constant for Linux to set number of attempts to send + SYN packets from the client. (David Carlier) + . Added the SO_EXCLBIND constant for exclusive socket binding on illumos/solaris. + (David Carlier) + . Updated the socket_create_listen backlog argument default value to SOMAXCONN. + (David Carlier) + . Added the SO_NOSIGPIPE constant to control the generation of SIGPIPE for + macOs and FreeBSD. (David Carlier) + . Added SO_LINGER_SEC for macOs, true equivalent of SO_LINGER in other platforms. + (David Carlier) + . Add close-on-exec on socket created with socket_accept on unixes. (David Carlier) + +- SNMP: + . Removed the deprecated inet_ntoa call support. (David Carlier) - SOAP: - . Fixed bug #49169 (SoapServer calls wrong function, although "SOAP action" - header is correct). (nielsdos) + . Add support for clark notation for namespaces in class map. (lxShaDoWxl) + . Mitigate #51561 (SoapServer with a extented class and using sessions, + lost the setPersistence()). (nielsdos) + . Fixed bug #49278 (SoapClient::__getLastResponseHeaders returns NULL if + wsdl operation !has output). (nielsdos) + . Fixed bug #44383 (PHP DateTime not converted to xsd:datetime). (nielsdos) + . Fixed bug GH-11941 (soap with session persistence will silently fail when + "session" built as a shared object). (nielsdos) + +- Sockets: + . Removed the deprecated inet_ntoa call support. (David Carlier) + . Added the SO_EXECLUSIVEADDRUSE windows constant. (David Carlier) + . Added the SOCK_CONN_DGRAM/SOCK_DCCP netbsd constants. (David Carlier) + +- Sodium: + . Add support for AEGIS-128L and AEGIS-256. (jedisct1) + . Enable AES-GCM on aarch64 with the ARM crypto extensions. (jedisct1) + +- SPL: + . Implement SeekableIterator for SplObjectStorage. (nielsdos) - Standard: - . Fixed crypt() tests on musl when using --with-external-libcrypt - (Michael Orlitzky). + . Implement GH-12188 (Indication for the int size in phpinfo()). (timwolla) + . Partly fix GH-12143 (Incorrect round() result for 0.49999999999999994). + (timwolla) + . Fix GH-12252 (round(): Validate the rounding mode). (timwolla) + . Increase the default BCrypt cost to 12. (timwolla) + . Fixed bug GH-12592 (strcspn() odd behaviour with NUL bytes and empty mask). + (nielsdos) + . Removed the deprecated inet_ntoa call support. (David Carlier) + . Cast large floats that are within int range to int in number_format so + the precision is not lost. (Marc Bennewitz) + . Add support for 4 new rounding modes to the round() function. (Jorg Sowa) + . debug_zval_dump() now indicates whether an array is packed. (Max Semenik) + . Fix GH-12143 (Optimize round). (SakiTakamachi) + . Changed return type of long2ip to string from string|false. (Jorg Sowa) + . Fix GH-12143 (Extend the maximum precision round can handle by one digit). + (SakiTakamachi) + . Added the http_get_last_response_headers() and + http_clear_last_response_headers() that allows retrieving the same content + as the magic $http_response_header variable. + . Add php_base64_encode_ex() API. (Remi) + . Implemented "Raising zero to the power of negative number" RFC. (Jorg Sowa) + . Added array_find(), array_find_key(), array_all(), and array_any(). (josh) -- Windows: - . Fixed bug GH-10992 (Improper long path support for relative paths). (cmb, - nielsdos) +- XML: + . Added XML_OPTION_PARSE_HUGE parser option. (nielsdos) + +- XMLReader: + . Declares class constant types. (Ayesh) + . Add XMLReader::fromStream(), XMLReader::fromUri(), XMLReader::fromString(). (nielsdos) - XMLWriter: - . Improved performance and reduce memory consumption. (nielsdos) + . Add XMLWriter::toStream(), XMLWriter::toUri(), XMLWriter::toMemory(). (nielsdos) - XSL: - . Implement request #30622 (make $namespace parameter functional). (nielsdos) - -- Zlib: - . gzfile, gzopen and readgzfile, their "use_include_path" argument - is now a boolean. (David Carlier) - + . Implement request #64137 (XSLTProcessor::setParameter() should allow both + quotes to be used). (nielsdos) + . Implemented "Improve callbacks in ext/dom and ext/xsl" RFC. (nielsdos) + . Added XSLTProcessor::$maxTemplateDepth and XSLTProcessor::$maxTemplateVars. + (nielsdos) <<< NOTE: Insert NEWS from last stable release here prior to actual release! >>> From 7bbf2eae8c4568fe7eab9119aec3197ccb0963d6 Mon Sep 17 00:00:00 2001 From: FraOre Date: Fri, 8 Nov 2024 19:18:37 +0100 Subject: [PATCH 19/40] [skip ci] Fix array_any() and array_all() descriptions Closes GH-16731. --- ext/standard/array.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/standard/array.c b/ext/standard/array.c index 111966562bf4f..73a5f1ee4a328 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -6699,7 +6699,7 @@ PHP_FUNCTION(array_find_key) } /* }}} */ -/* {{{ Search within an array and returns true if an element is found. */ +/* {{{ Checks if at least one array element satisfies a callback function. */ PHP_FUNCTION(array_any) { zval *array = NULL; @@ -6719,7 +6719,7 @@ PHP_FUNCTION(array_any) } /* }}} */ -/* {{{ Search within an array and returns true if an element is found. */ +/* {{{ Checks if all array elements satisfy a callback function. */ PHP_FUNCTION(array_all) { zval *array = NULL; From 6e6373ab8934a1202cdc0a757a362b1e84f0b7a1 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Fri, 8 Nov 2024 20:10:14 +0100 Subject: [PATCH 20/40] [skip ci] Fix typo in test name --- ...iteheader_tranpoline.phpt => curl_writeheader_trampoline.phpt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename ext/curl/tests/{curl_writeheader_tranpoline.phpt => curl_writeheader_trampoline.phpt} (100%) diff --git a/ext/curl/tests/curl_writeheader_tranpoline.phpt b/ext/curl/tests/curl_writeheader_trampoline.phpt similarity index 100% rename from ext/curl/tests/curl_writeheader_tranpoline.phpt rename to ext/curl/tests/curl_writeheader_trampoline.phpt From 73c4fa0ea45d66e73128a12db213f6bc1831f89b Mon Sep 17 00:00:00 2001 From: Maximilian Bosch Date: Fri, 8 Nov 2024 19:36:14 +0100 Subject: [PATCH 21/40] ext/soap: fix `make check` being invoked in `ext/soap` On NixOS we run `make` & `make check` inside `ext/soap` which broke the test like this: 001+ Fatal error: Uncaught SoapFault exception: [WSDL] SOAP-ERROR: Parsing WSDL: Couldn't load from 'ext/soap/tests/gh15711.wsdl' : failed to load "ext/soap/tests/gh15711.wsdl": No such file or directory 002+ in /build/php-8.3.13/ext/soap/tests/gh15711.php:29 003+ Stack trace: 004+ #0 /build/php-8.3.13/ext/soap/tests/gh15711.php(29): SoapClient->__construct('ext/soap/tests/...', Array) 005+ #1 {main} 006+ thrown in /build/php-8.3.13/ext/soap/tests/gh15711.php on line 29 Fix is to make the path dependant on `__DIR__` as it's the case in other testcases including WSDLs. Closes GH-16733. --- NEWS | 3 +++ ext/soap/tests/gh15711.phpt | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 8f3da809a180b..89c461bccdff9 100644 --- a/NEWS +++ b/NEWS @@ -11,6 +11,9 @@ PHP NEWS - PDO: . Fixed memory leak of `setFetchMode()`. (SakiTakamachi) +- SOAP: + . Fix make check being invoked in ext/soap. (Ma27) + 07 Nov 2024, PHP 8.3.14RC1 - Cli: diff --git a/ext/soap/tests/gh15711.phpt b/ext/soap/tests/gh15711.phpt index a49ff280fee59..b72251cc6f95b 100644 --- a/ext/soap/tests/gh15711.phpt +++ b/ext/soap/tests/gh15711.phpt @@ -33,7 +33,7 @@ class TestSoapClient extends SoapClient { } } -$client = new TestSoapClient('ext/soap/tests/gh15711.wsdl', ['classmap' => ['book' => 'book']]); +$client = new TestSoapClient(__DIR__ . '/gh15711.wsdl', ['classmap' => ['book' => 'book']]); echo "--- Test with backed enum ---\n"; From a3b27c083f673d7eb90a7336340214d9a5bc9bcc Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 9 Nov 2024 10:52:06 +0100 Subject: [PATCH 22/40] Add Dom\Element::insertAdjacentHTML() (#16614) --- NEWS | 1 + UPGRADING | 3 + ext/dom/element.c | 92 ++++++++++++++ ext/dom/inner_outer_html_mixin.c | 2 +- ext/dom/php_dom.h | 1 + ext/dom/php_dom.stub.php | 1 + ext/dom/php_dom_arginfo.h | 9 +- .../Dom_Element_insertAdjacentHTML.phpt | 114 ++++++++++++++++++ ..._Element_insertAdjacentHTML_edge_case.phpt | 24 ++++ ...Dom_Element_insertAdjacentHTML_errors.phpt | 54 +++++++++ .../xml/Element_insertAdjacentHTML.phpt | 101 ++++++++++++++++ .../Element_insertAdjacentHTML_errors.phpt | 17 +++ 12 files changed, 417 insertions(+), 2 deletions(-) create mode 100644 ext/dom/tests/modern/html/interactions/Dom_Element_insertAdjacentHTML.phpt create mode 100644 ext/dom/tests/modern/html/interactions/Dom_Element_insertAdjacentHTML_edge_case.phpt create mode 100644 ext/dom/tests/modern/html/interactions/Dom_Element_insertAdjacentHTML_errors.phpt create mode 100644 ext/dom/tests/modern/xml/Element_insertAdjacentHTML.phpt create mode 100644 ext/dom/tests/modern/xml/Element_insertAdjacentHTML_errors.phpt diff --git a/NEWS b/NEWS index 8653ae145cda7..819726aaa663c 100644 --- a/NEWS +++ b/NEWS @@ -14,6 +14,7 @@ PHP NEWS - DOM: . Added Dom\Element::$outerHTML. (nielsdos) + . Added Dom\Element::insertAdjacentHTML(). (nielsdos) - Output: . Fixed calculation of aligned buffer size. (cmb) diff --git a/UPGRADING b/UPGRADING index 13e834f2610a3..1805d04e26061 100644 --- a/UPGRADING +++ b/UPGRADING @@ -92,6 +92,9 @@ PHP 8.5 UPGRADE NOTES attached to a CurlMultiHandle. This includes both handles added using curl_multi_add_handle() and handles accepted by CURLMOPT_PUSHFUNCTION. +- DOM: + . Added Dom\Element::insertAdjacentHTML(). + - PGSQL: . pg_close_stmt offers an alternative way to close a prepared statement from the DEALLOCATE sql command in that we can reuse diff --git a/ext/dom/element.c b/ext/dom/element.c index 418096312c456..e96f4547d8f3f 100644 --- a/ext/dom/element.c +++ b/ext/dom/element.c @@ -1715,6 +1715,98 @@ PHP_METHOD(Dom_Element, insertAdjacentText) } /* }}} end DOMElement::insertAdjacentText */ +/* https://html.spec.whatwg.org/#dom-element-insertadjacenthtml */ +PHP_METHOD(Dom_Element, insertAdjacentHTML) +{ + zval *where_zv; + zend_string *string; + + dom_object *this_intern; + zval *id; + xmlNodePtr thisp; + + bool created_context = false; + + ZEND_PARSE_PARAMETERS_START(2, 2) + Z_PARAM_OBJECT_OF_CLASS(where_zv, dom_adjacent_position_class_entry) + Z_PARAM_STR(string) + ZEND_PARSE_PARAMETERS_END(); + + DOM_GET_THIS_OBJ(thisp, id, xmlNodePtr, this_intern); + + const zend_string *where = Z_STR_P(zend_enum_fetch_case_name(Z_OBJ_P(where_zv))); + + /* 1. We don't do injection sinks. */ + + /* 2. Let context be NULL */ + xmlNodePtr context = NULL; + + /* 3. Use the first matching item from this list: (...) */ + switch (ZSTR_LEN(where) + ZSTR_VAL(where)[2]) { + case sizeof("BeforeBegin") - 1 + 'f': + case sizeof("AfterEnd") - 1 + 't': + /* 1. Set context to this's parent. */ + context = thisp->parent; + + /* 2. If context is null or a Document, throw a "NoModificationAllowedError" DOMException. */ + if (context == NULL || context->type == XML_DOCUMENT_NODE || context->type == XML_HTML_DOCUMENT_NODE) { + php_dom_throw_error(NO_MODIFICATION_ALLOWED_ERR, true); + RETURN_THROWS(); + } + break; + case sizeof("AfterBegin") - 1 + 't': + case sizeof("BeforeEnd") - 1 + 'f': + /* Set context to this. */ + context = thisp; + break; + EMPTY_SWITCH_DEFAULT_CASE(); + } + + /* 4. If context is not an Element or all of the following are true: (...) */ + if (context->type != XML_ELEMENT_NODE + || (php_dom_ns_is_html_and_document_is_html(context) && xmlStrEqual(context->name, BAD_CAST "html"))) { + /* set context to the result of creating an element given this's node document, body, and the HTML namespace. */ + xmlNsPtr html_ns = php_dom_libxml_ns_mapper_ensure_html_ns(php_dom_get_ns_mapper(this_intern)); + + context = xmlNewDocNode(thisp->doc, html_ns, BAD_CAST "body", NULL); + created_context = true; + if (UNEXPECTED(context == NULL)) { + php_dom_throw_error(INVALID_STATE_ERR, true); + goto err; + } + } + + /* 5. Let fragment be the result of invoking the fragment parsing algorithm steps with context and compliantString. */ + xmlNodePtr fragment = dom_parse_fragment(this_intern, context, string); + if (fragment == NULL) { + goto err; + } + + php_libxml_invalidate_node_list_cache(this_intern->document); + + /* 6. Use the first matching item from this list: (...) */ + switch (ZSTR_LEN(where) + ZSTR_VAL(where)[2]) { + case sizeof("BeforeBegin") - 1 + 'f': + php_dom_pre_insert(this_intern->document, fragment, thisp->parent, thisp); + break; + case sizeof("AfterEnd") - 1 + 't': + php_dom_pre_insert(this_intern->document, fragment, thisp->parent, thisp->next); + break; + case sizeof("AfterBegin") - 1 + 't': + php_dom_pre_insert(this_intern->document, fragment, thisp, thisp->children); + break; + case sizeof("BeforeEnd") - 1 + 'f': + php_dom_node_append(this_intern->document, fragment, thisp); + break; + EMPTY_SWITCH_DEFAULT_CASE(); + } + +err: + if (created_context) { + xmlFreeNode(context); + } +} + /* {{{ URL: https://dom.spec.whatwg.org/#dom-element-toggleattribute Since: */ diff --git a/ext/dom/inner_outer_html_mixin.c b/ext/dom/inner_outer_html_mixin.c index 37283ef351116..b14c3ba708ffb 100644 --- a/ext/dom/inner_outer_html_mixin.c +++ b/ext/dom/inner_outer_html_mixin.c @@ -342,7 +342,7 @@ static xmlNodePtr dom_xml_fragment_parsing_algorithm(dom_object *obj, const xmlN } /* https://w3c.github.io/DOM-Parsing/#dfn-fragment-parsing-algorithm */ -static xmlNodePtr dom_parse_fragment(dom_object *obj, xmlNodePtr context_node, const zend_string *input) +xmlNodePtr dom_parse_fragment(dom_object *obj, xmlNodePtr context_node, const zend_string *input) { if (context_node->doc->type == XML_DOCUMENT_NODE) { return dom_xml_fragment_parsing_algorithm(obj, context_node, input); diff --git a/ext/dom/php_dom.h b/ext/dom/php_dom.h index 851bc14d12574..e4013e448ae26 100644 --- a/ext/dom/php_dom.h +++ b/ext/dom/php_dom.h @@ -211,6 +211,7 @@ void dom_parent_node_query_selector(xmlNodePtr thisp, dom_object *intern, zval * void dom_parent_node_query_selector_all(xmlNodePtr thisp, dom_object *intern, zval *return_value, const zend_string *selectors_str); void dom_element_matches(xmlNodePtr thisp, dom_object *intern, zval *return_value, const zend_string *selectors_str); void dom_element_closest(xmlNodePtr thisp, dom_object *intern, zval *return_value, const zend_string *selectors_str); +xmlNodePtr dom_parse_fragment(dom_object *obj, xmlNodePtr context_node, const zend_string *input); /* nodemap and nodelist APIs */ xmlNodePtr php_dom_named_node_map_get_named_item(dom_nnodemap_object *objmap, const zend_string *named, bool may_transform); diff --git a/ext/dom/php_dom.stub.php b/ext/dom/php_dom.stub.php index 587694f5dfa70..ac11623471f19 100644 --- a/ext/dom/php_dom.stub.php +++ b/ext/dom/php_dom.stub.php @@ -1632,6 +1632,7 @@ public function getElementsByTagNameNS(?string $namespace, string $localName): H public function insertAdjacentElement(AdjacentPosition $where, Element $element): ?Element {} public function insertAdjacentText(AdjacentPosition $where, string $data): void {} + public function insertAdjacentHTML(AdjacentPosition $where, string $string): void {} /** * @readonly diff --git a/ext/dom/php_dom_arginfo.h b/ext/dom/php_dom_arginfo.h index 3d6f093eb22e9..08dbf22a9b91c 100644 --- a/ext/dom/php_dom_arginfo.h +++ b/ext/dom/php_dom_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 20c13a727cffb452475989a743ec29a8412a52f1 */ + * Stub hash: 860bf40a97ec6570e9f5b0616407ba55d7c8d6f8 */ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_dom_import_simplexml, 0, 1, DOMAttr|DOMElement, 0) ZEND_ARG_TYPE_INFO(0, node, IS_OBJECT, 0) @@ -785,6 +785,11 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Dom_Element_insertAdjacent ZEND_ARG_TYPE_INFO(0, data, IS_STRING, 0) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Dom_Element_insertAdjacentHTML, 0, 2, IS_VOID, 0) + ZEND_ARG_OBJ_INFO(0, where, Dom\\AdjacentPosition, 0) + ZEND_ARG_TYPE_INFO(0, string, IS_STRING, 0) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Dom_Element_setIdAttribute, 0, 2, IS_VOID, 0) ZEND_ARG_TYPE_INFO(0, qualifiedName, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, isId, _IS_BOOL, 0) @@ -1275,6 +1280,7 @@ ZEND_METHOD(Dom_Element, getElementsByTagName); ZEND_METHOD(Dom_Element, getElementsByTagNameNS); ZEND_METHOD(Dom_Element, insertAdjacentElement); ZEND_METHOD(Dom_Element, insertAdjacentText); +ZEND_METHOD(Dom_Element, insertAdjacentHTML); ZEND_METHOD(Dom_Element, setIdAttributeNode); ZEND_METHOD(Dom_Element, querySelector); ZEND_METHOD(Dom_Element, querySelectorAll); @@ -1649,6 +1655,7 @@ static const zend_function_entry class_Dom_Element_methods[] = { ZEND_ME(Dom_Element, getElementsByTagNameNS, arginfo_class_Dom_Element_getElementsByTagNameNS, ZEND_ACC_PUBLIC) ZEND_ME(Dom_Element, insertAdjacentElement, arginfo_class_Dom_Element_insertAdjacentElement, ZEND_ACC_PUBLIC) ZEND_ME(Dom_Element, insertAdjacentText, arginfo_class_Dom_Element_insertAdjacentText, ZEND_ACC_PUBLIC) + ZEND_ME(Dom_Element, insertAdjacentHTML, arginfo_class_Dom_Element_insertAdjacentHTML, ZEND_ACC_PUBLIC) ZEND_RAW_FENTRY("setIdAttribute", zim_DOMElement_setIdAttribute, arginfo_class_Dom_Element_setIdAttribute, ZEND_ACC_PUBLIC, NULL, NULL) ZEND_RAW_FENTRY("setIdAttributeNS", zim_DOMElement_setIdAttributeNS, arginfo_class_Dom_Element_setIdAttributeNS, ZEND_ACC_PUBLIC, NULL, NULL) ZEND_ME(Dom_Element, setIdAttributeNode, arginfo_class_Dom_Element_setIdAttributeNode, ZEND_ACC_PUBLIC) diff --git a/ext/dom/tests/modern/html/interactions/Dom_Element_insertAdjacentHTML.phpt b/ext/dom/tests/modern/html/interactions/Dom_Element_insertAdjacentHTML.phpt new file mode 100644 index 0000000000000..a2c9471e669f0 --- /dev/null +++ b/ext/dom/tests/modern/html/interactions/Dom_Element_insertAdjacentHTML.phpt @@ -0,0 +1,114 @@ +--TEST-- +Dom\Element::insertAdjacentHTML() with HTML nodes +--EXTENSIONS-- +dom +--FILE-- +name, " ---\n"; + + $dom = Dom\HTMLDocument::createFromString("
", LIBXML_NOERROR); + $div = $dom->body->firstChild; + $div->append("Sample text"); + + $div->insertAdjacentHTML($position, $html); + + echo $dom->saveXML(), "\n"; + echo $dom->saveHTML(), "\n"; + var_dump($div->childNodes->length); + var_dump($dom->body->childNodes->length); + } +} + +test("

foo

bar

"); +test("text"); +test(""); + +?> +--EXPECT-- +=== HTML (

foo

bar

) === +--- Position BeforeBegin --- + +

foo

bar

Sample text
+

foo

bar

Sample text
+int(1) +int(3) +--- Position AfterBegin --- + +

foo

bar

Sample text
+

foo

bar

Sample text
+int(3) +int(1) +--- Position BeforeEnd --- + +
Sample text

foo

bar

+
Sample text

foo

bar

+int(3) +int(1) +--- Position AfterEnd --- + +
Sample text

foo

bar

+
Sample text

foo

bar

+int(1) +int(3) +=== HTML (text) === +--- Position BeforeBegin --- + +text
Sample text
+text
Sample text
+int(1) +int(2) +--- Position AfterBegin --- + +
textSample text
+
textSample text
+int(2) +int(1) +--- Position BeforeEnd --- + +
Sample texttext
+
Sample texttext
+int(2) +int(1) +--- Position AfterEnd --- + +
Sample text
text +
Sample text
text +int(1) +int(2) +=== HTML () === +--- Position BeforeBegin --- + +
Sample text
+
Sample text
+int(1) +int(1) +--- Position AfterBegin --- + +
Sample text
+
Sample text
+int(1) +int(1) +--- Position BeforeEnd --- + +
Sample text
+
Sample text
+int(1) +int(1) +--- Position AfterEnd --- + +
Sample text
+
Sample text
+int(1) +int(1) diff --git a/ext/dom/tests/modern/html/interactions/Dom_Element_insertAdjacentHTML_edge_case.phpt b/ext/dom/tests/modern/html/interactions/Dom_Element_insertAdjacentHTML_edge_case.phpt new file mode 100644 index 0000000000000..f3f47eebf3319 --- /dev/null +++ b/ext/dom/tests/modern/html/interactions/Dom_Element_insertAdjacentHTML_edge_case.phpt @@ -0,0 +1,24 @@ +--TEST-- +Dom\Element::insertAdjacentHTML() with HTML nodes - edge case +--EXTENSIONS-- +dom +--FILE-- +createDocumentFragment(); +$node = $fragment->appendChild($dom->createElement("node")); + +$node->insertAdjacentHTML(Dom\AdjacentPosition::BeforeBegin, "

foo

"); + +echo $dom->saveHtml($fragment), "\n"; + +$dom->firstChild->insertAdjacentHTML(Dom\AdjacentPosition::AfterBegin, $node->outerHTML); + +echo $dom->saveHtml(), "\n"; + +?> +--EXPECT-- +

foo

+ diff --git a/ext/dom/tests/modern/html/interactions/Dom_Element_insertAdjacentHTML_errors.phpt b/ext/dom/tests/modern/html/interactions/Dom_Element_insertAdjacentHTML_errors.phpt new file mode 100644 index 0000000000000..b8e13ba436b6b --- /dev/null +++ b/ext/dom/tests/modern/html/interactions/Dom_Element_insertAdjacentHTML_errors.phpt @@ -0,0 +1,54 @@ +--TEST-- +Dom\Element::insertAdjacentHTML() with HTML nodes - error conditions +--EXTENSIONS-- +dom +--FILE-- +createElement('root'); + +echo "--- BeforeBegin no parent ---\n"; + +try { + $element->insertAdjacentHTML(Dom\AdjacentPosition::BeforeBegin, "test"); +} catch (DOMException $e) { + echo $e->getMessage(), "\n"; +} + +echo "--- AfterEnd no parent ---\n"; + +try { + $element->insertAdjacentHTML(Dom\AdjacentPosition::AfterEnd, "test"); +} catch (DOMException $e) { + echo $e->getMessage(), "\n"; +} + +$dom->appendChild($element); + +echo "--- BeforeBegin document parent ---\n"; + +try { + $element->insertAdjacentHTML(Dom\AdjacentPosition::BeforeBegin, "test"); +} catch (DOMException $e) { + echo $e->getMessage(), "\n"; +} + +echo "--- AfterEnd document parent ---\n"; + +try { + $element->insertAdjacentHTML(Dom\AdjacentPosition::AfterEnd, "test"); +} catch (DOMException $e) { + echo $e->getMessage(), "\n"; +} + +?> +--EXPECT-- +--- BeforeBegin no parent --- +No Modification Allowed Error +--- AfterEnd no parent --- +No Modification Allowed Error +--- BeforeBegin document parent --- +No Modification Allowed Error +--- AfterEnd document parent --- +No Modification Allowed Error diff --git a/ext/dom/tests/modern/xml/Element_insertAdjacentHTML.phpt b/ext/dom/tests/modern/xml/Element_insertAdjacentHTML.phpt new file mode 100644 index 0000000000000..a233e01759f6f --- /dev/null +++ b/ext/dom/tests/modern/xml/Element_insertAdjacentHTML.phpt @@ -0,0 +1,101 @@ +--TEST-- +Dom\Element::insertAdjacentHTML() with XML nodes +--EXTENSIONS-- +dom +--FILE-- +name, " ---\n"; + + $dom = Dom\XMLDocument::createFromString('
'); + $div = $dom->documentElement->firstChild; + $div->append("Sample text"); + + $div->insertAdjacentHTML($position, $xml); + + echo $dom->saveXML(), "\n"; + var_dump($div->childNodes->length); + var_dump($dom->documentElement->childNodes->length); + } +} + +test(''); +test('&'); +test('text node'); + +?> +--EXPECT-- +=== XML () === +--- Position BeforeBegin --- + +
Sample text
+int(1) +int(3) +--- Position AfterBegin --- + +
Sample text
+int(3) +int(1) +--- Position BeforeEnd --- + +
Sample text
+int(3) +int(1) +--- Position AfterEnd --- + +
Sample text
+int(1) +int(3) +=== XML (&) === +--- Position BeforeBegin --- + +&
Sample text
+int(1) +int(4) +--- Position AfterBegin --- + +
&Sample text
+int(4) +int(1) +--- Position BeforeEnd --- + +
Sample text&
+int(4) +int(1) +--- Position AfterEnd --- + +
Sample text
&
+int(1) +int(4) +=== XML (text node) === +--- Position BeforeBegin --- + +text node
Sample text
+int(1) +int(2) +--- Position AfterBegin --- + +
text nodeSample text
+int(2) +int(1) +--- Position BeforeEnd --- + +
Sample texttext node
+int(2) +int(1) +--- Position AfterEnd --- + +
Sample text
text node
+int(1) +int(2) diff --git a/ext/dom/tests/modern/xml/Element_insertAdjacentHTML_errors.phpt b/ext/dom/tests/modern/xml/Element_insertAdjacentHTML_errors.phpt new file mode 100644 index 0000000000000..0ecd1d4873605 --- /dev/null +++ b/ext/dom/tests/modern/xml/Element_insertAdjacentHTML_errors.phpt @@ -0,0 +1,17 @@ +--TEST-- +Dom\Element::insertAdjacentHTML() with XML nodes - errors +--EXTENSIONS-- +dom +--FILE-- +'); +try { + $dom->documentElement->insertAdjacentHTML(Dom\AdjacentPosition::AfterBegin, ""); +} catch (DOMException $e) { + echo $e->getMessage(), "\n"; +} + +?> +--EXPECT-- +XML fragment is not well-formed From ac8d0e57d9a1e641fe880082a010cfdf50b26ad7 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 3 Nov 2024 21:58:06 +0100 Subject: [PATCH 23/40] Prevent unexpected array entry conversion when reading key When passing an array, the key entry can get converted to a string if it is an object, but this actually modifies the original array entry. The test originally outputted: ``` array(2) { [0]=> string(...) => ... [1]=> string(0) "" } ``` This is unexpected. Use zval_try_get_string() to prevent this behaviour. Closes GH-16693. --- NEWS | 3 +++ ext/openssl/openssl.c | 18 ++++++++----- ..._pkey_export_to_file_object_to_string.phpt | 27 +++++++++++++++++++ 3 files changed, 42 insertions(+), 6 deletions(-) create mode 100644 ext/openssl/tests/openssl_pkey_export_to_file_object_to_string.phpt diff --git a/NEWS b/NEWS index 6f370c9f096e4..805a45dacebf9 100644 --- a/NEWS +++ b/NEWS @@ -8,6 +8,9 @@ PHP NEWS - FPM: . Fixed GH-16432 (PHP-FPM 8.2 SIGSEGV in fpm_get_status). (Jakub Zelenka) +- OpenSSL: + . Prevent unexpected array entry conversion when reading key. (nielsdos) + - PDO: . Fixed memory leak of `setFetchMode()`. (SakiTakamachi) diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index a50a3074117cf..d756c3bf25c90 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -3577,19 +3577,21 @@ static EVP_PKEY *php_openssl_pkey_from_zval( if (!(Z_TYPE_P(val) == IS_STRING || Z_TYPE_P(val) == IS_OBJECT)) { TMP_CLEAN; } - if (!try_convert_to_string(val)) { + zend_string *val_str = zval_try_get_string(val); + if (!val_str) { TMP_CLEAN; } - if (Z_STRLEN_P(val) > 7 && memcmp(Z_STRVAL_P(val), "file://", sizeof("file://") - 1) == 0) { - if (!php_openssl_check_path_str(Z_STR_P(val), file_path, arg_num)) { + if (ZSTR_LEN(val_str) > 7 && memcmp(ZSTR_VAL(val_str), "file://", sizeof("file://") - 1) == 0) { + if (!php_openssl_check_path_str(val_str, file_path, arg_num)) { + zend_string_release_ex(val_str, false); TMP_CLEAN; } is_file = true; } /* it's an X509 file/cert of some kind, and we need to extract the data from that */ if (public_key) { - cert = php_openssl_x509_from_str(Z_STR_P(val), arg_num, false, NULL); + cert = php_openssl_x509_from_str(val_str, arg_num, false, NULL); if (cert) { free_cert = 1; @@ -3599,10 +3601,11 @@ static EVP_PKEY *php_openssl_pkey_from_zval( if (is_file) { in = BIO_new_file(file_path, PHP_OPENSSL_BIO_MODE_R(PKCS7_BINARY)); } else { - in = BIO_new_mem_buf(Z_STRVAL_P(val), (int)Z_STRLEN_P(val)); + in = BIO_new_mem_buf(ZSTR_VAL(val_str), (int)ZSTR_LEN(val_str)); } if (in == NULL) { php_openssl_store_errors(); + zend_string_release_ex(val_str, false); TMP_CLEAN; } key = PEM_read_bio_PUBKEY(in, NULL,NULL, NULL); @@ -3615,10 +3618,11 @@ static EVP_PKEY *php_openssl_pkey_from_zval( if (is_file) { in = BIO_new_file(file_path, PHP_OPENSSL_BIO_MODE_R(PKCS7_BINARY)); } else { - in = BIO_new_mem_buf(Z_STRVAL_P(val), (int)Z_STRLEN_P(val)); + in = BIO_new_mem_buf(ZSTR_VAL(val_str), (int)ZSTR_LEN(val_str)); } if (in == NULL) { + zend_string_release_ex(val_str, false); TMP_CLEAN; } if (passphrase == NULL) { @@ -3631,6 +3635,8 @@ static EVP_PKEY *php_openssl_pkey_from_zval( } BIO_free(in); } + + zend_string_release_ex(val_str, false); } if (key == NULL) { diff --git a/ext/openssl/tests/openssl_pkey_export_to_file_object_to_string.phpt b/ext/openssl/tests/openssl_pkey_export_to_file_object_to_string.phpt new file mode 100644 index 0000000000000..0e504bfa4ac63 --- /dev/null +++ b/ext/openssl/tests/openssl_pkey_export_to_file_object_to_string.phpt @@ -0,0 +1,27 @@ +--TEST-- +openssl_pkey_export_to_file object to string conversion +--EXTENSIONS-- +openssl +--FILE-- + +--EXPECT-- +array(2) { + [0]=> + object(Test)#1 (0) { + } + [1]=> + string(0) "" +} From 2f4f09f7e65b8f731b1d1d9055f2f738a35dbd38 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 3 Nov 2024 21:42:47 +0100 Subject: [PATCH 24/40] Fix various memory leaks related to openssl exports Closes GH-16692. --- NEWS | 1 + ext/openssl/openssl.c | 19 +++++++++++-------- .../openssl_csr_export_to_file_leak.phpt | 14 ++++++++++++++ .../openssl_pkey_export_to_file_leak.phpt | 15 +++++++++++++++ .../openssl_x509_export_to_file_leak.phpt | 14 ++++++++++++++ 5 files changed, 55 insertions(+), 8 deletions(-) create mode 100644 ext/openssl/tests/openssl_csr_export_to_file_leak.phpt create mode 100644 ext/openssl/tests/openssl_pkey_export_to_file_leak.phpt create mode 100644 ext/openssl/tests/openssl_x509_export_to_file_leak.phpt diff --git a/NEWS b/NEWS index 805a45dacebf9..fadcea2106857 100644 --- a/NEWS +++ b/NEWS @@ -10,6 +10,7 @@ PHP NEWS - OpenSSL: . Prevent unexpected array entry conversion when reading key. (nielsdos) + . Fix various memory leaks related to openssl exports. (nielsdos) - PDO: . Fixed memory leak of `setFetchMode()`. (SakiTakamachi) diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index d756c3bf25c90..4a8aca8f99921 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -1495,7 +1495,7 @@ PHP_FUNCTION(openssl_x509_export_to_file) } if (!php_openssl_check_path(filename, filename_len, file_path, 2)) { - return; + goto exit_cleanup_cert; } bio_out = BIO_new_file(file_path, PHP_OPENSSL_BIO_MODE_W(PKCS7_BINARY)); @@ -1513,13 +1513,14 @@ PHP_FUNCTION(openssl_x509_export_to_file) php_error_docref(NULL, E_WARNING, "Error opening file %s", file_path); } - if (cert_str) { - X509_free(cert); - } - if (!BIO_free(bio_out)) { php_openssl_store_errors(); } + +exit_cleanup_cert: + if (cert_str) { + X509_free(cert); + } } /* }}} */ @@ -3070,7 +3071,7 @@ PHP_FUNCTION(openssl_csr_export_to_file) } if (!php_openssl_check_path(filename, filename_len, file_path, 2)) { - return; + goto exit_cleanup; } bio_out = BIO_new_file(file_path, PHP_OPENSSL_BIO_MODE_W(PKCS7_BINARY)); @@ -3090,6 +3091,7 @@ PHP_FUNCTION(openssl_csr_export_to_file) php_error_docref(NULL, E_WARNING, "Error opening file %s", file_path); } +exit_cleanup: if (csr_str) { X509_REQ_free(csr); } @@ -4567,7 +4569,7 @@ PHP_FUNCTION(openssl_pkey_export_to_file) } if (!php_openssl_check_path(filename, filename_len, file_path, 2)) { - RETURN_FALSE; + goto clean_exit_key; } PHP_SSL_REQ_INIT(&req); @@ -4603,8 +4605,9 @@ PHP_FUNCTION(openssl_pkey_export_to_file) clean_exit: PHP_SSL_REQ_DISPOSE(&req); - EVP_PKEY_free(key); BIO_free(bio_out); +clean_exit_key: + EVP_PKEY_free(key); } /* }}} */ diff --git a/ext/openssl/tests/openssl_csr_export_to_file_leak.phpt b/ext/openssl/tests/openssl_csr_export_to_file_leak.phpt new file mode 100644 index 0000000000000..e6ce373d355b1 --- /dev/null +++ b/ext/openssl/tests/openssl_csr_export_to_file_leak.phpt @@ -0,0 +1,14 @@ +--TEST-- +openssl_csr_export_to_file memory leak +--EXTENSIONS-- +openssl +--FILE-- + +--EXPECTF-- +Warning: openssl_csr_export_to_file(output_filename): must be a valid file path %s +bool(false) diff --git a/ext/openssl/tests/openssl_pkey_export_to_file_leak.phpt b/ext/openssl/tests/openssl_pkey_export_to_file_leak.phpt new file mode 100644 index 0000000000000..5e2bdff6b48fc --- /dev/null +++ b/ext/openssl/tests/openssl_pkey_export_to_file_leak.phpt @@ -0,0 +1,15 @@ +--TEST-- +openssl_pkey_export_to_file memory leak +--EXTENSIONS-- +openssl +--FILE-- + +--EXPECTF-- +Warning: openssl_pkey_export_to_file(output_filename): must be a valid file path %s +bool(false) diff --git a/ext/openssl/tests/openssl_x509_export_to_file_leak.phpt b/ext/openssl/tests/openssl_x509_export_to_file_leak.phpt new file mode 100644 index 0000000000000..5775c2597c3e0 --- /dev/null +++ b/ext/openssl/tests/openssl_x509_export_to_file_leak.phpt @@ -0,0 +1,14 @@ +--TEST-- +openssl_x509_export_to_file memory leak +--EXTENSIONS-- +openssl +--FILE-- + +--EXPECTF-- +Warning: openssl_x509_export_to_file(output_filename): must be a valid file path %s +bool(false) From 994e866cf2ad3b84882e7070e7097ee5553130e1 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 3 Nov 2024 21:18:34 +0100 Subject: [PATCH 25/40] Fix memory leak in php_openssl_pkey_from_zval() Closes GH-16691. --- NEWS | 1 + ext/openssl/openssl.c | 1 + .../php_openssl_pkey_from_zval_leak.phpt | 23 +++++++++++++++++++ 3 files changed, 25 insertions(+) create mode 100644 ext/openssl/tests/php_openssl_pkey_from_zval_leak.phpt diff --git a/NEWS b/NEWS index fadcea2106857..72b3d645cf915 100644 --- a/NEWS +++ b/NEWS @@ -11,6 +11,7 @@ PHP NEWS - OpenSSL: . Prevent unexpected array entry conversion when reading key. (nielsdos) . Fix various memory leaks related to openssl exports. (nielsdos) + . Fix memory leak in php_openssl_pkey_from_zval(). (nielsdos) - PDO: . Fixed memory leak of `setFetchMode()`. (SakiTakamachi) diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index 4a8aca8f99921..9e703f7586363 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -3533,6 +3533,7 @@ static EVP_PKEY *php_openssl_pkey_from_zval( } else { ZVAL_COPY(&tmp, zphrase); if (!try_convert_to_string(&tmp)) { + zval_ptr_dtor(&tmp); return NULL; } diff --git a/ext/openssl/tests/php_openssl_pkey_from_zval_leak.phpt b/ext/openssl/tests/php_openssl_pkey_from_zval_leak.phpt new file mode 100644 index 0000000000000..2b19dd311150a --- /dev/null +++ b/ext/openssl/tests/php_openssl_pkey_from_zval_leak.phpt @@ -0,0 +1,23 @@ +--TEST-- +php_openssl_pkey_from_zval memory leak +--EXTENSIONS-- +openssl +--FILE-- +getMessage(), "\n"; +} + +?> +--EXPECT-- +create a leak From 10f1f924cf854e3f8ed97b6f2eec72cba4893fc9 Mon Sep 17 00:00:00 2001 From: DanielEScherzer Date: Sat, 9 Nov 2024 02:08:02 -0800 Subject: [PATCH 26/40] Add `ReflectionConstant::getExtension()` and `::getExtensionName()` (#16603) --- UPGRADING | 2 + ext/reflection/php_reflection.c | 73 +++++++++++++++++-- ext/reflection/php_reflection.stub.php | 4 + ext/reflection/php_reflection_arginfo.h | 11 ++- .../ReflectionConstant_getExtension.phpt | 32 ++++++++ .../ReflectionConstant_getExtensionName.phpt | 26 +++++++ 6 files changed, 140 insertions(+), 8 deletions(-) create mode 100644 ext/reflection/tests/ReflectionConstant_getExtension.phpt create mode 100644 ext/reflection/tests/ReflectionConstant_getExtensionName.phpt diff --git a/UPGRADING b/UPGRADING index 1805d04e26061..6d6fa0030e603 100644 --- a/UPGRADING +++ b/UPGRADING @@ -102,6 +102,8 @@ PHP 8.5 UPGRADE NOTES - Reflection: . ReflectionConstant::getFileName() was introduced. + . ReflectionConstant::getExtension() and + ReflectionConstant::getExtensionName() were introduced. ======================================== 7. New Classes and Interfaces diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index 36682e62a55d3..76894fc12621e 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -1325,10 +1325,21 @@ PHPAPI void zend_reflection_class_factory(zend_class_entry *ce, zval *object) } /* }}} */ +/* {{{ reflection_extension_factory_ex */ +static void reflection_extension_factory_ex(zval *object, zend_module_entry *module) +{ + reflection_instantiate(reflection_extension_ptr, object); + reflection_object *intern = Z_REFLECTION_P(object); + intern->ptr = module; + intern->ref_type = REF_TYPE_OTHER; + intern->ce = NULL; + ZVAL_STRING(reflection_prop_name(object), module->name); +} +/* }}} */ + /* {{{ reflection_extension_factory */ static void reflection_extension_factory(zval *object, const char *name_str) { - reflection_object *intern; size_t name_len = strlen(name_str); zend_string *lcname; struct _zend_module_entry *module; @@ -1341,12 +1352,7 @@ static void reflection_extension_factory(zval *object, const char *name_str) return; } - reflection_instantiate(reflection_extension_ptr, object); - intern = Z_REFLECTION_P(object); - intern->ptr = module; - intern->ref_type = REF_TYPE_OTHER; - intern->ce = NULL; - ZVAL_STRINGL(reflection_prop_name(object), module->name, name_len); + reflection_extension_factory_ex(object, module); } /* }}} */ @@ -7592,6 +7598,59 @@ ZEND_METHOD(ReflectionConstant, getFileName) RETURN_FALSE; } +static void reflection_constant_find_ext(INTERNAL_FUNCTION_PARAMETERS, bool only_name) +{ + reflection_object *intern; + zend_constant *const_; + + ZEND_PARSE_PARAMETERS_NONE(); + + GET_REFLECTION_OBJECT_PTR(const_); + int module_number = ZEND_CONSTANT_MODULE_NUMBER(const_); + if (module_number == PHP_USER_CONSTANT) { + // For user constants, ReflectionConstant::getExtension() returns null, + // ReflectionConstant::getExtensionName() returns false + if (only_name) { + RETURN_FALSE; + } + RETURN_NULL(); + } + zend_module_entry *module; + ZEND_HASH_MAP_FOREACH_PTR(&module_registry, module) { + if (module->module_number != module_number) { + continue; + } + if (only_name) { + RETURN_STRING(module->name); + } + reflection_extension_factory_ex(return_value, module); + return; + } ZEND_HASH_FOREACH_END(); + + zend_throw_exception_ex( + reflection_exception_ptr, + 0, + "Unable to locate extension with module_number %d that provides constant %s", + module_number, + ZSTR_VAL(const_->name) + ); + RETURN_THROWS(); +} + +/* {{{ Returns NULL or the extension the constant belongs to */ +ZEND_METHOD(ReflectionConstant, getExtension) +{ + reflection_constant_find_ext(INTERNAL_FUNCTION_PARAM_PASSTHRU, false); +} +/* }}} */ + +/* {{{ Returns false or the name of the extension the constant belongs to */ +ZEND_METHOD(ReflectionConstant, getExtensionName) +{ + reflection_constant_find_ext(INTERNAL_FUNCTION_PARAM_PASSTHRU, true); +} +/* }}} */ + ZEND_METHOD(ReflectionConstant, __toString) { reflection_object *intern; diff --git a/ext/reflection/php_reflection.stub.php b/ext/reflection/php_reflection.stub.php index eb64f0de72b43..de15e405c7329 100644 --- a/ext/reflection/php_reflection.stub.php +++ b/ext/reflection/php_reflection.stub.php @@ -918,5 +918,9 @@ public function isDeprecated(): bool {} public function getFileName(): string|false {} + public function getExtension(): ?ReflectionExtension {} + + public function getExtensionName(): string|false {} + public function __toString(): string {} } diff --git a/ext/reflection/php_reflection_arginfo.h b/ext/reflection/php_reflection_arginfo.h index 6ad146c6ef9d5..6cdadc5c5b300 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: 603181d7e1d8292ef694913d4495d3cbb9dd7798 */ + * Stub hash: dbb59b2dd53c2849f66c00ce12228ebb07f50773 */ ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_Reflection_getModifierNames, 0, 1, IS_ARRAY, 0) ZEND_ARG_TYPE_INFO(0, modifiers, IS_LONG, 0) @@ -708,6 +708,11 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_ReflectionConstant_getFileName, 0, 0, MAY_BE_STRING|MAY_BE_FALSE) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_ReflectionConstant_getExtension, 0, 0, ReflectionExtension, 1) +ZEND_END_ARG_INFO() + +#define arginfo_class_ReflectionConstant_getExtensionName arginfo_class_ReflectionConstant_getFileName + #define arginfo_class_ReflectionConstant___toString arginfo_class_ReflectionFunction___toString ZEND_METHOD(Reflection, getModifierNames); @@ -975,6 +980,8 @@ ZEND_METHOD(ReflectionConstant, getShortName); ZEND_METHOD(ReflectionConstant, getValue); ZEND_METHOD(ReflectionConstant, isDeprecated); ZEND_METHOD(ReflectionConstant, getFileName); +ZEND_METHOD(ReflectionConstant, getExtension); +ZEND_METHOD(ReflectionConstant, getExtensionName); ZEND_METHOD(ReflectionConstant, __toString); static const zend_function_entry class_Reflection_methods[] = { @@ -1341,6 +1348,8 @@ static const zend_function_entry class_ReflectionConstant_methods[] = { ZEND_ME(ReflectionConstant, getValue, arginfo_class_ReflectionConstant_getValue, ZEND_ACC_PUBLIC) ZEND_ME(ReflectionConstant, isDeprecated, arginfo_class_ReflectionConstant_isDeprecated, ZEND_ACC_PUBLIC) ZEND_ME(ReflectionConstant, getFileName, arginfo_class_ReflectionConstant_getFileName, ZEND_ACC_PUBLIC) + ZEND_ME(ReflectionConstant, getExtension, arginfo_class_ReflectionConstant_getExtension, ZEND_ACC_PUBLIC) + ZEND_ME(ReflectionConstant, getExtensionName, arginfo_class_ReflectionConstant_getExtensionName, ZEND_ACC_PUBLIC) ZEND_ME(ReflectionConstant, __toString, arginfo_class_ReflectionConstant___toString, ZEND_ACC_PUBLIC) ZEND_FE_END }; diff --git a/ext/reflection/tests/ReflectionConstant_getExtension.phpt b/ext/reflection/tests/ReflectionConstant_getExtension.phpt new file mode 100644 index 0000000000000..9cc010461dc57 --- /dev/null +++ b/ext/reflection/tests/ReflectionConstant_getExtension.phpt @@ -0,0 +1,32 @@ +--TEST-- +ReflectionConstant::getExtension() +--EXTENSIONS-- +json +--FILE-- +getExtension()); + +$reflectionConstant = new ReflectionConstant('JSON_ERROR_NONE'); +var_dump($reflectionConstant->getExtension()); + +const CT_CONST = 5; +$reflectionConstant = new ReflectionConstant('CT_CONST'); +var_dump($reflectionConstant->getExtension()); + +define('RT_CONST', 6); +$reflectionConstant = new ReflectionConstant('RT_CONST'); +var_dump($reflectionConstant->getExtension()); +?> +--EXPECTF-- +object(ReflectionExtension)#%d (1) { + ["name"]=> + string(4) "Core" +} +object(ReflectionExtension)#%d (1) { + ["name"]=> + string(4) "json" +} +NULL +NULL diff --git a/ext/reflection/tests/ReflectionConstant_getExtensionName.phpt b/ext/reflection/tests/ReflectionConstant_getExtensionName.phpt new file mode 100644 index 0000000000000..dc4322dce4aba --- /dev/null +++ b/ext/reflection/tests/ReflectionConstant_getExtensionName.phpt @@ -0,0 +1,26 @@ +--TEST-- +ReflectionConstant::getExtensionName() +--EXTENSIONS-- +json +--FILE-- +getExtensionName()); + +$reflectionConstant = new ReflectionConstant('JSON_ERROR_NONE'); +var_dump($reflectionConstant->getExtensionName()); + +const CT_CONST = 5; +$reflectionConstant = new ReflectionConstant('CT_CONST'); +var_dump($reflectionConstant->getExtensionName()); + +define('RT_CONST', 6); +$reflectionConstant = new ReflectionConstant('RT_CONST'); +var_dump($reflectionConstant->getExtensionName()); +?> +--EXPECT-- +string(4) "Core" +string(4) "json" +bool(false) +bool(false) From 56bd0571234e6e5f5ebec7616d31c2fe4bd432ff Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 9 Nov 2024 11:09:36 +0100 Subject: [PATCH 27/40] [ci skip] NEWS for ReflectionConstant additions --- NEWS | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS b/NEWS index 819726aaa663c..ee1fa5cd79802 100644 --- a/NEWS +++ b/NEWS @@ -37,6 +37,10 @@ PHP NEWS - Random: . Moves from /dev/urandom usage to arc4random_buf on Haiku. (David Carlier) +- Reflection: + . Added ReflectionConstant::getExtension() and ::getExtensionName(). + (DanielEScherzer) + - SOAP: . Fixed bug #49169 (SoapServer calls wrong function, although "SOAP action" header is correct). (nielsdos) From 80dd5a0306b5709de8a57d339d464b0e15ac6f9d Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 9 Nov 2024 11:49:08 +0100 Subject: [PATCH 28/40] Fix wrong merge --- ext/openssl/openssl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index fd714ea5bf44d..c5720ee97e38c 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -3635,7 +3635,7 @@ static EVP_PKEY *php_openssl_pkey_from_zval( /* it's an X509 file/cert of some kind, and we need to extract the data from that */ if (public_key) { php_openssl_errors_set_mark(); - cert = php_openssl_x509_from_str(Z_STR_P(val), arg_num, false, NULL); + cert = php_openssl_x509_from_str(val_str, arg_num, false, NULL); if (cert) { free_cert = 1; From 3a1a205f2a3a275713197d540f73ae8fc6b9619d Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Fri, 8 Nov 2024 18:47:49 +0100 Subject: [PATCH 29/40] Fix GH-16723: CURLMOPT_PUSHFUNCTION issues We copy the source handler's FCCs to those of the destination. We also fix the erroneous test assumption that the trampoline wouldn't be called. Closes GH-16732. --- NEWS | 3 +++ ext/curl/interface.c | 6 +++--- ext/curl/tests/curl_pushfunction_trampoline.phpt | 1 + 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index 86672aea04a32..50248f5a7e2cb 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,9 @@ PHP NEWS - Calendar: . Fixed jdtogregorian overflow. (David Carlier) +- Curl: + . Fixed bug GH-16723 (CURLMOPT_PUSHFUNCTION issues). (cmb) + - PDO: . Fixed memory leak of `setFetchMode()`. (SakiTakamachi) diff --git a/ext/curl/interface.c b/ext/curl/interface.c index b75dce2e4c75d..c7309b829f6dd 100644 --- a/ext/curl/interface.c +++ b/ext/curl/interface.c @@ -1284,13 +1284,13 @@ void _php_setup_easy_copy_handlers(php_curl *ch, php_curl *source) ch->handlers.read->res = source->handlers.read->res; if (ZEND_FCC_INITIALIZED(source->handlers.read->fcc)) { - zend_fcc_dup(&source->handlers.read->fcc, &source->handlers.read->fcc); + zend_fcc_dup(&ch->handlers.read->fcc, &source->handlers.read->fcc); } if (ZEND_FCC_INITIALIZED(source->handlers.write->fcc)) { - zend_fcc_dup(&source->handlers.write->fcc, &source->handlers.write->fcc); + zend_fcc_dup(&ch->handlers.write->fcc, &source->handlers.write->fcc); } if (ZEND_FCC_INITIALIZED(source->handlers.write_header->fcc)) { - zend_fcc_dup(&source->handlers.write_header->fcc, &source->handlers.write_header->fcc); + zend_fcc_dup(&ch->handlers.write_header->fcc, &source->handlers.write_header->fcc); } curl_easy_setopt(ch->cp, CURLOPT_ERRORBUFFER, ch->err.str); diff --git a/ext/curl/tests/curl_pushfunction_trampoline.phpt b/ext/curl/tests/curl_pushfunction_trampoline.phpt index 741f3fa6662a0..73a23097968e2 100644 --- a/ext/curl/tests/curl_pushfunction_trampoline.phpt +++ b/ext/curl/tests/curl_pushfunction_trampoline.phpt @@ -60,6 +60,7 @@ sort($responses); print_r($responses); ?> --EXPECT-- +Trampoline for trampoline Array ( [0] => main response From c0755463208b7b1d549b3d1e6367fc6f88147f47 Mon Sep 17 00:00:00 2001 From: "Hans Krentel (hakre)" Date: Thu, 7 Nov 2024 21:00:23 +0100 Subject: [PATCH 30/40] Fail early in *nix configuration build script Adding two exit early safeguards in the *nix configuration build script: 1) Given the initial cd into the build tree fails (the project root), the `buildconf` script exits with non-zero status (failure). 2) Given the grep command does not exist or `configure.ac` AC_INIT [1] expectations are unmet, the buildconf script exits non-zero. Additionally quoting the pathname to cd into and the empty CD_PATH parameter for portability, also for systems that are using a non-portable pathname [2] for the build tree. The initial CD safeguard has been applied to the `buildconf` and four more scripts: - build/genif.sh - scripts/dev/credits - scripts/dev/genfiles - scripts/dev/makedist Rationale: Cd-ing into the project root should always prematurely exit w/ FAILURE as a required precondition for its invocation has not been met. This should never go unnoticed as it always requires user intervention. Similar and more specifically to the PHP build on *nix systems, the grep command is required early to obtain the `php_extra_version` from configure.ac. Previously, if the grep command is missing (or failing due to not matching the line with the AC_INIT macro [1]), the internal dev parameter would always be zero (0) which can easily result in the situation that the configure script is not being rebuilt. This is cumbersome as the rebuild of a configure script is more likely required with checked-out dev versions under change rather than an already properly set-up build environment on a dedicated build or release system. Missing the fact that either the grep utility is missing or the expectation of having the AC_INIT macro in configure.ac is unmet should never go unnoticed as it always requires user intervention. [1]: https://www.gnu.org/software/autoconf/manual/autoconf-2.67/html_node/Initializing-configure.html [2]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_271 Closes GH-16717. --- NEWS | 3 +++ build/genif.sh | 2 +- buildconf | 4 ++-- scripts/dev/credits | 2 +- scripts/dev/genfiles | 2 +- scripts/dev/makedist | 2 +- 6 files changed, 9 insertions(+), 6 deletions(-) diff --git a/NEWS b/NEWS index 72b3d645cf915..c441f4c25e3b1 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,9 @@ PHP NEWS - Calendar: . Fixed jdtogregorian overflow. (David Carlier) +- Core: + . Fail early in *nix configuration build script. (hakre) + - FPM: . Fixed GH-16432 (PHP-FPM 8.2 SIGSEGV in fpm_get_status). (Jakub Zelenka) diff --git a/build/genif.sh b/build/genif.sh index 697bef95912e4..f6d6fff953476 100755 --- a/build/genif.sh +++ b/build/genif.sh @@ -32,7 +32,7 @@ header_list= olddir=$(pwd) # Go to project root. -cd $(CDPATH= cd -- "$(dirname -- "$0")/../" && pwd -P) +cd "$(CDPATH='' cd -- "$(dirname -- "$0")/../" && pwd -P)" || exit module_ptrs="$(echo $extensions | $AWK -f ./build/order_by_dep.awk)" diff --git a/buildconf b/buildconf index af0937db1dc28..8c16c9b82747d 100755 --- a/buildconf +++ b/buildconf @@ -8,9 +8,9 @@ force=0 debug=0 # Go to project root. -cd $(CDPATH= cd -- "$(dirname -- "$0")" && pwd -P) +cd "$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd -P)" || exit -php_extra_version=$(grep '^AC_INIT(' configure.ac) +php_extra_version=$(grep '^AC_INIT(' configure.ac) || exit case "$php_extra_version" in *-dev*) dev=1 diff --git a/scripts/dev/credits b/scripts/dev/credits index e59cc109b88d7..783bc5f18f79d 100755 --- a/scripts/dev/credits +++ b/scripts/dev/credits @@ -3,7 +3,7 @@ # Generate credits_*.h headers from the ext/*/CREDITS and sapi/*/CREDITS files. # Go to project root directory -cd $(CDPATH= cd -- "$(dirname -- "$0")/../../" && pwd -P) +cd "$(CDPATH='' cd -- "$(dirname -- "$0")/../../" && pwd -P)" || exit awkprog=' BEGIN { FS = "\n|\r\n|\r"; RS = "" } diff --git a/scripts/dev/genfiles b/scripts/dev/genfiles index 3e085c3e5397f..32b4c8851e2d1 100755 --- a/scripts/dev/genfiles +++ b/scripts/dev/genfiles @@ -41,7 +41,7 @@ SED=${SED:-sed} MAKE=${MAKE:-make} # Go to project root. -cd $(CDPATH= cd -- "$(dirname -- "$0")/../../" && pwd -P) +cd "$(CDPATH='' cd -- "$(dirname -- "$0")/../../" && pwd -P)" || exit # Check required bison version from the configure.ac file. required_bison_version=$($SED -n 's/PHP_PROG_BISON(\[\([0-9\.]*\)\].*/\1/p' configure.ac) diff --git a/scripts/dev/makedist b/scripts/dev/makedist index ffdf536907651..c9ad6059004be 100755 --- a/scripts/dev/makedist +++ b/scripts/dev/makedist @@ -15,7 +15,7 @@ if [[ $($tar --version) == *"bsdtar"* ]]; then fi # Go to project root directory. -cd $(CDPATH= cd -- "$(dirname -- "$0")/../../" && pwd -P) +cd "$(CDPATH='' cd -- "$(dirname -- "$0")/../../" && pwd -P)" || exit # Process options and arguments. while :; do From 329890c149fe5a7e04f9e348be30253241437126 Mon Sep 17 00:00:00 2001 From: "Hans Krentel (hakre)" Date: Thu, 7 Nov 2024 18:49:58 +0100 Subject: [PATCH 31/40] Fail early in *nix build script Adding one more [1] exit early safeguard in *nix build scripts: Given the initial cd into the build tree fails (the project root), the `buildconf` script exits with non-zero status (failure). Additionally quoting the pathname to cd into and the empty CD_PATH parameter for portability, also for systems that are using a non-portable pathname [2] for the build tree. [1]: https://github.com/php/php-src/pull/16717 [2]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_271 Closes GH-16724. --- ext/fileinfo/generate_patch.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/fileinfo/generate_patch.sh b/ext/fileinfo/generate_patch.sh index da99b1fcdb2af..4e3fade8ec566 100755 --- a/ext/fileinfo/generate_patch.sh +++ b/ext/fileinfo/generate_patch.sh @@ -3,7 +3,7 @@ VERSION=5.45 # Go to fileinfo extension directory. -cd $(CDPATH= cd -- "$(dirname -- "$0")" && pwd -P) +cd "$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd -P)" || exit if [ ! -d libmagic.orig ]; then mkdir libmagic.orig From 54003aecc420dfd5c2736aed0ba4c0b32f3084af Mon Sep 17 00:00:00 2001 From: DanielEScherzer Date: Sat, 9 Nov 2024 06:32:53 -0800 Subject: [PATCH 32/40] Fix description of `ReflectionParameter::getPosition()` (GH-16738) Appears to have been copied from `ReflectionParameter::isOptional()`. [skip ci] --- ext/reflection/php_reflection.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index 76894fc12621e..0a3f54b530ff1 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -2827,7 +2827,7 @@ ZEND_METHOD(ReflectionParameter, getAttributes) param->fptr->type == ZEND_USER_FUNCTION ? param->fptr->op_array.filename : NULL); } -/* {{{ Returns whether this parameter is an optional parameter */ +/* {{{ Returns the index of the parameter, starting from 0 */ ZEND_METHOD(ReflectionParameter, getPosition) { reflection_object *intern; From 89e750a2019af1a398582ef59e0ead21d541e63f Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 9 Nov 2024 15:34:17 +0100 Subject: [PATCH 33/40] Fix macOS CI Install curl via brew. Closes GH-16735. Co-authored-by: "Christoph M. Becker" --- .github/actions/brew/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/brew/action.yml b/.github/actions/brew/action.yml index 287062e6f9f9c..07595a5ada931 100644 --- a/.github/actions/brew/action.yml +++ b/.github/actions/brew/action.yml @@ -13,7 +13,7 @@ runs: # Some packages exist on x86 but not arm, or vice versa. # Install them with reinstall to avoid warnings. - brew reinstall autoconf webp tidy-html5 libzip libsodium icu4c + brew reinstall autoconf webp tidy-html5 libzip libsodium icu4c curl brew install \ bison \ re2c From 72c0222926ab81076e2256fd461462152988e7ca Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Mon, 4 Nov 2024 21:18:37 +0100 Subject: [PATCH 34/40] Fix GH-16695: phar:// tar parser and zero-length file header blocks There are two issues: 1) There's an off-by-one in the check for the minimum file size for a tar (i.e. `>` instead of `>=`). 2) The loop in the tar parsing parses a header, and then unconditionally reads the next one. However, that doesn't necessarily exist. Instead, we remove the loop condition and check for the end of the file before reading the next header. Note that we can't use php_stream_eof as the flag may not be set yet when we're already at the end. Closes GH-16700. --- NEWS | 4 ++++ ext/phar/phar.c | 2 +- ext/phar/tar.c | 10 +++++++--- ext/phar/tests/tar/gh16695_1.phpt | 28 ++++++++++++++++++++++++++++ ext/phar/tests/tar/gh16695_2.phpt | 26 ++++++++++++++++++++++++++ ext/phar/tests/tar/gh16695_3.phpt | 26 ++++++++++++++++++++++++++ 6 files changed, 92 insertions(+), 4 deletions(-) create mode 100644 ext/phar/tests/tar/gh16695_1.phpt create mode 100644 ext/phar/tests/tar/gh16695_2.phpt create mode 100644 ext/phar/tests/tar/gh16695_3.phpt diff --git a/NEWS b/NEWS index c441f4c25e3b1..6e9e23670a14b 100644 --- a/NEWS +++ b/NEWS @@ -19,6 +19,10 @@ PHP NEWS - PDO: . Fixed memory leak of `setFetchMode()`. (SakiTakamachi) +- Phar: + . Fixed bug GH-16695 (phar:// tar parser and zero-length file header blocks). + (nielsdos) + 21 Nov 2024, PHP 8.2.26 - Cli: diff --git a/ext/phar/phar.c b/ext/phar/phar.c index e3d6ea74c6182..01a3d54625470 100644 --- a/ext/phar/phar.c +++ b/ext/phar/phar.c @@ -1774,7 +1774,7 @@ static int phar_open_from_fp(php_stream* fp, char *fname, size_t fname_len, char return phar_parse_zipfile(fp, fname, fname_len, alias, alias_len, pphar, error); } - if (got > 512) { + if (got >= 512) { if (phar_is_tar(pos, fname)) { php_stream_rewind(fp); return phar_parse_tarfile(fp, fname, fname_len, alias, alias_len, pphar, is_data, compression, error); diff --git a/ext/phar/tar.c b/ext/phar/tar.c index 60e248c78df5f..652062679d70a 100644 --- a/ext/phar/tar.c +++ b/ext/phar/tar.c @@ -254,9 +254,8 @@ int phar_parse_tarfile(php_stream* fp, char *fname, size_t fname_len, char *alia entry.is_tar = 1; entry.is_crc_checked = 1; entry.phar = myphar; - pos += sizeof(buf); - do { + while (true) { phar_entry_info *newentry; pos = php_stream_tell(fp); @@ -597,6 +596,11 @@ int phar_parse_tarfile(php_stream* fp, char *fname, size_t fname_len, char *alia } } + /* Only read next header if we're not yet at the end */ + if (php_stream_tell(fp) == totalsize) { + break; + } + read = php_stream_read(fp, buf, sizeof(buf)); if (read != sizeof(buf)) { @@ -607,7 +611,7 @@ int phar_parse_tarfile(php_stream* fp, char *fname, size_t fname_len, char *alia phar_destroy_phar_data(myphar); return FAILURE; } - } while (!php_stream_eof(fp)); + } if (zend_hash_str_exists(&(myphar->manifest), ".phar/stub.php", sizeof(".phar/stub.php")-1)) { myphar->is_data = 0; diff --git a/ext/phar/tests/tar/gh16695_1.phpt b/ext/phar/tests/tar/gh16695_1.phpt new file mode 100644 index 0000000000000..8ce82bcf28dd9 --- /dev/null +++ b/ext/phar/tests/tar/gh16695_1.phpt @@ -0,0 +1,28 @@ +--TEST-- +GH-16695 (phar:// tar parser and zero-length file header blocks) +--CREDITS-- +hakre +--EXTENSIONS-- +phar +--INI-- +phar.require_hash=0 +--FILE-- + +--CLEAN-- + +--EXPECTF-- +int(512) + +Warning: file_get_contents(%stls): Failed to open stream: phar error: path "tls" is a directory in %s on line %d +bool(false) diff --git a/ext/phar/tests/tar/gh16695_2.phpt b/ext/phar/tests/tar/gh16695_2.phpt new file mode 100644 index 0000000000000..5b7200398c496 --- /dev/null +++ b/ext/phar/tests/tar/gh16695_2.phpt @@ -0,0 +1,26 @@ +--TEST-- +GH-16695 (phar:// tar parser and zero-length file header blocks) +--CREDITS-- +hakre +--EXTENSIONS-- +phar +--INI-- +phar.require_hash=0 +--FILE-- + +--CLEAN-- + +--EXPECT-- +int(1024) +string(122) "{"Name":"default","Metadata":{},"Endpoints":{"docker":{"Host":"unix:///run/user/1000/docker.sock","SkipTLSVerify":false}}}" diff --git a/ext/phar/tests/tar/gh16695_3.phpt b/ext/phar/tests/tar/gh16695_3.phpt new file mode 100644 index 0000000000000..eddf697b0137c --- /dev/null +++ b/ext/phar/tests/tar/gh16695_3.phpt @@ -0,0 +1,26 @@ +--TEST-- +GH-16695 (phar:// tar parser and zero-length file header blocks) +--CREDITS-- +hakre +--EXTENSIONS-- +phar +--INI-- +phar.require_hash=0 +--FILE-- + +--CLEAN-- + +--EXPECT-- +int(512) +string(0) "" From d87f3ff66219d808ff0d8ac5fa69cc75c8db1ce6 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 9 Nov 2024 17:09:35 +0100 Subject: [PATCH 35/40] [ci skip] Add credit for test --- NEWS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 6e9e23670a14b..1b4b7effb50cf 100644 --- a/NEWS +++ b/NEWS @@ -21,7 +21,7 @@ PHP NEWS - Phar: . Fixed bug GH-16695 (phar:// tar parser and zero-length file header blocks). - (nielsdos) + (nielsdos, Hans Krentel) 21 Nov 2024, PHP 8.2.26 From 62e53e6f4965f37d379a3fd21f65a4210c5c86b5 Mon Sep 17 00:00:00 2001 From: DanielEScherzer Date: Sat, 9 Nov 2024 08:40:45 -0800 Subject: [PATCH 36/40] Inline and remove `reflection_instantiate()` (#16739) Since the return value is never used, the only difference between using this method and using `object_init_ex()` directly is the flipped order of parameters, and the added level of indirection - remove that level of indirection by replacing its uses. --- ext/reflection/php_reflection.c | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index 0a3f54b530ff1..ecfa20fe0c0c8 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -301,13 +301,6 @@ static zend_object *reflection_objects_new(zend_class_entry *class_type) /* {{{ } /* }}} */ -static zval *reflection_instantiate(zend_class_entry *pce, zval *object) /* {{{ */ -{ - object_init_ex(object, pce); - return object; -} -/* }}} */ - static void _const_string(smart_str *str, const char *name, zval *value, const char *indent); static void _function_string(smart_str *str, zend_function *fptr, zend_class_entry *scope, const char* indent); static void _property_string(smart_str *str, zend_property_info *prop, const char *prop_name, const char* indent); @@ -1168,7 +1161,7 @@ static void reflection_attribute_factory(zval *object, HashTable *attributes, ze reflection_object *intern; attribute_reference *reference; - reflection_instantiate(reflection_attribute_ptr, object); + object_init_ex(object, reflection_attribute_ptr); intern = Z_REFLECTION_P(object); reference = (attribute_reference*) emalloc(sizeof(attribute_reference)); reference->attributes = attributes; @@ -1316,7 +1309,7 @@ PHPAPI void zend_reflection_class_factory(zend_class_entry *ce, zval *object) zend_class_entry *reflection_ce = ce->ce_flags & ZEND_ACC_ENUM ? reflection_enum_ptr : reflection_class_ptr; - reflection_instantiate(reflection_ce, object); + object_init_ex(object, reflection_ce); intern = Z_REFLECTION_P(object); intern->ptr = ce; intern->ref_type = REF_TYPE_OTHER; @@ -1328,7 +1321,7 @@ PHPAPI void zend_reflection_class_factory(zend_class_entry *ce, zval *object) /* {{{ reflection_extension_factory_ex */ static void reflection_extension_factory_ex(zval *object, zend_module_entry *module) { - reflection_instantiate(reflection_extension_ptr, object); + object_init_ex(object, reflection_extension_ptr); reflection_object *intern = Z_REFLECTION_P(object); intern->ptr = module; intern->ref_type = REF_TYPE_OTHER; @@ -1363,7 +1356,7 @@ static void reflection_parameter_factory(zend_function *fptr, zval *closure_obje parameter_reference *reference; zval *prop_name; - reflection_instantiate(reflection_parameter_ptr, object); + object_init_ex(object, reflection_parameter_ptr); intern = Z_REFLECTION_P(object); reference = (parameter_reference*) emalloc(sizeof(parameter_reference)); reference->arg_info = arg_info; @@ -1438,13 +1431,13 @@ static void reflection_type_factory(zend_type type, zval *object, bool legacy_be switch (type_kind) { case INTERSECTION_TYPE: - reflection_instantiate(reflection_intersection_type_ptr, object); + object_init_ex(object, reflection_intersection_type_ptr); break; case UNION_TYPE: - reflection_instantiate(reflection_union_type_ptr, object); + object_init_ex(object, reflection_union_type_ptr); break; case NAMED_TYPE: - reflection_instantiate(reflection_named_type_ptr, object); + object_init_ex(object, reflection_named_type_ptr); break; EMPTY_SWITCH_DEFAULT_CASE(); } @@ -1471,7 +1464,7 @@ static void reflection_type_factory(zend_type type, zval *object, bool legacy_be static void reflection_function_factory(zend_function *function, zval *closure_object, zval *object) { reflection_object *intern; - reflection_instantiate(reflection_function_ptr, object); + object_init_ex(object, reflection_function_ptr); intern = Z_REFLECTION_P(object); intern->ptr = function; intern->ref_type = REF_TYPE_FUNCTION; @@ -1488,7 +1481,7 @@ static void reflection_method_factory(zend_class_entry *ce, zend_function *metho { reflection_object *intern; - reflection_instantiate(reflection_method_ptr, object); + object_init_ex(object, reflection_method_ptr); intern = Z_REFLECTION_P(object); intern->ptr = method; intern->ref_type = REF_TYPE_FUNCTION; @@ -1508,7 +1501,7 @@ static void reflection_property_factory(zend_class_entry *ce, zend_string *name, reflection_object *intern; property_reference *reference; - reflection_instantiate(reflection_property_ptr, object); + object_init_ex(object, reflection_property_ptr); intern = Z_REFLECTION_P(object); reference = (property_reference*) emalloc(sizeof(property_reference)); reference->prop = prop; @@ -1533,7 +1526,7 @@ static void reflection_class_constant_factory(zend_string *name_str, zend_class_ { reflection_object *intern; - reflection_instantiate(reflection_class_constant_ptr, object); + object_init_ex(object, reflection_class_constant_ptr); intern = Z_REFLECTION_P(object); intern->ptr = constant; intern->ref_type = REF_TYPE_CLASS_CONSTANT; @@ -1551,7 +1544,7 @@ static void reflection_enum_case_factory(zend_class_entry *ce, zend_string *name zend_class_entry *case_reflection_class = ce->enum_backing_type == IS_UNDEF ? reflection_enum_unit_case_ptr : reflection_enum_backed_case_ptr; - reflection_instantiate(case_reflection_class, object); + object_init_ex(object, case_reflection_class); intern = Z_REFLECTION_P(object); intern->ptr = constant; intern->ref_type = REF_TYPE_CLASS_CONSTANT; From 92132c8086764874a369aba2f676a2c0c6dff87b Mon Sep 17 00:00:00 2001 From: "Hans Krentel (hakre)" Date: Sun, 10 Nov 2024 00:53:52 +0100 Subject: [PATCH 37/40] bump ci From 5db97236ec622c2736c68450328062f2f760cf28 Mon Sep 17 00:00:00 2001 From: "Hans Krentel (hakre)" Date: Sun, 10 Nov 2024 01:32:27 +0100 Subject: [PATCH 38/40] bump ci (2) From a342071997c01101db167622d5be1f6abd6dd112 Mon Sep 17 00:00:00 2001 From: "Hans Krentel (hakre)" Date: Sun, 10 Nov 2024 01:50:04 +0100 Subject: [PATCH 39/40] Try paths-ignore (& for anchoring and * for aliasing) The list of pathnames/patterns was the same. Try because IIRC ms-gh-actions support it, but try first. --- .github/workflows/push.yml | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 6baf80d5f84b0..07c27f80ccdf8 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -1,7 +1,7 @@ name: Push on: push: - paths-ignore: + paths-ignore: &paths-ignore - docs/** - NEWS - UPGRADING @@ -18,16 +18,7 @@ on: - PHP-8.4 - master pull_request: - paths-ignore: - - docs/** - - NEWS - - UPGRADING - - UPGRADING.INTERNALS - - '**/README.*' - - CONTRIBUTING.md - - CODING_STANDARDS.md - - .cirrus.yml - - .circleci/** + paths-ignore: *paths-ignore branches: - '**' workflow_dispatch: ~ From e138f45816a94ba06ae13ff161d4e57f01d4d367 Mon Sep 17 00:00:00 2001 From: "Hans Krentel (hakre)" Date: Sun, 10 Nov 2024 01:55:08 +0100 Subject: [PATCH 40/40] Counter test openldap in list Most likely this effectively by $BREW_OPT only for "openlap". Could also levitate as otherwise commented was an issue specifically to brew (homebrew?!.) Previously (recently) failing jobs in Push: - MACOS_X64_DEBUG_NTS - MACOS_ARM64_DEBUG_NTS --- .github/actions/configure-macos/action.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/actions/configure-macos/action.yml b/.github/actions/configure-macos/action.yml index ab92dfb2d782f..645efe9de3da8 100644 --- a/.github/actions/configure-macos/action.yml +++ b/.github/actions/configure-macos/action.yml @@ -18,6 +18,7 @@ runs: export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:$BREW_OPT/libxslt/lib/pkgconfig" export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:$BREW_OPT/zlib/lib/pkgconfig" export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:$BREW_OPT/icu4c/lib/pkgconfig" + export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:$BREW_OPT/openldap/lib/pkgconfig" ./buildconf --force ./configure \ --enable-option-checking=fatal \